Skip to main content
Glama
gabrielserrao

pyResToolbox MCP Server

oil_rate_radial

Calculate oil production rates for vertical wells using Darcy's law for radial flow. Automatically computes PVT properties and applies Vogel IPR for two-phase flow when needed.

Instructions

Calculate oil production rate for radial flow (vertical well).

INFLOW PERFORMANCE TOOL - Computes oil production rate for vertical wells with radial flow geometry using Darcy's law. Automatically calculates PVT properties (Rs, Bo, μo) at average pressure. Optionally applies Vogel IPR model for two-phase flow below bubble point.

Parameters:

  • pi (float, required): Initial/reservoir pressure in psia. Must be > 0. Example: 4000.0.

  • pb (float, required): Bubble point pressure in psia. Must be ≥ 0. Example: 3500.0. If pi < pb, reservoir is saturated (gas cap present).

  • 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.

  • sg_g (float, required): Gas specific gravity (air=1). Valid: 0-3. Typical: 0.6-1.2. Example: 0.75.

  • psd (float or list, required): Sandface/draining pressure(s) in psia. Must be > 0 and < pi. Can be scalar or array. Example: 1500.0 or [1000, 1500, 2000].

  • h (float, required): Net pay thickness in feet. Must be > 0. Typical: 10-200 ft. Example: 50.0.

  • k (float, required): Permeability in millidarcies (mD). Must be > 0. Typical: 1-1000 mD. Example: 100.0.

  • s (float, optional, default=0.0): Skin factor (dimensionless). Negative = stimulation, positive = damage. Typical: -5 to +20. Example: 0.0 for undamaged well.

  • re (float, required): Drainage radius in feet. Must be > rw. Typical: 500-5000 ft. Example: 1000.0.

  • rw (float, required): Wellbore radius in feet. Must be > 0. Typical: 0.25-0.5 ft. Example: 0.5.

  • rsb (float, required): Solution GOR at bubble point in scf/stb. Must be ≥ 0. Example: 800.0.

  • vogel (bool, optional, default=False): Apply Vogel IPR model. Set True when pi < pb (saturated reservoir). Example: False.

Flow Regime:

  • Undersaturated (pi > pb): Single-phase oil flow, Darcy's law applies

  • Saturated (pi < pb): Two-phase flow, use Vogel=True for accurate IPR

Darcy's Law Formula: qo = (0.00708 × k × h × (pi - pwf)) / (μo × Bo × (ln(re/rw) + S))

Where PVT properties (μo, Bo) are calculated at average pressure (pi + pwf)/2.

Returns: Dictionary with:

  • value (float or list): Oil rate in STB/day (matches input psd shape)

  • method (str): "Darcy radial flow" or "Vogel IPR"

  • units (str): "STB/day"

  • inputs (dict): Echo of input parameters

Common Mistakes:

  • Using separator temperature instead of reservoir temperature

  • Pressure in barg/psig instead of psia (must be absolute)

  • Not setting vogel=True when pi < pb (underestimates rate)

  • Using wrong drainage radius (re) - should be well spacing/2

  • Confusing net pay (h) with gross thickness

  • Not accounting for skin factor (s)

Example Usage:

{ "pi": 4000.0, "pb": 3500.0, "api": 35.0, "degf": 180.0, "sg_g": 0.75, "psd": [1500, 2000, 2500], "h": 50.0, "k": 100.0, "s": 0.0, "re": 1000.0, "rw": 0.5, "rsb": 800.0, "vogel": False }

Result: Oil rate decreases as sandface pressure increases (typical IPR curve).

Note: This tool automatically calculates PVT properties. You don't need to provide Rs, Bo, or μo - they are computed internally at average pressure. For saturated reservoirs (pi < pb), set vogel=True for accurate two-phase flow.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
requestYes

Implementation Reference

  • The handler function for 'oil_rate_radial' tool, decorated with @mcp.tool(). Computes oil rate using Darcy's law for radial flow, automatically calculating PVT properties (Rs, Bo, μo) with pyrestoolbox.oil module and Vogel IPR option.
    @mcp.tool() def oil_rate_radial(request: OilRateRadialRequest) -> dict: """Calculate oil production rate for radial flow (vertical well). **INFLOW PERFORMANCE TOOL** - Computes oil production rate for vertical wells with radial flow geometry using Darcy's law. Automatically calculates PVT properties (Rs, Bo, μo) at average pressure. Optionally applies Vogel IPR model for two-phase flow below bubble point. **Parameters:** - **pi** (float, required): Initial/reservoir pressure in psia. Must be > 0. Example: 4000.0. - **pb** (float, required): Bubble point pressure in psia. Must be ≥ 0. Example: 3500.0. If pi < pb, reservoir is saturated (gas cap present). - **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. - **sg_g** (float, required): Gas specific gravity (air=1). Valid: 0-3. Typical: 0.6-1.2. Example: 0.75. - **psd** (float or list, required): Sandface/draining pressure(s) in psia. Must be > 0 and < pi. Can be scalar or array. Example: 1500.0 or [1000, 1500, 2000]. - **h** (float, required): Net pay thickness in feet. Must be > 0. Typical: 10-200 ft. Example: 50.0. - **k** (float, required): Permeability in millidarcies (mD). Must be > 0. Typical: 1-1000 mD. Example: 100.0. - **s** (float, optional, default=0.0): Skin factor (dimensionless). Negative = stimulation, positive = damage. Typical: -5 to +20. Example: 0.0 for undamaged well. - **re** (float, required): Drainage radius in feet. Must be > rw. Typical: 500-5000 ft. Example: 1000.0. - **rw** (float, required): Wellbore radius in feet. Must be > 0. Typical: 0.25-0.5 ft. Example: 0.5. - **rsb** (float, required): Solution GOR at bubble point in scf/stb. Must be ≥ 0. Example: 800.0. - **vogel** (bool, optional, default=False): Apply Vogel IPR model. Set True when pi < pb (saturated reservoir). Example: False. **Flow Regime:** - **Undersaturated (pi > pb)**: Single-phase oil flow, Darcy's law applies - **Saturated (pi < pb)**: Two-phase flow, use Vogel=True for accurate IPR **Darcy's Law Formula:** qo = (0.00708 × k × h × (pi - pwf)) / (μo × Bo × (ln(re/rw) + S)) Where PVT properties (μo, Bo) are calculated at average pressure (pi + pwf)/2. **Returns:** Dictionary with: - **value** (float or list): Oil rate in STB/day (matches input psd shape) - **method** (str): "Darcy radial flow" or "Vogel IPR" - **units** (str): "STB/day" - **inputs** (dict): Echo of input parameters **Common Mistakes:** - Using separator temperature instead of reservoir temperature - Pressure in barg/psig instead of psia (must be absolute) - Not setting vogel=True when pi < pb (underestimates rate) - Using wrong drainage radius (re) - should be well spacing/2 - Confusing net pay (h) with gross thickness - Not accounting for skin factor (s) **Example Usage:** ```python { "pi": 4000.0, "pb": 3500.0, "api": 35.0, "degf": 180.0, "sg_g": 0.75, "psd": [1500, 2000, 2500], "h": 50.0, "k": 100.0, "s": 0.0, "re": 1000.0, "rw": 0.5, "rsb": 800.0, "vogel": False } ``` Result: Oil rate decreases as sandface pressure increases (typical IPR curve). **Note:** This tool automatically calculates PVT properties. You don't need to provide Rs, Bo, or μo - they are computed internally at average pressure. For saturated reservoirs (pi < pb), set vogel=True for accurate two-phase flow. """ # Convert psd to numpy array for processing psd_array = np.asarray(request.psd) is_scalar = psd_array.ndim == 0 if is_scalar: psd_array = np.array([psd_array]) # Calculate oil specific gravity from API sg_o = oil.oil_sg(api_value=request.api) # Calculate solution GOR at sandface pressure(s) # oil_rs uses sg_sp (separator gas SG), use sg_g as separator gas SG rs_values = oil.oil_rs( api=request.api, degf=request.degf, p=psd_array, sg_sp=request.sg_g, # Use sg_g as separator gas SG pb=request.pb, rsb=request.rsb, rsmethod=rs_method.VELAR, ) # Calculate PVT properties at sandface pressure(s) # Use average pressure for PVT calculation (between reservoir and sandface) avg_pressures = (request.pi + psd_array) / 2.0 # Calculate Rs at average pressures for PVT rs_avg = oil.oil_rs( api=request.api, degf=request.degf, p=avg_pressures, sg_sp=request.sg_g, # Use sg_g as separator gas SG pb=request.pb, rsb=request.rsb, rsmethod=rs_method.VELAR, ) # Calculate Bo and uo at average pressures bo_values = oil.oil_bo( p=avg_pressures, pb=request.pb, degf=request.degf, rs=rs_avg, rsb=request.rsb, sg_o=sg_o, sg_g=request.sg_g, bomethod=bo_method.MCAIN, ) uo_values = oil.oil_viso( p=avg_pressures, api=request.api, degf=request.degf, pb=request.pb, rs=rs_avg, ) # Convert to scalars if needed if is_scalar: bo_values = float(bo_values[0]) if isinstance(bo_values, np.ndarray) else float(bo_values) uo_values = float(uo_values[0]) if isinstance(uo_values, np.ndarray) else float(uo_values) psd_array = psd_array[0] # Call oil_rate_radial with correct parameters qo = oil.oil_rate_radial( k=request.k, h=request.h, pr=request.pi, pwf=psd_array, r_w=request.rw, r_ext=request.re, uo=uo_values, bo=bo_values, S=request.s, vogel=request.vogel, pb=request.pb, ) # Convert numpy array to list for JSON serialization if isinstance(qo, np.ndarray): value = qo.tolist() else: value = float(qo) method = "Darcy radial flow" # Ensure scalar comparison (not array) to avoid "ambiguous truth value" error pi_scalar = float(request.pi) if isinstance(request.pi, (np.ndarray, list)) else request.pi pb_scalar = float(request.pb) if isinstance(request.pb, (np.ndarray, list)) else request.pb if request.vogel and pi_scalar < pb_scalar: method = "Vogel IPR" return { "value": value, "method": method, "units": "STB/day", "inputs": request.model_dump(), }
  • Pydantic model defining the input schema for oil_rate_radial tool, including all parameters with validation constraints (e.g., gt=0, descriptions) and custom validators for psd and rw.
    class OilRateRadialRequest(BaseModel): """Request model for radial oil inflow performance calculation.""" pi: float = Field(..., gt=0, description="Initial reservoir pressure (psia)") pb: float = Field(..., ge=0, description="Bubble point pressure (psia)") api: float = Field(..., gt=0, le=100, description="Oil API gravity (degrees)") degf: float = Field( ..., gt=-460, lt=1000, description="Temperature (degrees Fahrenheit)" ) sg_g: float = Field( ..., ge=0, le=3, description="Gas specific gravity (air=1, dimensionless)" ) psd: Union[float, List[float]] = Field( ..., description="Sandface pressure (psia) - scalar or array" ) h: float = Field(..., gt=0, description="Net pay thickness (ft)") k: float = Field(..., gt=0, description="Permeability (mD)") s: float = Field(0.0, description="Skin factor (dimensionless)") re: float = Field(..., gt=0, description="Drainage radius (ft)") rw: float = Field(..., gt=0, description="Wellbore radius (ft)") rsb: float = Field( 0.0, ge=0, description="Solution GOR at bubble point (scf/stb)" ) vogel: bool = Field( False, description="Use Vogel IPR for reservoir pressure below bubble point" ) @field_validator("psd") @classmethod def validate_pressure(cls, v): """Validate pressure values.""" if isinstance(v, list): if not all(p > 0 for p in v): raise ValueError("All sandface pressure values must be positive") else: if v <= 0: raise ValueError("Sandface pressure must be positive") return v @field_validator("rw") @classmethod def validate_rw(cls, v, info): """Validate wellbore radius is less than drainage radius.""" if "re" in info.data and v >= info.data["re"]: raise ValueError("Wellbore radius must be less than drainage radius") return v
  • Server initialization where register_inflow_tools(mcp) is called at line 26, which defines and registers the oil_rate_radial tool via @mcp.tool() decorator.
    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)
  • The register_inflow_tools function that contains the @mcp.tool() decorated oil_rate_radial handler definition.
    def register_inflow_tools(mcp: FastMCP) -> None: """Register all inflow performance tools with the MCP server."""

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/gabrielserrao/pyrestoolbox-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server