Skip to the content.

The package neqsim.process.fielddevelopment.wellplanning collects well-planning physics that complements the existing well and tubing classes (WellSystem, WellFlow, TubingPerformance, InjectionWellModel, WellIntegrityScreening, WellDesignCalculator). Every class is a screening calculator. Validation is by analytic limits and textbook formulas, not field data; nothing here replaces a qualified well-engineering tool.

Class Purpose Status
WellboreThermalModel Ramey / Hasan-Kabir flowing temperature for producers and injectors, layered U-value, lumped shut-in cooldown implemented, analytic-limit validated
DriftFluxWellboreHydraulics Vertical and deviated tubing traverse with flow regime, holdup, Turner loading ratio, API RP 14E erosional ratio implemented, analytic-limit and Beggs-Brill compared
GasCondensateInflowModel Radial gas-condensate inflow with banking (Fevang-Whitson style) and Forchheimer flow implemented, dry-gas limit validated
AnnularPressureBuildup Trapped-annulus APB with Lame compliance, steel expansion, bleed and gas cushion implemented, closed-form validated
TubingMovementCalculator Piston, ballooning, temperature and buckling length change, restraint force, von Mises check implemented, closed-form validated
WellChemicalTreatment CPA hydrate-inhibitor dose per station, partitioning, lean-solution rate, pump and line basis implemented, Hammerschmidt-compared
InjectionWellHydraulics Water/gas injector traverse with density change, fracture limit with thermal stress, matrix operating point implemented, analytic-limit validated
NodalAnalysis IPR x VLP intersections, stability, sensitivity sweeps, adapters implemented, closed-form validated

Wellbore temperature and shut-in

The flowing temperature uses the relaxation distance $A = w c_p (k_e + r_{to} U f(t)) / (2 \pi r_{to} U k_e)$. For a producer entering at depth $L$ with temperature $T_{in}$ the profile is $T(z) = T_f(z) + gA + (T_{in} - T_f(L) - gA)\,e^{-(L-z)/A}$; for an injector $T(z) = T_f(z) - gA + (T_{in} - T_f(0) + gA)\,e^{-z/A}$. Zero rate gives the geothermal profile and infinite rate keeps the inlet temperature. overallHeatTransferCoefficient(...) builds $U$ from tubing, insulation, annulus, casing and cement layers. timeToReachTemperatureHours(...) gives the lumped cooldown time to a hydrate temperature.

Drift-flux tubing hydraulics

SystemInterface fluid = new SystemSrkEos(273.15 + 80.0, 200.0);
fluid.addComponent("methane", 0.35);
fluid.addComponent("ethane", 0.05);
fluid.addComponent("propane", 0.04);
fluid.addComponent("n-butane", 0.03);
fluid.addComponent("n-hexane", 0.08);
fluid.addComponent("n-decane", 0.45);
fluid.setMixingRule("classic");

WellboreThermalModel thermal = new WellboreThermalModel().setSurfaceTemperatureC(5.0)
    .setGeothermalGradient(0.03).setTotalDepth(2500.0).setMassFlowRate(8.0).setInletTemperatureC(80.0);
DriftFluxWellboreHydraulics well = new DriftFluxWellboreHydraulics(fluid).setMassFlowRate(8.0)
    .setTubing(0.1, 4.5e-5).setStraightWell(2500.0, 0.0, 25).setThermalModel(thermal);
DriftFluxWellboreHydraulics.Result r = well.calculateFromWellhead(30.0);
double bhp = r.getBottomholePressureBara();
boolean loading = r.isLiquidLoadingRisk();
double erosionRatio = r.getMaxErosionalRatio();

Closures follow Hasan and Kabir: bubble ($\alpha \le 0.25$), slug ($\alpha < 0.52$), churn and annular ($v_{sg} \ge 3.1(\sigma g \Delta\rho/\rho_G^2)^{0.25}$, Wallis void fraction). Evidence: static column equals $\rho g L$; horizontal liquid matches Darcy-Weisbach; dry gas matches an independent fine-step integration; the oil case agrees with PipeBeggsAndBrills within 4 percent of the pressure drop. For the synthetic gas-condensate case the drift-flux drop is lower than Beggs and Brill (which over-predicts wet-gas holdup); the NeqSim PipeGray gave a still lower drop, so the three models spread and none is field-calibrated. Not modelled: acceleration drop, emulsion viscosity, entrainment, stratified flow below 10 degrees from horizontal (a warning is raised).

Gas-condensate inflow

SystemInterface gc = new SystemSrkEos(273.15 + 110.0, 300.0);
gc.addComponent("methane", 0.75);
gc.addComponent("ethane", 0.08);
gc.addComponent("propane", 0.05);
gc.addComponent("n-butane", 0.03);
gc.addComponent("n-hexane", 0.04);
gc.addComponent("n-octane", 0.03);
gc.addComponent("nC10", 0.02);
gc.setMixingRule("classic");

GasCondensateInflowModel inflow = new GasCondensateInflowModel(gc, 110.0).setReservoirPressure(450.0)
    .setFormation(20.0, 40.0).setGeometry(500.0, 0.108, 0.0).setRelativePermeability(0.2, 0.1, 1.0, 1.0, 3.0, 3.0);
inflow.useGeertsmaBeta(0.15);
GasCondensateInflowModel.Result res = inflow.calculate(100.0);
double q = res.getGasRateSm3PerDay();
double impairment = res.getBankingImpairment();
double dewPoint = res.getDewPointBara();

The molar rate solves $\Psi(p_e) - \Psi(p_{wf}) = a n_w + b n_w^2$ with $\Psi = \int k_{rg}\rho_g/(\mu_g V)\,dp$. Above the dew point this is the real-gas pseudo-pressure solution (validated against an independent integral of $2p/(\mu Z)$). Below it $k_{ro}/k_{rg}$ follows the constant-composition liquid-to-vapour ratio (region 2) and immobile oil uses the CCE saturation (region 3). Not implemented: velocity-dependent relative permeability, CVD composition change.

Annular pressure build-up and tubing movement

AnnularPressureBuildup.Result apb = new AnnularPressureBuildup().setAnnulusLength(1500.0)
    .setGeometry(0.1397, 0.1215, 0.2204, 0.2445).setFluidProperties(3.0e-4, 4.5e-5).setTemperatureChange(40.0)
    .setInitialPressure(10.0).calculate();
double dP = apb.getDeltaPressureBar();
WellIntegrityScreening.AnnulusReading reading = apb.toAnnulusReading("A", 200.0);

TubingMovementCalculator.Result mv = new TubingMovementCalculator().setLength(3000.0)
    .setGeometry(0.1143, 0.0985, 0.12, 0.1594).setLoadChange(150.0, 20.0, 120.0, 20.0, 40.0).calculate();
double freeMovement = mv.getFreeDeltaLM();

The APB solves $V_0\alpha\Delta T - V_0\kappa\Delta P - V_{bled} = C\Delta P + D + V_g \Delta P/(P_0+\Delta P)$; the rigid limit is $\alpha\Delta T/\kappa$. Fluid $\alpha,\kappa$ can be derived from a NeqSim liquid with setFluidFromThermoSystem. Tubing movement uses the Lubinski piston, ballooning, temperature and helical-buckling terms; a fixed packer returns $-EA_s\Delta L/L$. Vertical wells only; no deviated friction or bending.

Hydrate-inhibitor treatment along the well

SystemInterface fluid = new SystemSrkCPAstatoil(293.15, 100.0);
fluid.addComponent("methane", 0.85);
fluid.addComponent("ethane", 0.07);
fluid.addComponent("propane", 0.03);
fluid.addComponent("n-butane", 0.01);
fluid.addComponent("water", 0.05);
fluid.setMixingRule(10);

WellChemicalTreatment treatment = new WellChemicalTreatment(fluid)
    .setInhibitor(WellChemicalTreatment.HydrateInhibitor.MEG, 0.9).setSubcoolingMargin(3.0).setWaterRate(2000.0)
    .addStation("tree shut-in", 120.0, 8.0);
WellChemicalTreatment.Result r = treatment.evaluate();
double leanKgPerHour = r.getLeanSolutionKgPerHour();

The required mass fraction uses the rigorous CPA hydrate temperature of the whole fluid, so methanol losses to gas are included; the CPA inhibition effect agrees with Hammerschmidt within about 35 percent in the test fluid. Scale, corrosion and scavenger doses are sized with the existing classes in process.chemistry and converted to injection rates with chemicalInjectionRateLitresPerHour. Pump power and capillary-line friction have closed-form helpers. Salt-in-MEG solubility, regeneration and kinetic inhibitors are not modelled.

Injection wells

InjectionWellHydraulics integrates density along the tubing with NeqSim flashes (water with CPA, gas with SRK or GERG), applies a temperature profile, and reports the fracture margin with $\Delta\sigma = \alpha E \Delta T/(1-\nu)$ (upper bound). findOperatingPoint(whp) finds the matrix-injectivity rate and caps it at the fracture pressure. Hydrate and scale compatibility are screened with the existing flow-assurance and WaterCompatibilityScreener classes.

Nodal analysis

NodalAnalysis.InflowCurve ipr = NodalAnalysis.linearInflow(300.0, 2.0);
NodalAnalysis.OutflowCurve vlp = NodalAnalysis.tabulatedOutflow(new double[] {1.0, 100.0, 400.0},
    new double[] {85.0, 140.0, 300.0});
NodalAnalysis.Result result = new NodalAnalysis(ipr, vlp).setRateRange(1.0, 400.0).solve();
double q = result.getOperatingPoint().getRate();

Intersections are classified stable or unstable (liquid loading gives a U-shaped outflow with an unstable low-rate root). sweepOutflow and sweepInflow run tubing-size, wellhead-pressure, skin, GOR, water-cut or depletion sensitivities through factories; fromDriftFlux and fromGasCondensate adapt the classes above.

Not implemented

Mechanistic horizontal and stratified flow, tubing-annulus fluid conduction transient, permafrost thaw, velocity-dependent relative permeability, fracture (Hall plot) injection, salt-in-glycol solubility, triaxial design factors from ISO 13679 load cases and sour-service material approval (the existing SourServiceAssessment is a partial-pressure screen only).

The code snippets above are compiled and run by WellPlanningDocExamplesTest.