22 #include <opm/autodiff/StandardWells.hpp>
23 #include <opm/autodiff/WellDensitySegmented.hpp>
25 #include <opm/autodiff/VFPInjProperties.hpp>
26 #include <opm/autodiff/VFPProdProperties.hpp>
27 #include <opm/autodiff/WellHelpers.hpp>
37 WellOps::WellOps(
const Wells* wells)
44 w2p = Eigen::SparseMatrix<double>(wells->well_connpos[ wells->number_of_wells ], wells->number_of_wells);
45 p2w = Eigen::SparseMatrix<double>(wells->number_of_wells, wells->well_connpos[ wells->number_of_wells ]);
47 const int nw = wells->number_of_wells;
48 const int*
const wpos = wells->well_connpos;
50 typedef Eigen::Triplet<double> Tri;
52 std::vector<Tri> scatter, gather;
53 scatter.reserve(wpos[nw]);
54 gather .reserve(wpos[nw]);
56 for (
int w = 0, i = 0; w < nw; ++w) {
57 for (; i < wpos[ w + 1 ]; ++i) {
58 scatter.push_back(Tri(i, w, 1.0));
59 gather .push_back(Tri(w, i, 1.0));
63 w2p.setFromTriplets(scatter.begin(), scatter.end());
64 p2w.setFromTriplets(gather .begin(), gather .end());
66 well_cells.assign(wells->well_cells, wells->well_cells + wells->well_connpos[wells->number_of_wells]);
74 StandardWells::StandardWells(
const Wells* wells_arg, WellCollection* well_collection)
75 : wells_active_(wells_arg!=nullptr)
78 , well_collection_(well_collection)
79 , well_perforation_efficiency_factors_(Vector::Ones(wells_!=nullptr ? wells_->well_connpos[wells_->number_of_wells] : 0))
82 , phase_condition_(nullptr)
83 , vfp_properties_(nullptr)
84 , well_perforation_densities_(Vector())
85 , well_perforation_pressure_diffs_(Vector())
86 , store_well_perforation_fluxes_(false)
95 StandardWells::init(
const BlackoilPropsAdFromDeck* fluid_arg,
96 const std::vector<bool>* active_arg,
97 const std::vector<PhasePresence>* pc_arg,
98 const VFPProperties* vfp_properties_arg,
99 const double gravity_arg,
100 const Vector& depth_arg)
103 active_ = active_arg;
104 phase_condition_ = pc_arg;
105 vfp_properties_ = vfp_properties_arg;
106 gravity_ = gravity_arg;
107 perf_cell_depth_ =
subset(depth_arg, wellOps().well_cells);;
109 calculateEfficiencyFactors();
116 const Wells& StandardWells::wells()
const
123 const Wells* StandardWells::wellsPointer()
const
132 return wells_active_;
139 void StandardWells::setWellsActive(
const bool wells_active)
141 wells_active_ = wells_active;
150 return wells_ ? (wells_->number_of_wells > 0 ) :
false;
158 StandardWells::numWellVars()
const
166 const int nw = wells().number_of_wells;
167 return (numPhases() + 1) * nw;
174 const StandardWells::WellOps&
175 StandardWells::wellOps()
const
186 return well_perforation_densities_;
193 const StandardWells::Vector&
196 return well_perforation_densities_;
203 StandardWells::Vector&
206 return well_perforation_pressure_diffs_;
213 const StandardWells::Vector&
216 return well_perforation_pressure_diffs_;
222 template<
class SolutionState,
class WellState>
225 computePropertiesForWellConnectionPressures(
const SolutionState& state,
227 std::vector<double>& b_perf,
228 std::vector<double>& rsmax_perf,
229 std::vector<double>& rvmax_perf,
230 std::vector<double>& surf_dens_perf)
232 const int nperf = wells().well_connpos[wells().number_of_wells];
233 const int nw = wells().number_of_wells;
236 const Vector perf_press = Eigen::Map<const Vector>(xw.perfPress().data(), nperf);
237 Vector avg_press = perf_press*0;
238 for (
int w = 0; w < nw; ++w) {
239 for (
int perf = wells().well_connpos[w]; perf < wells().well_connpos[w+1]; ++perf) {
240 const double p_above = perf == wells().well_connpos[w] ? state.bhp.value()[w] : perf_press[perf - 1];
241 const double p_avg = (perf_press[perf] + p_above)/2;
242 avg_press[perf] = p_avg;
246 const std::vector<int>& well_cells = wellOps().well_cells;
249 const ADB perf_temp =
subset(state.temperature, well_cells);
255 std::vector<PhasePresence> perf_cond(nperf);
257 for (
int perf = 0; perf < nperf; ++perf) {
258 perf_cond[perf] = (*phase_condition_)[well_cells[perf]];
261 DataBlock b(nperf, pu.num_phases);
262 if (pu.phase_used[BlackoilPhases::Aqua]) {
263 const Vector bw = fluid_->
bWat(avg_press_ad, perf_temp, well_cells).
value();
264 b.col(pu.phase_pos[BlackoilPhases::Aqua]) = bw;
266 assert((*active_)[Oil]);
267 const Vector perf_so =
subset(state.saturation[pu.phase_pos[Oil]].value(), well_cells);
268 if (pu.phase_used[BlackoilPhases::Liquid]) {
269 const ADB perf_rs = (state.rs.size() > 0) ?
subset(state.rs, well_cells) :
ADB::null();
270 const Vector bo = fluid_->
bOil(avg_press_ad, perf_temp, perf_rs, perf_cond, well_cells).
value();
271 b.col(pu.phase_pos[BlackoilPhases::Liquid]) = bo;
273 if (pu.phase_used[BlackoilPhases::Vapour]) {
274 const ADB perf_rv = (state.rv.size() > 0) ?
subset(state.rv, well_cells) :
ADB::null();
275 const Vector bg = fluid_->
bGas(avg_press_ad, perf_temp, perf_rv, perf_cond, well_cells).
value();
276 b.col(pu.phase_pos[BlackoilPhases::Vapour]) = bg;
278 if (pu.phase_used[BlackoilPhases::Liquid] && pu.phase_used[BlackoilPhases::Vapour]) {
280 rsmax_perf.assign(rssat.data(), rssat.data() + nperf);
283 rvmax_perf.assign(rvsat.data(), rvsat.data() + nperf);
287 b_perf.assign(b.data(), b.data() + nperf * pu.num_phases);
292 Vector rho =
superset(fluid_->
surfaceDensity(0 , well_cells), Span(nperf, pu.num_phases, 0), nperf*pu.num_phases);
293 for (
int phase = 1; phase < pu.num_phases; ++phase) {
294 rho +=
superset(fluid_->
surfaceDensity(phase , well_cells), Span(nperf, pu.num_phases, phase), nperf*pu.num_phases);
296 surf_dens_perf.assign(rho.data(), rho.data() + nperf * pu.num_phases);
304 template <
class WellState>
307 computeWellConnectionDensitesPressures(
const WellState& xw,
308 const std::vector<double>& b_perf,
309 const std::vector<double>& rsmax_perf,
310 const std::vector<double>& rvmax_perf,
311 const std::vector<double>& surf_dens_perf,
312 const std::vector<double>& depth_perf,
316 std::vector<double> cd =
318 wells(), fluid_->
phaseUsage(), xw.perfPhaseRates(),
319 b_perf, rsmax_perf, rvmax_perf, surf_dens_perf);
321 const int nperf = wells().well_connpos[wells().number_of_wells];
324 std::vector<double> cdp =
326 wells(), depth_perf, cd, grav);
329 well_perforation_densities_ = Eigen::Map<const Vector>(cd.data(), nperf);
330 well_perforation_pressure_diffs_ = Eigen::Map<const Vector>(cdp.data(), nperf);
337 template <
class SolutionState,
class WellState>
340 computeWellConnectionPressures(
const SolutionState& state,
347 std::vector<double> b_perf;
348 std::vector<double> rsmax_perf;
349 std::vector<double> rvmax_perf;
350 std::vector<double> surf_dens_perf;
351 computePropertiesForWellConnectionPressures(state, xw, b_perf, rsmax_perf, rvmax_perf, surf_dens_perf);
353 const Vector& pdepth = perf_cell_depth_;
354 const int nperf = wells().well_connpos[wells().number_of_wells];
355 const std::vector<double> depth_perf(pdepth.data(), pdepth.data() + nperf);
357 computeWellConnectionDensitesPressures(xw, b_perf, rsmax_perf, rvmax_perf, surf_dens_perf, depth_perf, gravity_);
365 template <
class ReservoirRes
idualQuant,
class SolutionState>
368 extractWellPerfProperties(
const SolutionState& ,
369 const std::vector<ReservoirResidualQuant>& rq,
370 std::vector<ADB>& mob_perfcells,
371 std::vector<ADB>& b_perfcells)
const
376 mob_perfcells.clear();
380 const std::vector<int>& well_cells = wellOps().well_cells;
381 const int num_phases = wells().number_of_phases;
382 mob_perfcells.resize(num_phases,
ADB::null());
383 b_perfcells.resize(num_phases,
ADB::null());
384 for (
int phase = 0; phase < num_phases; ++phase) {
385 mob_perfcells[phase] =
subset(rq[phase].mob, well_cells);
386 b_perfcells[phase] =
subset(rq[phase].b, well_cells);
396 template <
class SolutionState>
399 computeWellFlux(
const SolutionState& state,
400 const std::vector<ADB>& mob_perfcells,
401 const std::vector<ADB>& b_perfcells,
403 std::vector<ADB>& cq_s)
const
407 const int np = wells().number_of_phases;
408 const int nw = wells().number_of_wells;
409 const int nperf = wells().well_connpos[nw];
410 Vector Tw = Eigen::Map<const Vector>(wells().WI, nperf);
411 const std::vector<int>& well_cells = wellOps().well_cells;
416 const ADB& p_perfcells =
subset(state.pressure, well_cells);
419 const ADB perfpressure = (wellOps().w2p * state.bhp) + cdp;
422 const ADB drawdown = p_perfcells - perfpressure;
428 Vector selectInjectingPerforations = Vector::Zero(nperf);
430 Vector selectProducingPerforations = Vector::Zero(nperf);
431 for (
int c = 0; c < nperf; ++c){
432 if (drawdown.value()[c] < 0)
433 selectInjectingPerforations[c] = 1;
435 selectProducingPerforations[c] = 1;
439 const Vector numInjectingPerforations = (wellOps().p2w *
ADB::constant(selectInjectingPerforations)).value();
440 const Vector numProducingPerforations = (wellOps().p2w *
ADB::constant(selectProducingPerforations)).value();
441 for (
int w = 0; w < nw; ++w) {
442 if (!wells().allow_cf[w]) {
443 for (
int perf = wells().well_connpos[w] ; perf < wells().well_connpos[w+1]; ++perf) {
448 if (wells().type[w] == INJECTOR && numInjectingPerforations[w] > 0) {
449 selectProducingPerforations[perf] = 0.0;
450 }
else if (wells().type[w] == PRODUCER && numProducingPerforations[w] > 0 ){
451 selectInjectingPerforations[perf] = 0.0;
461 for (
int phase = 0; phase < np; ++phase) {
462 cq_p[phase] = -(selectProducingPerforations * Tw) * (mob_perfcells[phase] * drawdown);
463 cq_ps[phase] = b_perfcells[phase] * cq_p[phase];
465 const Opm::PhaseUsage& pu = fluid_->
phaseUsage();
466 if ((*active_)[Oil] && (*active_)[Gas]) {
467 const int oilpos = pu.phase_pos[Oil];
468 const int gaspos = pu.phase_pos[Gas];
469 const ADB cq_psOil = cq_ps[oilpos];
470 const ADB cq_psGas = cq_ps[gaspos];
471 const ADB& rv_perfcells =
subset(state.rv, well_cells);
472 const ADB& rs_perfcells =
subset(state.rs, well_cells);
473 cq_ps[gaspos] += rs_perfcells * cq_psOil;
474 cq_ps[oilpos] += rv_perfcells * cq_psGas;
479 ADB total_mob = mob_perfcells[0];
480 for (
int phase = 1; phase < np; ++phase) {
481 total_mob += mob_perfcells[phase];
484 const ADB cqt_i = -(selectInjectingPerforations * Tw) * (total_mob * drawdown);
487 if (store_well_perforation_fluxes_) {
489 Vector& wf =
const_cast<Vector&
>(well_perforation_fluxes_);
491 for (
int phase = 0; phase < np; ++phase) {
492 wf += cq_p[phase].value();
501 const DataBlock compi = Eigen::Map<const DataBlock>(wells().comp_frac, nw, np);
504 for (
int phase = 0; phase < np; ++phase) {
505 const ADB& q_ps = wellOps().p2w * cq_ps[phase];
506 const ADB& q_s =
subset(state.qs, Span(nw, 1, phase*nw));
507 Selector<double> injectingPhase_selector(q_s.value(), Selector<double>::GreaterZero);
508 const int pos = pu.phase_pos[phase];
509 wbq[phase] = (compi.col(pos) * injectingPhase_selector.select(q_s,
ADB::constant(Vector::Zero(nw)))) - q_ps;
513 Selector<double> notDeadWells_selector(wbqt.value(), Selector<double>::Zero);
514 std::vector<ADB> cmix_s(np,
ADB::null());
515 for (
int phase = 0; phase < np; ++phase) {
516 const int pos = pu.phase_pos[phase];
517 cmix_s[phase] = wellOps().w2p * notDeadWells_selector.select(
ADB::constant(compi.col(pos)), wbq[phase]/wbqt);
523 if ((*active_)[Water]) {
524 const int watpos = pu.phase_pos[Water];
525 volumeRatio += cmix_s[watpos] / b_perfcells[watpos];
528 if ((*active_)[Oil] && (*active_)[Gas]) {
530 const ADB& rv_perfcells =
subset(state.rv, well_cells);
531 const ADB& rs_perfcells =
subset(state.rs, well_cells);
532 const ADB d = Vector::Constant(nperf,1.0) - rv_perfcells * rs_perfcells;
534 const int oilpos = pu.phase_pos[Oil];
535 const int gaspos = pu.phase_pos[Gas];
537 const ADB tmp_oil = (cmix_s[oilpos] - rv_perfcells * cmix_s[gaspos]) / d;
538 volumeRatio += tmp_oil / b_perfcells[oilpos];
540 const ADB tmp_gas = (cmix_s[gaspos] - rs_perfcells * cmix_s[oilpos]) / d;
541 volumeRatio += tmp_gas / b_perfcells[gaspos];
544 if ((*active_)[Oil]) {
545 const int oilpos = pu.phase_pos[Oil];
546 volumeRatio += cmix_s[oilpos] / b_perfcells[oilpos];
548 if ((*active_)[Gas]) {
549 const int gaspos = pu.phase_pos[Gas];
550 volumeRatio += cmix_s[gaspos] / b_perfcells[gaspos];
556 ADB cqt_is = cqt_i/volumeRatio;
560 for (
int phase = 0; phase < np; ++phase) {
561 cq_s[phase] = cq_ps[phase] + cmix_s[phase]*cqt_is;
565 aliveWells = Vector::Constant(nw, 1.0);
566 for (
int w = 0; w < nw; ++w) {
567 if (wbqt.value()[w] == 0) {
577 template <
class SolutionState,
class WellState>
580 updatePerfPhaseRatesAndPressures(
const std::vector<ADB>& cq_s,
581 const SolutionState& state,
592 const int np = wells().number_of_phases;
593 const int nw = wells().number_of_wells;
594 const int nperf = wells().well_connpos[nw];
595 Vector cq =
superset(cq_s[0].value(), Span(nperf, np, 0), nperf*np);
596 for (
int phase = 1; phase < np; ++phase) {
597 cq +=
superset(cq_s[phase].value(), Span(nperf, np, phase), nperf*np);
599 xw.perfPhaseRates().assign(cq.data(), cq.data() + nperf*np);
603 const Vector perfpressure = (wellOps().w2p * state.bhp.value().matrix()).array() + cdp;
604 xw.perfPress().assign(perfpressure.data(), perfpressure.data() + nperf);
611 template <
class WellState>
614 updateWellState(
const Vector& dwells,
615 const double dpmaxrel,
616 WellState& well_state)
620 const int np = wells().number_of_phases;
621 const int nw = wells().number_of_wells;
625 const Vector dqs =
subset(dwells, Span(np*nw, 1, varstart));
626 varstart += dqs.size();
627 const Vector dbhp =
subset(dwells, Span(nw, 1, varstart));
628 varstart += dbhp.size();
629 assert(varstart == dwells.size());
636 const DataBlock wwr = Eigen::Map<const DataBlock>(dqs.data(), np, nw).transpose();
637 const Vector dwr = Eigen::Map<const Vector>(wwr.data(), nw*np);
638 const Vector wr_old = Eigen::Map<const Vector>(&well_state.wellRates()[0], nw*np);
639 const Vector wr = wr_old - dwr;
640 std::copy(&wr[0], &wr[0] + wr.size(), well_state.wellRates().begin());
643 const Vector bhp_old = Eigen::Map<const Vector>(&well_state.bhp()[0], nw, 1);
644 const Vector dbhp_limited =
sign(dbhp) * dbhp.abs().min(bhp_old.abs()*dpmaxrel);
645 const Vector bhp = bhp_old - dbhp_limited;
646 std::copy(&bhp[0], &bhp[0] + bhp.size(), well_state.bhp().begin());
649 const Opm::PhaseUsage& pu = fluid_->
phaseUsage();
651 #pragma omp parallel for schedule(static)
652 for (
int w = 0; w < nw; ++w) {
653 const WellControls* wc = wells().ctrls[w];
654 const int nwc = well_controls_get_num(wc);
658 for (
int ctrl_index=0; ctrl_index < nwc; ++ctrl_index) {
659 if (well_controls_iget_type(wc, ctrl_index) == THP) {
664 if ((*active_)[ Water ]) {
665 aqua = wr[w*np + pu.phase_pos[ Water ] ];
667 if ((*active_)[ Oil ]) {
668 liquid = wr[w*np + pu.phase_pos[ Oil ] ];
670 if ((*active_)[ Gas ]) {
671 vapour = wr[w*np + pu.phase_pos[ Gas ] ];
674 double alq = well_controls_iget_alq(wc, ctrl_index);
675 int table_id = well_controls_iget_vfp(wc, ctrl_index);
677 const WellType& well_type = wells().type[w];
678 const int perf = wells().well_connpos[w];
679 if (well_type == INJECTOR) {
680 double dp = wellhelpers::computeHydrostaticCorrection(
681 wells(), w, vfp_properties_->
getInj()->
getTable(table_id)->getDatumDepth(),
684 well_state.thp()[w] = vfp_properties_->
getInj()->
thp(table_id, aqua, liquid, vapour, bhp[w] + dp);
686 else if (well_type == PRODUCER) {
687 double dp = wellhelpers::computeHydrostaticCorrection(
688 wells(), w, vfp_properties_->
getProd()->
getTable(table_id)->getDatumDepth(),
691 well_state.thp()[w] = vfp_properties_->
getProd()->
thp(table_id, aqua, liquid, vapour, bhp[w] + dp, alq);
694 OPM_THROW(std::logic_error,
"Expected INJECTOR or PRODUCER well");
709 template <
class WellState>
712 updateWellControls(WellState& xw)
const
714 wellhelpers::WellSwitchingLogger logger;
720 const int np = wells().number_of_phases;
721 const int nw = wells().number_of_wells;
722 #pragma omp parallel for schedule(dynamic)
723 for (
int w = 0; w < nw; ++w) {
724 const WellControls* wc = wells().ctrls[w];
728 int current = xw.currentControls()[w];
733 const int nwc = well_controls_get_num(wc);
738 bool constraint_violated =
false;
739 int number_iterations = 0;
740 const int max_iterations = 2 * nwc;
742 updateWellStateWithTarget(wc, current, w, xw);
744 for (; ctrl_index < nwc; ++ctrl_index) {
745 if (ctrl_index == current) {
751 if (wellhelpers::constraintBroken(
752 xw.bhp(), xw.thp(), xw.wellRates(),
753 w, np, wells().type[w], wc, ctrl_index)) {
760 if (ctrl_index != nwc) {
764 logger.wellSwitched(wells().name[w],
765 well_controls_iget_type(wc, current),
766 well_controls_iget_type(wc, ctrl_index));
768 xw.currentControls()[w] = ctrl_index;
769 current = xw.currentControls()[w];
770 constraint_violated =
true;
772 constraint_violated =
false;
776 if (number_iterations > max_iterations) {
777 OPM_THROW(Opm::NumericalProblem,
"Could not find proper control within " << number_iterations <<
" iterations!");
780 }
while (constraint_violated);
783 if (wellCollection()->groupControlActive()) {
786 WellNode& well_node = well_collection_->findWellNode(std::string(wells().name[w]));
789 if (well_node.groupControlIndex() >= 0 && current == well_node.groupControlIndex()) {
791 well_node.setIndividualControl(
false);
794 well_node.setIndividualControl(
true);
805 template <
class SolutionState>
808 addWellFluxEq(
const std::vector<ADB>& cq_s,
809 const SolutionState& state,
810 LinearisedBlackoilResidual& residual)
819 const int np = wells().number_of_phases;
820 const int nw = wells().number_of_wells;
822 for (
int phase = 0; phase < np; ++phase) {
823 qs -=
superset(wellOps().p2w * cq_s[phase], Span(nw, 1, phase*nw), nw*np);
827 residual.well_flux_eq = qs;
834 template <
class SolutionState,
class WellState>
836 StandardWells::addWellControlEq(
const SolutionState& state,
838 const Vector& aliveWells,
839 LinearisedBlackoilResidual& residual)
843 const int np = wells().number_of_phases;
844 const int nw = wells().number_of_wells;
850 if ((*active_)[Water]) {
851 aqua +=
subset(state.qs, Span(nw, 1, BlackoilPhases::Aqua*nw));
853 if ((*active_)[Oil]) {
854 liquid +=
subset(state.qs, Span(nw, 1, BlackoilPhases::Liquid*nw));
856 if ((*active_)[Gas]) {
857 vapour +=
subset(state.qs, Span(nw, 1, BlackoilPhases::Vapour*nw));
861 std::vector<int> inj_table_id(nw, -1);
862 std::vector<int> prod_table_id(nw, -1);
863 Vector thp_inj_target_v = Vector::Zero(nw);
864 Vector thp_prod_target_v = Vector::Zero(nw);
865 Vector alq_v = Vector::Zero(nw);
868 Vector rho_v = Vector::Zero(nw);
869 Vector vfp_ref_depth_v = Vector::Zero(nw);
872 Vector bhp_targets = Vector::Zero(nw);
873 Vector rate_targets = Vector::Zero(nw);
874 Eigen::SparseMatrix<double> rate_distr(nw, np*nw);
877 std::vector<int> bhp_elems;
878 std::vector<int> thp_inj_elems;
879 std::vector<int> thp_prod_elems;
880 std::vector<int> rate_elems;
884 for (
int w = 0; w < nw; ++w) {
885 auto wc = wells().ctrls[w];
890 const int current = xw.currentControls()[w];
892 switch (well_controls_iget_type(wc, current)) {
895 bhp_elems.push_back(w);
896 bhp_targets(w) = well_controls_iget_target(wc, current);
897 rate_targets(w) = -1e100;
903 const int perf = wells().well_connpos[w];
906 const int table_id = well_controls_iget_vfp(wc, current);
907 const double target = well_controls_iget_target(wc, current);
909 const WellType& well_type = wells().type[w];
910 if (well_type == INJECTOR) {
911 inj_table_id[w] = table_id;
912 thp_inj_target_v[w] = target;
915 vfp_ref_depth_v[w] = vfp_properties_->
getInj()->
getTable(table_id)->getDatumDepth();
917 thp_inj_elems.push_back(w);
919 else if (well_type == PRODUCER) {
920 prod_table_id[w] = table_id;
921 thp_prod_target_v[w] = target;
922 alq_v[w] = well_controls_iget_alq(wc, current);
924 vfp_ref_depth_v[w] = vfp_properties_->
getProd()->
getTable(table_id)->getDatumDepth();
926 thp_prod_elems.push_back(w);
929 OPM_THROW(std::logic_error,
"Expected INJECTOR or PRODUCER type well");
931 bhp_targets(w) = -1e100;
932 rate_targets(w) = -1e100;
939 rate_elems.push_back(w);
944 const double*
const distr =
945 well_controls_iget_distr(wc, current);
947 for (
int p = 0; p < np; ++p) {
948 rate_distr.insert(w, p*nw + w) = distr[p];
951 bhp_targets(w) = -1.0e100;
952 rate_targets(w) = well_controls_iget_target(wc, current);
960 const ADB thp_prod_target =
ADB::constant(thp_prod_target_v);
962 const ADB bhp_from_thp_inj = vfp_properties_->
getInj()->
bhp(inj_table_id, aqua, liquid, vapour, thp_inj_target);
963 const ADB bhp_from_thp_prod = vfp_properties_->
getProd()->
bhp(prod_table_id, aqua, liquid, vapour, thp_prod_target, alq);
966 const Vector dp_v = wellhelpers::computeHydrostaticCorrection(wells(), vfp_ref_depth_v,
wellPerforationDensities(), gravity_);
968 const ADB dp_inj =
superset(
subset(dp, thp_inj_elems), thp_inj_elems, nw);
969 const ADB dp_prod =
superset(
subset(dp, thp_prod_elems), thp_prod_elems, nw);
972 const ADB thp_inj_residual = state.bhp - bhp_from_thp_inj + dp_inj;
973 const ADB thp_prod_residual = state.bhp - bhp_from_thp_prod + dp_prod;
974 const ADB bhp_residual = state.bhp - bhp_targets;
975 const ADB rate_residual = rate_distr * state.qs - rate_targets;
978 residual.well_eq =
superset(
subset(bhp_residual, bhp_elems), bhp_elems, nw) +
979 superset(
subset(thp_inj_residual, thp_inj_elems), thp_inj_elems, nw) +
980 superset(
subset(thp_prod_residual, thp_prod_elems), thp_prod_elems, nw) +
986 Eigen::SparseMatrix<double> rate_summer(nw, np*nw);
987 for (
int w = 0; w < nw; ++w) {
988 for (
int phase = 0; phase < np; ++phase) {
989 rate_summer.insert(w, phase*nw + w) = 1.0;
992 Selector<double> alive_selector(aliveWells, Selector<double>::NotEqualZero);
993 residual.well_eq = alive_selector.select(residual.well_eq, rate_summer * state.qs);
1001 template <
class SolutionState,
class WellState>
1003 StandardWells::computeWellPotentials(
const std::vector<ADB>& mob_perfcells,
1004 const std::vector<ADB>& b_perfcells,
1005 const WellState& well_state,
1006 SolutionState& state0,
1007 std::vector<double>& well_potentials)
const
1009 const int nw = wells().number_of_wells;
1010 const int np = wells().number_of_phases;
1011 const Opm::PhaseUsage& pu = fluid_->
phaseUsage();
1013 Vector bhps = Vector::Zero(nw);
1014 for (
int w = 0; w < nw; ++w) {
1015 const WellControls* ctrl = wells().ctrls[w];
1016 const int nwc = well_controls_get_num(ctrl);
1020 for (
int ctrl_index=0; ctrl_index < nwc; ++ctrl_index) {
1022 if (well_controls_iget_type(ctrl, ctrl_index) == BHP) {
1023 bhps[w] = well_controls_iget_target(ctrl, ctrl_index);
1026 if (well_controls_iget_type(ctrl, ctrl_index) == THP) {
1028 double liquid = 0.0;
1029 double vapour = 0.0;
1031 if ((*active_)[ Water ]) {
1032 aqua = well_state.wellRates()[w*np + pu.phase_pos[ Water ] ];
1034 if ((*active_)[ Oil ]) {
1035 liquid = well_state.wellRates()[w*np + pu.phase_pos[ Oil ] ];
1037 if ((*active_)[ Gas ]) {
1038 vapour = well_state.wellRates()[w*np + pu.phase_pos[ Gas ] ];
1041 const int vfp = well_controls_iget_vfp(ctrl, ctrl_index);
1042 const double& thp = well_controls_iget_target(ctrl, ctrl_index);
1043 const double& alq = well_controls_iget_alq(ctrl, ctrl_index);
1046 const WellType& well_type = wells().type[w];
1047 const int perf = wells().well_connpos[w];
1049 if (well_type == INJECTOR) {
1050 double dp = wellhelpers::computeHydrostaticCorrection(
1051 wells(), w, vfp_properties_->
getInj()->
getTable(vfp)->getDatumDepth(),
1053 const double bhp = vfp_properties_->
getInj()->
bhp(vfp, aqua, liquid, vapour, thp) - dp;
1055 if ( bhp < bhps[w]) {
1059 else if (well_type == PRODUCER) {
1060 double dp = wellhelpers::computeHydrostaticCorrection(
1061 wells(), w, vfp_properties_->
getProd()->
getTable(vfp)->getDatumDepth(),
1064 const double bhp = vfp_properties_->
getProd()->
bhp(vfp, aqua, liquid, vapour, thp, alq) - dp;
1066 if ( bhp > bhps[w]) {
1071 OPM_THROW(std::logic_error,
"Expected PRODUCER or INJECTOR type of well");
1083 std::vector<ADB> perf_potentials;
1084 computeWellFlux(state0, mob_perfcells, b_perfcells, aliveWells, perf_potentials);
1086 well_potentials.resize(nw * np, 0.0);
1088 for (
int p = 0; p < np; ++p) {
1089 for (
int w = 0; w < nw; ++w) {
1090 for (
int perf = wells().well_connpos[w]; perf < wells().well_connpos[w + 1]; ++perf) {
1091 well_potentials[w * np + p] += perf_potentials[p].value()[perf];
1102 StandardWells::variableStateWellIndices(std::vector<int>& indices,
1105 indices[Qs] = next++;
1106 indices[Bhp] = next++;
1113 template <
class SolutionState>
1116 variableStateExtractWellsVars(
const std::vector<int>& indices,
1117 std::vector<ADB>& vars,
1118 SolutionState& state)
const
1121 state.qs = std::move(vars[indices[Qs]]);
1124 state.bhp = std::move(vars[indices[Bhp]]);
1132 StandardWells::variableWellStateIndices()
const
1136 std::vector<int> indices(5, -1);
1139 variableStateWellIndices(indices, next);
1149 template <
class WellState>
1151 StandardWells::variableWellStateInitials(
const WellState& xw,
1152 std::vector<Vector>& vars0)
const
1159 const int nw = wells().number_of_wells;
1160 const int np = wells().number_of_phases;
1163 const DataBlock wrates = Eigen::Map<const DataBlock>(& xw.wellRates()[0], nw, np).transpose();
1164 const Vector qs = Eigen::Map<const V>(wrates.data(), nw*np);
1165 vars0.push_back(qs);
1168 assert (not xw.bhp().empty());
1169 const Vector bhp = Eigen::Map<const V>(& xw.bhp()[0], xw.bhp().size());
1170 vars0.push_back(bhp);
1175 vars0.push_back(V());
1176 vars0.push_back(V());
1187 store_well_perforation_fluxes_ = store_fluxes;
1194 const StandardWells::Vector&
1197 assert(store_well_perforation_fluxes_);
1198 return well_perforation_fluxes_;
1206 template<
class WellState>
1210 const int current_step,
1211 const Wells* wells_struct,
1212 const WellState& well_state,
1213 DynamicListEconLimited& list_econ_limited)
const
1216 const int nw = ( wells_struct ) ? wells_struct->number_of_wells : 0;
1218 for (
int w = 0; w < nw; ++w) {
1220 bool rate_limit_violated =
false;
1221 const std::string& well_name = wells_struct->name[w];
1222 const Well* well_ecl = schedule.getWell(well_name);
1223 const WellEconProductionLimits& econ_production_limits = well_ecl->getEconProductionLimits(current_step);
1226 if (wells_struct->type[w] != PRODUCER) {
1231 if ( !econ_production_limits.onAnyEffectiveLimit() ) {
1236 const WellEcon::QuantityLimitEnum& quantity_limit = econ_production_limits.quantityLimit();
1237 if (quantity_limit == WellEcon::POTN) {
1238 const std::string msg = std::string(
"POTN limit for well ") + well_name + std::string(
" is not supported for the moment. \n")
1239 + std::string(
"All the limits will be evaluated based on RATE. ");
1240 OpmLog::warning(
"NOT_SUPPORTING_POTN", msg);
1243 const WellMapType& well_map = well_state.wellMap();
1244 const typename WellMapType::const_iterator i_well = well_map.find(well_name);
1245 assert(i_well != well_map.end());
1246 const WellMapEntryType& map_entry = i_well->second;
1247 const int well_number = map_entry[0];
1249 if (econ_production_limits.onAnyRateLimit()) {
1250 rate_limit_violated = checkRateEconLimits(econ_production_limits, well_state, well_number);
1253 if (rate_limit_violated) {
1254 if (econ_production_limits.endRun()) {
1255 const std::string warning_message = std::string(
"ending run after well closed due to economic limits is not supported yet \n")
1256 + std::string(
"the program will keep running after ") + well_name + std::string(
" is closed");
1257 OpmLog::warning(
"NOT_SUPPORTING_ENDRUN", warning_message);
1260 if (econ_production_limits.validFollowonWell()) {
1261 OpmLog::warning(
"NOT_SUPPORTING_FOLLOWONWELL",
"opening following on well after well closed is not supported yet");
1264 if (well_ecl->getAutomaticShutIn()) {
1265 list_econ_limited.addShutWell(well_name);
1266 const std::string msg = std::string(
"well ") + well_name + std::string(
" will be shut in due to economic limit");
1269 list_econ_limited.addStoppedWell(well_name);
1270 const std::string msg = std::string(
"well ") + well_name + std::string(
" will be stopped due to economic limit");
1278 bool ratio_limits_violated =
false;
1279 RatioCheckTuple ratio_check_return;
1281 if (econ_production_limits.onAnyRatioLimit()) {
1282 ratio_check_return = checkRatioEconLimits(econ_production_limits, well_state, map_entry);
1283 ratio_limits_violated = std::get<0>(ratio_check_return);
1286 if (ratio_limits_violated) {
1287 const bool last_connection = std::get<1>(ratio_check_return);
1288 const int worst_offending_connection = std::get<2>(ratio_check_return);
1290 const int perf_start = map_entry[1];
1292 assert((worst_offending_connection >= 0) && (worst_offending_connection < map_entry[2]));
1294 const int cell_worst_offending_connection = wells_struct->well_cells[perf_start + worst_offending_connection];
1295 list_econ_limited.addClosedConnectionsForWell(well_name, cell_worst_offending_connection);
1296 const std::string msg = std::string(
"Connection ") + std::to_string(worst_offending_connection) + std::string(
" for well ")
1297 + well_name + std::string(
" will be closed due to economic limit");
1300 if (last_connection) {
1301 list_econ_limited.addShutWell(well_name);
1302 const std::string msg2 = well_name + std::string(
" will be shut due to the last connection closed");
1314 template <
class WellState>
1317 checkRateEconLimits(
const WellEconProductionLimits& econ_production_limits,
1318 const WellState& well_state,
1319 const int well_number)
const
1321 const Opm::PhaseUsage& pu = fluid_->
phaseUsage();
1322 const int np = well_state.numPhases();
1324 if (econ_production_limits.onMinOilRate()) {
1325 assert((*active_)[Oil]);
1326 const double oil_rate = well_state.wellRates()[well_number * np + pu.phase_pos[ Oil ] ];
1327 const double min_oil_rate = econ_production_limits.minOilRate();
1328 if (std::abs(oil_rate) < min_oil_rate) {
1333 if (econ_production_limits.onMinGasRate() ) {
1334 assert((*active_)[Gas]);
1335 const double gas_rate = well_state.wellRates()[well_number * np + pu.phase_pos[ Gas ] ];
1336 const double min_gas_rate = econ_production_limits.minGasRate();
1337 if (std::abs(gas_rate) < min_gas_rate) {
1342 if (econ_production_limits.onMinLiquidRate() ) {
1343 assert((*active_)[Oil]);
1344 assert((*active_)[Water]);
1345 const double oil_rate = well_state.wellRates()[well_number * np + pu.phase_pos[ Oil ] ];
1346 const double water_rate = well_state.wellRates()[well_number * np + pu.phase_pos[ Water ] ];
1347 const double liquid_rate = oil_rate + water_rate;
1348 const double min_liquid_rate = econ_production_limits.minLiquidRate();
1349 if (std::abs(liquid_rate) < min_liquid_rate) {
1354 if (econ_production_limits.onMinReservoirFluidRate()) {
1355 OpmLog::warning(
"NOT_SUPPORTING_MIN_RESERVOIR_FLUID_RATE",
"Minimum reservoir fluid production rate limit is not supported yet");
1365 template <
class WellState>
1366 StandardWells::RatioCheckTuple
1368 checkRatioEconLimits(
const WellEconProductionLimits& econ_production_limits,
1369 const WellState& well_state,
1370 const WellMapEntryType& map_entry)
const
1380 bool any_limit_violated =
false;
1381 bool last_connection =
false;
1382 int worst_offending_connection = INVALIDCONNECTION;
1383 double violation_extent = -1.0;
1385 if (econ_production_limits.onMaxWaterCut()) {
1386 const RatioCheckTuple water_cut_return = checkMaxWaterCutLimit(econ_production_limits, well_state, map_entry);
1387 bool water_cut_violated = std::get<0>(water_cut_return);
1388 if (water_cut_violated) {
1389 any_limit_violated =
true;
1390 const double violation_extent_water_cut = std::get<3>(water_cut_return);
1391 if (violation_extent_water_cut > violation_extent) {
1392 violation_extent = violation_extent_water_cut;
1393 worst_offending_connection = std::get<2>(water_cut_return);
1394 last_connection = std::get<1>(water_cut_return);
1399 if (econ_production_limits.onMaxGasOilRatio()) {
1400 OpmLog::warning(
"NOT_SUPPORTING_MAX_GOR",
"the support for max Gas-Oil ratio is not implemented yet!");
1403 if (econ_production_limits.onMaxWaterGasRatio()) {
1404 OpmLog::warning(
"NOT_SUPPORTING_MAX_WGR",
"the support for max Water-Gas ratio is not implemented yet!");
1407 if (econ_production_limits.onMaxGasLiquidRatio()) {
1408 OpmLog::warning(
"NOT_SUPPORTING_MAX_GLR",
"the support for max Gas-Liquid ratio is not implemented yet!");
1411 if (any_limit_violated) {
1412 assert(worst_offending_connection >=0);
1413 assert(violation_extent > 1.);
1416 return std::make_tuple(any_limit_violated, last_connection, worst_offending_connection, violation_extent);
1423 template <
class WellState>
1424 StandardWells::RatioCheckTuple
1426 checkMaxWaterCutLimit(
const WellEconProductionLimits& econ_production_limits,
1427 const WellState& well_state,
1428 const WellMapEntryType& map_entry)
const
1430 bool water_cut_limit_violated =
false;
1431 int worst_offending_connection = INVALIDCONNECTION;
1432 bool last_connection =
false;
1433 double violation_extent = -1.0;
1435 const int np = well_state.numPhases();
1436 const Opm::PhaseUsage& pu = fluid_->
phaseUsage();
1437 const int well_number = map_entry[0];
1439 assert((*active_)[Oil]);
1440 assert((*active_)[Water]);
1442 const double oil_rate = well_state.wellRates()[well_number * np + pu.phase_pos[ Oil ] ];
1443 const double water_rate = well_state.wellRates()[well_number * np + pu.phase_pos[ Water ] ];
1444 const double liquid_rate = oil_rate + water_rate;
1446 if (std::abs(liquid_rate) != 0.) {
1447 water_cut = water_rate / liquid_rate;
1452 const double max_water_cut_limit = econ_production_limits.maxWaterCut();
1453 if (water_cut > max_water_cut_limit) {
1454 water_cut_limit_violated =
true;
1457 if (water_cut_limit_violated) {
1459 const int perf_start = map_entry[1];
1460 const int perf_number = map_entry[2];
1462 std::vector<double> water_cut_perf(perf_number);
1463 for (
int perf = 0; perf < perf_number; ++perf) {
1464 const int i_perf = perf_start + perf;
1465 const double oil_perf_rate = well_state.perfPhaseRates()[i_perf * np + pu.phase_pos[ Oil ] ];
1466 const double water_perf_rate = well_state.perfPhaseRates()[i_perf * np + pu.phase_pos[ Water ] ];
1467 const double liquid_perf_rate = oil_perf_rate + water_perf_rate;
1468 if (std::abs(liquid_perf_rate) != 0.) {
1469 water_cut_perf[perf] = water_perf_rate / liquid_perf_rate;
1471 water_cut_perf[perf] = 0.;
1475 last_connection = (perf_number == 1);
1476 if (last_connection) {
1477 worst_offending_connection = 0;
1478 violation_extent = water_cut_perf[0] / max_water_cut_limit;
1479 return std::make_tuple(water_cut_limit_violated, last_connection, worst_offending_connection, violation_extent);
1482 double max_water_cut_perf = 0.;
1483 for (
int perf = 0; perf < perf_number; ++perf) {
1484 if (water_cut_perf[perf] > max_water_cut_perf) {
1485 worst_offending_connection = perf;
1486 max_water_cut_perf = water_cut_perf[perf];
1490 assert(max_water_cut_perf != 0.);
1491 assert((worst_offending_connection >= 0) && (worst_offending_connection < perf_number));
1493 violation_extent = max_water_cut_perf / max_water_cut_limit;
1496 return std::make_tuple(water_cut_limit_violated, last_connection, worst_offending_connection, violation_extent);
1503 WellCollection* StandardWells::wellCollection()
const
1505 return well_collection_;
1512 void StandardWells::calculateEfficiencyFactors()
1518 const int nw = wells_->number_of_wells;
1520 Vector well_efficiency_factors = Vector::Ones(nw);
1522 for (
int w = 0; w < nw; ++w) {
1523 const std::string well_name = wells_->name[w];
1524 const WellNode& well_node = well_collection_->findWellNode(well_name);
1526 well_efficiency_factors(w) = well_node.getAccumulativeEfficiencyFactor();
1530 well_perforation_efficiency_factors_ = wellOps().w2p * well_efficiency_factors.matrix();
1537 const StandardWells::Vector&
1538 StandardWells::wellPerfEfficiencyFactors()
const
1540 return well_perforation_efficiency_factors_;
1547 template <
class WellState>
1550 updateWellStateWithTarget(
const WellControls* wc,
1552 const int well_index,
1553 WellState& xw)
const
1555 const int np = wells().number_of_phases;
1559 const double target = well_controls_iget_target(wc, current);
1560 const double* distr = well_controls_iget_distr(wc, current);
1561 switch (well_controls_iget_type(wc, current)) {
1563 xw.bhp()[well_index] = target;
1567 double liquid = 0.0;
1568 double vapour = 0.0;
1570 const Opm::PhaseUsage& pu = fluid_->
phaseUsage();
1572 if ((*active_)[ Water ]) {
1573 aqua = xw.wellRates()[well_index*np + pu.phase_pos[ Water ] ];
1575 if ((*active_)[ Oil ]) {
1576 liquid = xw.wellRates()[well_index*np + pu.phase_pos[ Oil ] ];
1578 if ((*active_)[ Gas ]) {
1579 vapour = xw.wellRates()[well_index*np + pu.phase_pos[ Gas ] ];
1582 const int vfp = well_controls_iget_vfp(wc, current);
1583 const double& thp = well_controls_iget_target(wc, current);
1584 const double& alq = well_controls_iget_alq(wc, current);
1587 const WellType& well_type = wells().type[well_index];
1589 const int perf = wells().well_connpos[well_index];
1590 const double rho = well_perforation_densities_[perf];
1592 if (well_type == INJECTOR) {
1593 double dp = wellhelpers::computeHydrostaticCorrection(
1594 wells(), well_index, vfp_properties_->
getInj()->
getTable(vfp)->getDatumDepth(),
1597 xw.bhp()[well_index] = vfp_properties_->
getInj()->
bhp(vfp, aqua, liquid, vapour, thp) - dp;
1599 else if (well_type == PRODUCER) {
1600 double dp = wellhelpers::computeHydrostaticCorrection(
1601 wells(), well_index, vfp_properties_->
getProd()->
getTable(vfp)->getDatumDepth(),
1604 xw.bhp()[well_index] = vfp_properties_->
getProd()->
bhp(vfp, aqua, liquid, vapour, thp, alq) - dp;
1607 OPM_THROW(std::logic_error,
"Expected PRODUCER or INJECTOR type of well");
1612 case RESERVOIR_RATE:
1622 const WellType& well_type = wells().type[well_index];
1623 if (well_type == INJECTOR) {
1624 for (
int phase = 0; phase < np; ++phase) {
1625 const double& compi = wells().comp_frac[np * well_index + phase];
1627 xw.wellRates()[np * well_index + phase] = target * compi;
1630 }
else if (well_type == PRODUCER) {
1635 int numPhasesWithTargetsUnderThisControl = 0;
1636 for (
int phase = 0; phase < np; ++phase) {
1637 if (distr[phase] > 0.0) {
1638 numPhasesWithTargetsUnderThisControl += 1;
1641 for (
int phase = 0; phase < np; ++phase) {
1642 if (distr[phase] > 0.0 && numPhasesWithTargetsUnderThisControl < 2 ) {
1643 xw.wellRates()[np * well_index + phase] = target * distr[phase];
1647 OPM_THROW(std::logic_error,
"Expected PRODUCER or INJECTOR type of well");
ADB bWat(const ADB &pw, const ADB &T, const Cells &cells) const
Water formation volume factor.
Definition: BlackoilPropsAdFromDeck.cpp:446
static AutoDiffBlock null()
Construct an empty AutoDiffBlock.
Definition: AutoDiffBlock.hpp:104
const V & value() const
Function value.
Definition: AutoDiffBlock.hpp:438
V rsSat(const V &po, const Cells &cells) const
Bubble point curve for Rs as function of oil pressure.
Vector & wellPerforationDensities()
Density of each well perforation.
Definition: StandardWells_impl.hpp:184
ADB bhp(const std::vector< int > &table_id, const Wells &wells, const ADB &qs, const ADB &thp) const
Linear interpolation of bhp as function of the input parameters.
Definition: VFPInjProperties.cpp:71
ADB rvSat(const ADB &po, const Cells &cells) const
Condensation curve for Rv as function of oil pressure.
Definition: BlackoilPropsAdFromDeck.cpp:688
double thp(int table_id, const double &aqua, const double &liquid, const double &vapour, const double &bhp, const double &alq) const
Linear interpolation of thp as a function of the input parameters.
Definition: VFPProdProperties.cpp:192
bool localWellsActive() const
return true if wells are available on this process
Definition: StandardWells_impl.hpp:148
bool wellsActive() const
return true if wells are available in the reservoir
Definition: StandardWells_impl.hpp:130
const VFPInjTable * getTable(const int table_id) const
Returns the table associated with the ID, or throws an exception if the table does not exist...
Definition: VFPInjProperties.cpp:218
Vector & wellPerforationPressureDiffs()
Diff to bhp for each well perforation.
Definition: StandardWells_impl.hpp:204
void setStoreWellPerforationFluxesFlag(const bool store_fluxes)
If set, computeWellFlux() will additionally store the total reservoir volume perforation fluxes...
Definition: StandardWells_impl.hpp:1185
double thp(int table_id, const double &aqua, const double &liquid, const double &vapour, const double &bhp) const
Linear interpolation of thp as a function of the input parameters.
Definition: VFPInjProperties.cpp:183
ADB bOil(const ADB &po, const ADB &T, const ADB &rs, const std::vector< PhasePresence > &cond, const Cells &cells) const
Oil formation volume factor.
Definition: BlackoilPropsAdFromDeck.cpp:493
const VFPInjProperties * getInj() const
Returns the VFP properties for injection wells.
Definition: VFPProperties.hpp:61
const VFPProdTable * getTable(const int table_id) const
Returns the table associated with the ID, or throws an exception if the table does not exist...
Definition: VFPProdProperties.cpp:234
ADB bGas(const ADB &pg, const ADB &T, const ADB &rv, const std::vector< PhasePresence > &cond, const Cells &cells) const
Gas formation volume factor.
Definition: BlackoilPropsAdFromDeck.cpp:566
AutoDiffBlock< Scalar > superset(const AutoDiffBlock< Scalar > &x, const IntVec &indices, const int n)
Returns v where v(indices) == x, v(!indices) == 0 and v.size() == n.
Definition: AutoDiffHelpers.hpp:319
V surfaceDensity(const int phaseIdx, const Cells &cells) const
Densities of stock components at surface conditions.
Definition: BlackoilPropsAdFromDeck.cpp:242
static AutoDiffBlock constant(V &&val)
Create an AutoDiffBlock representing a constant.
Definition: AutoDiffBlock.hpp:111
Eigen::Array< Scalar, Eigen::Dynamic, 1 > subset(const Eigen::Array< Scalar, Eigen::Dynamic, 1 > &x, const IntVec &indices)
Returns x(indices).
Definition: AutoDiffHelpers.hpp:292
static std::vector< double > computeConnectionPressureDelta(const Wells &wells, const std::vector< double > &z_perf, const std::vector< double > &dens_perf, const double gravity)
Compute pressure deltas.
Definition: WellDensitySegmented.cpp:271
static std::vector< double > computeConnectionDensities(const Wells &wells, const PhaseUsage &phase_usage, const std::vector< double > &perfComponentRates, const std::vector< double > &b_perf, const std::vector< double > &rsmax_perf, const std::vector< double > &rvmax_perf, const std::vector< double > &surf_dens_perf)
Compute well segment densities Notation: N = number of perforations, C = number of components...
Definition: WellDensitySegmented.cpp:32
ADB bhp(const std::vector< int > &table_id, const Wells &wells, const ADB &qs, const ADB &thp, const ADB &alq) const
Linear interpolation of bhp as function of the input parameters.
Definition: VFPProdProperties.cpp:58
const VFPProdProperties * getProd() const
Returns the VFP properties for production wells.
Definition: VFPProperties.hpp:68
PhaseUsage phaseUsage() const
Definition: BlackoilPropsAdFromDeck.cpp:231
void updateListEconLimited(const Schedule &schedule, const int current_step, const Wells *wells, const WellState &well_state, DynamicListEconLimited &list_econ_limited) const
upate the dynamic lists related to economic limits
Definition: StandardWells_impl.hpp:1209
const Vector & getStoredWellPerforationFluxes() const
Retrieves the stored fluxes.
Definition: StandardWells_impl.hpp:1195
Eigen::ArrayXd sign(const Eigen::ArrayXd &x)
Return a vector of (-1.0, 0.0 or 1.0), depending on sign per element.
Definition: AutoDiffHelpers.hpp:719