-
Notifications
You must be signed in to change notification settings - Fork 155
Store primary variables in well state, and improve well initialization #6114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
2f1e445
2e81e67
e77484b
a828ce3
463dfcf
272fb20
1e6c89c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1603,10 +1603,11 @@ namespace Opm | |
| template <typename TypeTag> | ||
| void | ||
| WellInterface<TypeTag>:: | ||
| updateWellStateRates(const Simulator& simulator, | ||
| WellState<Scalar>& well_state, | ||
| DeferredLogger& deferred_logger) const | ||
| initializeProducerWellState(const Simulator& simulator, | ||
| WellState<Scalar>& well_state, | ||
| DeferredLogger& deferred_logger) const | ||
| { | ||
| assert(this->isProducer()); | ||
| OPM_TIMEFUNCTION(); | ||
| // Check if the rates of this well only are single-phase, do nothing | ||
| // if more than one nonzero rate. | ||
|
|
@@ -1624,29 +1625,65 @@ namespace Opm | |
| } | ||
| } | ||
|
|
||
| // Calculate the rates that follow from the current primary variables. | ||
| std::vector<Scalar> well_q_s = computeCurrentWellRates(simulator, deferred_logger); | ||
| // Calculate rates at bhp limit, or 1 bar if no limit. | ||
| std::vector<Scalar> well_q_s(this->number_of_phases_, 0.0); | ||
| bool rates_evaluated_at_1bar = false; | ||
| { | ||
| const auto& summary_state = simulator.vanguard().summaryState(); | ||
| const auto& prod_controls = this->well_ecl_.productionControls(summary_state); | ||
| const double bhp_limit = std::max(prod_controls.bhp_limit, 1.0 * unit::barsa); | ||
| this->computeWellRatesWithBhp(simulator, bhp_limit, well_q_s, deferred_logger); | ||
| // Remember of we evaluated the rates at (approx.) 1 bar or not. | ||
| rates_evaluated_at_1bar = (bhp_limit < 1.1 * unit::barsa); | ||
| // Check that no rates are positive. | ||
| if (std::any_of(well_q_s.begin(), well_q_s.end(), [](Scalar q) { return q > 0.0; })) { | ||
| // Did we evaluate at 1 bar? If not, then we can try again at 1 bar. | ||
| if (!rates_evaluated_at_1bar) { | ||
| this->computeWellRatesWithBhp(simulator, 1.0 * unit::barsa, well_q_s, deferred_logger); | ||
| rates_evaluated_at_1bar = true; | ||
| } | ||
| // At this point we can only set the wrong-direction (if any) values to zero. | ||
| for (auto& q : well_q_s) { | ||
| q = std::min(q, Scalar{0.0}); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (nonzero_rate_index == -1) { | ||
| // No nonzero rates. | ||
| // Use the computed rate directly | ||
| // No nonzero rates on input. | ||
| // Use the computed rate directly, or scaled by a factor | ||
| // 0.5 (to avoid too high values) if it was evaluated at 1 bar. | ||
| const Scalar factor = rates_evaluated_at_1bar ? 0.5 : 1.0; | ||
| for (int p = 0; p < this->number_of_phases_; ++p) { | ||
| ws.surface_rates[p] = well_q_s[this->flowPhaseToModelCompIdx(p)]; | ||
| ws.surface_rates[p] = factor * well_q_s[p]; | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| // Set the currently-zero phase flows to be nonzero in proportion to well_q_s. | ||
| // If we are here, we had a single nonzero rate for the well, | ||
| // typically from a rate constraint. We must make sure it is | ||
| // respected, so if it was lower than the calculated rate for | ||
| // the same phase we scale all rates to match. | ||
| const Scalar initial_nonzero_rate = ws.surface_rates[nonzero_rate_index]; | ||
| const int comp_idx_nz = this->flowPhaseToModelCompIdx(nonzero_rate_index); | ||
| if (std::abs(well_q_s[comp_idx_nz]) > floating_point_error_epsilon) { | ||
| const Scalar computed_rate = well_q_s[nonzero_rate_index]; | ||
| if (std::abs(initial_nonzero_rate) < std::abs(computed_rate)) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need to check
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If An example: we have a GRAT control set to a high number as an important constraint for the later parts of the simulation, but at the start of simulation the gas rate is low. Then we might scale the rate up to be much higher than the BHP-limit rate. |
||
| // Note that both rates below are negative. The factor should be < 1.0. | ||
| const Scalar factor = initial_nonzero_rate / computed_rate; | ||
| assert(factor < 1.0); | ||
| for (int p = 0; p < this->number_of_phases_; ++p) { | ||
| // We skip the nonzero_rate_index, as that should remain as it was. | ||
| if (p != nonzero_rate_index) { | ||
| const int comp_idx = this->flowPhaseToModelCompIdx(p); | ||
| Scalar& rate = ws.surface_rates[p]; | ||
| rate = (initial_nonzero_rate / well_q_s[comp_idx_nz]) * (well_q_s[comp_idx]); | ||
| ws.surface_rates[p] = factor * well_q_s[p]; | ||
| } | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| // If we are here, we had a single nonzero rate, but it was | ||
| // higher than the one calculated from the bhp limit, so we | ||
| // use the calculated rates. | ||
| for (int p = 0; p < this->number_of_phases_; ++p) { | ||
| ws.surface_rates[p] = well_q_s[p]; | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removing
&& !zero_targetcaused the regression for the case, it is part of the difficulties that difficult to describe the flow fractions for zero rate situation when we use only surface rates to initialize the primary variables. We should have fraction information, basically zero total rate and proper fraction for the phases.11_udt-1d-03

some bumps at the end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not saying the master branch is well designed, I believe the initialized rates play difference in the following logic with
nonzero_rate_original.It will open a well previously stopped due to not solvable or operable.