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