RockCompressibility::RockCompressibility(Opm::DeckConstPtr deck, Opm::EclipseStateConstPtr eclipseState) : pref_(0.0), rock_comp_(0.0) { const auto tables = eclipseState->getTableManager(); const auto& rocktabTables = tables->getRocktabTables(); if (rocktabTables.size() > 0) { const auto& rocktabTable = rocktabTables.getTable<RocktabTable>(0); if (rocktabTables.size() != 1) OPM_THROW(std::runtime_error, "Can only handle a single region in ROCKTAB."); p_ = rocktabTable.getColumn("PO").vectorCopy( ); poromult_ = rocktabTable.getColumn("PV_MULT").vectorCopy(); if (rocktabTable.hasColumn("PV_MULT_TRAN")) { transmult_ = rocktabTable.getColumn("PV_MULT_TRAN").vectorCopy(); } else { transmult_ = rocktabTable.getColumn("PV_MULT_TRANX").vectorCopy(); } } else if (deck->hasKeyword("ROCK")) { Opm::DeckKeywordConstPtr rockKeyword = deck->getKeyword("ROCK"); if (rockKeyword->size() != 1) { // here it would be better not to use std::cout directly but to add the // warning to some "warning list"... std::cout << "Can only handle a single region in ROCK ("<<rockKeyword->size()<<" regions specified)." << " Ignoring all except for the first.\n"; } pref_ = rockKeyword->getRecord(0)->getItem("PREF")->getSIDouble(0); rock_comp_ = rockKeyword->getRecord(0)->getItem("COMPRESSIBILITY")->getSIDouble(0); } else { std::cout << "**** warning: no rock compressibility data found in deck (ROCK or ROCKTAB)." << std::endl; } }
/// set the tables which specify the temperature dependence of the water viscosity void initFromDeck(std::shared_ptr<const PvtInterface> isothermalPvt, Opm::DeckConstPtr deck, Opm::EclipseStateConstPtr eclipseState) { isothermalPvt_ = isothermalPvt; watvisctTables_ = 0; // stuff which we need to get from the PVTW keyword Opm::DeckKeywordConstPtr pvtwKeyword = deck->getKeyword("PVTW"); int numRegions = pvtwKeyword->size(); pvtwRefPress_.resize(numRegions); pvtwRefB_.resize(numRegions); pvtwCompressibility_.resize(numRegions); pvtwViscosity_.resize(numRegions); pvtwViscosibility_.resize(numRegions); for (int regionIdx = 0; regionIdx < numRegions; ++ regionIdx) { Opm::DeckRecordConstPtr pvtwRecord = pvtwKeyword->getRecord(regionIdx); pvtwRefPress_[regionIdx] = pvtwRecord->getItem("P_REF")->getSIDouble(0); pvtwRefB_[regionIdx] = pvtwRecord->getItem("WATER_VOL_FACTOR")->getSIDouble(0); pvtwViscosity_[regionIdx] = pvtwRecord->getItem("WATER_VISCOSITY")->getSIDouble(0); pvtwViscosibility_[regionIdx] = pvtwRecord->getItem("WATER_VISCOSIBILITY")->getSIDouble(0); } // quantities required for the temperature dependence of the viscosity // (basically we expect well-behaved VISCREF and WATVISCT keywords.) if (deck->hasKeyword("VISCREF")) { watvisctTables_ = &eclipseState->getWatvisctTables(); Opm::DeckKeywordConstPtr viscrefKeyword = deck->getKeyword("VISCREF"); assert(int(watvisctTables_->size()) == numRegions); assert(int(viscrefKeyword->size()) == numRegions); viscrefPress_.resize(numRegions); for (int regionIdx = 0; regionIdx < numRegions; ++ regionIdx) { Opm::DeckRecordConstPtr viscrefRecord = viscrefKeyword->getRecord(regionIdx); viscrefPress_[regionIdx] = viscrefRecord->getItem("REFERENCE_PRESSURE")->getSIDouble(0); } } // quantities required for the temperature dependence of the density if (deck->hasKeyword("WATDENT")) { DeckKeywordConstPtr watdentKeyword = deck->getKeyword("WATDENT"); assert(int(watdentKeyword->size()) == numRegions); watdentRefTemp_.resize(numRegions); watdentCT1_.resize(numRegions); watdentCT2_.resize(numRegions); for (int regionIdx = 0; regionIdx < numRegions; ++regionIdx) { Opm::DeckRecordConstPtr 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); } } }
void GridManager::createGrdecl(Opm::DeckConstPtr deck, struct grdecl &grdecl) { // Extract data from deck. const std::vector<double>& zcorn = deck->getKeyword("ZCORN")->getSIDoubleData(); const std::vector<double>& coord = deck->getKeyword("COORD")->getSIDoubleData(); const int* actnum = NULL; if (deck->hasKeyword("ACTNUM")) { actnum = &(deck->getKeyword("ACTNUM")->getIntData()[0]); } std::array<int, 3> dims; if (deck->hasKeyword("DIMENS")) { Opm::DeckKeywordConstPtr dimensKeyword = deck->getKeyword("DIMENS"); dims[0] = dimensKeyword->getRecord(0)->getItem(0)->getInt(0); dims[1] = dimensKeyword->getRecord(0)->getItem(1)->getInt(0); dims[2] = dimensKeyword->getRecord(0)->getItem(2)->getInt(0); } else if (deck->hasKeyword("SPECGRID")) { Opm::DeckKeywordConstPtr specgridKeyword = deck->getKeyword("SPECGRID"); dims[0] = specgridKeyword->getRecord(0)->getItem(0)->getInt(0); dims[1] = specgridKeyword->getRecord(0)->getItem(1)->getInt(0); dims[2] = specgridKeyword->getRecord(0)->getItem(2)->getInt(0); } else { OPM_THROW(std::runtime_error, "Deck must have either DIMENS or SPECGRID."); } // Collect in input struct for preprocessing. grdecl.zcorn = &zcorn[0]; grdecl.coord = &coord[0]; grdecl.actnum = actnum; grdecl.dims[0] = dims[0]; grdecl.dims[1] = dims[1]; grdecl.dims[2] = dims[2]; if (deck->hasKeyword("MAPAXES")) { Opm::DeckKeywordConstPtr mapaxesKeyword = deck->getKeyword("MAPAXES"); Opm::DeckRecordConstPtr mapaxesRecord = mapaxesKeyword->getRecord(0); // memleak alert: here we need to make sure that C code // can properly take ownership of the grdecl.mapaxes // object. if it is not freed, it will result in a // memleak... double *cWtfMapaxes = static_cast<double*>(malloc(sizeof(double)*mapaxesRecord->size())); for (unsigned i = 0; i < mapaxesRecord->size(); ++i) cWtfMapaxes[i] = mapaxesRecord->getItem(i)->getSIDouble(0); grdecl.mapaxes = cWtfMapaxes; } else grdecl.mapaxes = NULL; }
void PolymerInflowFromDeck::setInflowValues(Opm::DeckConstPtr deck, Opm::EclipseStateConstPtr eclipseState, size_t currentStep) { Opm::DeckKeywordConstPtr keyword = deck->getKeyword("WPOLYMER"); // Schedule schedule(deck); ScheduleConstPtr schedule = eclipseState->getSchedule(); for (size_t recordNr = 0; recordNr < keyword->size(); recordNr++) { DeckRecordConstPtr record = keyword->getRecord(recordNr); const std::string& wellNamesPattern = record->getItem("WELL")->getTrimmedString(0); std::string wellName = record->getItem("WELL")->getTrimmedString(0); std::vector<WellPtr> wells = schedule->getWells(wellNamesPattern); for (auto wellIter = wells.begin(); wellIter != wells.end(); ++wellIter) { WellPtr well = *wellIter; WellInjectionProperties injection = well->getInjectionProperties(currentStep); if (injection.injectorType == WellInjector::WATER) { WellPolymerProperties polymer = well->getPolymerProperties(currentStep); wellPolymerRate_.insert(std::make_pair(wellName, polymer.m_polymerConcentration)); } else { OPM_THROW(std::logic_error, "For polymer injector you must have a water injector"); } } } }
/// Constructor. /// @param[in] deck Input deck expected to contain WPOLYMER. PolymerInflowFromDeck::PolymerInflowFromDeck(Opm::DeckConstPtr deck, const Wells& wells, const int num_cells) : sparse_inflow_(num_cells) { if (!deck->hasKeyword("WPOLYMER")) { OPM_MESSAGE("PolymerInflowFromDeck initialized without WPOLYMER in current epoch."); return; } // Extract concentrations and put into cell->concentration map. Opm::DeckKeywordConstPtr wpolymerKeyword = deck->getKeyword("WPOLYMER"); const int num_wpl = wpolymerKeyword->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 (wpolymerKeyword->getRecord(i)->getItem("WELL")->getString(0) == wells.name[wix]) { break; } } if (wix == wells.number_of_wells) { OPM_THROW(std::runtime_error, "Could not find a match for well " << wpolymerKeyword->getRecord(i)->getItem("WELL")->getString(0) << " 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] = wpolymerKeyword->getRecord(i)->getItem("POLYMER_CONCENTRATION")->getSIDouble(0); } } // 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); } }
/*! * \brief Reads all relevant material parameters form a cell of a parsed ECL deck. * * This requires that the opm-parser module is available. */ void initFromDeck(Opm::DeckConstPtr deck) { enableHysteresis_ = false; if (!deck->hasKeyword("SATOPTS")) return; Opm::DeckItemConstPtr satoptsItem = deck->getKeyword("SATOPTS")->getRecord(0)->getItem(0); for (unsigned i = 0; i < satoptsItem->size(); ++i) { std::string satoptsValue = satoptsItem->getString(0); std::transform(satoptsValue.begin(), satoptsValue.end(), satoptsValue.begin(), ::toupper); if (satoptsValue == "HYSTER") enableHysteresis_ = true; } // check for the (deprecated) HYST keyword if (deck->hasKeyword("HYST")) enableHysteresis_ = true; if (!enableHysteresis_) return; if (!deck->hasKeyword("EHYSTR")) OPM_THROW(std::runtime_error, "Enabling hysteresis via the HYST parameter for SATOPTS requires the " "presence of the EHYSTR keyword"); Opm::DeckKeywordConstPtr ehystrKeyword = deck->getKeyword("EHYSTR"); if (deck->hasKeyword("NOHYKR")) krHysteresisModel_ = -1; else { krHysteresisModel_ = ehystrKeyword->getRecord(0)->getItem("relative_perm_hyst")->getInt(0); if (krHysteresisModel_ != 0) OPM_THROW(std::runtime_error, "Only the Carlson kr hystersis model (indicated by a 0 on the second item" " of the 'EHYSTR' keyword) is supported"); } if (deck->hasKeyword("NOHYPC")) pcHysteresisModel_ = -1; else { // if capillary pressure hysteresis is enabled, Eclipse always uses the // Killough model pcHysteresisModel_ = 0; } }
void initFromOil(Opm::DeckKeywordConstPtr pvcdoKeyword) { int numRegions = pvcdoKeyword->size(); ref_press_.resize(numRegions); ref_B_.resize(numRegions); comp_.resize(numRegions); viscosity_.resize(numRegions); visc_comp_.resize(numRegions); for (int regionIdx = 0; regionIdx < numRegions; ++ regionIdx) { Opm::DeckRecordConstPtr pvcdoRecord = pvcdoKeyword->getRecord(regionIdx); ref_press_[regionIdx] = pvcdoRecord->getItem("P_REF")->getSIDouble(0); ref_B_[regionIdx] = pvcdoRecord->getItem("OIL_VOL_FACTOR")->getSIDouble(0); comp_[regionIdx] = pvcdoRecord->getItem("OIL_COMPRESSIBILITY")->getSIDouble(0); viscosity_[regionIdx] = pvcdoRecord->getItem("OIL_VISCOSITY")->getSIDouble(0); visc_comp_[regionIdx] = pvcdoRecord->getItem("OIL_VISCOSIBILITY")->getSIDouble(0); } }
TimeMap::TimeMap(Opm::DeckConstPtr deck) { // The default start date is not specified in the Eclipse // reference manual. We hence just assume it is same as for // the START keyword for Eclipse R100, i.e., January 1st, // 1983... boost::posix_time::ptime startTime(boost::gregorian::date(1983, 1, 1)); // use the 'START' keyword to find out the start date (if the // keyword was specified) if (deck->hasKeyword("START")) { Opm::DeckKeywordConstPtr keyword = deck->getKeyword("START"); startTime = timeFromEclipse(keyword->getRecord(/*index=*/0)); } m_timeList.push_back( startTime ); // find all "TSTEP" and "DATES" keywords in the deck and deal // with them one after another size_t numKeywords = deck->size(); for (size_t keywordIdx = 0; keywordIdx < numKeywords; ++keywordIdx) { Opm::DeckKeywordConstPtr keyword = deck->getKeyword(keywordIdx); // We're only interested in "TSTEP" and "DATES" keywords, // so we ignore everything else here... if (keyword->name() != "TSTEP" && keyword->name() != "DATES") { continue; } if (keyword->name() == "TSTEP") addFromTSTEPKeyword(keyword); else if (keyword->name() == "DATES") addFromDATESKeyword(keyword); } }
/*! * \brief Implement the temperature part of the oil PVT properties. */ void initFromDeck(DeckConstPtr deck, EclipseStateConstPtr eclState) { ////// // initialize the isothermal part ////// isothermalPvt_ = new IsothermalPvt; isothermalPvt_->initFromDeck(deck, eclState); ////// // initialize the thermal part ////// auto tables = eclState->getTableManager(); enableThermalDensity_ = deck->hasKeyword("THERMEX1"); enableThermalViscosity_ = deck->hasKeyword("VISCREF"); unsigned numRegions = isothermalPvt_->numRegions(); setNumRegions(numRegions); // viscosity if (deck->hasKeyword("VISCREF")) { const auto& oilvisctTables = tables->getOilvisctTables(); Opm::DeckKeywordConstPtr 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); DeckRecordConstPtr 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]); } } // quantities required for density. note that we just always use the values // for the first EOS. (since EOS != PVT region.) refTemp_ = 0.0; if (deck->hasKeyword("THERMEX1")) { int oilCompIdx = deck->getKeyword("OCOMPIDX")->getRecord(0)->getItem("OIL_COMPONENT_INDEX")->getInt(0) - 1; // always use the values of the first EOS refTemp_ = deck->getKeyword("TREF")->getRecord(0)->getItem("TEMPERATURE")->getSIDouble(oilCompIdx); refPress_ = deck->getKeyword("PREF")->getRecord(0)->getItem("PRESSURE")->getSIDouble(oilCompIdx); refC_ = deck->getKeyword("CREF")->getRecord(0)->getItem("COMPRESSIBILITY")->getSIDouble(oilCompIdx); thermex1_ = deck->getKeyword("THERMEX1")->getRecord(0)->getItem("EXPANSION_COEFF")->getSIDouble(oilCompIdx); } }
void BlackoilPvtProperties::init(Opm::DeckConstPtr deck, Opm::EclipseStateConstPtr eclipseState, int numSamples) { phase_usage_ = phaseUsageFromDeck(deck); // Surface densities. Accounting for different orders in eclipse and our code. Opm::DeckKeywordConstPtr densityKeyword = deck->getKeyword("DENSITY"); int numRegions = densityKeyword->size(); densities_.resize(numRegions); for (int regionIdx = 0; regionIdx < numRegions; ++regionIdx) { if (phase_usage_.phase_used[Liquid]) { densities_[regionIdx][phase_usage_.phase_pos[Liquid]] = densityKeyword->getRecord(regionIdx)->getItem("OIL")->getSIDouble(0); } if (phase_usage_.phase_used[Aqua]) { densities_[regionIdx][phase_usage_.phase_pos[Aqua]] = densityKeyword->getRecord(regionIdx)->getItem("WATER")->getSIDouble(0); } if (phase_usage_.phase_used[Vapour]) { densities_[regionIdx][phase_usage_.phase_pos[Vapour]] = densityKeyword->getRecord(regionIdx)->getItem("GAS")->getSIDouble(0); } } // Resize the property objects container props_.resize(phase_usage_.num_phases); // Water PVT if (phase_usage_.phase_used[Aqua]) { // if water is used, we require the presence of the "PVTW" // keyword for now... std::shared_ptr<PvtConstCompr> pvtw(new PvtConstCompr); pvtw->initFromWater(deck->getKeyword("PVTW")); props_[phase_usage_.phase_pos[Aqua]] = pvtw; } { auto tables = eclipseState->getTableManager(); // Oil PVT if (phase_usage_.phase_used[Liquid]) { // for oil, we support the "PVDO", "PVTO" and "PVCDO" // keywords... const auto &pvdoTables = tables->getPvdoTables(); const auto &pvtoTables = tables->getPvtoTables(); if (pvdoTables.size() > 0) { if (numSamples > 0) { auto splinePvt = std::shared_ptr<PvtDeadSpline>(new PvtDeadSpline); splinePvt->initFromOil(pvdoTables, numSamples); props_[phase_usage_.phase_pos[Liquid]] = splinePvt; } else { auto deadPvt = std::shared_ptr<PvtDead>(new PvtDead); deadPvt->initFromOil(pvdoTables); props_[phase_usage_.phase_pos[Liquid]] = deadPvt; } } else if (pvtoTables.size() > 0) { props_[phase_usage_.phase_pos[Liquid]].reset(new PvtLiveOil(pvtoTables)); } else if (deck->hasKeyword("PVCDO")) { std::shared_ptr<PvtConstCompr> pvcdo(new PvtConstCompr); pvcdo->initFromOil(deck->getKeyword("PVCDO")); props_[phase_usage_.phase_pos[Liquid]] = pvcdo; } else { OPM_THROW(std::runtime_error, "Input is missing PVDO, PVCDO or PVTO\n"); } } // Gas PVT if (phase_usage_.phase_used[Vapour]) { // gas can be specified using the "PVDG" or "PVTG" keywords... const auto &pvdgTables = tables->getPvdgTables(); const auto &pvtgTables = tables->getPvtgTables(); if (pvdgTables.size() > 0) { if (numSamples > 0) { std::shared_ptr<PvtDeadSpline> splinePvt(new PvtDeadSpline); splinePvt->initFromGas(pvdgTables, numSamples); props_[phase_usage_.phase_pos[Vapour]] = splinePvt; } else { std::shared_ptr<PvtDead> deadPvt(new PvtDead); deadPvt->initFromGas(pvdgTables); props_[phase_usage_.phase_pos[Vapour]] = deadPvt; } } else if (pvtgTables.size() > 0) { props_[phase_usage_.phase_pos[Vapour]].reset(new PvtLiveGas(pvtgTables)); } else { OPM_THROW(std::runtime_error, "Input is missing PVDG or PVTG\n"); } } } }
/*! * \brief Reads all relevant material parameters form a cell of a parsed ECL deck. * * This requires that the opm-parser module is available. */ void initFromDeck(Opm::DeckConstPtr deck, Opm::EclipseStateConstPtr eclState, Opm::EclTwoPhaseSystemType twoPhaseSystemType) { // find out if endpoint scaling is used in the first place if (!deck->hasKeyword("ENDSCALE")) { // it is not used, i.e., just set all enable$Foo attributes to 0 and be done // with it. enableSatScaling_ = false; enableThreePointKrSatScaling_ = false; enablePcScaling_ = false; enableKrwScaling_ = false; enableKrnScaling_ = false; return; } // endpoint scaling is used, i.e., at least saturation scaling needs to be enabled enableSatScaling_ = true; // check if three-point scaling is to be used for the saturations of the relative // permeabilities if (deck->hasKeyword("SCALECRS")) { // if the deck features the SCALECRS keyword, it must be set to 'YES' Opm::DeckKeywordConstPtr scalecrsKeyword = deck->getKeyword("SCALECRS"); std::string scalecrsValue = scalecrsKeyword->getRecord(0)->getItem("VALUE")->getString(0); // convert the value of the SCALECRS keyword to upper case, just to be sure std::transform(scalecrsValue.begin(), scalecrsValue.end(), scalecrsValue.begin(), ::toupper); if (scalecrsValue == "YES" || scalecrsValue == "Y") enableThreePointKrSatScaling_ = true; else enableThreePointKrSatScaling_ = false; } else enableThreePointKrSatScaling_ = false; // check if we are supposed to scale the Y axis of the capillary pressure if (twoPhaseSystemType == EclOilWaterSystem) enablePcScaling_ = eclState->hasDoubleGridProperty("PCW") || eclState->hasDoubleGridProperty("SWATINIT"); else { assert(twoPhaseSystemType == EclGasOilSystem); enablePcScaling_ = eclState->hasDoubleGridProperty("PCG"); } // check if we are supposed to scale the Y axis of the wetting phase relperm if (twoPhaseSystemType == EclOilWaterSystem) enableKrwScaling_ = eclState->hasDoubleGridProperty("KRW"); else { assert(twoPhaseSystemType == EclGasOilSystem); enableKrwScaling_ = eclState->hasDoubleGridProperty("KRO"); } // check if we are supposed to scale the Y axis of the non-wetting phase relperm if (twoPhaseSystemType == EclOilWaterSystem) enableKrnScaling_ = eclState->hasDoubleGridProperty("KRO"); else { assert(twoPhaseSystemType == EclGasOilSystem); enableKrnScaling_ = eclState->hasDoubleGridProperty("KRG"); } }