Skip to the content.

Late-Life Operations Support in NeqSim

This document describes how NeqSim supports analysis of late-life field operations, a key topic in TPG4230 and critical for maximizing economic recovery from mature fields.


Overview

Late-life operations present unique challenges:

Challenge Description NeqSim Support
High water cut 80-98% water production Three-phase separator modeling
Increasing GOR Gas cap expansion, solution gas Phase behavior changes
Low rates Equipment turndown limits Off-design simulation
Declining pressure Artificial lift requirements Well performance
Infrastructure aging Debottlenecking needs Capacity analysis
Economic marginal Operating cost vs revenue Economic cut-off

1. High Water Cut Operations

1.1 Separator Performance at High Water Cut

import neqsim.process.equipment.separator.ThreePhaseSeparator;
import neqsim.process.fielddevelopment.evaluation.SeparatorSizingCalculator;

// Analyze separator at 90% water cut
SystemInterface fluid = new SystemSrkEos(333.15, 30.0);
fluid.addComponent("methane", 0.05);
fluid.addComponent("nC10", 0.05);  // 5% oil
fluid.addComponent("water", 0.90); // 90% water
fluid.setMixingRule("classic");

Stream wellStream = new Stream("well", fluid);
wellStream.setFlowRate(50000.0, "kg/hr");
wellStream.run();

ThreePhaseSeparator separator = new ThreePhaseSeparator("HP-Sep", wellStream);
separator.run();

// Check residence time adequacy
SeparatorSizingCalculator calc = new SeparatorSizingCalculator();
double oilDensity = separator.getOilOutStream().getFluid().getDensity("kg/m3");
double requiredRetention = calc.getAPI12JRetentionTime(oilDensity);

double waterVolume = separator.getWaterOutStream().getFlowRate("m3/hr");
double oilVolume = separator.getOilOutStream().getFlowRate("m3/hr");

System.out.println("Water cut: " + waterVolume / (waterVolume + oilVolume) * 100 + "%");
System.out.println("Required retention time: " + requiredRetention + " s");

1.2 Water Treatment Capacity

At high water cuts, produced water treatment becomes a bottleneck:

import neqsim.process.equipment.watertreatment.ProducedWaterTreatmentTrain;
import neqsim.process.fielddevelopment.evaluation.BottleneckAnalyzer;

// Late-life water production
ProducedWaterTreatmentTrain pwt = new ProducedWaterTreatmentTrain("PWTT");
pwt.setInletOilConcentration(800.0);  // mg/L (lower due to better separator)
pwt.setWaterFlowRate(1200.0);         // m³/hr (high volume)
pwt.run();

// Check if water treatment is bottleneck
BottleneckAnalyzer analyzer = new BottleneckAnalyzer("Late-Life Analysis");
analyzer.addEquipment("Water-Treatment", EquipmentType.WATER_TREATMENT,
    1200.0, 1500.0);  // 80% utilization

if (analyzer.getPrimaryBottleneck().getEquipmentName().equals("Water-Treatment")) {
    System.out.println("Water treatment is primary bottleneck");
    System.out.println("Consider: Additional hydrocyclones, IGF upgrade");
}

2. Increasing GOR Impact

2.1 Compression Capacity Analysis

// GOR evolution over field life
double[] yearlyGOR = {150, 180, 220, 280, 350, 450, 600, 800};

for (int year = 0; year < yearlyGOR.length; year++) {
    double oilRate = 5000.0 * Math.pow(0.88, year);  // Declining oil
    double gasRate = oilRate * yearlyGOR[year];       // Increasing gas
    
    // Check compression capacity
    double compressionPower = estimateCompressionPower(gasRate);
    double designCapacity = 25.0;  // MW
    double utilization = compressionPower / designCapacity;
    
    System.out.printf("Year %d: GOR=%.0f, Gas=%.0f Sm3/d, Comp=%.1f MW (%.0f%%)%n",
        2025 + year, yearlyGOR[year], gasRate, compressionPower, utilization * 100);
    
    if (utilization > 0.95) {
        System.out.println("  ⚠️ Compression constraint reached");
    }
}

2.2 Phase Envelope Shifts

Track how the phase envelope changes with depletion:

import neqsim.thermodynamicoperations.ThermodynamicOperations;

// Initial composition
SystemInterface initial = createReservoirFluid(GOR_initial);
ThermodynamicOperations opsInitial = new ThermodynamicOperations(initial);
opsInitial.calcPTphaseEnvelope();
double initialCricondenbar = opsInitial.get("cricondenbarP");

// Late-life composition (higher GOR = more gas)
SystemInterface latLife = createReservoirFluid(GOR_lateLife);
ThermodynamicOperations opsLate = new ThermodynamicOperations(latLife);
opsLate.calcPTphaseEnvelope();
double lateCricondenbar = opsLate.get("cricondenbarP");

System.out.println("Initial cricondenbar: " + initialCricondenbar + " bara");
System.out.println("Late-life cricondenbar: " + lateCricondenbar + " bara");
System.out.println("Phase envelope has shifted - check dewpoint constraints");

3. Low-Rate Operations

3.1 Equipment Turndown Analysis

import neqsim.process.fielddevelopment.evaluation.ScenarioAnalyzer;

ScenarioAnalyzer analyzer = new ScenarioAnalyzer(processSystem);

// Analyze different production rates
double[] rateScenarios = {10000, 7500, 5000, 3000, 1500};

for (double rate : rateScenarios) {
    analyzer.addScenario("Rate " + rate, 
        new ScenarioParameters()
            .setOilRate(rate)
            .setGOR(400.0)
            .setWaterCut(0.85));
}

List<ScenarioResult> results = analyzer.runAll();

System.out.println("=== TURNDOWN ANALYSIS ===");
for (ScenarioResult r : results) {
    System.out.printf("%s: Power=%.2f MW, Converged=%s%n",
        r.getName(), r.getPowerMW(), r.isConverged());
        
    if (!r.isConverged()) {
        System.out.println("  ⚠️ Process unstable at this rate - minimum turndown reached");
    }
}

3.2 Separator Turndown

Low liquid rates affect separation efficiency:

// Check separator liquid level and retention time
double designLiquidRate = 500.0;   // m³/hr design
double actualLiquidRate = 50.0;    // m³/hr late-life (10% of design)

double separatorVolume = 100.0;    // m³ (liquid section)
double actualRetention = separatorVolume / actualLiquidRate * 3600; // seconds
double requiredRetention = 120.0;  // seconds for medium crude

if (actualRetention > requiredRetention * 5) {
    System.out.println("Excessive retention time: " + actualRetention + " s");
    System.out.println("Risk: Gas carry-under, emulsion stabilization");
    System.out.println("Consider: Internals modification, level control upgrade");
}

4. Artificial Lift Requirements

4.1 Well Performance Decline

import neqsim.process.equipment.reservoir.WellFlow;

// Analyze well deliverability decline
double reservoirPressure = 150.0;  // bara (depleted from 300 bar initial)
double wellheadPressure = 30.0;    // bara

WellFlow well = new WellFlow(reservoirStream);
well.setProductivityIndex(5.0);  // Sm3/d/bar

// Calculate natural flow rate
double naturalRate = well.calculateFlowRate(reservoirPressure, wellheadPressure);

if (naturalRate < economicLimit) {
    System.out.println("Natural flow below economic limit: " + naturalRate + " Sm3/d");
    System.out.println("Artificial lift required");
    
    // Estimate ESP/gas lift benefit
    double liftedRate = naturalRate * 1.5;  // Typical 30-50% increase
    System.out.println("Potential with artificial lift: " + liftedRate + " Sm3/d");
}

5. Economic Cut-Off Analysis

5.1 Break-Even Rate Calculation

import neqsim.process.fielddevelopment.economics.CashFlowEngine;

// Fixed operating costs
double fixedOpex = 50.0;  // MUSD/year (regardless of rate)
double variableOpex = 5.0;  // USD/bbl

// Revenue vs cost at different rates
double oilPrice = 70.0;  // USD/bbl

System.out.println("=== ECONOMIC CUT-OFF ANALYSIS ===");
System.out.println("Rate (bbl/d)\tRevenue\t\tOPEX\t\tNet");

for (double rate = 10000; rate >= 500; rate -= 500) {
    double annualProduction = rate * 365;
    double revenue = annualProduction * oilPrice / 1e6;  // MUSD
    double opex = fixedOpex + (annualProduction * variableOpex / 1e6);
    double net = revenue - opex;
    
    System.out.printf("%.0f\t\t%.1f\t\t%.1f\t\t%.1f%n", rate, revenue, opex, net);
    
    if (net < 0) {
        System.out.printf("Economic cut-off between %.0f and %.0f bbl/d%n",
            rate + 500, rate);
        break;
    }
}

5.2 Tail Production Economics

// Include abandonment timing in economics
double abandonmentCost = 200.0;  // MUSD

CashFlowEngine engine = new CashFlowEngine("NO");
engine.setOpexPerUnit(variableOpexPerBbl);
engine.setFixedOpex(fixedOpexMUSD);
engine.setAbandonmentCost(abandonmentCost);

// Compare: Produce another 3 years vs abandon now
engine.setForecastYears(3);
CashFlowResult continue3Years = engine.calculate(0.08);

engine.setForecastYears(0);
CashFlowResult abandonNow = engine.calculate(0.08);

System.out.println("NPV if continue 3 years: " + continue3Years.getNpv());
System.out.println("NPV if abandon now: " + abandonNow.getNpv());

if (continue3Years.getNpv() > abandonNow.getNpv()) {
    System.out.println("Recommendation: Continue production");
} else {
    System.out.println("Recommendation: Initiate abandonment");
}

6. Debottlenecking Opportunities

6.1 Identify Late-Life Bottlenecks

import neqsim.process.fielddevelopment.evaluation.BottleneckAnalyzer;

BottleneckAnalyzer analyzer = new BottleneckAnalyzer("Mature Field");

// Equipment at late-life conditions
analyzer.addEquipment("HP-Separator-Gas", EquipmentType.SEPARATOR, 
    2.8, 3.0);  // 93% - gas limited at high GOR

analyzer.addEquipment("Water-Injection-Pump", EquipmentType.PUMP,
    12000, 15000);  // 80% - increased water injection

analyzer.addEquipment("Produced-Water-Treatment", EquipmentType.WATER_TREATMENT,
    1400, 1500);  // 93% - high water cut

analyzer.addEquipment("Export-Compressor", EquipmentType.COMPRESSOR,
    32, 35);  // 91% - increased gas volume

// Find primary constraint
BottleneckResult primary = analyzer.getPrimaryBottleneck();
System.out.println("Primary late-life bottleneck: " + primary.getEquipmentName());

// Evaluate debottleneck options
List<DebottleneckOption> options = analyzer.evaluateDebottleneckOptions();
for (DebottleneckOption opt : options) {
    System.out.printf("Option: %s, Cost: %.0f MUSD, Benefit: +%.0f bbl/d%n",
        opt.getDescription(), opt.getCostMUSD(), opt.getRateBenefit());
}

7. Decommissioning Timing

7.1 Optimal Abandonment Timing

import neqsim.process.fielddevelopment.evaluation.DecommissioningEstimator;
import neqsim.process.fielddevelopment.economics.CashFlowEngine;

DecommissioningEstimator decom = new DecommissioningEstimator("Platform");
double decomCost = decom.getTotalCostMUSD();

// NPV of different abandonment timing scenarios
int[] abandonYears = {2027, 2028, 2029, 2030, 2031};
double[] npvs = new double[abandonYears.length];

for (int i = 0; i < abandonYears.length; i++) {
    CashFlowEngine engine = createCashFlowToYear(abandonYears[i]);
    
    // Add discounted abandonment cost
    int yearsToAbandon = abandonYears[i] - 2025;
    double pvDecomCost = decomCost / Math.pow(1.08, yearsToAbandon);
    
    npvs[i] = engine.calculate(0.08).getNpv() - pvDecomCost;
    
    System.out.printf("Abandon in %d: NPV = %.0f MUSD%n", abandonYears[i], npvs[i]);
}

// Find optimal
int optimalYear = abandonYears[0];
double maxNpv = npvs[0];
for (int i = 1; i < npvs.length; i++) {
    if (npvs[i] > maxNpv) {
        maxNpv = npvs[i];
        optimalYear = abandonYears[i];
    }
}

System.out.println("\nOptimal abandonment year: " + optimalYear);

8. Key Performance Indicators for Late-Life

KPI Early Life Late Life Action Trigger
Water cut <30% >80% Water treatment upgrade
GOR <200 >500 Compression upgrade
Uptime >95% <90% Maintenance review
OPEX/bbl <10 USD >25 USD Cost reduction
Power consumption Design +50% Energy efficiency
CO₂ intensity <10 kg/boe >25 kg/boe Emissions reduction

9. NeqSim Classes for Late-Life Analysis

Class Purpose Key Methods
ScenarioAnalyzer Compare operating scenarios runAll(), generateReport()
BottleneckAnalyzer Identify constraints getPrimaryBottleneck()
ProducedWaterTreatmentTrain Water handling capacity isDischargeCompliant()
DecommissioningEstimator Abandonment cost getTotalCostMUSD()
ProductionProfile Decline forecasting forecast()
CashFlowEngine Economic analysis calculate(), getBreakevenOilPrice()

See Also