mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #4881 from vkip/no_network_solve_in_history
Avoid iterating network if no network wells are in prediciton mode
This commit is contained in:
@@ -405,9 +405,8 @@ namespace Opm {
|
||||
|
||||
SimulatorReportSingle last_report_{};
|
||||
|
||||
// solve to get a good network solution, group and well states might be updated during the process.
|
||||
// the reservoir should stay static during this solution procedure.
|
||||
void balanceNetwork(DeferredLogger& deferred_logger);
|
||||
// Pre-step network solve at static reservoir conditions (group and well states might be updated)
|
||||
void doPreStepNetworkRebalance(DeferredLogger& deferred_logger);
|
||||
|
||||
// used to better efficiency of calcuation
|
||||
mutable BVector scaleAddRes_{};
|
||||
|
@@ -139,6 +139,13 @@ wellsActive() const
|
||||
return wells_active_;
|
||||
}
|
||||
|
||||
bool
|
||||
BlackoilWellModelGeneric::
|
||||
networkActive() const
|
||||
{
|
||||
return network_active_;
|
||||
}
|
||||
|
||||
bool
|
||||
BlackoilWellModelGeneric::
|
||||
anyMSWellOpenLocal() const
|
||||
@@ -978,27 +985,43 @@ hasTHPConstraints() const
|
||||
return BlackoilWellModelConstraints(*this).hasTHPConstraints();
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BlackoilWellModelGeneric::
|
||||
needRebalanceNetwork(const int report_step) const
|
||||
{
|
||||
updateNetworkActiveState(const int report_step) {
|
||||
const auto& network = schedule()[report_step].network();
|
||||
if (!network.active()) {
|
||||
return false;
|
||||
this->network_active_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool network_active = false;
|
||||
for (const auto& well : well_container_generic_) {
|
||||
const bool is_partof_network = network.has_node(well->wellEcl().groupName());
|
||||
const bool prediction_mode = well->wellEcl().predictionMode();
|
||||
if (is_partof_network && prediction_mode) {
|
||||
network_active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->network_active_ = comm_.max(network_active);
|
||||
}
|
||||
|
||||
bool
|
||||
BlackoilWellModelGeneric::
|
||||
needPreStepNetworkRebalance(const int report_step) const
|
||||
{
|
||||
const auto& network = schedule()[report_step].network();
|
||||
bool network_rebalance_necessary = false;
|
||||
for (const auto& well : well_container_generic_) {
|
||||
const auto& events = this->wellState().well(well->indexOfWell()).events;
|
||||
const bool is_partof_network = network.has_node(well->wellEcl().groupName());
|
||||
// TODO: we might find more relevant events to be included here
|
||||
// TODO: we might find more relevant events to be included here (including network change events?)
|
||||
const auto& events = this->wellState().well(well->indexOfWell()).events;
|
||||
if (is_partof_network && events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE)) {
|
||||
network_rebalance_necessary = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
network_rebalance_necessary = comm_.max(network_rebalance_necessary);
|
||||
|
||||
return network_rebalance_necessary;
|
||||
}
|
||||
|
||||
@@ -1059,7 +1082,7 @@ double
|
||||
BlackoilWellModelGeneric::
|
||||
updateNetworkPressures(const int reportStepIdx)
|
||||
{
|
||||
// Get the network and return if inactive.
|
||||
// Get the network and return if inactive (no wells in network at this time)
|
||||
const auto& network = schedule()[reportStepIdx].network();
|
||||
if (!network.active()) {
|
||||
return 0.0;
|
||||
@@ -1076,6 +1099,8 @@ updateNetworkPressures(const int reportStepIdx)
|
||||
|
||||
// here, the network imbalance is the difference between the previous nodal pressure and the new nodal pressure
|
||||
double network_imbalance = 0.;
|
||||
if (!this->networkActive())
|
||||
return network_imbalance;
|
||||
|
||||
if (!previous_node_pressures.empty()) {
|
||||
for (const auto& [name, pressure]: previous_node_pressures) {
|
||||
@@ -1111,7 +1136,7 @@ updateNetworkPressures(const int reportStepIdx)
|
||||
// Producers only, since we so far only support the
|
||||
// "extended" network model (properties defined by
|
||||
// BRANPROP and NODEPROP) which only applies to producers.
|
||||
if (well->isProducer()) {
|
||||
if (well->isProducer() && well->wellEcl().predictionMode()) {
|
||||
const auto it = node_pressures_.find(well->wellEcl().groupName());
|
||||
if (it != node_pressures_.end()) {
|
||||
// The well belongs to a group with has a network pressure constraint,
|
||||
|
@@ -103,6 +103,9 @@ public:
|
||||
bool wellsActive() const;
|
||||
bool hasWell(const std::string& wname) const;
|
||||
|
||||
/// return true if network is active (at least one network well in prediction mode)
|
||||
bool networkActive() const;
|
||||
|
||||
// whether there exists any multisegment well open on this process
|
||||
bool anyMSWellOpenLocal() const;
|
||||
|
||||
@@ -169,8 +172,13 @@ public:
|
||||
/// Return true if any well has a THP constraint.
|
||||
bool hasTHPConstraints() const;
|
||||
|
||||
/// Whether it is necessary to re-balance network
|
||||
bool needRebalanceNetwork(const int report_step) const;
|
||||
/// Checks if network is active (at least one network well on prediction).
|
||||
void updateNetworkActiveState(const int report_step);
|
||||
|
||||
/// Checks if there are reasons to perform a pre-step network re-balance.
|
||||
/// (Currently, the only reasons are network well status changes.)
|
||||
/// (TODO: Consider if adding network change events would be helpful.)
|
||||
bool needPreStepNetworkRebalance(const int report_step) const;
|
||||
|
||||
/// Shut down any single well
|
||||
/// Returns true if the well was actually found and shut.
|
||||
@@ -431,6 +439,7 @@ protected:
|
||||
PhaseUsage phase_usage_;
|
||||
bool terminal_output_{false};
|
||||
bool wells_active_{false};
|
||||
bool network_active_{false};
|
||||
bool initial_step_{};
|
||||
bool report_step_starts_{};
|
||||
|
||||
|
@@ -1006,11 +1006,11 @@ namespace Opm {
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
balanceNetwork(DeferredLogger& deferred_logger) {
|
||||
doPreStepNetworkRebalance(DeferredLogger& deferred_logger) {
|
||||
const double dt = this->ebosSimulator_.timeStepSize();
|
||||
// TODO: should we also have the group and network backed-up here in case the solution did not get converged?
|
||||
auto& well_state = this->wellState();
|
||||
constexpr std::size_t max_iter = 100;
|
||||
const std::size_t max_iter = param_.network_max_iterations_;
|
||||
bool converged = false;
|
||||
std::size_t iter = 0;
|
||||
bool changed_well_group = false;
|
||||
@@ -1030,11 +1030,11 @@ namespace Opm {
|
||||
} while (iter < max_iter);
|
||||
|
||||
if (!converged) {
|
||||
const std::string msg = fmt::format("balanceNetwork did not get converged with {} iterations, and unconverged "
|
||||
"network balance result will be used", max_iter);
|
||||
const std::string msg = fmt::format("Initial (pre-step) network balance did not get converged with {} iterations, "
|
||||
"unconverged network balance result will be used", max_iter);
|
||||
deferred_logger.warning(msg);
|
||||
} else {
|
||||
const std::string msg = fmt::format("balanceNetwork get converged with {} iterations", iter);
|
||||
const std::string msg = fmt::format("Initial (pre-step) network balance converged with {} iterations", iter);
|
||||
deferred_logger.debug(msg);
|
||||
}
|
||||
}
|
||||
@@ -1853,7 +1853,7 @@ namespace Opm {
|
||||
const auto& balance = schedule()[episodeIdx].network_balance();
|
||||
constexpr double relaxtion_factor = 10.0;
|
||||
const double tolerance = relax_network_tolerance ? relaxtion_factor * balance.pressure_tolerance() : balance.pressure_tolerance();
|
||||
more_network_update = network_imbalance > tolerance;
|
||||
more_network_update = this->networkActive() && network_imbalance > tolerance;
|
||||
}
|
||||
|
||||
bool changed_well_group = false;
|
||||
@@ -2239,7 +2239,13 @@ namespace Opm {
|
||||
BlackoilWellModel<TypeTag>::
|
||||
prepareTimeStep(DeferredLogger& deferred_logger)
|
||||
{
|
||||
const bool network_rebalance_necessary = this->needRebalanceNetwork(ebosSimulator_.episodeIndex());
|
||||
// Check if there is a network with active prediction wells at this time step.
|
||||
const auto episodeIdx = ebosSimulator_.episodeIndex();
|
||||
this->updateNetworkActiveState(episodeIdx);
|
||||
|
||||
// Rebalance the network initially if any wells in the network have status changes
|
||||
// (Need to check this before clearing events)
|
||||
const bool do_prestep_network_rebalance = this->needPreStepNetworkRebalance(episodeIdx);
|
||||
|
||||
for (const auto& well : well_container_) {
|
||||
auto& events = this->wellState().well(well->indexOfWell()).events;
|
||||
@@ -2257,7 +2263,7 @@ namespace Opm {
|
||||
try {
|
||||
well->solveWellEquation(ebosSimulator_, this->wellState(), this->groupState(), deferred_logger);
|
||||
} catch (const std::exception& e) {
|
||||
const std::string msg = "Compute initial well solution for " + well->name() + " initially failed. Continue with the privious rates";
|
||||
const std::string msg = "Compute initial well solution for " + well->name() + " initially failed. Continue with the previous rates";
|
||||
deferred_logger.warning("WELL_INITIAL_SOLVE_FAILED", msg);
|
||||
}
|
||||
}
|
||||
@@ -2267,10 +2273,8 @@ namespace Opm {
|
||||
}
|
||||
updatePrimaryVariables(deferred_logger);
|
||||
|
||||
if (network_rebalance_necessary) {
|
||||
// this is to obtain good network solution
|
||||
balanceNetwork(deferred_logger);
|
||||
}
|
||||
// Actually do the pre-step network rebalance, using the updated well states and initial solutions
|
||||
if (do_prestep_network_rebalance) doPreStepNetworkRebalance(deferred_logger);
|
||||
}
|
||||
|
||||
template<typename TypeTag>
|
||||
|
Reference in New Issue
Block a user