void readFromDeck(const EclipseGridParser& gridparser) { // We assume NTMISC=1 const std::vector<double>& plymax = gridparser.getPLYMAX().plymax_; c_max_ = plymax[0]; const std::vector<double>& tlmixpar = gridparser.getTLMIXPAR().tlmixpar_; mix_param_ = tlmixpar[0]; // We assume NTSFUN=1 const std::vector<double>& plyrock = gridparser.getPLYROCK().plyrock_; assert(plyrock.size() == 5); dead_pore_vol_ = plyrock[0]; res_factor_ = plyrock[1]; rock_density_ = plyrock[2]; ads_index_ = static_cast<AdsorptionBehaviour>(plyrock[3]); c_max_ads_ = plyrock[4]; // We assume NTPVT=1 const PLYVISC& plyvisc = gridparser.getPLYVISC(); c_vals_visc_ = plyvisc.concentration_; visc_mult_vals_ = plyvisc.factor_; // We assume NTSFUN=1 const PLYADS& plyads = gridparser.getPLYADS(); c_vals_ads_ = plyads.local_concentration_; ads_vals_ = plyads.adsorbed_concentration_; }
void SaturationPropsFromDeck<SatFuncSet>::init(const EclipseGridParser& deck, const UnstructuredGrid& grid, const int samples) { phase_usage_ = phaseUsageFromDeck(deck); // Extract input data. // Oil phase should be active. if (!phase_usage_.phase_used[Liquid]) { THROW("SaturationPropsFromDeck::init() -- oil phase must be active."); } // Obtain SATNUM, if it exists, and create cell_to_func_. // Otherwise, let the cell_to_func_ mapping be just empty. int satfuncs_expected = 1; if (deck.hasField("SATNUM")) { const std::vector<int>& satnum = deck.getIntegerValue("SATNUM"); satfuncs_expected = *std::max_element(satnum.begin(), satnum.end()); const int num_cells = grid.number_of_cells; cell_to_func_.resize(num_cells); const int* gc = grid.global_cell; for (int cell = 0; cell < num_cells; ++cell) { const int deck_pos = (gc == NULL) ? cell : gc[cell]; cell_to_func_[cell] = satnum[deck_pos] - 1; } } // Find number of tables, check for consistency. enum { Uninitialized = -1 }; int num_tables = Uninitialized; if (phase_usage_.phase_used[Aqua]) { const SWOF::table_t& swof_table = deck.getSWOF().swof_; num_tables = swof_table.size(); if (num_tables < satfuncs_expected) { THROW("Found " << num_tables << " SWOF tables, SATNUM specifies at least " << satfuncs_expected); } } if (phase_usage_.phase_used[Vapour]) { const SGOF::table_t& sgof_table = deck.getSGOF().sgof_; int num_sgof_tables = sgof_table.size(); if (num_sgof_tables < satfuncs_expected) { THROW("Found " << num_tables << " SGOF tables, SATNUM specifies at least " << satfuncs_expected); } if (num_tables == Uninitialized) { num_tables = num_sgof_tables; } else if (num_tables != num_sgof_tables) { THROW("Inconsistent number of tables in SWOF and SGOF."); } } // Initialize tables. satfuncset_.resize(num_tables); for (int table = 0; table < num_tables; ++table) { satfuncset_[table].init(deck, table, phase_usage_, samples); } }
void initBlackoilStateFromDeck(const UnstructuredGrid& grid, const Props& props, const EclipseGridParser& deck, const double gravity, State& state) { initStateFromDeck(grid, props, deck, gravity, state); initBlackoilSurfvol(grid, props, state); if (deck.hasField("RS")) { const std::vector<double>& rs_deck = deck.getFloatingPointValue("RS"); const int num_cells = grid.number_of_cells; for (int c = 0; c < num_cells; ++c) { int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; state.gasoilratio()[c] = rs_deck[c_deck]; } } else { THROW("Temporarily, we require the RS field."); } }
void SatFuncGwsegUniform::init(const EclipseGridParser& deck, const int table_num, const PhaseUsage phase_usg, const int samples) { phase_usage = phase_usg; double swco = 0.0; double swmax = 1.0; if (phase_usage.phase_used[Aqua]) { const SWOF::table_t& swof_table = deck.getSWOF().swof_; const std::vector<double>& sw = swof_table[table_num][0]; const std::vector<double>& krw = swof_table[table_num][1]; const std::vector<double>& krow = swof_table[table_num][2]; const std::vector<double>& pcow = swof_table[table_num][3]; buildUniformMonotoneTable(sw, krw, samples, krw_); buildUniformMonotoneTable(sw, krow, samples, krow_); buildUniformMonotoneTable(sw, pcow, samples, pcow_); krocw_ = krow[0]; // At connate water -> ecl. SWOF swco = sw[0]; smin_[phase_usage.phase_pos[Aqua]] = sw[0]; swmax = sw.back(); smax_[phase_usage.phase_pos[Aqua]] = sw.back(); } if (phase_usage.phase_used[Vapour]) { const SGOF::table_t& sgof_table = deck.getSGOF().sgof_; const std::vector<double>& sg = sgof_table[table_num][0]; const std::vector<double>& krg = sgof_table[table_num][1]; const std::vector<double>& krog = sgof_table[table_num][2]; const std::vector<double>& pcog = sgof_table[table_num][3]; buildUniformMonotoneTable(sg, krg, samples, krg_); buildUniformMonotoneTable(sg, krog, samples, krog_); buildUniformMonotoneTable(sg, pcog, samples, pcog_); smin_[phase_usage.phase_pos[Vapour]] = sg[0]; if (std::fabs(sg.back() + swco - 1.0) > 1e-3) { THROW("Gas maximum saturation in SGOF table = " << sg.back() << ", should equal (1.0 - connate water sat) = " << (1.0 - swco)); } smax_[phase_usage.phase_pos[Vapour]] = sg.back(); } // These only consider water min/max sats. Consider gas sats? smin_[phase_usage.phase_pos[Liquid]] = 1.0 - swmax; smax_[phase_usage.phase_pos[Liquid]] = 1.0 - swco; }
RockCompressibility::RockCompressibility(const EclipseGridParser& deck) : pref_(0.0), rock_comp_(0.0) { if (deck.hasField("ROCKTAB")) { const table_t& rt = deck.getROCKTAB().rocktab_; int n = rt[0][0].size(); p_.resize(n); poromult_.resize(n); for (int i = 0; i < n; ++i) { p_[i] = rt[0][0][i]; poromult_[i] = rt[0][1][i]; } } else if (deck.hasField("ROCK")) { const ROCK& r = deck.getROCK(); pref_ = r.rock_compressibilities_[0][0]; rock_comp_ = r.rock_compressibilities_[0][1]; } else { std::cout << "**** warning: no rock compressibility data found in deck (ROCK or ROCKTAB)." << std::endl; } }
/// Constructor. /// @param[in] deck Input deck expected to contain WPOLYMER. PolymerInflowFromDeck::PolymerInflowFromDeck(const EclipseGridParser& deck, const Wells& wells, const int num_cells) : sparse_inflow_(num_cells) { if (!deck.hasField("WPOLYMER")) { OPM_MESSAGE("PolymerInflowFromDeck initialized without WPOLYMER in current epoch."); return; } // Extract concentrations and put into cell->concentration map. const std::vector<WpolymerLine>& wpl = deck.getWPOLYMER().wpolymer_; const int num_wpl = wpl.size(); std::map<int, double> perfcell_conc; for (int i = 0; i < num_wpl; ++i) { // Only use well name and polymer concentration. // That is, we ignore salt concentration and group // names. int wix = 0; for (; wix < wells.number_of_wells; ++wix) { if (wpl[i].well_ == wells.name[wix]) { break; } } if (wix == wells.number_of_wells) { OPM_THROW(std::runtime_error, "Could not find a match for well " << wpl[i].well_ << " from WPOLYMER."); } for (int j = wells.well_connpos[wix]; j < wells.well_connpos[wix+1]; ++j) { const int perf_cell = wells.well_cells[j]; perfcell_conc[perf_cell] = wpl[i].polymer_concentration_; } } // Build sparse vector from map. std::map<int, double>::const_iterator it = perfcell_conc.begin(); for (; it != perfcell_conc.end(); ++it) { sparse_inflow_.addElement(it->second, it->first); } }
void PvtPropertiesIncompFromDeck::init(const EclipseGridParser& deck) { typedef std::vector<std::vector<std::vector<double> > > table_t; // If we need multiple regions, this class and the SinglePvt* classes must change. int region_number = 0; PhaseUsage phase_usage = phaseUsageFromDeck(deck); if (phase_usage.phase_used[PhaseUsage::Vapour] || !phase_usage.phase_used[PhaseUsage::Aqua] || !phase_usage.phase_used[PhaseUsage::Liquid]) { THROW("PvtPropertiesIncompFromDeck::init() -- must have gas and oil phases (only) in deck input.\n"); } // Surface densities. Accounting for different orders in eclipse and our code. if (deck.hasField("DENSITY")) { const std::vector<double>& d = deck.getDENSITY().densities_[region_number]; enum { ECL_oil = 0, ECL_water = 1, ECL_gas = 2 }; surface_density_[phase_usage.phase_pos[PhaseUsage::Aqua]] = d[ECL_water]; surface_density_[phase_usage.phase_pos[PhaseUsage::Liquid]] = d[ECL_oil]; } else { THROW("Input is missing DENSITY\n"); } // Make reservoir densities the same as surface densities initially. // We will modify them with formation volume factors if found. reservoir_density_ = surface_density_; // Water viscosity. if (deck.hasField("PVTW")) { const std::vector<double>& pvtw = deck.getPVTW().pvtw_[region_number]; if (pvtw[2] != 0.0 || pvtw[4] != 0.0) { MESSAGE("Compressibility effects in PVTW are ignored."); } reservoir_density_[phase_usage.phase_pos[PhaseUsage::Aqua]] /= pvtw[1]; viscosity_[phase_usage.phase_pos[PhaseUsage::Aqua]] = pvtw[3]; } else { // Eclipse 100 default. // viscosity_[phase_usage.phase_pos[PhaseUsage::Aqua]] = 0.5*Opm::prefix::centi*Opm::unit::Poise; THROW("Input is missing PVTW\n"); } // Oil viscosity. if (deck.hasField("PVCDO")) { const std::vector<double>& pvcdo = deck.getPVCDO().pvcdo_[region_number]; if (pvcdo[2] != 0.0 || pvcdo[4] != 0.0) { MESSAGE("Compressibility effects in PVCDO are ignored."); } reservoir_density_[phase_usage.phase_pos[PhaseUsage::Liquid]] /= pvcdo[1]; viscosity_[phase_usage.phase_pos[PhaseUsage::Liquid]] = pvcdo[3]; } else { THROW("Input is missing PVCDO\n"); } }
void initStateFromDeck(const UnstructuredGrid& grid, const Props& props, const EclipseGridParser& deck, const double gravity, State& state) { const int num_phases = props.numPhases(); const PhaseUsage pu = phaseUsageFromDeck(deck); if (num_phases != pu.num_phases) { THROW("initStateFromDeck(): user specified property object with " << num_phases << " phases, " "found " << pu.num_phases << " phases in deck."); } state.init(grid, num_phases); if (deck.hasField("EQUIL")) { if (num_phases != 2) { THROW("initStateFromDeck(): EQUIL-based init currently handling only two-phase scenarios."); } if (pu.phase_used[BlackoilPhases::Vapour]) { THROW("initStateFromDeck(): EQUIL-based init currently handling only oil-water scenario (no gas)."); } // Set saturations depending on oil-water contact. const EQUIL& equil= deck.getEQUIL(); if (equil.equil.size() != 1) { THROW("initStateFromDeck(): No region support yet."); } const double woc = equil.equil[0].water_oil_contact_depth_; initWaterOilContact(grid, props, woc, WaterBelow, state); // Set pressure depending on densities and depths. const double datum_z = equil.equil[0].datum_depth_; const double datum_p = equil.equil[0].datum_depth_pressure_; initHydrostaticPressure(grid, props, woc, gravity, datum_z, datum_p, state); } else if (deck.hasField("PRESSURE")) { // Set saturations from SWAT/SGAS, pressure from PRESSURE. std::vector<double>& s = state.saturation(); std::vector<double>& p = state.pressure(); const std::vector<double>& p_deck = deck.getFloatingPointValue("PRESSURE"); const int num_cells = grid.number_of_cells; if (num_phases == 2) { if (!pu.phase_used[BlackoilPhases::Aqua]) { // oil-gas: we require SGAS if (!deck.hasField("SGAS")) { THROW("initStateFromDeck(): missing SGAS keyword in 2-phase init"); } const std::vector<double>& sg_deck = deck.getFloatingPointValue("SGAS"); const int gpos = pu.phase_pos[BlackoilPhases::Vapour]; const int opos = pu.phase_pos[BlackoilPhases::Liquid]; for (int c = 0; c < num_cells; ++c) { int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; s[2*c + gpos] = sg_deck[c_deck]; s[2*c + opos] = 1.0 - sg_deck[c_deck]; p[c] = p_deck[c_deck]; } } else { // water-oil or water-gas: we require SWAT if (!deck.hasField("SWAT")) { THROW("initStateFromDeck(): missing SWAT keyword in 2-phase init"); } const std::vector<double>& sw_deck = deck.getFloatingPointValue("SWAT"); const int wpos = pu.phase_pos[BlackoilPhases::Aqua]; const int nwpos = (wpos + 1) % 2; for (int c = 0; c < num_cells; ++c) { int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; s[2*c + wpos] = sw_deck[c_deck]; s[2*c + nwpos] = 1.0 - sw_deck[c_deck]; p[c] = p_deck[c_deck]; } } } else if (num_phases == 3) { const bool has_swat_sgas = deck.hasField("SWAT") && deck.hasField("SGAS"); if (!has_swat_sgas) { THROW("initStateFromDeck(): missing SGAS or SWAT keyword in 3-phase init."); } const int wpos = pu.phase_pos[BlackoilPhases::Aqua]; const int gpos = pu.phase_pos[BlackoilPhases::Vapour]; const int opos = pu.phase_pos[BlackoilPhases::Liquid]; const std::vector<double>& sw_deck = deck.getFloatingPointValue("SWAT"); const std::vector<double>& sg_deck = deck.getFloatingPointValue("SGAS"); for (int c = 0; c < num_cells; ++c) { int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; s[3*c + wpos] = sw_deck[c_deck]; s[3*c + opos] = 1.0 - (sw_deck[c_deck] + sg_deck[c_deck]); s[3*c + gpos] = sg_deck[c_deck]; p[c] = p_deck[c_deck]; } } else { THROW("initStateFromDeck(): init with SWAT etc. only available with 2 or 3 phases."); } } else { THROW("initStateFromDeck(): we must either have EQUIL, or PRESSURE and SWAT/SOIL/SGAS."); } // Finally, init face pressures. initFacePressure(grid, state); }
void SatFuncSimpleUniform::init(const EclipseGridParser& deck, const int table_num, const PhaseUsage phase_usg, const int samples) { phase_usage = phase_usg; double swco = 0.0; double swmax = 1.0; if (phase_usage.phase_used[Aqua]) { const SWOF::table_t& swof_table = deck.getSWOF().swof_; const std::vector<double>& sw = swof_table[table_num][0]; const std::vector<double>& krw = swof_table[table_num][1]; const std::vector<double>& krow = swof_table[table_num][2]; const std::vector<double>& pcow = swof_table[table_num][3]; if (krw.front() != 0.0 || krow.back() != 0.0) { THROW("Error SWOF data - non-zero krw(swco) and/or krow(1-sor)"); } buildUniformMonotoneTable(sw, krw, samples, krw_); buildUniformMonotoneTable(sw, krow, samples, krow_); buildUniformMonotoneTable(sw, pcow, samples, pcow_); krocw_ = krow[0]; // At connate water -> ecl. SWOF swco = sw[0]; smin_[phase_usage.phase_pos[Aqua]] = sw[0]; swmax = sw.back(); smax_[phase_usage.phase_pos[Aqua]] = sw.back(); krwmax_ = krw.back(); kromax_ = krow.front(); swcr_ = swmax; sowcr_ = 1.0 - swco; krwr_ = krw.back(); krorw_ = krow.front(); for (std::vector<double>::size_type i=1; i<sw.size(); ++i) { if (krw[i]> 0.0) { swcr_ = sw[i-1]; krorw_ = krow[i-1]; break; } } for (std::vector<double>::size_type i=sw.size()-1; i>=1; --i) { if (krow[i-1]> 0.0) { sowcr_ = 1.0 - sw[i]; krwr_ = krw[i]; break; } } } if (phase_usage.phase_used[Vapour]) { const SGOF::table_t& sgof_table = deck.getSGOF().sgof_; const std::vector<double>& sg = sgof_table[table_num][0]; const std::vector<double>& krg = sgof_table[table_num][1]; const std::vector<double>& krog = sgof_table[table_num][2]; const std::vector<double>& pcog = sgof_table[table_num][3]; buildUniformMonotoneTable(sg, krg, samples, krg_); buildUniformMonotoneTable(sg, krog, samples, krog_); buildUniformMonotoneTable(sg, pcog, samples, pcog_); smin_[phase_usage.phase_pos[Vapour]] = sg[0]; if (std::fabs(sg.back() + swco - 1.0) > 1e-3) { THROW("Gas maximum saturation in SGOF table = " << sg.back() << ", should equal (1.0 - connate water sat) = " << (1.0 - swco)); } smax_[phase_usage.phase_pos[Vapour]] = sg.back(); } // These only consider water min/max sats. Consider gas sats? smin_[phase_usage.phase_pos[Liquid]] = 1.0 - swmax; smax_[phase_usage.phase_pos[Liquid]] = 1.0 - swco; }
void SatFuncBase<TableType>::init(const EclipseGridParser& deck, const int table_num, const PhaseUsage phase_usg, const int samples) { phase_usage = phase_usg; double swco = 0.0; double swmax = 1.0; if (phase_usage.phase_used[Aqua]) { const SWOF::table_t& swof_table = deck.getSWOF().swof_; const std::vector<double>& sw = swof_table[table_num][0]; const std::vector<double>& krw = swof_table[table_num][1]; const std::vector<double>& krow = swof_table[table_num][2]; const std::vector<double>& pcow = swof_table[table_num][3]; if (krw.front() != 0.0 || krow.back() != 0.0) { OPM_THROW(std::runtime_error, "Error SWOF data - non-zero krw(swco) and/or krow(1-sor)"); } // Extend the tables with constant values such that the // derivatives at the endpoints are zero int n = sw.size(); std::vector<double> sw_ex(n+2); std::vector<double> krw_ex(n+2); std::vector<double> krow_ex(n+2); std::vector<double> pcow_ex(n+2); extendTable(sw,sw_ex,1); extendTable(krw,krw_ex,0); extendTable(krow,krow_ex,0); extendTable(pcow,pcow_ex,0); initializeTableType(krw_,sw_ex, krw_ex, samples); initializeTableType(krow_,sw_ex, krow_ex, samples); initializeTableType(pcow_,sw_ex, pcow_ex, samples); krocw_ = krow[0]; // At connate water -> ecl. SWOF swco = sw[0]; smin_[phase_usage.phase_pos[Aqua]] = sw[0]; swmax = sw.back(); smax_[phase_usage.phase_pos[Aqua]] = sw.back(); krwmax_ = krw.back(); kromax_ = krow.front(); swcr_ = swmax; sowcr_ = 1.0 - swco; krwr_ = krw.back(); krorw_ = krow.front(); for (std::vector<double>::size_type i=1; i<sw.size(); ++i) { if (krw[i]> 0.0) { swcr_ = sw[i-1]; krorw_ = krow[i-1]; break; } } for (std::vector<double>::size_type i=sw.size()-1; i>=1; --i) { if (krow[i-1]> 0.0) { sowcr_ = 1.0 - sw[i]; krwr_ = krw[i]; break; } } } if (phase_usage.phase_used[Vapour]) { const SGOF::table_t& sgof_table = deck.getSGOF().sgof_; const std::vector<double>& sg = sgof_table[table_num][0]; const std::vector<double>& krg = sgof_table[table_num][1]; const std::vector<double>& krog = sgof_table[table_num][2]; const std::vector<double>& pcog = sgof_table[table_num][3]; // Extend the tables with constant values such that the // derivatives at the endpoints are zero int n = sg.size(); std::vector<double> sg_ex(n+2); std::vector<double> krg_ex(n+2); std::vector<double> krog_ex(n+2); std::vector<double> pcog_ex(n+2); extendTable(sg,sg_ex,1); extendTable(krg,krg_ex,0); extendTable(krog,krog_ex,0); extendTable(pcog,pcog_ex,0); initializeTableType(krg_,sg_ex, krg_ex, samples); initializeTableType(krog_,sg_ex, krog_ex, samples); initializeTableType(pcog_,sg_ex, pcog_ex, samples); smin_[phase_usage.phase_pos[Vapour]] = sg[0]; if (std::fabs(sg.back() + swco - 1.0) > 1e-3) { OPM_THROW(std::runtime_error, "Gas maximum saturation in SGOF table = " << sg.back() << ", should equal (1.0 - connate water sat) = " << (1.0 - swco)); } smax_[phase_usage.phase_pos[Vapour]] = sg.back(); smin_[phase_usage.phase_pos[Vapour]] = sg.front(); krgmax_ = krg.back(); sgcr_ = sg.front(); sogcr_ = 1.0 - sg.back(); krgr_ = krg.back(); krorg_ = krg.front(); for (std::vector<double>::size_type i=1; i<sg.size(); ++i) { if (krg[i]> 0.0) { sgcr_ = sg[i-1]; krorg_ = krog[i-1]; break; } } for (std::vector<double>::size_type i=sg.size()-1; i>=1; --i) { if (krog[i-1]> 0.0) { sogcr_ = 1.0 - sg[i]; krgr_ = krg[i]; break; } } } if (phase_usage.phase_used[Vapour] && phase_usage.phase_used[Aqua]) { sowcr_ -= smin_[phase_usage.phase_pos[Vapour]]; sogcr_ -= smin_[phase_usage.phase_pos[Aqua]]; smin_[phase_usage.phase_pos[Liquid]] = 0.0; smax_[phase_usage.phase_pos[Liquid]] = 1.0 - smin_[phase_usage.phase_pos[Aqua]] - smin_[phase_usage.phase_pos[Vapour]]; // First entry in SGOF-table supposed to be zero anyway ... } else if (phase_usage.phase_used[Aqua]) { smin_[phase_usage.phase_pos[Liquid]] = 1.0 - smax_[phase_usage.phase_pos[Aqua]]; smax_[phase_usage.phase_pos[Liquid]] = 1.0 - smin_[phase_usage.phase_pos[Aqua]]; } else if (phase_usage.phase_used[Vapour]) { smin_[phase_usage.phase_pos[Liquid]] = 1.0 - smax_[phase_usage.phase_pos[Vapour]]; smax_[phase_usage.phase_pos[Liquid]] = 1.0 - smin_[phase_usage.phase_pos[Vapour]]; } }
/// Initialize from TSTEP field. void SimulatorTimer::init(const EclipseGridParser& deck) { timesteps_ = deck.getTSTEP().tstep_; total_time_ = std::accumulate(timesteps_.begin(), timesteps_.end(), 0.0); }
/// Constructor wrapping an opm-core black oil interface. BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const EclipseGridParser& deck, const UnstructuredGrid& grid, const bool init_rock) { if (init_rock){ rock_.init(deck, grid); } const int samples = 0; const int region_number = 0; phase_usage_ = phaseUsageFromDeck(deck); // Surface densities. Accounting for different orders in eclipse and our code. if (deck.hasField("DENSITY")) { const std::vector<double>& d = deck.getDENSITY().densities_[region_number]; enum { ECL_oil = 0, ECL_water = 1, ECL_gas = 2 }; if (phase_usage_.phase_used[Aqua]) { densities_[phase_usage_.phase_pos[Aqua]] = d[ECL_water]; } if (phase_usage_.phase_used[Vapour]) { densities_[phase_usage_.phase_pos[Vapour]] = d[ECL_gas]; } if (phase_usage_.phase_used[Liquid]) { densities_[phase_usage_.phase_pos[Liquid]] = d[ECL_oil]; } } else { OPM_THROW(std::runtime_error, "Input is missing DENSITY\n"); } // Set the properties. props_.resize(phase_usage_.num_phases); // Water PVT if (phase_usage_.phase_used[Aqua]) { if (deck.hasField("PVTW")) { props_[phase_usage_.phase_pos[Aqua]].reset(new SinglePvtConstCompr(deck.getPVTW().pvtw_)); } else { // Eclipse 100 default. props_[phase_usage_.phase_pos[Aqua]].reset(new SinglePvtConstCompr(0.5*Opm::prefix::centi*Opm::unit::Poise)); } } // Oil PVT if (phase_usage_.phase_used[Liquid]) { if (deck.hasField("PVDO")) { if (samples > 0) { props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtDeadSpline(deck.getPVDO().pvdo_, samples)); } else { props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtDead(deck.getPVDO().pvdo_)); } } else if (deck.hasField("PVTO")) { props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtLiveOil(deck.getPVTO().pvto_)); } else if (deck.hasField("PVCDO")) { props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtConstCompr(deck.getPVCDO().pvcdo_)); } else { OPM_THROW(std::runtime_error, "Input is missing PVDO or PVTO\n"); } } // Gas PVT if (phase_usage_.phase_used[Vapour]) { if (deck.hasField("PVDG")) { if (samples > 0) { props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtDeadSpline(deck.getPVDG().pvdg_, samples)); } else { props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtDead(deck.getPVDG().pvdg_)); } // } else if (deck.hasField("PVTG")) { // props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtLiveGas(deck.getPVTG().pvtg_)); } else { OPM_THROW(std::runtime_error, "Input is missing PVDG or PVTG\n"); } } SaturationPropsFromDeck<SatFuncGwsegNonuniform>* ptr = new SaturationPropsFromDeck<SatFuncGwsegNonuniform>(); satprops_.reset(ptr); ptr->init(deck, grid, -1); if (phase_usage_.num_phases != satprops_->numPhases()) { OPM_THROW(std::runtime_error, "BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck() - " "Inconsistent number of phases in pvt data (" << phase_usage_.num_phases << ") and saturation-dependent function data (" << satprops_->numPhases() << ")."); } }
void BlackoilPvtProperties::init(const EclipseGridParser& deck, const int samples) { // If we need multiple regions, this class and the SinglePvt* classes must change. region_number_ = 0; phase_usage_ = phaseUsageFromDeck(deck); // Surface densities. Accounting for different orders in eclipse and our code. if (deck.hasField("DENSITY")) { const std::vector<double>& d = deck.getDENSITY().densities_[region_number_]; enum { ECL_oil = 0, ECL_water = 1, ECL_gas = 2 }; if (phase_usage_.phase_used[Aqua]) { densities_[phase_usage_.phase_pos[Aqua]] = d[ECL_water]; } if (phase_usage_.phase_used[Vapour]) { densities_[phase_usage_.phase_pos[Vapour]] = d[ECL_gas]; } if (phase_usage_.phase_used[Liquid]) { densities_[phase_usage_.phase_pos[Liquid]] = d[ECL_oil]; } } else { OPM_THROW(std::runtime_error, "Input is missing DENSITY\n"); } // Set the properties. props_.resize(phase_usage_.num_phases); // Water PVT if (phase_usage_.phase_used[Aqua]) { if (deck.hasField("PVTW")) { props_[phase_usage_.phase_pos[Aqua]].reset(new SinglePvtConstCompr(deck.getPVTW().pvtw_)); } else { // Eclipse 100 default. props_[phase_usage_.phase_pos[Aqua]].reset(new SinglePvtConstCompr(0.5*Opm::prefix::centi*Opm::unit::Poise)); } } // Oil PVT if (phase_usage_.phase_used[Liquid]) { if (deck.hasField("PVDO")) { if (samples > 0) { props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtDeadSpline(deck.getPVDO().pvdo_, samples)); } else { props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtDead(deck.getPVDO().pvdo_)); } } else if (deck.hasField("PVTO")) { props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtLiveOil(deck.getPVTO().pvto_)); } else if (deck.hasField("PVCDO")) { props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtConstCompr(deck.getPVCDO().pvcdo_)); } else { OPM_THROW(std::runtime_error, "Input is missing PVDO or PVTO\n"); } } // Gas PVT if (phase_usage_.phase_used[Vapour]) { if (deck.hasField("PVDG")) { if (samples > 0) { props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtDeadSpline(deck.getPVDG().pvdg_, samples)); } else { props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtDead(deck.getPVDG().pvdg_)); } } else if (deck.hasField("PVTG")) { props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtLiveGas(deck.getPVTG().pvtg_)); } else { OPM_THROW(std::runtime_error, "Input is missing PVDG or PVTG\n"); } } // Must inform pvt property objects of phase structure. for (int i = 0; i < phase_usage_.num_phases; ++i) { props_[i]->setPhaseConfiguration(phase_usage_.num_phases, phase_usage_.phase_pos); } }
void SatFuncGwsegUniform::init(const EclipseGridParser& deck, const int table_num, const PhaseUsage phase_usg, const int samples) { phase_usage = phase_usg; double swco = 0.0; double swmax = 1.0; if (phase_usage.phase_used[Aqua]) { const SWOF::table_t& swof_table = deck.getSWOF().swof_; const std::vector<double>& sw = swof_table[table_num][0]; const std::vector<double>& krw = swof_table[table_num][1]; const std::vector<double>& krow = swof_table[table_num][2]; const std::vector<double>& pcow = swof_table[table_num][3]; // Extend the tables with constant values such that the // derivatives at the endpoints are zero int n = sw.size(); std::vector<double> sw_ex(n+2); std::vector<double> krw_ex(n+2); std::vector<double> krow_ex(n+2); std::vector<double> pcow_ex(n+2); SatFuncGwsegUniform::ExtendTable(sw,sw_ex,1); SatFuncGwsegUniform::ExtendTable(krw,krw_ex,0); SatFuncGwsegUniform::ExtendTable(krow,krow_ex,0); SatFuncGwsegUniform::ExtendTable(pcow,pcow_ex,0); buildUniformMonotoneTable(sw_ex, krw_ex, samples, krw_); buildUniformMonotoneTable(sw_ex, krow_ex, samples, krow_); buildUniformMonotoneTable(sw_ex, pcow_ex, samples, pcow_); krocw_ = krow[0]; // At connate water -> ecl. SWOF swco = sw[0]; smin_[phase_usage.phase_pos[Aqua]] = sw[0]; swmax = sw.back(); smax_[phase_usage.phase_pos[Aqua]] = sw.back(); } if (phase_usage.phase_used[Vapour]) { const SGOF::table_t& sgof_table = deck.getSGOF().sgof_; const std::vector<double>& sg = sgof_table[table_num][0]; const std::vector<double>& krg = sgof_table[table_num][1]; const std::vector<double>& krog = sgof_table[table_num][2]; const std::vector<double>& pcog = sgof_table[table_num][3]; // Extend the tables with constant values such that the // derivatives at the endpoints are zero int n = sg.size(); std::vector<double> sg_ex(n+2); std::vector<double> krg_ex(n+2); std::vector<double> krog_ex(n+2); std::vector<double> pcog_ex(n+2); SatFuncGwsegUniform::ExtendTable(sg,sg_ex,1); SatFuncGwsegUniform::ExtendTable(krg,krg_ex,0); SatFuncGwsegUniform::ExtendTable(krog,krog_ex,0); SatFuncGwsegUniform::ExtendTable(pcog,pcog_ex,0); buildUniformMonotoneTable(sg_ex, krg_ex, samples, krg_); buildUniformMonotoneTable(sg_ex, krog_ex, samples, krog_); buildUniformMonotoneTable(sg_ex, pcog_ex, samples, pcog_); smin_[phase_usage.phase_pos[Vapour]] = sg[0]; if (std::fabs(sg.back() + swco - 1.0) > 1e-3) { OPM_THROW(std::runtime_error, "Gas maximum saturation in SGOF table = " << sg.back() << ", should equal (1.0 - connate water sat) = " << (1.0 - swco)); } smax_[phase_usage.phase_pos[Vapour]] = sg.back(); } // These only consider water min/max sats. Consider gas sats? smin_[phase_usage.phase_pos[Liquid]] = 1.0 - swmax; smax_[phase_usage.phase_pos[Liquid]] = 1.0 - swco; }