refactoring to shorten the function computeBhpAtThpLimitProd

better readibility hopefully.
This commit is contained in:
Kai Bao 2022-01-07 15:49:48 +01:00
parent 5824acbf92
commit 3b7e62979c
2 changed files with 180 additions and 130 deletions

View File

@ -480,10 +480,68 @@ computeBhpAtThpLimitProd(const std::function<std::vector<double>(const double)>&
};
// Find the bhp-point where production becomes nonzero.
double bhp_max = 0.0;
{
auto fflo = [&flo, &frates](double bhp) { return flo(frates(bhp)); };
double low = controls.bhp_limit;
auto bhp_max = this->bhpMax(fflo, controls.bhp_limit, maxPerfPress, table.getFloAxis().front(), deferred_logger);
// could not solve for the bhp-point, we could not contrinue to find the bhp
if (!bhp_max.has_value()) {
return {};
}
// Define the equation we want to solve.
auto eq = [&fbhp, &frates](double bhp) {
return fbhp(frates(bhp)) - bhp;
};
// Find appropriate brackets for the solution.
const std::array<double, 2> range {controls.bhp_limit, *bhp_max};
std::optional<double> approximate_solution;
double low, high;
// trying to use bisect way to locate a bracket
bool finding_bracket = this->bisectBracket(eq, range, low, high, approximate_solution, deferred_logger);
// based on the origional design, if an approximate solution is suggested, we use this value directly
// in the long run, we might change it
if (approximate_solution.has_value()) {
return *approximate_solution;
}
if (!finding_bracket) {
deferred_logger.debug(" trying the brute force way for last attempt ");
finding_bracket = this->bruteForceBracket(eq, range, low, high, deferred_logger);
}
if (!finding_bracket) {
return std::nullopt;
}
// Solve for the proper solution in the given interval.
const int max_iteration = 100;
const double bhp_tolerance = 0.01 * unit::barsa;
int iteration = 0;
try {
const double solved_bhp = RegulaFalsiBisection<ThrowOnError>::
solve(eq, low, high, max_iteration, bhp_tolerance, iteration);
return solved_bhp;
}
catch (...) {
deferred_logger.warning("FAILED_ROBUST_BHP_THP_SOLVE",
"Robust bhp(thp) solve failed for well " + baseif_.name());
return std::nullopt;
}
}
template<typename Scalar>
std::optional<double>
MultisegmentWellGeneric<Scalar>::
bhpMax(const std::function<double(const double)>& fflo,
const double bhp_limit,
const double maxPerfPress,
const double vfp_flo_front,
DeferredLogger& deferred_logger) const
{
// Find the bhp-point where production becomes nonzero.
double bhp_max = 0.0;
double low = bhp_limit;
double high = maxPerfPress + 1.0 * unit::barsa;
double f_low = fflo(low);
double f_high = fflo(high);
@ -508,7 +566,7 @@ computeBhpAtThpLimitProd(const std::function<std::vector<double>(const double)>&
// empty optional.
deferred_logger.warning("FAILED_ROBUST_BHP_THP_SOLVE_INOPERABLE",
"Robust bhp(thp) solve failed due to inoperability for well " + baseif_.name());
return std::optional<double>();
return {};
} else {
// Still producing, even at high bhp.
assert(f_high < 0.0);
@ -517,7 +575,7 @@ computeBhpAtThpLimitProd(const std::function<std::vector<double>(const double)>&
} else {
// Bisect to find a bhp point where we produce, but
// not a large amount ('eps' below).
const double eps = 0.1 * std::fabs(table.getFloAxis().front());
const double eps = 0.1 * std::fabs(vfp_flo_front);
const int maxit = 50;
int it = 0;
while (std::fabs(f_low) > eps && it < maxit) {
@ -540,18 +598,23 @@ computeBhpAtThpLimitProd(const std::function<std::vector<double>(const double)>&
" f(low) = " + std::to_string(f_low) +
" f(high) = " + std::to_string(f_high) +
" bhp_max = " + std::to_string(bhp_max));
}
return bhp_max;
}
// Define the equation we want to solve.
auto eq = [&fbhp, &frates](double bhp) {
return fbhp(frates(bhp)) - bhp;
};
// Find appropriate brackets for the solution.
template<typename Scalar>
bool
MultisegmentWellGeneric<Scalar>::
bisectBracket(const std::function<double(const double)>& eq,
const std::array<double, 2>& range,
double& low, double& high,
std::optional<double>& approximate_solution,
DeferredLogger& deferred_logger) const
{
bool finding_bracket = false;
double low = controls.bhp_limit;
double high = bhp_max;
{
low = range[0];
high = range[1];
double eq_high = eq(high);
double eq_low = eq(low);
const double eq_bhplimit = eq_low;
@ -590,7 +653,7 @@ computeBhpAtThpLimitProd(const std::function<std::vector<double>(const double)>&
// highest flow.
if (eq_low * eq_bhplimit <= 0.0) {
high = low;
low = controls.bhp_limit;
low = range[0];
}
} else { // eq_low * eq_high > 0.0
// Still failed bracketing!
@ -599,7 +662,7 @@ computeBhpAtThpLimitProd(const std::function<std::vector<double>(const double)>&
// Return the least bad solution if less off than 3 bar.
deferred_logger.warning("FAILED_ROBUST_BHP_THP_SOLVE_BRACKETING_FAILURE",
"Robust bhp(thp) not solved precisely for well " + baseif_.name());
return abs_low < abs_high ? low : high;
approximate_solution = abs_low < abs_high ? low : high;
} else {
// Return failure.
deferred_logger.warning("FAILED_ROBUST_BHP_THP_SOLVE_BRACKETING_FAILURE",
@ -608,38 +671,13 @@ computeBhpAtThpLimitProd(const std::function<std::vector<double>(const double)>&
}
}
}
}
if (!finding_bracket) {
deferred_logger.debug(" trying the brute force way for last attempt ");
const std::array<double, 2> range {controls.bhp_limit, bhp_max};
finding_bracket = this->bruteForcingBracket(eq, range, low, high, deferred_logger);
}
if (!finding_bracket) {
return std::nullopt;
}
// Solve for the proper solution in the given interval.
const int max_iteration = 100;
const double bhp_tolerance = 0.01 * unit::barsa;
int iteration = 0;
try {
const double solved_bhp = RegulaFalsiBisection<ThrowOnError>::
solve(eq, low, high, max_iteration, bhp_tolerance, iteration);
return solved_bhp;
}
catch (...) {
deferred_logger.warning("FAILED_ROBUST_BHP_THP_SOLVE",
"Robust bhp(thp) solve failed for well " + baseif_.name());
return std::nullopt;
}
return finding_bracket;
}
template<typename Scalar>
bool
MultisegmentWellGeneric<Scalar>::
bruteForcingBracket(const std::function<double(const double)>& eq,
bruteForceBracket(const std::function<double(const double)>& eq,
const std::array<double, 2>& range,
double& low, double& high,
DeferredLogger& deferred_logger) const

View File

@ -76,11 +76,23 @@ protected:
const double rho,
DeferredLogger& deferred_logger) const;
bool bruteForcingBracket(const std::function<double(const double)>& eq,
std::optional<double> bhpMax(const std::function<double(const double)>& fflo,
const double bhp_limit,
const double maxPerfPress,
const double vfp_flo_front,
DeferredLogger& deferred_logger) const;
bool bruteForceBracket(const std::function<double(const double)>& eq,
const std::array<double, 2>& range,
double& low, double& high,
DeferredLogger& deferred_logger) const;
bool bisectBracket(const std::function<double(const double)>& eq,
const std::array<double, 2>& range,
double& low, double& high,
std::optional<double>& approximate_solution,
DeferredLogger& deferred_logger) const;
/// Detect oscillation or stagnation based on the residual measure history
void detectOscillations(const std::vector<double>& measure_history,
const int it,