oil_density
Calculate oil density at reservoir conditions for gradient calculations, well pressure analysis, and material balance using PVT properties.
Instructions
Calculate oil density (ρo) at reservoir conditions.
CRITICAL PVT PROPERTY - Computes oil density from PVT properties using mass balance approach. Essential for gradient calculations, well pressure analysis, and material balance calculations.
Parameters:
p (float or list, required): Pressure(s) in psia. Must be > 0. Can be scalar or array. Example: 3000.0.
api (float, required): Oil API gravity in degrees. Valid: 0-100. Example: 35.0.
degf (float, required): Reservoir temperature in °F. Valid: -460 to 1000. Example: 180.0.
rs (float or list, required): Solution GOR at pressure p in scf/stb. Must match p shape. Example: 600.0 or [400, 600, 800].
sg_g (float, required): Gas specific gravity (air=1). Valid: 0-3. Typical: 0.6-1.2. Example: 0.75.
bo (float or list, required): Oil formation volume factor at pressure p in rb/stb. Must match p shape. Calculate using oil_formation_volume_factor tool first. Example: 1.25 or [1.15, 1.25, 1.30].
Calculation Method: Density = (Stock tank oil mass + Dissolved gas mass) / Reservoir volume ρo = (sg_o × 62.372 + 0.01357 × Rs × sg_g) / Bo
Where:
sg_o = oil specific gravity (calculated from API)
62.372 = water density at standard conditions (lb/cuft)
0.01357 = gas density conversion factor
Typical Ranges:
Light oils: 40-50 lb/cuft
Medium oils: 50-55 lb/cuft
Heavy oils: 55-65 lb/cuft
Returns: Dictionary with:
value (float or list): Density in lb/cuft (matches input p shape)
method (str): "Standard"
units (str): "lb/cuft"
inputs (dict): Echo of input parameters
Common Mistakes:
Using stock tank density instead of reservoir density
Not providing matching rs and bo arrays
Using wrong bo value (must be at same pressure as p)
Confusing density (mass/volume) with specific gravity (dimensionless)
Example Usage:
Result: Density ≈ 48-52 lb/cuft for typical medium gravity oil.
Note: Always calculate Bo first using oil_formation_volume_factor tool, then use matching rs and bo values for accurate density calculation.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| request | Yes |
Implementation Reference
- The handler function for the 'oil_density' tool. It calculates reservoir oil density using the mass balance formula involving stock tank oil specific gravity, dissolved gas contribution, and formation volume factor. Handles both scalar and array inputs, with comprehensive validation and documentation.@mcp.tool() def oil_density(request: OilDensityRequest) -> dict: """Calculate oil density (ρo) at reservoir conditions. **CRITICAL PVT PROPERTY** - Computes oil density from PVT properties using mass balance approach. Essential for gradient calculations, well pressure analysis, and material balance calculations. **Parameters:** - **p** (float or list, required): Pressure(s) in psia. Must be > 0. Can be scalar or array. Example: 3000.0. - **api** (float, required): Oil API gravity in degrees. Valid: 0-100. Example: 35.0. - **degf** (float, required): Reservoir temperature in °F. Valid: -460 to 1000. Example: 180.0. - **rs** (float or list, required): Solution GOR at pressure p in scf/stb. Must match p shape. Example: 600.0 or [400, 600, 800]. - **sg_g** (float, required): Gas specific gravity (air=1). Valid: 0-3. Typical: 0.6-1.2. Example: 0.75. - **bo** (float or list, required): Oil formation volume factor at pressure p in rb/stb. Must match p shape. Calculate using oil_formation_volume_factor tool first. Example: 1.25 or [1.15, 1.25, 1.30]. **Calculation Method:** Density = (Stock tank oil mass + Dissolved gas mass) / Reservoir volume ρo = (sg_o × 62.372 + 0.01357 × Rs × sg_g) / Bo Where: - sg_o = oil specific gravity (calculated from API) - 62.372 = water density at standard conditions (lb/cuft) - 0.01357 = gas density conversion factor **Typical Ranges:** - Light oils: 40-50 lb/cuft - Medium oils: 50-55 lb/cuft - Heavy oils: 55-65 lb/cuft **Returns:** Dictionary with: - **value** (float or list): Density in lb/cuft (matches input p shape) - **method** (str): "Standard" - **units** (str): "lb/cuft" - **inputs** (dict): Echo of input parameters **Common Mistakes:** - Using stock tank density instead of reservoir density - Not providing matching rs and bo arrays - Using wrong bo value (must be at same pressure as p) - Confusing density (mass/volume) with specific gravity (dimensionless) **Example Usage:** ```python { "p": 3000.0, "api": 35.0, "degf": 180.0, "rs": 600.0, "sg_g": 0.75, "bo": 1.25 } ``` Result: Density ≈ 48-52 lb/cuft for typical medium gravity oil. **Note:** Always calculate Bo first using oil_formation_volume_factor tool, then use matching rs and bo values for accurate density calculation. """ # Calculate sg_o from API sg_o = oil.oil_sg(api_value=request.api) # Calculate density - note: oil_deno doesn't calculate from bo, # it calculates density directly. We use bo to back-calculate rs if needed. # For simple density, we can use the formula: density = (sg_o * 62.372 + 0.01357 * rs * sg_g) / bo density = (sg_o * 62.372 + 0.01357 * request.rs * request.sg_g) / request.bo deno = density # Convert numpy array to list for JSON serialization if isinstance(deno, np.ndarray): value = deno.tolist() else: value = float(deno) return { "value": value, "method": "Standard", "units": "lb/cuft", "inputs": request.model_dump(), }
- Pydantic BaseModel defining the input schema and validation for the 'oil_density' tool, including fields for pressure, API gravity, temperature, solution GOR, gas specific gravity, and oil FVF.class OilDensityRequest(BaseModel): """Request model for oil density calculation.""" p: Union[float, List[float]] = Field( ..., description="Pressure (psia) - scalar or array" ) api: float = Field(..., gt=0, le=100, description="Oil API gravity (degrees)") degf: float = Field( ..., gt=-460, lt=1000, description="Temperature (degrees Fahrenheit)" ) rs: Union[float, List[float]] = Field( ..., description="Solution GOR (scf/stb) - scalar or array" ) sg_g: float = Field( ..., ge=0, le=3, description="Gas specific gravity (air=1, dimensionless)" ) bo: Union[float, List[float]] = Field( ..., description="Oil FVF (rb/stb) - scalar or array" ) @field_validator("p", "rs", "bo") @classmethod def validate_arrays(cls, v): """Validate array inputs.""" if isinstance(v, list): if not all(val > 0 for val in v): raise ValueError("All values must be positive") else: if v <= 0: raise ValueError("Value must be positive") return v
- src/pyrestoolbox_mcp/server.py:15-30 (registration)The main server initialization file where register_oil_tools(mcp) is called at line 24, which registers all oil tools including 'oil_density' via decorators inside the register function.# Import and register tools from .tools.oil_tools import register_oil_tools from .tools.gas_tools import register_gas_tools from .tools.inflow_tools import register_inflow_tools from .tools.simtools_tools import register_simtools_tools from .tools.brine_tools import register_brine_tools from .tools.layer_tools import register_layer_tools from .tools.library_tools import register_library_tools register_oil_tools(mcp) register_gas_tools(mcp) register_inflow_tools(mcp) register_simtools_tools(mcp) register_brine_tools(mcp) register_layer_tools(mcp) register_library_tools(mcp)