void check_controls_epoch0( struct WellControls ** ctrls) { // The injector { const struct WellControls * ctrls0 = ctrls[0]; BOOST_CHECK_EQUAL( 3 , well_controls_get_num(ctrls0)); // The number of controls for the injector == 3?? BOOST_CHECK_EQUAL( SURFACE_RATE , well_controls_iget_type(ctrls0 , 0) ); BOOST_CHECK_EQUAL( RESERVOIR_RATE , well_controls_iget_type(ctrls0 , 1) ); BOOST_CHECK_EQUAL( BHP , well_controls_iget_type(ctrls0 , 2) ); // The different targets BOOST_CHECK_EQUAL( 100.0 / 86400 , well_controls_iget_target(ctrls0,0)); BOOST_CHECK_EQUAL( 200.0 / 86400 , well_controls_iget_target(ctrls0,1)); BOOST_CHECK_EQUAL( 400 * 100000 , well_controls_iget_target(ctrls0,2)); // Which control is active BOOST_CHECK_EQUAL( 0 , well_controls_get_current(ctrls0) ); // The phase distribution in the active target { const double * distr = well_controls_iget_distr( ctrls0 , 0 ); BOOST_CHECK_EQUAL( 0 , distr[0] ); // Water BOOST_CHECK_EQUAL( 0 , distr[1] ); // Oil BOOST_CHECK_EQUAL( 1 , distr[2] ); // Gas } } // The producer { const struct WellControls * ctrls1 = ctrls[1]; BOOST_CHECK_EQUAL( 2 , well_controls_get_num( ctrls1 )); // The number of controls for the producer == 2?? BOOST_CHECK_EQUAL( SURFACE_RATE , well_controls_iget_type(ctrls1 , 0) ); BOOST_CHECK_EQUAL( BHP , well_controls_iget_type(ctrls1 , 1) ); // The different targets BOOST_CHECK_EQUAL( -20000.0 / 86400 , well_controls_iget_target(ctrls1,0)); BOOST_CHECK_EQUAL( 1000 * 100000 , well_controls_iget_target(ctrls1,1)); // Which control is active BOOST_CHECK_EQUAL( 0 , well_controls_get_current(ctrls1)); // The phase distribution in the active target { const double * distr = well_controls_iget_distr( ctrls1 , 0 ); BOOST_CHECK_EQUAL( 0 , distr[0] ); // Water BOOST_CHECK_EQUAL( 1 , distr[1] ); // Oil BOOST_CHECK_EQUAL( 0 , distr[2] ); // Gas } } }
/// Create a src vector equivalent to a wells structure. /// For this to be valid, the wells must be all rate-controlled and /// single-perforation. void wellsToSrc(const Wells& wells, const int num_cells, std::vector<double>& src) { const int np = wells.number_of_phases; if (np != 2) { OPM_THROW(std::runtime_error, "wellsToSrc() requires a 2 phase case."); } src.resize(num_cells); for (int w = 0; w < wells.number_of_wells; ++w) { const int cur = well_controls_get_current(wells.ctrls[w]); if (well_controls_get_num(wells.ctrls[w]) != 1) { OPM_MESSAGE("In wellsToSrc(): well has more than one control, all but current control will be ignored."); } if (well_controls_iget_type(wells.ctrls[w] , cur) != RESERVOIR_RATE) { OPM_THROW(std::runtime_error, "In wellsToSrc(): well is something other than RESERVOIR_RATE."); } if (wells.well_connpos[w+1] - wells.well_connpos[w] != 1) { OPM_THROW(std::runtime_error, "In wellsToSrc(): well has multiple perforations."); } { const double * distr = well_controls_iget_distr( wells.ctrls[w] , cur); for (int p = 0; p < np; ++p) { if (distr[p] != 1.0) { OPM_THROW(std::runtime_error, "In wellsToSrc(): well not controlled on total rate."); } } } double flow = well_controls_iget_target(wells.ctrls[w] , cur); if (wells.type[w] == INJECTOR) { flow *= wells.comp_frac[np*w + 0]; // Obtaining water rate for inflow source. } const int cell = wells.well_cells[wells.well_connpos[w]]; src[cell] = flow; } }
void SimulatorBase<Implementation>::computeWellPotentials(const Wells* wells, const BlackoilState& x, const WellState& xw, std::vector<double>& well_potentials) { const int nw = wells->number_of_wells; const int np = wells->number_of_phases; well_potentials.clear(); well_potentials.resize(nw*np,0.0); for (int w = 0; w < nw; ++w) { for (int perf = wells->well_connpos[w]; perf < wells->well_connpos[w + 1]; ++perf) { const double well_cell_pressure = x.pressure()[wells->well_cells[perf]]; const double drawdown_used = well_cell_pressure - xw.perfPress()[perf]; const WellControls* ctrl = wells->ctrls[w]; const int nwc = well_controls_get_num(ctrl); //Loop over all controls until we find a BHP control //that specifies what we need... double bhp = 0.0; for (int ctrl_index=0; ctrl_index < nwc; ++ctrl_index) { if (well_controls_iget_type(ctrl, ctrl_index) == BHP) { bhp = well_controls_iget_target(ctrl, ctrl_index); } // TODO: do something for thp; } // Calculate the pressure difference in the well perforation const double dp = xw.perfPress()[perf] - xw.bhp()[w]; const double drawdown_maximum = well_cell_pressure - (bhp + dp); for (int phase = 0; phase < np; ++phase) { well_potentials[w*np + phase] += (drawdown_maximum / drawdown_used * xw.perfPhaseRates()[perf*np + phase]); } } } }
void check_controls_epoch1( struct WellControls ** ctrls) { // The injector { const struct WellControls * ctrls0 = ctrls[0]; BOOST_CHECK_EQUAL( 3 , well_controls_get_num(ctrls0)); // The number of controls for the injector == 3?? BOOST_CHECK_EQUAL( SURFACE_RATE , well_controls_iget_type(ctrls0 , 0 )); BOOST_CHECK_EQUAL( RESERVOIR_RATE , well_controls_iget_type(ctrls0 , 1 )); BOOST_CHECK_EQUAL( BHP , well_controls_iget_type(ctrls0 , 2 )); // The different targets BOOST_CHECK_CLOSE( 10.0 / 86400 , well_controls_iget_target(ctrls0 , 0) , 0.001); BOOST_CHECK_CLOSE( 20.0 / 86400 , well_controls_iget_target(ctrls0 , 1) , 0.001); BOOST_CHECK_CLOSE( 40 * 100000 , well_controls_iget_target(ctrls0 , 2) , 0.001); // Which control is active BOOST_CHECK_EQUAL( 1 , well_controls_get_current(ctrls0)); { const double * distr = well_controls_iget_distr( ctrls0 , 1 ); BOOST_CHECK_EQUAL( 1 , distr[0] ); // Water BOOST_CHECK_EQUAL( 0 , distr[1] ); // Oil BOOST_CHECK_EQUAL( 0 , distr[2] ); // Gas } } // The producer { const struct WellControls * ctrls1 = ctrls[1]; BOOST_CHECK_EQUAL( 3 , well_controls_get_num(ctrls1)); // The number of controls for the producer - now 3. BOOST_CHECK_EQUAL( SURFACE_RATE , well_controls_iget_type(ctrls1 , 0) ); BOOST_CHECK_EQUAL( RESERVOIR_RATE , well_controls_iget_type(ctrls1 , 1) ); BOOST_CHECK_EQUAL( BHP , well_controls_iget_type(ctrls1 , 2) ); // The different targets BOOST_CHECK_CLOSE( -999.0 / 86400 , well_controls_iget_target(ctrls1 , 0), 0.001); BOOST_CHECK_CLOSE( -123.0 / 86400 , well_controls_iget_target(ctrls1 , 1), 0.001); BOOST_CHECK_CLOSE( 100 * 100000 , well_controls_iget_target(ctrls1 , 2), 0.001); // Which control is active BOOST_CHECK_EQUAL( 1 , well_controls_get_current(ctrls1) ); { const double * distr = well_controls_iget_distr( ctrls1 , 1 ); BOOST_CHECK_EQUAL( 1 , distr[0] ); // Water BOOST_CHECK_EQUAL( 1 , distr[1] ); // Oil BOOST_CHECK_EQUAL( 1 , distr[2] ); // Gas } } }
inline bool constraintBroken(const std::vector<double>& bhp, const std::vector<double>& thp, const std::vector<double>& well_phase_flow_rate, const int well, const int num_phases, const WellType& well_type, const WellControls* wc, const int ctrl_index) { const WellControlType ctrl_type = well_controls_iget_type(wc, ctrl_index); const double target = well_controls_iget_target(wc, ctrl_index); const double* distr = well_controls_iget_distr(wc, ctrl_index); bool broken = false; switch (well_type) { case INJECTOR: { switch (ctrl_type) { case BHP: broken = bhp[well] > target; break; case THP: broken = thp[well] > target; break; case RESERVOIR_RATE: // Intentional fall-through case SURFACE_RATE: broken = rateToCompare(well_phase_flow_rate, well, num_phases, distr) > target; break; } } break; case PRODUCER: { switch (ctrl_type) { case BHP: broken = bhp[well] < target; break; case THP: broken = thp[well] < target; break; case RESERVOIR_RATE: // Intentional fall-through case SURFACE_RATE: // Note that the rates compared below are negative, // so breaking the constraints means: too high flow rate // (as for injection). broken = rateToCompare(well_phase_flow_rate, well, num_phases, distr) < target; break; } } break; default: OPM_THROW(std::logic_error, "Can only handle INJECTOR and PRODUCER wells."); } return broken; }