mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
refactoring to shorten the function computeBhpAtThpLimitProd
better readibility hopefully.
This commit is contained in:
parent
5824acbf92
commit
3b7e62979c
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user