std::pair<RestartValue, SummaryState> load(const std::string& filename, int report_step, const std::vector<RestartKey>& solution_keys, const EclipseState& es, const EclipseGrid& grid, const Schedule& schedule, const std::vector<RestartKey>& extra_keys) { const auto rst_view = RestartFileView{ filename, report_step }; auto xr = restoreSOLUTION(rst_view, solution_keys, grid.getNumActive()); xr.convertToSI(es.getUnits()); auto xw = Opm::RestartIO::ecl_file_view_has_kw(rst_view, "OPM_XWEL") ? restore_wells_opm(rst_view, es, grid, schedule) : restore_wells_ecl(rst_view, es, grid, schedule); auto rst_value = RestartValue{ std::move(xr), std::move(xw) }; if (! extra_keys.empty()) { restoreExtra(rst_view, extra_keys, es.getUnits(), rst_value); } return { std::move(rst_value), restore_cumulative(rst_view, schedule) }; }
SummaryConfig::SummaryConfig( const Deck& deck, const EclipseState& es , const ParseContext& parseContext) : SummaryConfig( deck, *es.getSchedule(), es.get3DProperties(), parseContext, dimensions( *es.getInputGrid() ) ) {}
void pressure(const EclipseState& es, const Schedule& /* sched */, data::Solution& sol, size_t /* report_step */, double seconds_elapsed) { const auto& grid = es.getInputGrid(); const auto& units = es.getUnits(); if (!sol.has("PRESSURE")) sol.insert("PRESSURE", UnitSystem::measure::pressure, std::vector<double>(grid.getNumActive()), data::TargetType::RESTART_SOLUTION); auto& data = sol.data("PRESSURE"); std::fill(data.begin(), data.end(), units.to_si(UnitSystem::measure::pressure, seconds_elapsed)); }
Setup( const char* path, const ParseContext& parseContext = ParseContext( )) : deck( Parser().parseFile( path, parseContext ) ), es( deck, parseContext ), grid( es.getInputGrid( ) ), schedule( deck, grid, es.get3DProperties(), es.runspec().phases(), parseContext), summary_config( deck, schedule, es.getTableManager( ), parseContext) { auto& io_config = es.getIOConfig(); io_config.setEclCompatibleRST(false); }
EclipseIO::Impl::Impl( const EclipseState& eclipseState, EclipseGrid grid_, const Schedule& schedule_, const SummaryConfig& summary_config) : es( eclipseState ) , grid( std::move( grid_ ) ) , schedule( schedule_ ) , outputDir( eclipseState.getIOConfig().getOutputDir() ) , baseName( uppercase( eclipseState.getIOConfig().getBaseName() ) ) , summary( eclipseState, summary_config, grid , schedule ) , rft( outputDir.c_str(), baseName.c_str(), es.getIOConfig().getFMTOUT() ) , output_enabled( eclipseState.getIOConfig().getOutputEnabled() ) {}
/*! * \brief Initialize the oil parameters via the data specified by the PVDO ECL keyword. */ void initFromDeck(const Deck& deck, const EclipseState& eclState) { const auto& pvdoTables = eclState.getTableManager().getPvdoTables(); const auto& densityKeyword = deck.getKeyword("DENSITY"); assert(pvdoTables.size() == densityKeyword.size()); size_t numRegions = pvdoTables.size(); setNumRegions(numRegions); for (unsigned regionIdx = 0; regionIdx < numRegions; ++ regionIdx) { Scalar rhoRefO = densityKeyword.getRecord(regionIdx).getItem("OIL").getSIDouble(0); Scalar rhoRefG = densityKeyword.getRecord(regionIdx).getItem("GAS").getSIDouble(0); Scalar rhoRefW = densityKeyword.getRecord(regionIdx).getItem("WATER").getSIDouble(0); setReferenceDensities(regionIdx, rhoRefO, rhoRefG, rhoRefW); const auto& pvdoTable = pvdoTables.getTable<PvdoTable>(regionIdx); const auto& BColumn(pvdoTable.getFormationFactorColumn()); std::vector<Scalar> invBColumn(BColumn.size()); for (unsigned i = 0; i < invBColumn.size(); ++i) invBColumn[i] = 1/BColumn[i]; inverseOilB_[regionIdx].setXYArrays(pvdoTable.numRows(), pvdoTable.getPressureColumn(), invBColumn); oilMu_[regionIdx].setXYArrays(pvdoTable.numRows(), pvdoTable.getPressureColumn(), pvdoTable.getViscosityColumn()); } initEnd(); }
void Opm::checkConsistentArrayDimensions(const EclipseState& es, const Schedule& sched, const ParseContext& ctxt, ErrorGuard& guard) { consistentWellDims(es.runspec().wellDimensions(), sched, ctxt, guard); }
double prod_wpr_P2(const EclipseState& es, const Schedule& sched, const data::Solution& sol, size_t report_step, double seconds_elapsed) { const auto& units = es.getUnits(); double water_rate = 0.0; if (report_step > 5) water_rate = 2.0; // => WWCT = WWPR / (WOPR + WWPR) = 2/3 return -units.to_si(UnitSystem::measure::rate, water_rate); }
std::vector<int> Opm::RestartIO::Helpers:: createInteHead(const EclipseState& es, const EclipseGrid& grid, const Schedule& sched, const double simTime, const int num_solver_steps, const int lookup_step) { const auto nwgmax = maxGroupSize(sched, lookup_step); const auto ngmax = numGroupsInField(sched, lookup_step); const auto& rspec = es.runspec(); const auto& tdim = es.getTableManager(); const auto& rdim = tdim.getRegdims(); const auto ih = InteHEAD{} .dimensions (grid.getNXYZ()) .numActive (static_cast<int>(grid.getNumActive())) .unitConventions (getUnitConvention(es.getDeckUnitSystem())) .wellTableDimensions(getWellTableDims(nwgmax, rspec, sched, lookup_step)) .calendarDate (getSimulationTimePoint(sched.posixStartTime(), simTime)) .activePhases (getActivePhases(rspec)) // The numbers below have been determined experimentally to work // across a range of reference cases, but are not guaranteed to be // universally valid. .params_NWELZ (155, 122, 130, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL .params_NCON (25, 40, 58) // n{isx}conz: number of data elements per completion in ICON .params_GRPZ (getNGRPZ(nwgmax, ngmax, rspec)) // ncamax: max number of analytical aquifer connections // n{isx}aaqz: number of data elements per aquifer in {ISX}AAQ // n{isa}caqz: number of data elements per aquifer connection in {ISA}CAQ .params_NAAQZ (1, 18, 24, 10, 7, 2, 4) .stepParam (num_solver_steps, lookup_step) .tuningParam (getTuningPars(sched.getTuning(), lookup_step)) .wellSegDimensions (getWellSegDims(rspec, sched, lookup_step)) .regionDimensions (getRegDims(tdim, rdim)) .ngroups ({ ngmax }) .variousParam (201702, 100) // Output should be compatible with Eclipse 100, 2017.02 version. ; return ih.data(); }
/*! * \brief Implement the temperature part of the water PVT properties. */ void initFromDeck(const Deck& deck, const EclipseState& eclState) { ////// // initialize the isothermal part ////// isothermalPvt_ = new IsothermalPvt; isothermalPvt_->initFromDeck(deck, eclState); ////// // initialize the thermal part ////// const auto& tables = eclState.getTableManager(); enableThermalDensity_ = deck.hasKeyword("WATDENT"); enableThermalViscosity_ = deck.hasKeyword("VISCREF"); unsigned numRegions = isothermalPvt_->numRegions(); setNumRegions(numRegions); if (enableThermalDensity_) { const auto& watdentKeyword = deck.getKeyword("WATDENT"); assert(watdentKeyword.size() == numRegions); for (unsigned regionIdx = 0; regionIdx < numRegions; ++regionIdx) { const auto& watdentRecord = watdentKeyword.getRecord(regionIdx); watdentRefTemp_[regionIdx] = watdentRecord.getItem("REFERENCE_TEMPERATURE").getSIDouble(0); watdentCT1_[regionIdx] = watdentRecord.getItem("EXPANSION_COEFF_LINEAR").getSIDouble(0); watdentCT2_[regionIdx] = watdentRecord.getItem("EXPANSION_COEFF_QUADRATIC").getSIDouble(0); } } if (enableThermalViscosity_) { const auto& viscrefKeyword = deck.getKeyword("VISCREF"); const auto& watvisctTables = tables.getWatvisctTables(); assert(watvisctTables.size() == numRegions); assert(viscrefKeyword.size() == numRegions); for (unsigned regionIdx = 0; regionIdx < numRegions; ++ regionIdx) { const auto& T = watvisctTables[regionIdx].getColumn("Temperature").vectorCopy(); const auto& mu = watvisctTables[regionIdx].getColumn("Viscosity").vectorCopy(); watvisctCurves_[regionIdx].setXYContainers(T, mu); const auto& viscrefRecord = viscrefKeyword.getRecord(regionIdx); viscrefPress_[regionIdx] = viscrefRecord.getItem("REFERENCE_PRESSURE").getSIDouble(0); } } }
std::vector<bool> Opm::RestartIO::Helpers:: createLogiHead(const EclipseState& es) { const auto& rspec = es.runspec(); const auto& wsd = rspec.wellSegmentDimensions(); const auto& hystPar = rspec.hysterPar(); const auto lh = LogiHEAD{} .variousParam(false, false, wsd.maxSegmentedWells(), hystPar.active()) ; return lh.data(); }
RestartValue first_sim(const EclipseState& es, EclipseIO& eclWriter, bool write_double) { const auto& grid = es.getInputGrid(); auto num_cells = grid.getNumActive( ); auto start_time = ecl_util_make_date( 1, 11, 1979 ); auto first_step = ecl_util_make_date( 10, 10, 2008 ); auto sol = mkSolution( num_cells ); auto wells = mkWells(); RestartValue restart_value(sol, wells); eclWriter.writeTimeStep( 1, false, first_step - start_time, restart_value, {}, {}, {}, write_double); return restart_value; }
/*! * \brief Implement the temperature part of the gas PVT properties. */ void initFromDeck(const Deck& deck, const EclipseState& eclState) { ////// // initialize the isothermal part ////// isothermalPvt_ = new IsothermalPvt; isothermalPvt_->initFromDeck(deck, eclState); ////// // initialize the thermal part ////// const auto& tables = eclState.getTableManager(); enableThermalDensity_ = deck.hasKeyword("TREF"); enableThermalViscosity_ = deck.hasKeyword("GASVISCT"); unsigned numRegions = isothermalPvt_->numRegions(); setNumRegions(numRegions); // viscosity if (enableThermalViscosity_) { const auto& gasvisctTables = tables.getGasvisctTables(); int gasCompIdx = deck.getKeyword("GCOMPIDX").getRecord(0).getItem("GAS_COMPONENT_INDEX").get< int >(0) - 1; std::string gasvisctColumnName = "Viscosity"+std::to_string(static_cast<long long>(gasCompIdx)); for (unsigned regionIdx = 0; regionIdx < numRegions; ++regionIdx) { const auto& T = gasvisctTables[regionIdx].getColumn("Temperature").vectorCopy(); const auto& mu = gasvisctTables[regionIdx].getColumn(gasvisctColumnName).vectorCopy(); gasvisctCurves_[regionIdx].setXYContainers(T, mu); } } // quantities required for density. note that we just always use the values // for the first EOS. (since EOS != PVT region.) refTemp_ = 0.0; if (enableThermalDensity_) { refTemp_ = deck.getKeyword("TREF").getRecord(0).getItem("TEMPERATURE").getSIDouble(0); } }
AquiferCT::AquiferCT(const EclipseState& eclState, const Deck& deck) { if (!deck.hasKeyword("AQUCT")) return; const auto& aquctKeyword = deck.getKeyword("AQUCT"); for (auto& aquctRecord : aquctKeyword){ AquiferCT::AQUCT_data data; data.aquiferID = aquctRecord.getItem("AQUIFER_ID").template get<int>(0); data.h = aquctRecord.getItem("THICKNESS_AQ").getSIDouble(0); data.phi_aq = aquctRecord.getItem("PORO_AQ").getSIDouble(0); data.d0 = aquctRecord.getItem("DAT_DEPTH").getSIDouble(0); data.C_t = aquctRecord.getItem("C_T").getSIDouble(0); data.r_o = aquctRecord.getItem("RAD").getSIDouble(0); data.k_a = aquctRecord.getItem("PERM_AQ").getSIDouble(0); data.theta = aquctRecord.getItem("INFLUENCE_ANGLE").getSIDouble(0); data.c1 = 0.008527; // We are using SI data.c2 = 6.283; data.inftableID = aquctRecord.getItem("TABLE_NUM_INFLUENCE_FN").template get<int>(0); data.pvttableID = aquctRecord.getItem("TABLE_NUM_WATER_PRESS").template get<int>(0); // Get the correct influence table values if (data.inftableID > 1){ const auto& aqutabTable = eclState.getTableManager().getAqutabTables().getTable(data.inftableID - 2); const auto& aqutab_tdColumn = aqutabTable.getColumn(0); const auto& aqutab_piColumn = aqutabTable.getColumn(1); data.td = aqutab_tdColumn.vectorCopy(); data.pi = aqutab_piColumn.vectorCopy(); } else { set_default_tables(data.td,data.pi); } m_aquct.push_back( std::move(data) ); } }
/*! * \brief Initialize the oil parameters via the data specified by the PVTO ECL keyword. */ void initFromDeck(const Deck& deck, const EclipseState& eclState) { const auto& pvtoTables = eclState.getTableManager().getPvtoTables(); const auto& densityKeyword = deck.getKeyword("DENSITY"); assert(pvtoTables.size() == densityKeyword.size()); size_t numRegions = pvtoTables.size(); setNumRegions(numRegions); for (unsigned regionIdx = 0; regionIdx < numRegions; ++ regionIdx) { Scalar rhoRefO = densityKeyword.getRecord(regionIdx).getItem("OIL").getSIDouble(0); Scalar rhoRefG = densityKeyword.getRecord(regionIdx).getItem("GAS").getSIDouble(0); Scalar rhoRefW = densityKeyword.getRecord(regionIdx).getItem("WATER").getSIDouble(0); setReferenceDensities(regionIdx, rhoRefO, rhoRefG, rhoRefW); } // initialize the internal table objects for (unsigned regionIdx = 0; regionIdx < numRegions; ++ regionIdx) { const auto& pvtoTable = pvtoTables[regionIdx]; const auto& saturatedTable = pvtoTable.getSaturatedTable(); assert(saturatedTable.numRows() > 1); auto& oilMu = oilMuTable_[regionIdx]; auto& satOilMu = saturatedOilMuTable_[regionIdx]; auto& invOilB = inverseOilBTable_[regionIdx]; auto& invSatOilB = inverseSaturatedOilBTable_[regionIdx]; auto& gasDissolutionFac = saturatedGasDissolutionFactorTable_[regionIdx]; std::vector<Scalar> invSatOilBArray; std::vector<Scalar> satOilMuArray; // extract the table for the gas dissolution and the oil formation volume factors for (unsigned outerIdx = 0; outerIdx < saturatedTable.numRows(); ++ outerIdx) { Scalar Rs = saturatedTable.get("RS", outerIdx); Scalar BoSat = saturatedTable.get("BO", outerIdx); Scalar muoSat = saturatedTable.get("MU", outerIdx); satOilMuArray.push_back(muoSat); invSatOilBArray.push_back(1.0/BoSat); invOilB.appendXPos(Rs); oilMu.appendXPos(Rs); assert(invOilB.numX() == outerIdx + 1); assert(oilMu.numX() == outerIdx + 1); const auto& underSaturatedTable = pvtoTable.getUnderSaturatedTable(outerIdx); size_t numRows = underSaturatedTable.numRows(); for (unsigned innerIdx = 0; innerIdx < numRows; ++ innerIdx) { Scalar po = underSaturatedTable.get("P", innerIdx); Scalar Bo = underSaturatedTable.get("BO", innerIdx); Scalar muo = underSaturatedTable.get("MU", innerIdx); invOilB.appendSamplePoint(outerIdx, po, 1.0/Bo); oilMu.appendSamplePoint(outerIdx, po, muo); } } // update the tables for the formation volume factor and for the gas // dissolution factor of saturated oil { const auto& tmpPressureColumn = saturatedTable.getColumn("P"); const auto& tmpGasSolubilityColumn = saturatedTable.getColumn("RS"); invSatOilB.setXYContainers(tmpPressureColumn, invSatOilBArray); satOilMu.setXYContainers(tmpPressureColumn, satOilMuArray); gasDissolutionFac.setXYContainers(tmpPressureColumn, tmpGasSolubilityColumn); } updateSaturationPressure_(regionIdx); // make sure to have at least two sample points per Rs value for (unsigned xIdx = 0; xIdx < invOilB.numX(); ++xIdx) { // a single sample point is definitely needed assert(invOilB.numY(xIdx) > 0); // everything is fine if the current table has two or more sampling points // for a given mole fraction if (invOilB.numY(xIdx) > 1) continue; // find the master table which will be used as a template to extend the // current line. We define master table as the first table which has values // for undersaturated oil... size_t masterTableIdx = xIdx + 1; for (; masterTableIdx < saturatedTable.numRows(); ++masterTableIdx) { if (pvtoTable.getUnderSaturatedTable(masterTableIdx).numRows() > 1) break; } if (masterTableIdx >= saturatedTable.numRows()) throw std::runtime_error("PVTO tables are invalid: The last table must exhibit at least one " "entry for undersaturated oil!"); // extend the current table using the master table. extendPvtoTable_(regionIdx, xIdx, pvtoTable.getUnderSaturatedTable(xIdx), pvtoTable.getUnderSaturatedTable(masterTableIdx)); } } vapPar2_ = 0.0; if (deck.hasKeyword("VAPPARS")) { const auto& vapParsKeyword = deck.getKeyword("VAPPARS"); vapPar2_ = vapParsKeyword.getRecord(0).getItem("OIL_DENSITY_PROPENSITY").template get<double>(0); } initEnd(); }
double prod_opr(const EclipseState& es, const Schedule& /* sched */, const data::Solution& /* sol */, size_t /* report_step */, double seconds_elapsed) { const auto& units = es.getUnits(); return -units.to_si(UnitSystem::measure::rate, seconds_elapsed); }
/*! * \brief Implement the temperature part of the gas PVT properties. */ void initFromDeck(const Deck& deck, const EclipseState& eclState) { ////// // initialize the isothermal part ////// isothermalPvt_ = new IsothermalPvt; isothermalPvt_->initFromDeck(deck, eclState); ////// // initialize the thermal part ////// const auto& tables = eclState.getTableManager(); enableThermalDensity_ = deck.hasKeyword("GASDENT"); enableThermalViscosity_ = deck.hasKeyword("GASVISCT"); enableInternalEnergy_ = deck.hasKeyword("SPECHEAT"); unsigned numRegions = isothermalPvt_->numRegions(); setNumRegions(numRegions); // viscosity if (enableThermalViscosity_) { const auto& gasvisctTables = tables.getGasvisctTables(); int gasCompIdx = deck.getKeyword("GCOMPIDX").getRecord(0).getItem("GAS_COMPONENT_INDEX").get< int >(0) - 1; std::string gasvisctColumnName = "Viscosity"+std::to_string(static_cast<long long>(gasCompIdx)); for (unsigned regionIdx = 0; regionIdx < numRegions; ++regionIdx) { const auto& T = gasvisctTables[regionIdx].getColumn("Temperature").vectorCopy(); const auto& mu = gasvisctTables[regionIdx].getColumn(gasvisctColumnName).vectorCopy(); gasvisctCurves_[regionIdx].setXYContainers(T, mu); } } // temperature dependence of gas density if (enableThermalDensity_) { const auto& gasdentKeyword = deck.getKeyword("GASDENT"); assert(gasdentKeyword.size() == numRegions); for (unsigned regionIdx = 0; regionIdx < numRegions; ++regionIdx) { const auto& gasdentRecord = gasdentKeyword.getRecord(regionIdx); gasdentRefTemp_[regionIdx] = gasdentRecord.getItem("REFERENCE_TEMPERATURE").getSIDouble(0); gasdentCT1_[regionIdx] = gasdentRecord.getItem("EXPANSION_COEFF_LINEAR").getSIDouble(0); gasdentCT2_[regionIdx] = gasdentRecord.getItem("EXPANSION_COEFF_QUADRATIC").getSIDouble(0); } } if (deck.hasKeyword("SPECHEAT")) { // the specific internal energy of gas. be aware that ecl only specifies the heat capacity // (via the SPECHEAT keyword) and we need to integrate it ourselfs to get the // internal energy for (unsigned regionIdx = 0; regionIdx < numRegions; ++regionIdx) { const auto& specHeatTable = tables.getSpecheatTables()[regionIdx]; const auto& temperatureColumn = specHeatTable.getColumn("TEMPERATURE"); const auto& cvGasColumn = specHeatTable.getColumn("CV_GAS"); std::vector<double> uSamples(temperatureColumn.size()); // the specific enthalpy of vaporization. since ECL does not seem to // feature a proper way to specify this quantity, we use the value for // methane. A proper model would also need to consider the enthalpy // change due to dissolution, i.e. the enthalpies of the gas and oil // phases should depend on the phase composition const Scalar hVap = 480.6e3; // [J / kg] Scalar u = temperatureColumn[0]*cvGasColumn[0] + hVap; for (size_t i = 0;; ++i) { uSamples[i] = u; if (i >= temperatureColumn.size() - 1) break; // integrate to the heat capacity from the current sampling point to the next // one. this leads to a quadratic polynomial. Scalar c_v0 = cvGasColumn[i]; Scalar c_v1 = cvGasColumn[i + 1]; Scalar T0 = temperatureColumn[i]; Scalar T1 = temperatureColumn[i + 1]; u += 0.5*(c_v0 + c_v1)*(T1 - T0); } internalEnergyCurves_[regionIdx].setXYContainers(temperatureColumn.vectorCopy(), uSamples); } } }
void RelpermDiagnostics::scaledEndPointsCheck_(const Deck& deck, const EclipseState& eclState, const GridT& grid) { const int nc = Opm::UgGridHelpers::numCells(grid); const auto& global_cell = Opm::UgGridHelpers::globalCell(grid); const auto dims = Opm::UgGridHelpers::cartDims(grid); const auto& compressedToCartesianIdx = Opm::compressedToCartesian(nc, global_cell); scaledEpsInfo_.resize(nc); EclEpsGridProperties epsGridProperties; epsGridProperties.initFromDeck(deck, eclState, /*imbibition=*/false); const auto& satnum = eclState.get3DProperties().getIntGridProperty("SATNUM"); const std::string tag = "Scaled endpoints"; for (int c = 0; c < nc; ++c) { const int cartIdx = compressedToCartesianIdx[c]; const std::string satnumIdx = std::to_string(satnum.iget(cartIdx)); std::array<int, 3> ijk; ijk[0] = cartIdx % dims[0]; ijk[1] = (cartIdx / dims[0]) % dims[1]; ijk[2] = cartIdx / dims[0] / dims[1]; const std::string cellIdx = "(" + std::to_string(ijk[0]) + ", " + std::to_string(ijk[1]) + ", " + std::to_string(ijk[2]) + ")"; scaledEpsInfo_[c].extractScaled(eclState, epsGridProperties, cartIdx); // SGU <= 1.0 - SWL if (scaledEpsInfo_[c].Sgu > (1.0 - scaledEpsInfo_[c].Swl)) { const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SGU exceed 1.0 - SWL"; OpmLog::warning(tag, msg); } // SGL <= 1.0 - SWU if (scaledEpsInfo_[c].Sgl > (1.0 - scaledEpsInfo_[c].Swu)) { const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SGL exceed 1.0 - SWU"; OpmLog::warning(tag, msg); } if (deck.hasKeyword("SCALECRS") && fluidSystem_ == FluidSystem::BlackOil) { // Mobilility check. if ((scaledEpsInfo_[c].Sowcr + scaledEpsInfo_[c].Swcr) >= 1.0) { const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SOWCR + SWCR exceed 1.0"; OpmLog::warning(tag, msg); } if ((scaledEpsInfo_[c].Sogcr + scaledEpsInfo_[c].Sgcr + scaledEpsInfo_[c].Swl) >= 1.0) { const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SOGCR + SGCR + SWL exceed 1.0"; OpmLog::warning(tag, msg); } } ///Following rules come from NEXUS. if (fluidSystem_ != FluidSystem::WaterGas) { if (scaledEpsInfo_[c].Swl > scaledEpsInfo_[c].Swcr) { const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SWL > SWCR"; OpmLog::warning(tag, msg); } if (scaledEpsInfo_[c].Swcr > scaledEpsInfo_[c].Sowcr) { const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SWCR > SOWCR"; OpmLog::warning(tag, msg); } if (scaledEpsInfo_[c].Sowcr > scaledEpsInfo_[c].Swu) { const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SOWCR > SWU"; OpmLog::warning(tag, msg); } } if (fluidSystem_ != FluidSystem::OilWater) { if (scaledEpsInfo_[c].Sgl > scaledEpsInfo_[c].Sgcr) { const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SGL > SGCR"; OpmLog::warning(tag, msg); } } if (fluidSystem_ != FluidSystem::BlackOil) { if (scaledEpsInfo_[c].Sgcr > scaledEpsInfo_[c].Sogcr) { const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SGCR > SOGCR"; OpmLog::warning(tag, msg); } if (scaledEpsInfo_[c].Sogcr > scaledEpsInfo_[c].Sgu) { const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SOGCR > SGU"; OpmLog::warning(tag, msg); } } } }
/*! * \brief Implement the temperature part of the oil PVT properties. */ void initFromDeck(const Deck& deck, const EclipseState& eclState) { ////// // initialize the isothermal part ////// isothermalPvt_ = new IsothermalPvt; isothermalPvt_->initFromDeck(deck, eclState); ////// // initialize the thermal part ////// const auto& tables = eclState.getTableManager(); enableThermalDensity_ = deck.hasKeyword("OILDENT"); enableThermalViscosity_ = deck.hasKeyword("OILVISCT"); enableInternalEnergy_ = deck.hasKeyword("SPECHEAT"); unsigned numRegions = isothermalPvt_->numRegions(); setNumRegions(numRegions); // viscosity if (deck.hasKeyword("OILVISCT")) { if (!deck.hasKeyword("VISCREF")) throw std::runtime_error("VISCREF is required when OILVISCT is present"); const auto& oilvisctTables = tables.getOilvisctTables(); const auto& viscrefKeyword = deck.getKeyword("VISCREF"); assert(oilvisctTables.size() == numRegions); assert(viscrefKeyword.size() == numRegions); for (unsigned regionIdx = 0; regionIdx < numRegions; ++regionIdx) { const auto& TCol = oilvisctTables[regionIdx].getColumn("Temperature").vectorCopy(); const auto& muCol = oilvisctTables[regionIdx].getColumn("Viscosity").vectorCopy(); oilvisctCurves_[regionIdx].setXYContainers(TCol, muCol); const auto& viscrefRecord = viscrefKeyword.getRecord(regionIdx); viscrefPress_[regionIdx] = viscrefRecord.getItem("REFERENCE_PRESSURE").getSIDouble(0); viscrefRs_[regionIdx] = viscrefRecord.getItem("REFERENCE_RS").getSIDouble(0); // temperature used to calculate the reference viscosity [K]. the // value does not really matter if the underlying PVT object really // is isothermal... Scalar Tref = 273.15 + 20; // compute the reference viscosity using the isothermal PVT object. viscRef_[regionIdx] = isothermalPvt_->viscosity(regionIdx, Tref, viscrefPress_[regionIdx], viscrefRs_[regionIdx]); } } // temperature dependence of oil density if (enableThermalDensity_) { const auto& oildentKeyword = deck.getKeyword("OILDENT"); assert(oildentKeyword.size() == numRegions); for (unsigned regionIdx = 0; regionIdx < numRegions; ++regionIdx) { const auto& oildentRecord = oildentKeyword.getRecord(regionIdx); oildentRefTemp_[regionIdx] = oildentRecord.getItem("REFERENCE_TEMPERATURE").getSIDouble(0); oildentCT1_[regionIdx] = oildentRecord.getItem("EXPANSION_COEFF_LINEAR").getSIDouble(0); oildentCT2_[regionIdx] = oildentRecord.getItem("EXPANSION_COEFF_QUADRATIC").getSIDouble(0); } } if (deck.hasKeyword("SPECHEAT")) { // the specific internal energy of liquid oil. be aware that ecl only specifies the // heat capacity (via the SPECHEAT keyword) and we need to integrate it // ourselfs to get the internal energy for (unsigned regionIdx = 0; regionIdx < numRegions; ++regionIdx) { const auto& specheatTable = tables.getSpecheatTables()[regionIdx]; const auto& temperatureColumn = specheatTable.getColumn("TEMPERATURE"); const auto& cvOilColumn = specheatTable.getColumn("CV_OIL"); std::vector<double> uSamples(temperatureColumn.size()); Scalar u = temperatureColumn[0]*cvOilColumn[0]; for (size_t i = 0;; ++i) { uSamples[i] = u; if (i >= temperatureColumn.size() - 1) break; // integrate to the heat capacity from the current sampling point to the next // one. this leads to a quadratic polynomial. Scalar c_v0 = cvOilColumn[i]; Scalar c_v1 = cvOilColumn[i + 1]; Scalar T0 = temperatureColumn[i]; Scalar T1 = temperatureColumn[i + 1]; u += 0.5*(c_v0 + c_v1)*(T1 - T0); } internalEnergyCurves_[regionIdx].setXYContainers(temperatureColumn.vectorCopy(), uSamples); } } }
double prod_wpr_P3(const EclipseState& es, const Schedule& sched, const data::Solution& sol, size_t report_step, double seconds_elapsed) { const auto& units = es.getUnits(); double water_rate = 0.0; return -units.to_si(UnitSystem::measure::rate, water_rate); }