adding THP well control equation

This commit is contained in:
Kai Bao 2018-05-15 16:17:01 +02:00
parent b2bace449e
commit 18917b81f4
5 changed files with 41 additions and 38 deletions

View File

@ -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.;

View File

@ -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);
}

View File

@ -25,8 +25,6 @@
#include <numeric>
#include <cmath>
std::vector<double>
Opm::WellDensitySegmented::computeConnectionDensities(const Wells& wells,
const PhaseUsage& phase_usage,

View File

@ -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

View File

@ -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);