mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-22 15:33:29 -06:00
adding THP well control equation
This commit is contained in:
parent
b2bace449e
commit
18917b81f4
@ -170,10 +170,6 @@ namespace Opm
|
||||
comp_frac = comp_frac_[legacyCompIdx];
|
||||
}
|
||||
|
||||
// testing code
|
||||
if (comp_frac > 0.) {
|
||||
const double target_rate = well_controls_get_current_target(well_controls_);
|
||||
}
|
||||
// testing code end
|
||||
return comp_frac * primary_variables_evaluation_[GTotal];
|
||||
} else { // producers
|
||||
@ -623,10 +619,7 @@ namespace Opm
|
||||
// do the local inversion of D.
|
||||
// we do this manually with invertMatrix to always get our
|
||||
// specializations in for 3x3 and 4x4 matrices.
|
||||
// auto original = invDuneD_[0][0];
|
||||
// Dune::FMatrixHelp::invertMatrix(original, invDuneD_[0][0]);
|
||||
Dune::ISTLUtility::invertMatrix(invDuneD_[0][0]);
|
||||
// invDuneD_[0][0].invert();
|
||||
}
|
||||
|
||||
|
||||
@ -642,8 +635,18 @@ namespace Opm
|
||||
switch (well_controls_get_current_type(well_controls_)) {
|
||||
case THP:
|
||||
{
|
||||
OPM_THROW(std::runtime_error, "Not handling THP control for Multisegment wells for now");
|
||||
// TODO: it will be a function based on BHP <-> THP relation
|
||||
std::vector<EvalWell> rates(3, 0.);
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
|
||||
rates[ Water ] = getQs(flowPhaseToEbosCompIdx(Water));
|
||||
}
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
|
||||
rates[ Oil ] = getQs(flowPhaseToEbosCompIdx(Oil));
|
||||
}
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
|
||||
rates[ Gas ] = getQs(flowPhaseToEbosCompIdx(Gas));
|
||||
}
|
||||
const int current = well_controls_get_current(well_controls_);
|
||||
control_eq = getBhp() - calculateBhpFromThp(rates, current);
|
||||
break;
|
||||
}
|
||||
case BHP:
|
||||
@ -1054,14 +1057,13 @@ namespace Opm
|
||||
const WellControls* wc = well_controls_;
|
||||
// TODO: we should only maintain one current control either from the well_state or from well_controls struct.
|
||||
// Either one can be more favored depending on the final strategy for the initilzation of the well control
|
||||
const int current = well_state.currentControls()[index_of_well_];
|
||||
const int nwc = well_controls_get_num(wc);
|
||||
// Looping over all controls until we find a THP constraint
|
||||
for (int ctrl_index = 0; ctrl_index < nwc; ++ctrl_index) {
|
||||
if (well_controls_iget_type(wc, ctrl_index) == THP) {
|
||||
// the current control
|
||||
const int current = well_state.currentControls()[index_of_well_];
|
||||
// If under THP control at the moment
|
||||
// if well under THP control at the moment
|
||||
if (current == ctrl_index) {
|
||||
const double thp_target = well_controls_iget_target(wc, current);
|
||||
well_state.thp()[index_of_well_] = thp_target;
|
||||
@ -1083,8 +1085,8 @@ namespace Opm
|
||||
|
||||
well_state.thp()[index_of_well_] = calculateThpFromBhp(rates, ctrl_index, bhp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1476,9 +1478,9 @@ namespace Opm
|
||||
const double maxResidualAllowed = param_.max_residual_allowed_;
|
||||
|
||||
std::vector<double> res(numWellEq);
|
||||
for (int comp = 0; comp < numWellEq; ++comp) {
|
||||
for (int eq_idx = 0; eq_idx < numWellEq; ++eq_idx) {
|
||||
// magnitude of the residual matters
|
||||
res[comp] = std::abs(resWell_[0][comp]);
|
||||
res[eq_idx] = std::abs(resWell_[0][eq_idx]);
|
||||
}
|
||||
|
||||
std::vector<double> well_flux_residual(num_components_);
|
||||
@ -1521,7 +1523,7 @@ namespace Opm
|
||||
switch(well_controls_get_current_type(well_controls_)) {
|
||||
case THP:
|
||||
case BHP: // pressure type of control
|
||||
control_tolerance = 1.e4; // 0.1 bar
|
||||
control_tolerance = 1.e3; // 0.01 bar
|
||||
break;
|
||||
case RESERVOIR_RATE:
|
||||
case SURFACE_RATE:
|
||||
@ -1538,7 +1540,8 @@ namespace Opm
|
||||
const typename ConvergenceReport::ProblemWell problem_well = {name(), "control"};
|
||||
report.nan_residual_wells.push_back(problem_well);
|
||||
} else {
|
||||
if (well_control_residual > maxResidualAllowed) {
|
||||
// TODO: for pressure control equations, it can be pretty big during Newton iteration
|
||||
if (well_control_residual > maxResidualAllowed * 10.) {
|
||||
report.too_large_residual_found = true;
|
||||
const typename ConvergenceReport::ProblemWell problem_well = {name(), "control"};
|
||||
report.too_large_residual_wells.push_back(problem_well);
|
||||
@ -2042,6 +2045,7 @@ namespace Opm
|
||||
const double& alq = well_controls_iget_alq(well_controls_, control_index);
|
||||
|
||||
// pick the density in the top layer
|
||||
// TODO: it is possible it should be a Evaluation
|
||||
const double rho = perf_densities_[0];
|
||||
|
||||
ValueType bhp = 0.;
|
||||
|
@ -295,7 +295,6 @@ namespace Opm
|
||||
rho += superset(fluid_->surfaceDensity(phase , well_cells), Span(nperf, pu.num_phases, phase), nperf*pu.num_phases);
|
||||
}
|
||||
surf_dens_perf.assign(rho.data(), rho.data() + nperf * pu.num_phases);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,8 +25,6 @@
|
||||
#include <numeric>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
|
||||
std::vector<double>
|
||||
Opm::WellDensitySegmented::computeConnectionDensities(const Wells& wells,
|
||||
const PhaseUsage& phase_usage,
|
||||
|
@ -91,6 +91,17 @@ namespace Opm
|
||||
well_dissolved_gas_rates_.resize(nw, 0.0);
|
||||
well_vaporized_oil_rates_.resize(nw, 0.0);
|
||||
|
||||
is_new_well_.resize(nw, true);
|
||||
if ( !prevState.wellMap().empty() ) {
|
||||
const auto& end = prevState.wellMap().end();
|
||||
for (int w = 0; w < nw; ++w) {
|
||||
const auto& it = prevState.wellMap().find( wells->name[w]);
|
||||
if (it != end) {
|
||||
is_new_well_[w] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that we start out with zero rates by default.
|
||||
perfphaserates_.clear();
|
||||
perfphaserates_.resize(nperf * np, 0.0);
|
||||
@ -101,6 +112,14 @@ namespace Opm
|
||||
if (well_controls_well_is_stopped(ctrl)) {
|
||||
// Shut well: perfphaserates_ are all zero.
|
||||
} else {
|
||||
// increasing the gas rates so that there is a better guess of the gas rate, when the well is
|
||||
// a new well
|
||||
// TODO: a better way to make good use of the events in the Schedule from parser.
|
||||
if (pu.phase_used[Gas] && is_new_well_[w]) {
|
||||
const int gaspos = pu.phase_pos[Gas];
|
||||
wellRates()[np * w + gaspos] *= 100.;
|
||||
}
|
||||
|
||||
const int num_perf_this_well = wells->well_connpos[w + 1] - wells->well_connpos[w];
|
||||
// Open well: Initialize perfphaserates_ to well
|
||||
// rates divided by the number of perforations.
|
||||
@ -121,8 +140,6 @@ namespace Opm
|
||||
current_controls_[w] = well_controls_get_current(wells->ctrls[w]);
|
||||
}
|
||||
|
||||
is_new_well_.resize(nw, true);
|
||||
|
||||
perfRateSolvent_.clear();
|
||||
perfRateSolvent_.resize(nperf, 0.0);
|
||||
|
||||
@ -137,9 +154,6 @@ namespace Opm
|
||||
const_iterator it = prevState.wellMap().find( name );
|
||||
if( it != end )
|
||||
{
|
||||
// this is not a new added well
|
||||
is_new_well_[w] = false;
|
||||
|
||||
const int oldIndex = (*it).second[ 0 ];
|
||||
const int newIndex = w;
|
||||
|
||||
@ -402,18 +416,6 @@ namespace Opm
|
||||
const int start_perf = wells->well_connpos[w];
|
||||
const int start_perf_next_well = wells->well_connpos[w + 1];
|
||||
assert(nperf == (start_perf_next_well - start_perf)); // make sure the information from wells_ecl consistent with wells
|
||||
if (pu.phase_used[Gas]) {
|
||||
const int gaspos = pu.phase_pos[Gas];
|
||||
// scale the phase rates for Gas to avoid too bad initial guess for gas fraction
|
||||
// it will probably benefit the standard well too, while it needs to be justified
|
||||
// TODO: to see if this strategy can benefit StandardWell too
|
||||
// TODO: it might cause big problem for gas rate control or if there is a gas rate limit
|
||||
// maybe the best way is to initialize the fractions first then get the rates
|
||||
for (int perf = 0; perf < nperf; perf++) {
|
||||
const int perf_pos = start_perf + perf;
|
||||
perfPhaseRates()[np * perf_pos + gaspos] *= 100.;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<double> perforation_rates(perfPhaseRates().begin() + np * start_perf,
|
||||
perfPhaseRates().begin() + np * start_perf_next_well); // the perforation rates for this well
|
||||
|
@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE(TestBehavoir) {
|
||||
BOOST_CHECK_EQUAL(well->name(), "PROD1");
|
||||
BOOST_CHECK(well->wellType() == PRODUCER);
|
||||
BOOST_CHECK(well->numEq == 3);
|
||||
BOOST_CHECK(well->numWellEq == 3);
|
||||
BOOST_CHECK(well->numWellEq == 4);
|
||||
const auto& wc = well->wellControls();
|
||||
const int ctrl_num = well_controls_get_num(wc);
|
||||
BOOST_CHECK(ctrl_num > 0);
|
||||
@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(TestBehavoir) {
|
||||
BOOST_CHECK_EQUAL(well->name(), "INJE1");
|
||||
BOOST_CHECK(well->wellType() == INJECTOR);
|
||||
BOOST_CHECK(well->numEq == 3);
|
||||
BOOST_CHECK(well->numWellEq == 3);
|
||||
BOOST_CHECK(well->numWellEq == 4);
|
||||
const auto& wc = well->wellControls();
|
||||
const int ctrl_num = well_controls_get_num(wc);
|
||||
BOOST_CHECK(ctrl_num > 0);
|
||||
|
Loading…
Reference in New Issue
Block a user