Best for
- USE WHEN: optimizing production rates, identifying facility bottlenecks, forecasting production profiles, fitting decline curves to production history, estimating reserves from pressure/production data, analyzing gas li…
equinor/neqsim/.github/skills/neqsim-production-optimization/SKILL.md
Production optimization, bottleneck analysis, decline modeling, decline-curve history matching (Arps + Duong), reservoir material balance surveillance (OGIP/OOIP, drive indices, aquifer influx), and IOR/EOR screening with NeqSim. USE WHEN: optimizing production rates, identifying facility bottlenecks, forecasting production profiles, fitting decline curves to production history, estimating reserves from pressure/production data, analyzing gas lift allocation, evaluating IOR/EOR options, or runni
Decision brief
Reference for production forecasting, optimization, bottleneck analysis, and improved recovery using NeqSim's field development and process simulation tools.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/equinor/neqsim --skill ".github/skills/neqsim-production-optimization"Inspect the Agent Skill "neqsim-production-optimization" from https://github.com/equinor/neqsim/blob/9e4e36d4b6a59404ac9aa629740fbc312610d3c8/.github/skills/neqsim-production-optimization/SKILL.md at commit 9e4e36d4b6a59404ac9aa629740fbc312610d3c8. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Review the “Production Profile Modeling” section in the pinned source before continuing.
Review the “Decline Curve Types” section in the pinned source before continuing.
Review the “Production Profile Generation” section in the pinned source before continuing.
Review the “Multi-Well Drill Schedule” section in the pinned source before continuing.
neqsim.pvtsimulation.util.DeclineCurveAnalysis is a static, unit-agnostic Arps + Duong decline toolkit. Besides the forward rate(...), cumulativeProduction(...), eur(...) and forecast(...) methods it now least-squares fits decline parameters to a measured rate-time history — the…
Permission review
No configured static risk pattern was detected
This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.
Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 91/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 147 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Reference for production forecasting, optimization, bottleneck analysis, and improved recovery using NeqSim's field development and process simulation tools.
| Model | Formula | Use Case |
|---|---|---|
| Exponential | $q(t) = q_i e^{-Dt}$ | Gas wells, constant decline |
| Hyperbolic | $q(t) = q_i (1 + bDt)^{-1/b}$ | Oil wells, b = 0.3-0.8 |
| Harmonic | $q(t) = q_i / (1 + Dt)$ | Hyperbolic with b = 1 |
| Plateau + exponential | Build-up → plateau → decline | Constrained by facility |
ProductionProfile profile = new ProductionProfile();
// Method 1: Arps decline
profile.setDeclineModel(ProductionProfile.DeclineModel.EXPONENTIAL);
profile.setPeakRate(25000.0); // boe/d
profile.setDeclineRate(0.15); // 15% per year (Di)
profile.setPlateauDuration(3); // years at peak
profile.setProjectLife(25); // total years
double[] rates = profile.generateProfile();
// Method 2: Hyperbolic with b-factor
profile.setDeclineModel(ProductionProfile.DeclineModel.HYPERBOLIC);
profile.setHyperbolicB(0.5);
// Method 3: Resource-constrained
ProductionProfileGenerator gen = new ProductionProfileGenerator();
gen.setResourceVolume(100.0); // MMboe recoverable
gen.setRecoveryFactor(0.55);
gen.setPeakRate(25000.0);
gen.setBuildUpYears(2);
gen.setPlateauYears(5);
gen.generate();
FieldProductionScheduler scheduler = new FieldProductionScheduler();
scheduler.setNumberOfWells(8);
scheduler.setDrillingInterval(6); // months between wells
scheduler.setFirstOil(2027);
scheduler.setWellProductivity(4000.0); // initial boe/d/well
scheduler.setDeclineRate(0.12); // 12%/year per well
scheduler.setFacilityCapacity(28000.0);// boe/d plateau constraint
double[][] schedule = scheduler.generateSchedule(25);
// schedule[year][0] = oil rate, [1] = gas rate, [2] = water rate
DeclineCurveAnalysis)neqsim.pvtsimulation.util.DeclineCurveAnalysis is a static, unit-agnostic
Arps + Duong decline toolkit. Besides the forward rate(...),
cumulativeProduction(...), eur(...) and forecast(...) methods it now
least-squares fits decline parameters to a measured rate-time history — the
inverse (surveillance) direction used to estimate remaining reserves and EUR
directly from production data. Times are in days; rates keep whatever consistent
unit you supply.
import java.util.Map;
import neqsim.pvtsimulation.util.DeclineCurveAnalysis;
// t[] in days, q[] in bbl/d (or Sm3/d, MMscf/d — unit-agnostic)
Map<String, Double> fit = DeclineCurveAnalysis.fitArps(t, q);
double qi = fit.get("qi"); // initial rate
double di = fit.get("di"); // nominal decline (1/day)
double b = fit.get("b"); // Arps exponent (grid-searched 0..1)
double r2 = fit.get("rSquared"); // goodness of fit
// EUR to an economic-limit rate straight from the fit
double eur = DeclineCurveAnalysis.eurFromFit(fit, 50.0); // rate-unit * days
// Windowed fit — exclude early transient / cleanup points (indices 0..2 here)
Map<String, Double> fitW = DeclineCurveAnalysis.fitArps(t, q, 3, t.length - 1);
The fitArps overloads grid-search the exponent b over [0, 1] (coarse then
fine), analytically solving qi and di for each candidate by linearising in
rate space (ln q vs t for b≈0; q^-b vs t otherwise). Use the windowed
overload to fit only the established boundary-dominated decline.
For fracture-dominated tight-gas and shale wells the Arps model over-estimates reserves. The Duong (2011) model is included:
// Forward
double q = DeclineCurveAnalysis.rateDuong(q1, a, m, t); // rate at time t
double gp = DeclineCurveAnalysis.cumulativeDuong(q1, a, m, t); // cumulative
// Fit q1, a, m to a rate history (log-log q/Gp vs t straight line)
Map<String, Double> duong = DeclineCurveAnalysis.fitDuong(t, q);
// keys: "q1", "a", "m", "rSquared"
Model selection: fit both fitArps and fitDuong, compare rSquared, and
prefer Duong when the well is in transient linear (fracture-dominated) flow.
neqsim.pvtsimulation.reservoirproperties.materialbalance regresses original
hydrocarbon in place, drive mechanism and aquifer support directly from a
measured pressure-vs-cumulative-production history. These "inverse" tank models
complement the forward depletion model (SimpleReservoir) — use them for
reserves surveillance and drive diagnosis. Pressures are in bara, temperatures in
Kelvin; cumulative volumes keep any consistent surface unit and the returned
in-place volume is in the same unit.
GasMaterialBalance)import neqsim.pvtsimulation.reservoirproperties.materialbalance.GasMaterialBalance;
// P/Z straight line → OGIP (supply Z, or let it compute Z from Sutton + Hall-Yarborough)
GasMaterialBalance.Result r = GasMaterialBalance.fitVolumetric(pressure, z, gp);
double ogip = r.getOgip(); // x-intercept where p/Z = 0
double piZi = r.getPiOverZi(); // initial p/Z intercept (bara)
double r2 = r.getRSquared();
// Compute Z internally (Sutton pseudo-criticals + Hall-Yarborough)
GasMaterialBalance.Result r2fit = GasMaterialBalance.fitVolumetric(pressure, gp, tempK, gasGravity);
// Cole plot — aquifer diagnostic (flat = volumetric depletion, rising = water influx)
double[][] cole = GasMaterialBalance.colePlot(pressure, z, gp, tempK); // [0]=Gp, [1]=F/Eg
// Havlena-Odeh with a supplied cumulative water influx We
GasMaterialBalance.Result rHO = GasMaterialBalance.fitHavlenaOdeh(pressure, z, gp, we, tempK);
OilMaterialBalance)import neqsim.pvtsimulation.reservoirproperties.materialbalance.OilMaterialBalance;
// Build the F / Eo / Eg / Efw terms from black-oil PVT, then regress:
OilMaterialBalance.Result dep = OilMaterialBalance.fitDepletionDrive(f, eo); // OOIP (no gas cap / aquifer)
OilMaterialBalance.Result gc = OilMaterialBalance.fitGasCapDrive(f, eo, eg); // OOIP + gas-cap ratio m
OilMaterialBalance.Result wd = OilMaterialBalance.fitWaterDrive(f, eo, we, bw); // OOIP with known We
// Pirson fractional drive indices {DDI, SDI, WDI, EDI} (sum ≈ 1)
double[] di = OilMaterialBalance.driveIndices(n, m, eoTerm, egTerm, efwTerm, we, bw, fTerm);
VanEverdingenHurstAquifer)import neqsim.pvtsimulation.reservoirproperties.materialbalance.VanEverdingenHurstAquifer;
double u = VanEverdingenHurstAquifer.aquiferConstant(porosity, ct, thickness, radius, angleDeg);
double[] we = VanEverdingenHurstAquifer.cumulativeInfluxCarterTracy(tD, deltaP, u, reD); // reservoir m3
String aqutab = VanEverdingenHurstAquifer.exportAqutab(tD, reD); // ECLIPSE AQUTAB include table
The We array feeds the aquifer term of GasMaterialBalance.fitHavlenaOdeh /
OilMaterialBalance.fitWaterDrive. Use reD = Double.POSITIVE_INFINITY for an
infinite-acting aquifer or a finite reD for a bounded one.
Workflow: (1) diagnose drive with the Cole plot / drive indices, (2) if
water drive, build We with Carter-Tracy, (3) regress OGIP/OOIP with the
matching fit* method, (4) cross-check reserves against the DeclineCurveAnalysis
EUR.
BottleneckAnalyzer analyzer = new BottleneckAnalyzer(processSystem);
analyzer.setReservoirDecline(reservoirModel);
analyzer.setRateRange(10000, 60000, 5000); // min, max, step (boe/d)
Map<String, Double> bottlenecks = analyzer.findBottlenecks();
// Returns: {"HP Separator": 35000, "Gas Compressor": 28000,
// "Export Pump": 40000, "Water Treatment": 45000}
// Bottleneck = Gas Compressor at 28,000 boe/d
FacilityCapacity capacity = new FacilityCapacity();
capacity.setEquipment("HP Separator", 35000.0); // boe/d
capacity.setEquipment("Gas Compressor", 28000.0);
capacity.setEquipment("Export Pump", 40000.0);
capacity.setEquipment("Water Treatment", 45000.0);
// Apply to production profile
double[] constrainedProfile = capacity.constrain(unconstrained);
String bottleneck = capacity.getActiveBottleneck(year);
ProductionAllocator allocator = new ProductionAllocator();
allocator.addField("Field A", fieldAProfile, 0.60); // priority weight
allocator.addField("Field B", fieldBProfile, 0.30);
allocator.addField("Field C", fieldCProfile, 0.10);
allocator.setFacilityCapacity(50000.0); // boe/d
Map<String, double[]> allocation = allocator.allocate();
// Returns constrained profiles per field
NetworkSolver network = new NetworkSolver("Production Network");
network.addWell(well1, 3.0); // well, flowline length (km)
network.addWell(well2, 5.5);
network.addWell(well3, 8.0);
network.addWell(well4, 4.2);
// Mode 1: Fixed manifold pressure → find well rates
network.setSolutionMode(SolutionMode.FIXED_MANIFOLD_PRESSURE);
network.setManifoldPressure(60.0); // bara
NetworkResult result = network.solve();
for (String wellName : result.getWellNames()) {
double rate = result.getWellRate(wellName); // Sm3/d
double whp = result.getWellheadPressure(wellName); // bara
}
// Mode 2: Fixed total rate → find required manifold pressure
network.setSolutionMode(SolutionMode.FIXED_TOTAL_RATE);
network.setTargetTotalRate(50000.0); // Sm3/d
result = network.solve();
double requiredManifoldP = result.getManifoldPressure();
Full NR-GGA production network solver with IPR, chokes, tubing VLP, Beggs-Brill multiphase, compressors, artificial lift, water/sand/corrosion/emissions:
LoopedPipeNetwork net = new LoopedPipeNetwork("Gathering");
net.setFluidTemplate(gas);
net.setSolverType(LoopedPipeNetwork.SolverType.NEWTON_RAPHSON);
net.setMaxIterations(500);
net.setTolerance(500.0);
// Wells with IPR
net.addSourceNode("R1", 230.0, 0.0);
net.addJunctionNode("MF1");
net.addWellIPR("R1", "MF1", "W1", 5e-13, true);
// Artificial lift
net.setGasLift("W1", 500.0); // kg/hr
net.setESP("W2", 80.0, 0.55); // kW, efficiency
// Water, sand, corrosion tracking
net.setWaterCut("W1", 0.15);
net.setSandRate("W1", 3.0); // kg/hr
net.setCorrosiveGas("trunk", 0.035, 0.002); // CO2, H2S mol frac
net.setCorrosionModel("trunk", "NORSOK"); // NORSOK M-506
// GHG emissions
net.setCO2EmissionFactor(2.75);
net.setMethaneSlipFactor(0.02);
net.run();
// Post-run analysis
Map<String, double[]> sand = net.calculateSandTransport();
Map<String, double[]> corr = net.calculateCorrosion();
Map<String, double[]> em = net.calculateEmissions();
double annualCO2 = net.getAnnualCO2EmissionsTonnes();
See production_well_networks.md for full API documentation of all features.
GasLiftCalculator glCalc = new GasLiftCalculator();
glCalc.setWellDepth(3000.0); // m
glCalc.setReservoirPressure(250.0); // bara
glCalc.setProductionRate(5000.0); // boe/d
glCalc.setGLR(500.0); // Sm3/Sm3
glCalc.setInjectionPressure(150.0); // bara
double optimalGLR = glCalc.calculateOptimalGLR();
double gasRate = glCalc.calculateInjectionRate(); // Sm3/d
GasLiftOptimizer optimizer = new GasLiftOptimizer();
optimizer.addWell("P1", well1, glCalc1);
optimizer.addWell("P2", well2, glCalc2);
optimizer.addWell("P3", well3, glCalc3);
optimizer.setTotalGasAvailable(500000.0); // Sm3/d field gas supply
Map<String, Double> allocation = optimizer.optimize();
// Returns optimal gas injection rate per well
double totalOilGain = optimizer.getTotalOilGain();
When the decision is which wells to choke back or open up under several shared
facility ceilings at once (gas handling, produced-water/PWRI, and the lift-gas budget) —
the classic offshore "strupe/øke liste" — use the choke-and-gas-lift allocation stack in
neqsim.process.fielddevelopment.integrated. It co-optimizes choke opening and
lift-gas per well, honours discrete on/off locks (sand, lost comms, life extension) and
per-well gas ceilings, and emits an operator-ranked action list.
// NIP-1: build a per-well GLPC anchored on a rigorous WellSystem nodal solve.
// base oil rate comes from NeqSim IPR-VLP; the lift response is fitted to a
// well-test peak (optimumLift, peakOil) or a fractional uplift.
GasLiftPerformanceCurve curve =
GasLiftPerformanceCurve.fromWellSystem(wellSystem, 60000.0, peakOil, 150000.0);
// or: GasLiftPerformanceCurve.fromWellSystemUplift(wellSystem, 0.25, 50000.0, 150000.0);
// NIP-2: a chokeable, gas-lifted well with bounds and operational locks.
ChokeableGasLiftWell w = new ChokeableGasLiftWell("S-24", curve)
.setMaxChokeFraction(0.60) // "0-60%"
.setCurrentChokeFraction(0.0) // current strupe setting
.setGor(750.0).setWaterCut(0.35) // for facility roll-up
.setGasHandlingLimit(750_000.0); // per-well "mye gass" ceiling
// .setForcedShut(true, "sand production"); // hard lock
// NIP-3: co-optimize choke + lift under multiple facility constraints (never throws).
ChokeAndGasLiftAllocationOptimizer opt = new ChokeAndGasLiftAllocationOptimizer()
.addWell(w) /* ...add all wells... */
.setLiftGasBudget(totalLiftGasSm3d)
.setGasHandlingLimit(maxGasSm3d) // shared compressor limit
.setWaterHandlingLimit(maxWaterSm3d) // shared produced-water/PWRI limit
.setObjective(ChokeAndGasLiftAllocationOptimizer.Objective.OIL);
ChokeAndGasLiftAllocationOptimizer.AllocationResult r = opt.optimize();
String json = r.toJson(); // schema-versioned
// NIP-4: turn the optimum into the ranked strupe/øke recommendation list.
StrupeOkeReport report = StrupeOkeReport.build(Arrays.asList(w /* ... */), r);
System.out.println(report.toTable()); // per well: OPEN / CHOKE_BACK / SHUT / NO_CHANGE + uplift
Screening-grade: choke is a linear deliverability scale, the facility relief is a greedy
"choke back the least valuable barrels first" search. Use LoopedPipeNetwork for a
rigorous coupled network solve. Distinct from GasLiftOptimizer (lift gas + compression
only) and ReservoirToMarketOptimizer (choke + one throughput cap only).
ScenarioAnalyzer scenarios = new ScenarioAnalyzer();
// Base case
scenarios.addScenario("Base", baseEngine);
// High oil price
CashFlowEngine highPrice = baseEngine.clone();
highPrice.setOilPrice(90.0);
scenarios.addScenario("High Price", highPrice);
// Low recovery
CashFlowEngine lowRecovery = baseEngine.clone();
lowRecovery.setRecoveryFactor(0.45);
scenarios.addScenario("Low Recovery", lowRecovery);
// Accelerated drilling
CashFlowEngine accelerated = baseEngine.clone();
accelerated.setDrillingInterval(3); // 3 months vs 6
scenarios.addScenario("Accelerated", accelerated);
Map<String, CashFlowResult> results = scenarios.runAll();
scenarios.generateComparisonTable();
InjectionStrategy waterInj = InjectionStrategy.waterInjection(1.0); // VRR = 1.0
InjectionResult result = waterInj.calculateInjection(
reservoir, oilRate, gasRate, waterRate
);
double requiredRate = result.waterInjectionRate; // Sm3/d
double achievedVRR = result.achievedVRR;
InjectionStrategy gasInj = InjectionStrategy.gasInjection(0.8); // VRR = 0.8
// May also use produced gas reinjection
| Method | Viscosity Limit | Depth Limit | API Gravity | Recovery Boost |
|---|---|---|---|---|
| Water flood | < 150 cP | Any | > 15° | 5-30% OOIP |
| WAG | < 10 cP | > 1500 m | 25-50° | 5-15% OOIP |
| Polymer | 10-150 cP | < 3000 m | > 15° | 5-15% OOIP |
| Steam (SAGD) | > 200 cP | < 1500 m | 7-20° | 20-50% OOIP |
| CO2 flooding | < 12 cP | > 600 m | > 25° | 8-20% OOIP |
| Surfactant | < 35 cP | < 3000 m | > 20° | 5-15% OOIP |
EmissionsTracker emissions = new EmissionsTracker();
emissions.setProcessSystem(processSystem);
emissions.setFuelType("natural_gas");
emissions.setProductionRate(25000.0); // boe/d
double co2Tonnes = emissions.calculateAnnualCO2();
double intensity = emissions.getCO2Intensity(); // kgCO2/boe
DetailedEmissionsCalculator detailedCalc = new DetailedEmissionsCalculator();
detailedCalc.setGasTurbinePower(25.0); // MW
detailedCalc.setFlareRate(5000.0); // Sm3/d
detailedCalc.setFugitiveRate(0.001); // fraction of throughput
Map<String, Double> breakdown = detailedCalc.calculate();
// {"turbine_CO2": ..., "flare_CO2": ..., "fugitive_CH4": ..., "total_CO2e": ...}
EnergyEfficiencyCalculator efficiency = new EnergyEfficiencyCalculator();
efficiency.setProcessSystem(processSystem);
efficiency.setExportRate(25000.0); // boe/d
double specificPower = efficiency.getSpecificPower(); // kW/boe
double energyEfficiency = efficiency.getEfficiency(); // %
Map<String, Double> consumers = efficiency.getPowerBreakdown();
// {"Gas Compression": 15.2, "Water Injection": 8.5, "Utilities": 3.1}
| Strategy | NeqSim Support | Key Considerations |
|---|---|---|
| Infill drilling | New WellSystem + network rebalance | Marginal well economics |
| Water shut-off | Adjust WellSystem water cut | Intervention cost vs benefit |
| Gas lift optimization | GasLiftOptimizer | Declining reservoir pressure |
| Choke + lift under gas/water/lift limits (strupe/øke list) | ChokeAndGasLiftAllocationOptimizer + StrupeOkeReport | Multi-constraint fleet, on/off locks |
| Tie-back satellite | TiebackAnalyzer | Host capacity utilization |
| EOR (CO2, polymer) | InjectionStrategy + EOS | Fluid compatibility |
| Cessation of production | DecommissioningEstimator | Regulatory requirements |
DecommissioningEstimator decom = new DecommissioningEstimator();
decom.setNumberOfWells(6);
decom.setWellAbandonment(true); // P&A wells
decom.setSubseaRemoval(true); // Remove subsea equipment
decom.setPlatformRemoval(false); // Subsea tieback — no platform
decom.setPipelineDecommissioning(true);
decom.setWaterDepth(350.0);
decom.setRegion("Norway");
double abex = decom.estimate(); // MUSD
Map<String, Double> breakdown = decom.getBreakdown();
| Pitfall | Impact | Prevention |
|---|---|---|
| Optimizing wells independently | Sub-optimal network, back-pressure effects | Always use NetworkSolver for coupled optimization |
| Ignoring facility constraints | Unrealistic production profile | Apply FacilityCapacity constraints to profile |
| Static gas lift allocation | Missed oil as reservoir depletes | Re-optimize gas lift periodically as BHP declines |
| Ignoring water cut increase | Overstated revenue, understated OPEX | Model watercut trajectory, include water treatment costs |
| Over-producing from best wells | Premature water/gas coning | Balanced withdrawal per reservoir zone |
| Ignoring backpressure coupling | Wrong wellhead pressures | Network solver captures well-to-well interactions |
| Encoding minimum limits as design/max constraints | Safe NPSH, minimum-flow, or residence-time margins appear overloaded | Use setMinValue(...) without setDesignValue(...); use a HARD constraint type for trip/infeasibility limits |
Recomputing every engineering margin as design - current | Minimum limits show infinite or incorrectly signed spare capacity | Use the evaluator/throughput result's minimumConstraint direction; feasible margins are current - minimum for lower limits and maximum - current for upper limits |
Dropping dataSource when exporting bottlenecks | Installed, calculated, and default limits become indistinguishable to Python or AI workflows | Set provenance on each CapacityConstraint and preserve the throughput row's dataSource in ranking, recommendations, and archives |
| Joining plant-wide bottlenecks by unit name alone | Duplicate names in separate process areas resolve to the wrong train or area | For ProcessModel.getUtilizationSnapshotJson(), preserve the bottleneck area and use qualifiedName (area::unit) as the stable join key |
| Treating every constraint as equally credible and universally applicable | AI or optimization recommendations can rely on a screening/default limit outside its evidence range | Set confidence and a validity range on CapacityConstraint; consume the propagated ThroughputCaseRow presence flags, bounds, and in-range state in Java/JSON/CSV; require review when absent/out of range, and never interpret confidence as a safety probability |
| Showing only the leading constraint | Near-active constraints and weak evidence remain hidden from debottleneck decisions | For a simulated case, retain EvaluationResult.getRankedCapacityConstraints() or ThroughputCaseRow.getRankedCapacityConstraints() so later runs cannot overwrite the snapshot. Use rankCapacityConstraints(model) only for direct live-model inspection. Preserve getEvidenceApplicability() beside each item, and keep confidence/applicability out of utilization order and feasibility. |
| Dividing a finite difference by a step removed by parameter clamping | Local production and margin sensitivities are understated near operating bounds | Use the bound-aware ProcessModelSimulationEvaluator gradient/Jacobian methods. Keep FORWARD for the historical one-run-per-parameter cost or select CENTRAL for smooth interior points, and always check step-size stability before interpreting a derivative as shadow-value evidence. |
| Ranking debottlenecking value from one unchecked finite-difference step | Truncation error, non-converged perturbations, or regime changes look like defensible sensitivity | Use estimateSensitivitiesWithQuality(...) before ranking. Retain the applied stencil/steps and every perturbation's convergence, feasibility, and error; require a justified isNumericallyStable(tolerance) result, inspect feasibility separately, and validate nearby operating points. |
| Joining archived sensitivity arrays back to mutable evaluator lists | Objective or constraint rows can be relabelled after definition changes or later runs | Archive getParameterSnapshots(), getObjectiveSnapshot(), and getConstraintSnapshots() from the same SensitivityQualityResult. Preserve indices, units, bounds, direction/type, base values/margins, and capacity origin. Do not rank unlike raw margins or derivatives without explicit engineering scaling. |
| Treating one globally stable sensitivity matrix as evidence that every bottleneck action is usable | A failed perturbation, infeasible sample, fixed control, one-sided stencil, or unstable row/column pair can be hidden by manual joins and ad hoc filtering | Call assessConstraintSensitivities(SensitivityQualificationPolicy) and retain evidence flags, rejection reasons, and diagnostics for every constraint/parameter pair. Use getAcceptedConstraintSensitivities(...) only after selecting and recording the policy. Acceptance is local numerical evidence, not scaling, active-set proof, a KKT multiplier, or engineering approval. |
| Comparing raw margins or declaring an active set without explicit engineering scales | Unlike units become numerically rankable by accident, stale limits are reused, and a near-boundary heuristic is mistaken for KKT evidence | Create one positive, provenance-bearing ConstraintScale from each immutable constraint snapshot and run ConstraintActivityAnalyzer.assess(...) with a recorded dimensionless tolerance and sensitivity policy. Missing, duplicate, unitless, or identity-stale scales must fail closed. Keep VIOLATED separate from CANDIDATE_ACTIVE, require each scaled derivative's isUsable(), and do not claim ranking, shadow price, or optimizer active-set proof. |
| Interpolating a discrete operating choice or mutating a candidate without a restoration token | A solver can invent an invalid line-up, target the wrong area, hide conversion resolution behind a false rejection, or leave a rejected point in the model | Define a provenance-bearing ProcessModelOperatingAction with an area-qualified address. Enumerate getAllowedValues() for discrete actions, capture the baseline before mutation, and restore the identity-matched state after candidate validation. Keep the strict default read-back comparison unless the exact automation conversion or control tag has a known resolution; then declare it with withReadBackTolerance(absolute, relative, provenance) and retain the numeric residual/tolerance diagnostics. Capability or read-back success is not process feasibility or operating approval. |
| Screening a well or gathering action from a live model without rerunning and restoring the baseline | A rejected candidate can leak into the next evaluation, an exact hydraulic limit can be missing, or evidence can be used outside its validity range | Configure a zero-parameter ProcessModelSimulationEvaluator, wrap one action with ProcessModelOperatingActionEvaluator, and bind every required hydraulic constraint by exact area/equipment/constraint identity and provenance. Require candidate convergence, finite utilization/margin, no violation, in-range evidence when a range is declared, and successful baseline restoration and reconvergence. Use separate model instances for parallel candidates. |
| Applying coupled well-allocation actions independently or simulating a partial vector | A later rejected write can leave earlier wells changed, shared limits can be evaluated at an impossible mixed state, and rollback evidence is lost | Use one provenance-bearing ProcessModelOperatingActionSetEvaluator with unique action IDs and addresses. Require exact per-well and shared constraints. Inspect every ActionCandidateEvidence, reject any partial application, and require reverse-order restoration plus baseline reconvergence before the next candidate. Validate total/component balance and nearby monotonic constraint response; the transaction does not choose or approve the allocation. |
| Reducing fixed-total allocation to a score-only callback or continuing after rollback failure | Constraint provenance and rejected-point evidence disappear, a shared total can drift, or later trials can start from a corrupted process state | For continuous common-unit actions, compose the atomic action set with ProcessModelAllocationOptimizer. Declare the fixed total, seed, objective row, budget, transfer tolerance and objective tolerance provenance. Require isModelRecovered(), retain the full candidate trace, and inspect utilization-ranked constraints at the best feasible and best sampled objective points. Treat the sampled opportunity gap and transfer convergence as local search diagnostics, not production loss, global optimality, a shadow price, or approval. |
| Labelling normalized installed-capacity utilization or margin with RPM, kW, or a flow unit | External solvers and AI agents can mistake a fraction for physical headroom, resample a mutable supplier, or join relief to only a selected hydraulic subset | Register capacities with addEquipmentCapacityConstraints() and retain EvaluationResult.getInstalledEquipmentCapacityEvidence(). Treat getNormalizedUnit() as "1"; use getPhysicalUnit() only for current, applicable limit, physical margin, and required relief. Preserve qualified identity, origin, evidence status, and validity applicability. |
| Joining an improving rejected allocation to mutable constraint definitions or calling one sampled gap causal debottleneck value | Archived rows can be relabelled, normalized capacity margins can be mistaken for engineering-unit relief, and coupled or weak evidence can look isolated | Retain CandidateSetEvaluationResult.getObjectiveEvidence() and getConstraintEvidence(), then call ProcessModelAllocationBottleneckAnalyzer.analyze(search). Require complete recovery, inspect every hard violation and its evidence class, and keep unlike relief units separate. Treat results as sampled non-causal associations, not capacity sizing, production loss, shadow price, economics, or approval. |
Frequently asked questions
Reference for production forecasting, optimization, bottleneck analysis, and improved recovery using NeqSim's field development and process simulation tools.
The source record exposes this install command: npx skills add https://github.com/equinor/neqsim --skill ".github/skills/neqsim-production-optimization". Inspect the command and pinned source before running it.
Alternatives
coreyhaines31/marketingskills
When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program
coreyhaines31/marketingskills
When the user wants to reduce churn, build cancellation flows, set up save offers, recover failed payments, or implement retention strategies. Also use when the user mentions 'churn,' 'cancel flow,' 'offboarding,' 'save offer,' 'dunning,' 'failed payment recovery,' 'win-back,' 'retention,' 'exit survey,' 'pause subscription,' 'involuntary churn,' 'people keep canceling,' 'churn rate is too high,' 'how do I keep users,' or 'customers are leaving.' Use this whenever someone is losing subscribers o
alirezarezvani/claude-skills
App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist
wanshuiyin/Auto-claude-code-research-in-sleep
Use it for operations and research tasks; the detail page covers purpose, installation, and practical steps.