Class ProductionProfileGenerator
- All Implemented Interfaces:
Serializable
This class implements the classic Arps decline curve equations (exponential, hyperbolic, and harmonic) for forecasting oil and gas production over the field life. These empirical models are widely used in reservoir engineering for production forecasting and reserves estimation.
Decline Curve Types
- Exponential (b=0): Constant percentage decline per period. Common for solution-gas drive reservoirs and boundary-dominated flow.
- Hyperbolic (0<b<1): Declining percentage decline over time. Most common for multiphase flow and heterogeneous reservoirs.
- Harmonic (b=1): Linear decline rate. Represents gravity drainage or some water drive reservoirs.
Arps Equations
The general Arps hyperbolic equation:
q(t) = qi / (1 + b * Di * t) ^ (1 / b)
Where:
- q(t) = production rate at time t
- qi = initial production rate
- Di = initial decline rate (fraction per time period)
- b = decline exponent (0 = exponential, 0<b<1 = hyperbolic, 1 = harmonic)
- t = time
Example Usage
// Create generator
ProductionProfileGenerator generator = new ProductionProfileGenerator();
// Generate exponential decline (typical for gas wells)
Map<Integer, Double> gasProfile = generator.generateExponentialDecline(10.0e6, // Initial rate:
// 10 MSm3/d
0.15, // 15% annual decline
2026, // Start year
20, // 20 years
0.5e6 // Economic limit: 0.5 MSm3/d
);
// Generate hyperbolic decline (typical for oil wells)
Map<Integer, Double> oilProfile = generator.generateHyperbolicDecline(15000, // Initial rate:
// 15,000 bbl/d
0.20, // 20% initial decline
0.5, // b-factor = 0.5
2026, // Start year
25, // 25 years
100 // Economic limit: 100 bbl/d
);
// Use with CashFlowEngine
CashFlowEngine engine = new CashFlowEngine("NO");
engine.setProductionProfile(oilProfile, gasProfile, null);
Plateau Period
Many fields have a plateau period before decline begins. Use the methods with plateau parameters to model this behavior:
// 3 years plateau, then exponential decline
Map<Integer, Double> profile = generator.generateWithPlateau(10.0e6, // Plateau rate
3, // Plateau years
0.12, // 12% decline after plateau
DeclineType.EXPONENTIAL, 2026, // Start year
20 // Total years
);
- Version:
- 1.0
- Author:
- ESOL
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enumDecline curve type enumeration.static final classFitted decline case from production history. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final doubleDays per year for rate conversions.private static final long -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic doublecalculateCumulativeProduction(Map<Integer, Double> profile) Calculates cumulative production from a profile.static doublecalculateEUR(double initialRatePerDay, double declineRate, ProductionProfileGenerator.DeclineType declineType, double bFactor) Calculates the estimated ultimate recovery (EUR) using Arps equations.private doublecalculateFitQuality(TreeMap<Integer, Double> history, int firstYear, double intercept, double slope) Calculates linear-regression fit quality for a log-production history.capProfileToCumulativeLimit(Map<Integer, Double> profile, double cumulativeLimit) Caps a profile at a cumulative production limit.combineProfiles(Map<Integer, Double>... profiles) Combines multiple production profiles (e.g., for multiple wells or phases).fitHistoryMatchedDecline(Map<Integer, Double> history) Fits an exponential decline case to annual production history.generateExponentialDecline(double initialRatePerDay, double annualDeclineRate, int startYear, int years) Generates exponential decline with default economic limit of 0.generateExponentialDecline(double initialRatePerDay, double annualDeclineRate, int startYear, int maxYears, double economicLimit) Generates an exponential decline production profile.generateFromReservoirInput(ReservoirInput reservoir, double peakRatePerDay, boolean gasProfile, int startYear, int totalYears) Generates a resource-capped profile from reservoir screening input.generateFromSimpleReservoir(SimpleReservoir reservoir, boolean gasProfile, double recoveryFactor, double peakRatePerDay, int startYear, int totalYears) Generates a resource-capped profile from a SimpleReservoir in-place volume.generateFullProfile(double peakRatePerDay, int rampUpYears, int plateauYears, double declineRate, double bFactor, ProductionProfileGenerator.DeclineType declineType, int startYear, int totalYears, double economicLimit) Generates a full production profile with all configurable parameters.generateFullProfile(double peakRatePerDay, int rampUpYears, int plateauYears, double declineRate, ProductionProfileGenerator.DeclineType declineType, int startYear, int totalYears) Generates a production profile with ramp-up, plateau, and decline phases.generateHarmonicDecline(double initialRatePerDay, double initialDeclineRate, int startYear, int years) Generates harmonic decline with default economic limit.generateHarmonicDecline(double initialRatePerDay, double initialDeclineRate, int startYear, int maxYears, double economicLimit) Generates a harmonic decline production profile.generateHistoryMatchedProfile(ProductionProfileGenerator.HistoryMatchedDeclineCase declineCase, int forecastStartYear, int forecastYears, double economicLimit) Generates a forecast profile from a fitted history-matched decline case.generateHyperbolicDecline(double initialRatePerDay, double initialDeclineRate, double bFactor, int startYear, int years) Generates hyperbolic decline with default economic limit.generateHyperbolicDecline(double initialRatePerDay, double initialDeclineRate, double bFactor, int startYear, int maxYears, double economicLimit) Generates a hyperbolic decline production profile.generateWithPlateau(double plateauRatePerDay, int plateauYears, double declineRate, double bFactor, ProductionProfileGenerator.DeclineType declineType, int startYear, int totalYears, double economicLimit) Generates a production profile with plateau and configurable decline parameters.generateWithPlateau(double plateauRatePerDay, int plateauYears, double declineRate, ProductionProfileGenerator.DeclineType declineType, int startYear, int totalYears) Generates a production profile with an initial plateau period followed by decline.static StringgetProfileSummary(Map<Integer, Double> profile) Gets a summary of a production profile.private doublegetRecoverableVolumeInProfileUnit(ReservoirInput reservoir, boolean gasProfile) Gets recoverable resource in the profile unit.scaleProfile(Map<Integer, Double> profile, double scaleFactor) Scales a production profile by a factor.shiftProfile(Map<Integer, Double> profile, int yearShift) Shifts a production profile by a number of years.static StringtoVfpRateTableCsv(Map<Integer, Double> profile, String rateUnit, double exportPressureBara) Exports a production profile as a rate table for VFP/export workflows.
-
Field Details
-
serialVersionUID
private static final long serialVersionUID- See Also:
-
DAYS_PER_YEAR
private static final double DAYS_PER_YEARDays per year for rate conversions.- See Also:
-
-
Constructor Details
-
ProductionProfileGenerator
public ProductionProfileGenerator()Creates a new production profile generator.
-
-
Method Details
-
generateExponentialDecline
public Map<Integer,Double> generateExponentialDecline(double initialRatePerDay, double annualDeclineRate, int startYear, int maxYears, double economicLimit) Generates an exponential decline production profile.Exponential decline assumes a constant percentage decline per time period:
q(t) = qi * e ^ (-Di * t)
- Parameters:
initialRatePerDay- initial production rate (volume per day)annualDeclineRate- annual decline rate as fraction (e.g., 0.15 for 15%)startYear- first year of productionmaxYears- maximum years to generateeconomicLimit- minimum economic rate (stops when rate falls below)- Returns:
- map of year to annual production volume
-
generateExponentialDecline
public Map<Integer,Double> generateExponentialDecline(double initialRatePerDay, double annualDeclineRate, int startYear, int years) Generates exponential decline with default economic limit of 0.- Parameters:
initialRatePerDay- initial production rate (volume per day)annualDeclineRate- annual decline rate as fractionstartYear- first year of productionyears- number of years to generate- Returns:
- map of year to annual production volume
-
generateHyperbolicDecline
public Map<Integer,Double> generateHyperbolicDecline(double initialRatePerDay, double initialDeclineRate, double bFactor, int startYear, int maxYears, double economicLimit) Generates a hyperbolic decline production profile.Hyperbolic decline uses the Arps equation with 0 < b < 1:
q(t) = qi / (1 + b * Di * t) ^ (1 / b)
- Parameters:
initialRatePerDay- initial production rate (volume per day)initialDeclineRate- initial decline rate as fraction (e.g., 0.20 for 20%)bFactor- Arps b-factor (0 < b < 1, typically 0.3-0.7)startYear- first year of productionmaxYears- maximum years to generateeconomicLimit- minimum economic rate- Returns:
- map of year to annual production volume
-
generateHyperbolicDecline
public Map<Integer,Double> generateHyperbolicDecline(double initialRatePerDay, double initialDeclineRate, double bFactor, int startYear, int years) Generates hyperbolic decline with default economic limit.- Parameters:
initialRatePerDay- initial production rate (volume per day)initialDeclineRate- initial decline rate as fractionbFactor- Arps b-factor (0 < b < 1)startYear- first year of productionyears- number of years to generate- Returns:
- map of year to annual production volume
-
generateHarmonicDecline
public Map<Integer,Double> generateHarmonicDecline(double initialRatePerDay, double initialDeclineRate, int startYear, int maxYears, double economicLimit) Generates a harmonic decline production profile.Harmonic decline is a special case of hyperbolic decline with b = 1:
q(t) = qi / (1 + Di * t)
- Parameters:
initialRatePerDay- initial production rate (volume per day)initialDeclineRate- initial decline rate as fractionstartYear- first year of productionmaxYears- maximum years to generateeconomicLimit- minimum economic rate- Returns:
- map of year to annual production volume
-
generateHarmonicDecline
public Map<Integer,Double> generateHarmonicDecline(double initialRatePerDay, double initialDeclineRate, int startYear, int years) Generates harmonic decline with default economic limit.- Parameters:
initialRatePerDay- initial production rate (volume per day)initialDeclineRate- initial decline rate as fractionstartYear- first year of productionyears- number of years to generate- Returns:
- map of year to annual production volume
-
generateWithPlateau
public Map<Integer,Double> generateWithPlateau(double plateauRatePerDay, int plateauYears, double declineRate, ProductionProfileGenerator.DeclineType declineType, int startYear, int totalYears) Generates a production profile with an initial plateau period followed by decline.- Parameters:
plateauRatePerDay- plateau production rate (volume per day)plateauYears- number of years at plateau before decline beginsdeclineRate- decline rate after plateaudeclineType- type of decline (exponential, hyperbolic, harmonic)startYear- first year of productiontotalYears- total years including plateau- Returns:
- map of year to annual production volume
-
generateWithPlateau
public Map<Integer,Double> generateWithPlateau(double plateauRatePerDay, int plateauYears, double declineRate, double bFactor, ProductionProfileGenerator.DeclineType declineType, int startYear, int totalYears, double economicLimit) Generates a production profile with plateau and configurable decline parameters.- Parameters:
plateauRatePerDay- plateau production rate (volume per day)plateauYears- number of years at plateaudeclineRate- decline rate after plateaubFactor- b-factor for hyperbolic decline (ignored for other types)declineType- type of declinestartYear- first year of productiontotalYears- total years including plateaueconomicLimit- minimum economic rate- Returns:
- map of year to annual production volume
-
generateFullProfile
public Map<Integer,Double> generateFullProfile(double peakRatePerDay, int rampUpYears, int plateauYears, double declineRate, ProductionProfileGenerator.DeclineType declineType, int startYear, int totalYears) Generates a production profile with ramp-up, plateau, and decline phases.This is the most realistic model for new field developments, with:
- Ramp-up: Linear increase from first production to plateau
- Plateau: Constant rate at peak production
- Decline: Arps decline curve after plateau
- Parameters:
peakRatePerDay- peak/plateau production rate (volume per day)rampUpYears- years to ramp from 0 to plateauplateauYears- years at plateau ratedeclineRate- decline rate after plateaudeclineType- type of decline curvestartYear- first year of productiontotalYears- total project years- Returns:
- map of year to annual production volume
-
generateFullProfile
public Map<Integer,Double> generateFullProfile(double peakRatePerDay, int rampUpYears, int plateauYears, double declineRate, double bFactor, ProductionProfileGenerator.DeclineType declineType, int startYear, int totalYears, double economicLimit) Generates a full production profile with all configurable parameters.- Parameters:
peakRatePerDay- peak/plateau production rate (volume per day)rampUpYears- years to ramp from 0 to plateauplateauYears- years at plateau ratedeclineRate- decline rate after plateaubFactor- b-factor for hyperbolic declinedeclineType- type of decline curvestartYear- first year of productiontotalYears- total project yearseconomicLimit- minimum economic rate- Returns:
- map of year to annual production volume
-
generateFromReservoirInput
public Map<Integer,Double> generateFromReservoirInput(ReservoirInput reservoir, double peakRatePerDay, boolean gasProfile, int startYear, int totalYears) Generates a resource-capped profile from reservoir screening input.- Parameters:
reservoir- reservoir input with resource estimate and recovery factorpeakRatePerDay- peak rate in Sm3/d for gas profiles or bbl/d for oil profilesgasProfile- true for gas profiles, false for oil profilesstartYear- first production yeartotalYears- total forecast years- Returns:
- annual production profile capped at recoverable resource
-
generateFromSimpleReservoir
public Map<Integer,Double> generateFromSimpleReservoir(SimpleReservoir reservoir, boolean gasProfile, double recoveryFactor, double peakRatePerDay, int startYear, int totalYears) Generates a resource-capped profile from a SimpleReservoir in-place volume.- Parameters:
reservoir- SimpleReservoir instance with initialized in-place fluidsgasProfile- true to use gas in place, false to use oil in placerecoveryFactor- recovery factor from zero to onepeakRatePerDay- peak rate in Sm3/d for gas profiles or bbl/d for oil profilesstartYear- first production yeartotalYears- total forecast years- Returns:
- annual production profile capped at recoverable resource
-
capProfileToCumulativeLimit
public static Map<Integer,Double> capProfileToCumulativeLimit(Map<Integer, Double> profile, double cumulativeLimit) Caps a profile at a cumulative production limit.- Parameters:
profile- original annual production profilecumulativeLimit- cumulative limit in the same annual production unit- Returns:
- capped production profile
-
fitHistoryMatchedDecline
public ProductionProfileGenerator.HistoryMatchedDeclineCase fitHistoryMatchedDecline(Map<Integer, Double> history) Fits an exponential decline case to annual production history.- Parameters:
history- annual production history with positive volumes- Returns:
- fitted decline case
-
generateHistoryMatchedProfile
public Map<Integer,Double> generateHistoryMatchedProfile(ProductionProfileGenerator.HistoryMatchedDeclineCase declineCase, int forecastStartYear, int forecastYears, double economicLimit) Generates a forecast profile from a fitted history-matched decline case.- Parameters:
declineCase- fitted decline caseforecastStartYear- first forecast yearforecastYears- number of forecast yearseconomicLimit- minimum economic rate- Returns:
- forecast production profile
-
toVfpRateTableCsv
public static String toVfpRateTableCsv(Map<Integer, Double> profile, String rateUnit, double exportPressureBara) Exports a production profile as a rate table for VFP/export workflows.- Parameters:
profile- annual production profilerateUnit- average-rate unit label such as Sm3/d or bbl/dexportPressureBara- export or tubing-head pressure in bara- Returns:
- CSV text with year, annual volume, average rate, unit, and pressure
-
getRecoverableVolumeInProfileUnit
Gets recoverable resource in the profile unit.- Parameters:
reservoir- reservoir inputgasProfile- true for gas profile unit Sm3, false for oil profile unit bbl- Returns:
- recoverable resource in Sm3 for gas or bbl for oil
-
calculateFitQuality
private double calculateFitQuality(TreeMap<Integer, Double> history, int firstYear, double intercept, double slope) Calculates linear-regression fit quality for a log-production history.- Parameters:
history- sorted production historyfirstYear- first history yearintercept- fitted interceptslope- fitted slope- Returns:
- coefficient of determination
-
calculateCumulativeProduction
-
calculateEUR
public static double calculateEUR(double initialRatePerDay, double declineRate, ProductionProfileGenerator.DeclineType declineType, double bFactor) Calculates the estimated ultimate recovery (EUR) using Arps equations.For exponential decline, EUR = qi / Di. For hyperbolic/harmonic, the calculation is more complex and depends on economic limit.
- Parameters:
initialRatePerDay- initial production ratedeclineRate- initial decline ratedeclineType- type of declinebFactor- b-factor (for hyperbolic)- Returns:
- estimated ultimate recovery
-
scaleProfile
-
shiftProfile
-
combineProfiles
-
getProfileSummary
-