Perform best-fits of Arps decline curves to rate or cumulative data.
best.exponential(q, t,
lower=c( # lower bounds
0, # qi > 0
0), # D > 0
upper=c( # upper bounds
max(q) * 5, # qi < qmax * 5
10) # = 0.99995 / [time] effective
)best.hyperbolic(q, t,
lower=c( # lower bounds
0, # qi > 0
0, # Di > 0
0), # b > 0
upper=c( # upper bounds
max(q) * 5, # qi < qmax * 5
10, # = 0.99995 / [time] effective
2) # b <= 2.0="" )<="" p="">
best.hyp2exp(q, t,
lower=c( # lower bounds
0, # qi > 0
0.35, # Di > 0
0, # b > 0
0), # Df > 0
upper=c( # upper bounds
max(q) * 5, # qi < qmax * 5
10, # = 0.99995 / [time] effective
2, # b <= 2.0="" 0.35)="" #="" df="" <="0.35" )<="" p="">
best.exponential.curtailed(q, t,
lower=c( # lower bounds
0, # qi > 0
0, # D > 0
0 # t.curtail > 0
),
upper=c( # upper bounds
max(q) * 5, # qi < qmax * 5
10, # = 0.99995 / [time] effective
t[length(t)])
)
best.hyperbolic.curtailed(q, t,
lower=c( # lower bounds
0, # qi > 0
0, # Di > 0
0, # b > 0
0 # t.curtail > 0
),
upper=c( # upper bounds
max(q) * 5, # qi < qmax * 5
10, # = 0.99995 / [time] effective
2, # b <= 2.0="" t[length(t)])="" )<="" p="">
best.hyp2exp.curtailed(q, t,
lower=c( # lower bounds
0, # qi > 0
0.35, # Di > 0
0, # b > 0
0, # Df > 0
0 # t.curtail > 0
),
upper=c( # upper bounds
max(q) * 5, # qi < qmax * 5
10, # = 0.99995 / [time] effective
2, # b <= 2.0="" 0.35,="" #="" df="" <="0.35" t[length(t)])="" )<="" p="">
best.fit(q, t)
best.curtailed.fit(q, t)
best.exponential.from.Np(Np, t,
lower=c( # lower bounds
0, # qi > 0
0), # D > 0
upper=c( # upper bounds
max(c(Np[1], diff(Np)) / diff(c(0, t))) * 5, # qi < max(rate) * 5
10) # = 0.99995 / [time] effective)
)
best.exponential.from.interval(volume, t, t.begin=0.0,
lower=c( # lower bounds
0, # qi > 0
0), # D > 0
upper=c( # upper bounds
max(volume / diff(c(t.begin, t))) * 5, # qi < max(rate) * 5
10) # = 0.99995 / [time] effective)
)
best.hyperbolic.from.Np(Np, t,
lower=c( # lower bounds
0, # qi > 0
0, # Di > 0
0), # b > 0
upper=c( # upper bounds
max(c(Np[1], diff(Np)) / diff(c(0, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
2) # b <= 2.0="" )<="" p="">
best.hyperbolic.from.interval(volume, t, t.begin=0.0,
lower=c( # lower bounds
0, # qi > 0
0, # Di > 0
0), # b > 0
upper=c( # upper bounds
max(volume / diff(c(t.begin, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
2) # b <= 2.0="" )<="" p="">
best.hyp2exp.from.Np(Np, t,
lower=c( # lower bounds
0, # qi > 0
0.35, # Di > 0
0, # b > 0
0), # Df > 0
upper=c( # upper bounds
max(c(Np[1], diff(Np)) / diff(c(0, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
5, # b <= 2.0="" 0.35)="" #="" df="" <="0.35" )<="" p="">
best.hyp2exp.from.interval(volume, t, t.begin=0.0,
lower=c( # lower bounds
0, # qi > 0
0.35, # Di > 0
0, # b > 0
0), # Df > 0
upper=c( # upper bounds
max(volume / diff(c(t.begin, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
5, # b <= 2.0="" 0.35)="" #="" df="" <="0.35" )<="" p="">
best.exponential.curtailed.from.Np(Np, t,
lower=c( # lower bounds
0, # qi > 0
0, # D > 0
0 # t.curtail > 0
),
upper=c( # upper bounds
max(c(Np[1], diff(Np)) / diff(c(0, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
t[length(t)])
)
best.exponential.curtailed.from.interval(volume, t, t.begin=0.0,
lower=c( # lower bounds
0, # qi > 0
0, # D > 0
0 # t.curtail > 0
),
upper=c( # upper bounds
max(volume / diff(c(t.begin, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
t[length(t)])
)
best.hyperbolic.curtailed.from.Np(Np, t,
lower=c( # lower bounds
0, # qi > 0
0, # Di > 0
0, # b > 0
0 # t.curtail > 0
),
upper=c( # upper bounds
max(c(Np[1], diff(Np)) / diff(c(0, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
5, # b <= 2.0="" t[length(t)])="" )<="" p="">
best.hyperbolic.curtailed.from.interval(volume, t, t.begin=0.0,
lower=c( # lower bounds
0, # qi > 0
0, # Di > 0
0, # b > 0
0 # t.curtail > 0
),
upper=c( # upper bounds
max(volume / diff(c(t.begin, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
5, # b <= 2.0="" t[length(t)])="" )<="" p="">
best.hyp2exp.curtailed.from.Np(Np, t,
lower=c( # lower bounds
0, # qi > 0
0.35, # Di > 0
0, # b > 0
0, # Df > 0
0
),
upper=c( # upper bounds
max(c(Np[1], diff(Np)) / diff(c(0, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
5, # b <= 2.0="" 0.35,="" #="" df="" <="0.35" t[length(t)])="" )<="" p="">
best.hyp2exp.curtailed.from.interval(volume, t, t.begin=0.0,
lower=c( # lower bounds
0, # qi > 0
0.35, # Di > 0
0, # b > 0
0, # Df > 0
0
),
upper=c( # upper bounds
max(volume / diff(c(t.begin, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
5, # b <= 2.0="" 0.35,="" #="" df="" <="0.35" t[length(t)])="" )<="" p="">
best.fit.from.Np(Np, t)
best.fit.from.interval(volume, t, t.begin=0.0)
best.curtailed.fit.from.Np(Np, t)
best.curtailed.fit.from.interval(volume, t, t.begin=0.0)
best.exponential.with.buildup(q, t,
lower=c( # lower bounds
0, # qi > 0
0), # D > 0
upper=c( # upper bounds
max(q) * 5, # qi < qmax * 5
10), # = 0.99995 / [time] effective
initial.rate=q[1], time.to.peak=t[which.max(q)])
best.hyperbolic.with.buildup(q, t,
lower=c( # lower bounds
0, # qi > 0
0, # Di > 0
0), # b > 0
upper=c( # upper bounds
max(q) * 5, # qi < qmax * 5
10, # = 0.99995 / [time] effective
2), # b <= 2.0="" initial.rate="q[1]," time.to.peak="t[which.max(q)])
best.hyp2exp.with.buildup(q, t,
lower=c( # lower bounds
0, # qi > 0
0.35, # Di > 0
0, # b > 0
0), # Df > 0
upper=c( # upper bounds
max(q) * 5, # qi < qmax * 5
10, # = 0.99995 / [time] effective
2, # b <= 2.0="" 0.35),="" #="" df="" <="0.35" initial.rate="q[1]," time.to.peak="t[which.max(q)])
best.fit.with.buildup(q, t)
best.exponential.from.Np.with.buildup(Np, t,
lower=c( # lower bounds
0, # qi > 0
0), # D > 0
upper=c( # upper bounds
max(c(Np[1], diff(Np)) / diff(c(0, t))) * 5, # qi < max(rate) * 5
10), # = 0.99995 / [time] effective
initial.rate=Np[1] / t[1],
time.to.peak=(t[which.max(diff(Np))] + t[which.max(diff(Np)) + 1]) / 2.0)
best.exponential.from.interval.with.buildup(volume, t, t.begin=0.0,
lower=c( # lower bounds
0, # qi > 0
0), # D > 0
upper=c( # upper bounds
max(volume / diff(c(t.begin, t))) * 5, # qi < max(rate) * 5
10), # = 0.99995 / [time] effective
initial.rate=volume[1] / (t[1] - t.begin),
time.to.peak=(t - diff(c(t.begin, t)) / 2)[which.max(volume)])
best.hyperbolic.from.Np.with.buildup(Np, t,
lower=c( # lower bounds
0, # qi > 0
0, # Di > 0
0), # b > 0
upper=c( # upper bounds
max(c(Np[1], diff(Np)) / diff(c(0, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
2), # b <= 2.0="" initial.rate="Np[1]" t[1],="" time.to.peak="(t[which.max(diff(Np))]" +="" t[which.max(diff(np))="" 1])="" 2.0)<="" p="">
best.hyperbolic.from.interval.with.buildup(volume, t, t.begin=0.0,
lower=c( # lower bounds
0, # qi > 0
0, # Di > 0
0), # b > 0
upper=c( # upper bounds
max(volume / diff(c(t.begin, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
2), # b <= 2.0="" initial.rate="volume[1]" (t[1]="" -="" t.begin),="" time.to.peak="(t" diff(c(t.begin,="" t))="" 2)[which.max(volume)])<="" p="">
best.hyp2exp.from.Np.with.buildup(Np, t,
lower=c( # lower bounds
0, # qi > 0
0.35, # Di > 0
0, # b > 0
0), # Df > 0
upper=c( # upper bounds
max(c(Np[1], diff(Np)) / diff(c(0, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
5, # b <= 2.0="" 0.35),="" #="" df="" <="0.35" initial.rate="Np[1]" t[1],="" time.to.peak="(t[which.max(diff(Np))]" +="" t[which.max(diff(np))="" 1])="" 2.0)<="" p="">
best.hyp2exp.from.interval.with.buildup(volume, t, t.begin=0.0,
lower=c( # lower bounds
0, # qi > 0
0.35, # Di > 0
0, # b > 0
0), # Df > 0
upper=c( # upper bounds
max(volume / diff(c(t.begin, t))) * 5, # qi < max(rate) * 5
10, # = 0.99995 / [time] effective
5, # b <= 2.0="" 0.35),="" #="" df="" <="0.35" initial.rate="volume[1]" (t[1]="" -="" t.begin),="" time.to.peak="(t" diff(c(t.begin,="" t))="" 2)[which.max(volume)])<="" p="">
best.fit.from.Np.with.buildup(Np, t)
best.fit.from.interval.with.buildup(volume, t, t.begin=0.0)
=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>vector of rate data.
vector of cumulative production data.
vector of interval volume data.
vector of times at which q, Np, or volume is measured.
initial time for interval volume data, if non-zero.
lower bounds for decline parameters (sane defaults are provided).
upper bounds for decline parameters (sane defaults are provided).
initial rate, for declines with buildup.
time to peak rate, for declines with buildup.
best.exponential, best.hyperbolic, and best.hyp2exp
return objects of the appropriate class (as from arps.decline)
representing best fits of the appropriate type against q and
t, in the same units as q and t.
best.fit returns the best overall fit, considering results from each
function above.
best.exponential.from.Np, best.hyperbolic.from.Np, and
best.hyp2exp.from.Np return objects of the appropriate class (as
from arps.decline) representing best fits of the appropriate type
against Np and t, in the same units as Np and t.
best.fit.from.Np returns the best overall fit, considering results
from each function above.
best.exponential.from.interval, best.hyperbolic.from.interval,
and best.hyp2exp.from.interval return objects of the appropriate
class (as from arps.decline) representing best fits of the
appropriate type against volume and t, in the same units as
volume and t.
For these functions, t is taken to represent the time at the end of
each producing interval; the beginning time for the first interval may be
specified as t.begin if it is non-zero.
best.fit.from.interval returns the best overall fit, considering
results from each function above.
best.exponential.curtailed, best.hyperbolic.curtailed,
best.hyp2exp.curtailed, best.curtailed.fit,
best.exponential.curtailed.from.Np,
best.hyperbolic.curtailed.from.Np,
best.hyp2exp.curtailed.from.Np, best.curtailed.fit.from.Np,
best.exponential.curtailed.from.interval,
best.hyperbolic.curtailed.from.interval,
best.hyp2exp.curtailed.from.interval, and
best.curtailed.fit.from.interval work as the corresponding functions
above, but may return curtailed declines (as from curtail).
best.exponential.with.buildup, best.hyperbolic.with.buildup,
best.hyp2exp.with.buildup, best.fit.with.buildup,
best.exponential.from.Np.with.buildup,
best.hyperbolic.from.Np.with.buildup,
best.hyp2exp.from.Np.with.buildup,
best.fit.from.Np.with.buildup,
best.exponential.from.interval.with.buildup,
best.hyperbolic.from.interval.with.buildup,
best.hyp2exp.from.interval.with.buildup, and
best.fit.from.interval.with.buildup work as the corresponding
functions above, but will return a fit including a linear buildup
portion (as from arps.with.buildup).
Best-fitting is carried out by minimizing the sum of squared error in the
rate or cumulative forecast, using nlminb as the optimizer.
Appropriate bounds are applied to decline-curve parameters by default, but
may be altered using the lower and upper arguments to each
specific function.
# NOT RUN {
fitme.hyp2exp.t <- seq(0, 5, 1 / 12) # 5 years
fitme.hyp2exp.q <- hyp2exp.q(
1000, # Bbl/d
as.nominal(0.70), # / year
1.9,
as.nominal(0.15), # / year
fitme.hyp2exp.t
) * rnorm(n=length(fitme.hyp2exp.t), mean=1, sd=0.1) # perturb
hyp2exp.fit <- best.hyp2exp(fitme.hyp2exp.q, fitme.hyp2exp.t)
cat(paste("SSE:", hyp2exp.fit$sse))
dev.new()
plot(fitme.hyp2exp.q ~ fitme.hyp2exp.t, main="Hyperbolic-to-Exponential Fit",
col="blue", log="y", xlab="Time", ylab="Rate")
lines(arps.q(hyp2exp.fit$decline, fitme.hyp2exp.t) ~ fitme.hyp2exp.t,
col="red")
legend("topright", pch=c(1, NA), lty=c(NA, 1), col=c("blue", "red"), legend=c("Actual", "Fit"))
# }
Run the code above in your browser using DataLab