Class WellFlow

All Implemented Interfaces:
Serializable, Runnable, ProcessEquipmentInterface, TwoPortInterface, SimulationInterface, NamedInterface

public class WellFlow extends TwoPortEquipment

WellFlow class - Inflow Performance Relationship (IPR) model for reservoir-to-wellbore flow.

This class models the reservoir inflow into the wellbore using various IPR correlations. It calculates either the bottom-hole flowing pressure (Pwf) from a specified flow rate, or the flow rate from a specified Pwf, depending on the operating mode.

Supported IPR Models

  • PRODUCTION_INDEX - Constant PI using squared-pressure drawdown: q = PI × (Pr² - Pwf²)
  • VOGEL - Solution gas drive oil wells (1968): q/qmax = 1 - 0.2(Pwf/Pr) - 0.8(Pwf/Pr)²
  • FETKOVICH - Gas well deliverability (1973): q = C × (Pr² - Pwf²)ⁿ
  • BACKPRESSURE - Non-Darcy/turbulence effects: Pr² - Pwf² = a×q + b×q²
  • TABLE - Tabulated IPR from well tests

Usage Example 1 - Basic Gas Well

// Create reservoir stream at reservoir conditions
Stream reservoirStream = new Stream("reservoir", reservoirFluid);
reservoirStream.setFlowRate(5.0, "MSm3/day");
reservoirStream.run();

// Create WellFlow with production index
WellFlow well = new WellFlow("gas producer");
well.setInletStream(reservoirStream);
well.setWellProductionIndex(5.0e-4); // MSm3/day/bar²
well.run();

System.out.println("BHP = " + well.getOutletStream().getPressure("bara") + " bara");

Usage Example 2 - Vogel IPR for Oil Well

WellFlow oilWell = new WellFlow("oil producer");
oilWell.setInletStream(reservoirStream);

// Set Vogel parameters from well test
// qTest=3000 Sm3/day at Pwf=180 bara, Pr=250 bara
oilWell.setVogelParameters(3000, 180, 250);
oilWell.run();

Usage Example 3 - Multi-Layer Commingled Well

WellFlow commingledWell = new WellFlow("commingled producer");
commingledWell.setInletStream(mainReservoirStream);

// Add multiple producing layers
commingledWell.addLayer("Upper Sand", upperStream, 220.0, 3.0e-4);
commingledWell.addLayer("Middle Sand", middleStream, 200.0, 2.0e-4);
commingledWell.addLayer("Lower Sand", lowerStream, 180.0, 1.5e-4);

// Solve for commingled production at specified BHP
commingledWell.setOutletPressure(150.0, "bara");
commingledWell.solveFlowFromOutletPressure(true);
commingledWell.run();

// Get individual layer contributions
double[] layerRates = commingledWell.getLayerFlowRates("Sm3/day");

Integration with Process Simulation

// Create reservoir
SimpleReservoir reservoir = new SimpleReservoir("Field");
reservoir.setReservoirFluid(fluid, gasVol, oilVol, waterVol);
StreamInterface prodStream = reservoir.addGasProducer("PROD-1");
prodStream.setFlowRate(5.0, "MSm3/day");

// Create well with IPR
WellFlow wellIPR = new WellFlow("PROD-1 IPR");
wellIPR.setInletStream(prodStream);
wellIPR.setWellProductionIndex(5.0e-4);

// Create tubing (VLP)
PipeBeggsAndBrills tubing = new PipeBeggsAndBrills("tubing", wellIPR.getOutletStream());
tubing.setLength(2500);
tubing.setElevation(2500);
tubing.setDiameter(0.1016);

// Add to process system
ProcessSystem process = new ProcessSystem();
process.add(reservoir);
process.add(wellIPR);
process.add(tubing);
process.run();
Version:
$Id: $Id
Author:
asmund
See Also:
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      Serialization version UID.
      See Also:
    • logger

      static org.apache.logging.log4j.Logger logger
      Logger object for class.
    • thermoSystem

      SystemInterface thermoSystem
    • wellProductionIndex

      private double wellProductionIndex
    • pressureOut

      double pressureOut
    • pressureUnit

      String pressureUnit
    • useWellProductionIndex

      boolean useWellProductionIndex
    • calcpressure

      boolean calcpressure
    • inflowModel

    • vogelQmax

      double vogelQmax
    • vogelRefPres

      double vogelRefPres
    • fetkovichC

      double fetkovichC
    • fetkovichN

      double fetkovichN
    • backpressureA

      double backpressureA
    • backpressureB

      double backpressureB
    • inflowTablePwf

      double[] inflowTablePwf
    • inflowTableRate

      double[] inflowTableRate
    • layers

      private List<WellFlow.ReservoirLayer> layers
    • isMultiLayer

      private boolean isMultiLayer
  • Constructor Details

    • WellFlow

      public WellFlow(String name)

      Constructor for WellFlow.

      Parameters:
      name - a String object
  • Method Details

    • addLayer

      public void addLayer(String name, StreamInterface stream, double reservoirPressure, double pi)
      Add a reservoir layer for commingled production.

      Multiple layers can contribute to the total well flow. Each layer has its own reservoir pressure and productivity index. The flow from each layer is calculated based on the common bottom-hole pressure.

      Parameters:
      name - layer identifier
      stream - stream representing the layer fluid
      reservoirPressure - layer reservoir pressure (bara)
      pi - layer productivity index (Sm3/day/bar² for gas)
    • getNumberOfLayers

      public int getNumberOfLayers()
      Get the number of reservoir layers.
      Returns:
      number of layers
    • getLayerFlowRates

      public double[] getLayerFlowRates(String unit)
      Get flow rates from individual layers.
      Parameters:
      unit - flow rate unit ("Sm3/day", "MSm3/day", etc.)
      Returns:
      array of layer flow rates
    • getLayer

      public WellFlow.ReservoirLayer getLayer(int index)
      Get a specific layer by index.
      Parameters:
      index - layer index
      Returns:
      ReservoirLayer object
    • run

      public void run(UUID id)

      In this method all thermodynamic and unit operations will be calculated in a steady state calculation.

      Parameters:
      id - UUID
    • runMultiLayer

      private void runMultiLayer(UUID id)
      Run multi-layer commingled production calculation.

      For commingled wells, the flow from each layer is calculated based on the common bottom-hole pressure. The total flow is the sum of individual layer contributions.

      Parameters:
      id - calculation UUID
    • runTransient

      public void runTransient(double dt, UUID id)

      runTransient

      This method calculates thermodynamic and unit operations using difference equations if available and calculateSteadyState is true. Use setCalculateSteadyState to set the parameter. Sets calc identifier UUID.
      Parameters:
      dt - Delta time [s]
      id - Calculation identifier
    • getWellProductionIndex

      public double getWellProductionIndex()

      Getter for the field wellProductionIndex.

      Returns:
      a double
    • setWellProductionIndex

      public void setWellProductionIndex(double wellProductionIndex)

      Setter for the field wellProductionIndex.

      Parameters:
      wellProductionIndex - a double
    • setOutletPressure

      public void setOutletPressure(double pressure, String unit)
      Specify the well outlet pressure to be used when solving for flow from backpressure (i.e. solveFlowFromOutletPressure(boolean) set to true).
      Parameters:
      pressure - outlet pressure
      unit - pressure unit
    • solveFlowFromOutletPressure

      public void solveFlowFromOutletPressure(boolean solve)
      Enable solving for flow rate from a specified outlet pressure instead of solving for outlet pressure from a specified flow rate.
      Parameters:
      solve - true to compute flow from the set outlet pressure
    • isCalculatingOutletPressure

      public boolean isCalculatingOutletPressure()
      Returns:
      true if the well is set to compute outlet pressure from the inlet stream flowrate.
    • setVogelParameters

      public void setVogelParameters(double qTest, double pwfTest, double reservoirPressure)
      Use Vogel inflow performance relationship.
      Parameters:
      qTest - flow rate at test conditions (same unit as stream)
      pwfTest - bottom-hole pressure at test conditions in bara
      reservoirPressure - reservoir pressure in bara
    • setFetkovichParameters

      public void setFetkovichParameters(double c, double n, double reservoirPressure)
      Use Fetkovich inflow performance relationship.
      Parameters:
      c - Fetkovich constant C
      n - Fetkovich exponent n
      reservoirPressure - reservoir pressure in bara
    • setBackpressureParameters

      public void setBackpressureParameters(double a, double b, double reservoirPressure)
      Use backpressure equation for gas wells: pres2 - pwf2 = a·q + b·q². Parameter b captures non-Darcy (turbulence) effects.
      Parameters:
      a - deliverability coefficient a
      b - deliverability coefficient b (non-Darcy component)
      reservoirPressure - reservoir pressure in bara (stored for reference)
    • setTableInflow

      public void setTableInflow(double[] bottomHolePressures, double[] flowRates)
      Provide tabulated inflow data (flow rate vs. bottom-hole pressure). Arrays are sorted by pressure internally to allow monotonic interpolation.
      Parameters:
      bottomHolePressures - bottom-hole flowing pressures in bara
      flowRates - flow rates corresponding to each pressure point (same unit as stream)
    • setDarcyLawParameters

      public void setDarcyLawParameters(double permeability, double thickness, double viscosity, double reservoirRadius, double wellRadius, double skinFactor)
      Estimate well production index from Darcy law parameters. Units: permeability in mD, viscosity in cP and lengths in meter.
      Parameters:
      permeability - reservoir permeability
      thickness - reservoir thickness
      viscosity - fluid viscosity
      reservoirRadius - drainage radius
      wellRadius - wellbore radius
      skinFactor - skin factor
    • computeBackpressureFlow

      private double computeBackpressureFlow(double drawdown)
    • interpolateFlowForPressure

      private double interpolateFlowForPressure(double pwf)
    • interpolatePressureForFlow

      private double interpolatePressureForFlow(double flow)
    • sortTableByPressure

      private void sortTableByPressure()
    • loadIPRFromFile

      public void loadIPRFromFile(String filePath) throws IOException
      Load IPR curve from a CSV file.

      The CSV file should have two columns: bottom-hole pressure (bara) and flow rate. The first row can be a header (will be skipped if non-numeric). Columns can be separated by comma, semicolon, or tab.

      Example CSV format:

      Pwf(bara),Rate(MSm3/day)
      50,5.2
      80,4.1
      100,3.2
      120,2.4
      150,1.5
      180,0.8
      200,0.2
      
      Parameters:
      filePath - path to the CSV file
      Throws:
      IOException - if file cannot be read
    • loadIPRFromFile

      public void loadIPRFromFile(Path filePath) throws IOException
      Load IPR curve from a CSV file.
      Parameters:
      filePath - path to the CSV file
      Throws:
      IOException - if file cannot be read
      See Also:
    • getIPRTablePressures

      public double[] getIPRTablePressures()
      Get the current IPR table pressures.
      Returns:
      array of bottom-hole pressures (bara), or empty array if not using table IPR
    • getIPRTableRates

      public double[] getIPRTableRates()
      Get the current IPR table flow rates.
      Returns:
      array of flow rates, or empty array if not using table IPR