mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
cleaning up to preapre for pull request
This commit is contained in:
parent
035d216641
commit
e38e557bbc
@ -257,12 +257,12 @@ namespace Opm
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
virtual bool iterateWellEqWithSwitching(const Simulator& ebosSimulator,
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
WellState& well_state,
|
||||
const GroupState& group_state,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
WellState& well_state,
|
||||
const GroupState& group_state,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
virtual void assembleWellEqWithoutIteration(const Simulator& ebosSimulator,
|
||||
const double dt,
|
||||
|
@ -523,6 +523,9 @@ getResidualMeasureValue(const WellState& well_state,
|
||||
++count;
|
||||
}
|
||||
|
||||
// if (count == 0), it should be converged.
|
||||
assert(count != 0);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
@ -140,11 +140,9 @@ segmentNumberToIndex(const int segment_number) const
|
||||
template<typename Scalar>
|
||||
void
|
||||
MultisegmentWellGeneric<Scalar>::
|
||||
detectOscillations(const std::vector<double>& measure_history,
|
||||
const int it,
|
||||
bool& oscillate,
|
||||
bool& stagnate) const
|
||||
detectOscillations(const std::vector<double>& measure_history, bool& oscillate, bool& stagnate) const
|
||||
{
|
||||
const auto it = measure_history.size() - 1;
|
||||
if ( it < 2 ) {
|
||||
oscillate = false;
|
||||
stagnate = false;
|
||||
|
@ -65,7 +65,6 @@ protected:
|
||||
|
||||
/// Detect oscillation or stagnation based on the residual measure history
|
||||
void detectOscillations(const std::vector<double>& measure_history,
|
||||
const int it,
|
||||
bool& oscillate,
|
||||
bool& stagnate) const;
|
||||
|
||||
|
@ -1339,7 +1339,7 @@ namespace Opm
|
||||
bool is_oscillate = false;
|
||||
bool is_stagnate = false;
|
||||
|
||||
this->detectOscillations(measure_history, it, is_oscillate, is_stagnate);
|
||||
this->detectOscillations(measure_history, is_oscillate, is_stagnate);
|
||||
// TODO: maybe we should have more sophisticated strategy to recover the relaxation factor,
|
||||
// for example, to recover it to be bigger
|
||||
|
||||
@ -1444,13 +1444,13 @@ namespace Opm
|
||||
int stagnate_count = 0;
|
||||
bool relax_convergence = false;
|
||||
this->regularize_ = false;
|
||||
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
||||
|
||||
// Max status switch frequency should be 2 to avoid getting stuck in cycle
|
||||
const int min_its_after_switch = 2;
|
||||
int its_since_last_switch = min_its_after_switch;
|
||||
int switch_count= 0;
|
||||
const auto well_status = this->wellStatus_;
|
||||
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
||||
const bool allow_switching = !this->wellUnderZeroRateTarget(summary_state, well_state) && (this->well_ecl_.getStatus() == WellStatus::OPEN);
|
||||
bool changed = false;
|
||||
bool final_check = false;
|
||||
@ -1490,65 +1490,67 @@ namespace Opm
|
||||
its_since_last_switch = min_its_after_switch;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// getFinteWellResiduals returns false for nan/inf residuals
|
||||
{
|
||||
// getFinteWellResiduals returns false for nan/inf residuals
|
||||
const auto& [isFinite, residuals] = this->getFiniteWellResiduals(Base::B_avg_, deferred_logger);
|
||||
if (!isFinite)
|
||||
return false;
|
||||
|
||||
residual_history.push_back(residuals);
|
||||
measure_history.push_back(this->getResidualMeasureValue(well_state,
|
||||
residual_history[it],
|
||||
this->param_.tolerance_wells_,
|
||||
this->param_.tolerance_pressure_ms_wells_,
|
||||
deferred_logger) );
|
||||
}
|
||||
|
||||
if (!converged) {
|
||||
measure_history.push_back(this->getResidualMeasureValue(well_state,
|
||||
residual_history[it],
|
||||
this->param_.tolerance_wells_,
|
||||
this->param_.tolerance_pressure_ms_wells_,
|
||||
deferred_logger));
|
||||
|
||||
bool is_oscillate = false;
|
||||
bool is_stagnate = false;
|
||||
bool is_oscillate = false;
|
||||
bool is_stagnate = false;
|
||||
|
||||
this->detectOscillations(measure_history, it, is_oscillate, is_stagnate);
|
||||
// TODO: maybe we should have more sophisticated strategy to recover the relaxation factor,
|
||||
// for example, to recover it to be bigger
|
||||
this->detectOscillations(measure_history, is_oscillate, is_stagnate);
|
||||
// TODO: maybe we should have more sophisticated strategy to recover the relaxation factor,
|
||||
// for example, to recover it to be bigger
|
||||
|
||||
if (is_oscillate || is_stagnate) {
|
||||
// HACK!
|
||||
std::ostringstream sstr;
|
||||
if (relaxation_factor == min_relaxation_factor) {
|
||||
// Still stagnating, terminate iterations if 5 iterations pass.
|
||||
++stagnate_count;
|
||||
if (false){//(stagnate_count == 6) {
|
||||
sstr << " well " << this->name() << " observes severe stagnation and/or oscillation. We relax the tolerance and check for convergence. \n";
|
||||
const auto reportStag = getWellConvergence(summary_state, well_state, Base::B_avg_, deferred_logger, true);
|
||||
if (reportStag.converged()) {
|
||||
converged = true;
|
||||
sstr << " well " << this->name() << " manages to get converged with relaxed tolerances in " << it << " inner iterations";
|
||||
deferred_logger.debug(sstr.str());
|
||||
return converged;
|
||||
if (is_oscillate || is_stagnate) {
|
||||
// HACK!
|
||||
std::string message;
|
||||
if (relaxation_factor == min_relaxation_factor) {
|
||||
++stagnate_count;
|
||||
if (false) { // this disables the usage of the relaxed tolerance
|
||||
fmt::format_to(std::back_inserter(message), " Well {} observes severe stagnation and/or oscillation."
|
||||
" We relax the tolerance and check for convergence. \n", this->name());
|
||||
const auto reportStag = getWellConvergence(summary_state, well_state, Base::B_avg_,
|
||||
deferred_logger, true);
|
||||
if (reportStag.converged()) {
|
||||
converged = true;
|
||||
fmt::format_to(std::back_inserter(message), " Well {} manages to get converged with relaxed tolerances in {} inner iterations", this->name(), it);
|
||||
deferred_logger.debug(message);
|
||||
return converged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a factor value to reduce the relaxation_factor
|
||||
constexpr double reduction_mutliplier = 0.9;
|
||||
relaxation_factor = std::max(relaxation_factor * reduction_mutliplier, min_relaxation_factor);
|
||||
|
||||
// debug output
|
||||
if (is_stagnate) {
|
||||
fmt::format_to(std::back_inserter(message), " well {} observes stagnation in inner iteration {}\n", this->name(), it);
|
||||
}
|
||||
if (is_oscillate) {
|
||||
fmt::format_to(std::back_inserter(message), " well {} observes oscillation in inner iteration {}\n", this->name(), it);
|
||||
}
|
||||
fmt::format_to(std::back_inserter(message), " relaxation_factor is {} now\n", relaxation_factor);
|
||||
|
||||
this->regularize_ = true;
|
||||
deferred_logger.debug(message);
|
||||
}
|
||||
|
||||
// a factor value to reduce the relaxation_factor
|
||||
const double reduction_mutliplier = 0.9;
|
||||
relaxation_factor = std::max(relaxation_factor * reduction_mutliplier, min_relaxation_factor);
|
||||
|
||||
// debug output
|
||||
if (is_stagnate) {
|
||||
sstr << " well " << this->name() << " observes stagnation in inner iteration " << it << "\n";
|
||||
|
||||
}
|
||||
if (is_oscillate) {
|
||||
sstr << " well " << this->name() << " observes oscillation in inner iteration " << it << "\n";
|
||||
}
|
||||
sstr << " relaxation_factor is " << relaxation_factor << " now\n";
|
||||
|
||||
this->regularize_ = true;
|
||||
deferred_logger.debug(sstr.str());
|
||||
}
|
||||
updateWellState(summary_state, dx_well, well_state, deferred_logger, relaxation_factor);
|
||||
initPrimaryVariablesEvaluation();
|
||||
@ -1566,16 +1568,19 @@ namespace Opm
|
||||
}
|
||||
// We reset the well status to it's original state. Status is updated
|
||||
// on the outside based on operability status
|
||||
this->wellStatus_ = well_status;
|
||||
}
|
||||
std::ostringstream sstr;
|
||||
sstr << " Well " << this->name() << " converged in " << it << " inner iterations (" << switch_count << " local control switches).";
|
||||
if (relax_convergence)
|
||||
sstr << " (A relaxed tolerance was used after "<< this->param_.strict_inner_iter_wells_ << " iterations)";
|
||||
deferred_logger.debug(sstr.str());
|
||||
this->wellStatus_ = well_status;
|
||||
}
|
||||
std::string message = fmt::format(" Well {} converged in {} inner iterations ("
|
||||
"{} control/status switches).", this->name(), it, switch_count);
|
||||
if (relax_convergence) {
|
||||
message.append(fmt::format(" (A relaxed tolerance was used after {} iterations)",
|
||||
this->param_.strict_inner_iter_wells_));
|
||||
}
|
||||
deferred_logger.debug(message);
|
||||
} else {
|
||||
std::ostringstream sstr;
|
||||
sstr << " Well " << this->name() << " did not converge in " << it << " inner iterations (" << switch_count << " local control switches).";
|
||||
const std::string message = fmt::format(" Well {} did not converged in {} inner iterations ("
|
||||
"{} control/status switches).", this->name(), it, switch_count);
|
||||
deferred_logger.debug(message);
|
||||
}
|
||||
|
||||
return converged;
|
||||
|
@ -207,12 +207,12 @@ namespace Opm
|
||||
|
||||
// iterate well equations including control switching
|
||||
bool iterateWellEqWithSwitching(const Simulator& ebosSimulator,
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
WellState& well_state,
|
||||
const GroupState& group_state,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
WellState& well_state,
|
||||
const GroupState& group_state,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
/// \brief Wether the Jacobian will also have well contributions in it.
|
||||
virtual bool jacobianContainsWellContributions() const override
|
||||
|
@ -2175,7 +2175,7 @@ namespace Opm
|
||||
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
||||
|
||||
// Max status switch frequency should be 2 to avoid getting stuck in cycle
|
||||
const int min_its_after_switch = 2;
|
||||
constexpr int min_its_after_switch = 2;
|
||||
int its_since_last_switch = min_its_after_switch;
|
||||
int switch_count= 0;
|
||||
const auto well_status = this->wellStatus_;
|
||||
@ -2236,12 +2236,13 @@ namespace Opm
|
||||
}
|
||||
// We reset the well status to it's original state. Status is updated
|
||||
// on the outside based on operability status
|
||||
this->wellStatus_ = well_status;
|
||||
// TODO: this looks strange, let us check
|
||||
this->wellStatus_ = well_status;
|
||||
}
|
||||
} else {
|
||||
std::ostringstream sstr;
|
||||
sstr << " Well " << this->name() << " did not converge in " << it << " inner iterations (" << switch_count << " control/status switches).";
|
||||
deferred_logger.debug(sstr.str());
|
||||
const std::string message = fmt::format(" Well {} did not converged in {} inner iterations ("
|
||||
"{} control/status switches).", this->name(), it, switch_count);
|
||||
deferred_logger.debug(message);
|
||||
// add operability here as well ?
|
||||
}
|
||||
return converged;
|
||||
|
@ -242,12 +242,12 @@ public:
|
||||
DeferredLogger& deferred_logger) /* const */;
|
||||
|
||||
bool updateWellControlAndStatusLocalIteration(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
const GroupState& group_state,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const double& WQTotal,
|
||||
DeferredLogger& deferred_logger); /* const */
|
||||
WellState& well_state,
|
||||
const GroupState& group_state,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const double WQTotal,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
virtual void updatePrimaryVariables(const SummaryState& summary_state,
|
||||
const WellState& well_state,
|
||||
@ -402,12 +402,12 @@ protected:
|
||||
DeferredLogger& deferred_logger) = 0;
|
||||
|
||||
virtual bool iterateWellEqWithSwitching(const Simulator& ebosSimulator,
|
||||
const double dt,
|
||||
const WellInjectionControls& inj_controls,
|
||||
const WellProductionControls& prod_controls,
|
||||
WellState& well_state,
|
||||
const GroupState& group_state,
|
||||
DeferredLogger& deferred_logger) = 0;
|
||||
const double dt,
|
||||
const WellInjectionControls& inj_controls,
|
||||
const WellProductionControls& prod_controls,
|
||||
WellState& well_state,
|
||||
const GroupState& group_state,
|
||||
DeferredLogger& deferred_logger) = 0;
|
||||
|
||||
bool iterateWellEquations(const Simulator& ebosSimulator,
|
||||
const double dt,
|
||||
|
@ -344,22 +344,23 @@ void WellInterfaceGeneric::setVFPProperties(const VFPProperties* vfp_properties_
|
||||
vfp_properties_ = vfp_properties_arg;
|
||||
}
|
||||
|
||||
void WellInterfaceGeneric::setPrevSurfaceRates(WellState& well_state,
|
||||
void WellInterfaceGeneric::setPrevSurfaceRates(WellState& well_state,
|
||||
const WellState& prev_well_state) const
|
||||
{
|
||||
auto& ws = well_state.well(this->index_of_well_);
|
||||
auto& ws_prev = prev_well_state.well(this->index_of_well_);
|
||||
// The logic here is a bit fragile:
|
||||
// We need non-zero prev_surface_rates for the purpose of providing explicit fractions
|
||||
// We need non-zero prev_surface_rates for the purpose of providing explicit fractions
|
||||
// (if needed) for vfp interpolation.
|
||||
// We assume that current surface rates either are initialized from previous step
|
||||
// or (if newly opened) from updateWellStateRates. This is fine unless well was
|
||||
// stopped in previous step in which case it's rates will be zero. In this case,
|
||||
// or (if newly opened) from updateWellStateRates. This is fine unless well was
|
||||
// stopped in previous step in which case it's rates will be zero. In this case,
|
||||
// we select the previous rates of the previous well state (and hope for the best).
|
||||
bool zero_rates = true;
|
||||
for (const double& rate : ws.surface_rates){
|
||||
zero_rates &= (rate == 0.0);
|
||||
}
|
||||
const bool zero_rates = std::all_of(ws.surface_rates.begin(), ws.surface_rates.end(),
|
||||
[](double rate) {
|
||||
return rate == 0.; // TODO: should we use a threshhold for comparison?
|
||||
} );
|
||||
|
||||
if (zero_rates) {
|
||||
ws.prev_surface_rates = ws_prev.prev_surface_rates;
|
||||
} else {
|
||||
|
@ -209,9 +209,6 @@ public:
|
||||
bool stopppedOrZeroRateTarget(const SummaryState& summary_state,
|
||||
const WellState& well_state) const;
|
||||
|
||||
bool wellUnderZeroRateTarget(const SummaryState& summary_state,
|
||||
const WellState& well_state) const;
|
||||
|
||||
double wellEfficiencyFactor() const
|
||||
{ return well_efficiency_factor_; }
|
||||
|
||||
@ -221,7 +218,7 @@ public:
|
||||
inj_fc_multiplier_ = inj_fc_multiplier;
|
||||
}
|
||||
|
||||
void resetWellOperability();
|
||||
void resetWellOperability();
|
||||
|
||||
protected:
|
||||
bool getAllowCrossFlow() const;
|
||||
@ -237,6 +234,9 @@ protected:
|
||||
int polymerInjTable_() const;
|
||||
int polymerWaterTable_() const;
|
||||
|
||||
bool wellUnderZeroRateTarget(const SummaryState& summary_state,
|
||||
const WellState& well_state) const;
|
||||
|
||||
std::pair<bool,bool>
|
||||
computeWellPotentials(std::vector<double>& well_potentials,
|
||||
const WellState& well_state);
|
||||
|
@ -258,12 +258,12 @@ namespace Opm
|
||||
bool
|
||||
WellInterface<TypeTag>::
|
||||
updateWellControlAndStatusLocalIteration(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
const GroupState& group_state,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const double& wqTotal,
|
||||
DeferredLogger& deferred_logger) /* const */
|
||||
WellState& well_state,
|
||||
const GroupState& group_state,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const double wqTotal,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
const auto& summary_state = ebos_simulator.vanguard().summaryState();
|
||||
const auto& schedule = ebos_simulator.vanguard().schedule();
|
||||
@ -284,9 +284,11 @@ namespace Opm
|
||||
prod_controls.hasControl(Well::ProducerCMode::GRUP);
|
||||
|
||||
changed = this->checkIndividualConstraints(ws, summary_state, deferred_logger, inj_controls, prod_controls);
|
||||
// TODO: with current way, the checkGroupConstraints might overwrite the result from checkIndividualConstraints, which remains to be investigated
|
||||
if (hasGroupControl) {
|
||||
changed = this->checkGroupConstraints(well_state, group_state, schedule, summary_state, deferred_logger);
|
||||
changed = this->checkGroupConstraints(well_state, group_state, schedule, summary_state,deferred_logger);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
const bool thp_controlled = this->isInjector() ? ws.injection_cmode == Well::InjectorCMode::THP :
|
||||
ws.production_cmode == Well::ProducerCMode::THP;
|
||||
@ -436,6 +438,7 @@ namespace Opm
|
||||
const auto prod_controls = this->well_ecl_.isProducer() ? this->well_ecl_.productionControls(summary_state) : Well::ProductionControls(0);
|
||||
bool converged = false;
|
||||
try {
|
||||
// TODO: the following two functions will be refactored to be one to reduce the code duplication
|
||||
if (!this->param_.local_well_solver_control_switching_){
|
||||
converged = this->iterateWellEqWithControl(ebosSimulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
|
||||
} else {
|
||||
@ -782,7 +785,7 @@ namespace Opm
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
if (this->param_.local_well_solver_control_switching_) {
|
||||
bool success = updateWellOperabilityFromWellEq(ebos_simulator, well_state, deferred_logger);
|
||||
const bool success = updateWellOperabilityFromWellEq(ebos_simulator, well_state, deferred_logger);
|
||||
if (success) {
|
||||
return;
|
||||
} else {
|
||||
@ -817,7 +820,7 @@ namespace Opm
|
||||
const WellState& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
// only makes sense if we're using this parameter is true
|
||||
// only makes sense if we're using this parameter is true
|
||||
assert(this->param_.local_well_solver_control_switching_);
|
||||
this->operability_status_.resetOperability();
|
||||
WellState well_state_copy = well_state;
|
||||
|
Loading…
Reference in New Issue
Block a user