IncompPropertiesSinglePhase::IncompPropertiesSinglePhase(const Opm::Deck& deck, const Opm::EclipseState& eclState, const UnstructuredGrid& grid) { rock_.init(eclState, grid.number_of_cells, grid.global_cell, grid.cartdims); if (deck.hasKeyword("DENSITY")) { const auto& densityRecord = deck.getKeyword("DENSITY").getRecord(0); surface_density_ = densityRecord.getItem("OIL").getSIDouble(0); } else { surface_density_ = 1000.0; OPM_MESSAGE("Input is missing DENSITY -- using a standard density of " << surface_density_ << ".\n"); } // This will be modified if we have a PVCDO specification. reservoir_density_ = surface_density_; if (deck.hasKeyword("PVCDO")) { const auto& pvcdoRecord = deck.getKeyword("PVCDO").getRecord(0); if (pvcdoRecord.getItem("OIL_COMPRESSIBILITY").getSIDouble(0) != 0.0 || pvcdoRecord.getItem("OIL_VISCOSIBILITY").getSIDouble(0) != 0.0) { OPM_MESSAGE("Compressibility effects in PVCDO are ignored."); } reservoir_density_ /= pvcdoRecord.getItem("OIL_VOL_FACTOR").getSIDouble(0); viscosity_ = pvcdoRecord.getItem("OIL_VISCOSITY").getSIDouble(0); } else { viscosity_ = 1.0 * prefix::centi*unit::Poise; OPM_MESSAGE("Input is missing PVCDO -- using a standard viscosity of " << viscosity_ << " and reservoir density equal to surface density.\n"); } }
void GridManager::createGrdecl(const Opm::Deck& 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")) { const auto& dimensKeyword = deck.getKeyword("DIMENS"); dims[0] = dimensKeyword.getRecord(0).getItem(0).get< int >(0); dims[1] = dimensKeyword.getRecord(0).getItem(1).get< int >(0); dims[2] = dimensKeyword.getRecord(0).getItem(2).get< int >(0); } else if (deck.hasKeyword("SPECGRID")) { const auto& specgridKeyword = deck.getKeyword("SPECGRID"); dims[0] = specgridKeyword.getRecord(0).getItem(0).get< int >(0); dims[1] = specgridKeyword.getRecord(0).getItem(1).get< int >(0); dims[2] = specgridKeyword.getRecord(0).getItem(2).get< int >(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")) { const auto& mapaxesKeyword = deck.getKeyword("MAPAXES"); const auto& 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; }
static const Opm::DeckKeyword createTABDIMSKeyword( ) { const char* deckData = "TABDIMS\n" " 0 1 2 3 4 5 / \n" "\n"; Opm::Parser parser; Opm::Deck deck = parser.parseString(deckData, Opm::ParseContext()); return deck.getKeyword("TABDIMS"); }
static const Opm::DeckKeyword createSATNUMKeyword( ) { const char* deckData = "SATNUM \n" " 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 / \n" "\n"; Opm::Parser parser; Opm::Deck deck = parser.parseString(deckData, Opm::ParseContext()); return deck.getKeyword("SATNUM"); }
std::vector<double> getMapaxesValues(const Opm::Deck& deck) { const auto& mapaxesRecord = deck.getKeyword("MAPAXES").getRecord(0); std::vector<double> result; for (size_t itemIdx = 0; itemIdx < mapaxesRecord.size(); ++itemIdx) { const auto& curItem = mapaxesRecord.getItem(itemIdx); for (size_t dataItemIdx = 0; dataItemIdx < curItem.size(); ++dataItemIdx) { result.push_back(curItem.get< double >(dataItemIdx)); } } return result; }
/// Mirror keyword SPECGRID in deck void mirror_specgrid( const Opm::Deck& deck, std::string direction, std::ofstream& out) { // We only need to multiply the dimension by 2 in the correct direction. const auto& specgridRecord = deck.getKeyword("SPECGRID").getRecord(0); std::vector<int> dimensions(3); dimensions[0] = specgridRecord.getItem("NX").get< int >(0); dimensions[1] = specgridRecord.getItem("NY").get< int >(0); dimensions[2] = specgridRecord.getItem("NZ").get< int >(0); if (direction == "x") {dimensions[0] *= 2;} else if (direction == "y") {dimensions[1] *= 2;} else {std::cerr << "Direction should be either x or y" << std::endl; exit(1);} out << "SPECGRID" << std::endl << dimensions[0] << " " << dimensions[1] << " " << dimensions[2] << " " << specgridRecord.getItem("NUMRES").get< int >(0) << " " << specgridRecord.getItem("COORD_TYPE").get< std::string >(0) << " " << std::endl << "/" << std::endl << std::endl; }
void mirror_celldata(std::string keyword, const Opm::Deck& deck, std::string direction, std::ofstream& out) { if ( ! deck.hasKeyword(keyword)) { std::cout << "Ignoring keyword " << keyword << " as it was not found." << std::endl; return; } // Get data from eclipse deck const auto& specgridRecord = deck.getKeyword("SPECGRID").getRecord(0); std::vector<int> dimensions(3); dimensions[0] = specgridRecord.getItem("NX").get< int >(0); dimensions[1] = specgridRecord.getItem("NY").get< int >(0); dimensions[2] = specgridRecord.getItem("NZ").get< int >(0); std::vector<T> values = getKeywordValues(keyword, deck, T(0.0)); std::vector<T> values_mirrored(2*dimensions[0]*dimensions[1]*dimensions[2], 0.0); // Handle the two directions differently due to ordering of the pillars. if (direction == "x") { typename std::vector<T>::iterator it_orig = values.begin(); typename std::vector<T>::iterator it_new = values_mirrored.begin(); // Loop through each line and copy old cell data and add new (which are the old reversed) for ( ; it_orig != values.end(); it_orig += dimensions[0]) { // Copy old cell data copy(it_orig, it_orig + dimensions[0], it_new); it_new += dimensions[0]; // Add new cell data std::vector<double> next_vec(it_orig, it_orig + dimensions[0]); std::vector<double> next_reversed = next_vec; reverse(next_reversed.begin(), next_reversed.end()); copy(next_reversed.begin(), next_reversed.end(), it_new); it_new += dimensions[0]; } } else if (direction =="y") { typename std::vector<T>::iterator it_orig = values.begin(); typename std::vector<T>::iterator it_new = values_mirrored.begin(); // Entries per layer const int entries_per_layer = dimensions[0]*dimensions[1]; // Loop through each layer and copy old cell data and add new (which are the old reordered) for ( ; it_orig != values.end(); it_orig += entries_per_layer) { // Copy old cell data copy(it_orig, it_orig + entries_per_layer, it_new); it_new += entries_per_layer; // Add new cell data std::vector<T> next_vec(it_orig, it_orig + entries_per_layer); std::vector<T> next_reordered(entries_per_layer, 0.0); typename std::vector<T>::iterator it_next = next_vec.end(); typename std::vector<T>::iterator it_reordered = next_reordered.begin(); // Reorder next entries for ( ; it_reordered != next_reordered.end(); it_reordered += dimensions[0]) { copy(it_next - dimensions[0], it_next, it_reordered); it_next -= dimensions[0]; } copy(next_reordered.begin(), next_reordered.end(), it_new); it_new += entries_per_layer; } } else { std::cerr << "Direction should be either x or y" << std::endl; exit(1); } // Write new keyword values to output file printKeywordValues(out, keyword, values_mirrored, 8); }
std::vector<double> getKeywordValues(std::string keyword, const Opm::Deck& deck, double /*dummy*/) { return deck.getKeyword(keyword).getRawDoubleData(); }
std::vector<int> getKeywordValues(std::string keyword, const Opm::Deck& deck, int /*dummy*/) { return deck.getKeyword(keyword).getIntData(); }
/// Mirror keyword ZCORN in deck void mirror_zcorn(const Opm::Deck& deck, std::string direction, std::ofstream& out) { const auto& specgridRecord = deck.getKeyword("SPECGRID").getRecord(0); std::vector<int> dimensions(3); dimensions[0] = specgridRecord.getItem("NX").get< int >(0); dimensions[1] = specgridRecord.getItem("NY").get< int >(0); dimensions[2] = specgridRecord.getItem("NZ").get< int >(0); std::vector<double> zcorn = deck.getKeyword("ZCORN").getRawDoubleData(); std::vector<double> zcorn_mirrored; // Handle the two directions differently due to ordering of the pillars. if (direction == "x") { // Total entries in mirrored ZCORN. Eight corners per cell. const int entries = dimensions[0]*2*dimensions[1]*dimensions[2]*8; zcorn_mirrored.assign(entries, 0.0); // Entries per line in x-direction. Two for each cell. const int entries_per_line = dimensions[0]*2; std::vector<double>::iterator it_new = zcorn_mirrored.begin(); std::vector<double>::iterator it_orig = zcorn.begin(); // Loop through each line and copy old corner-points and add new (which are the old reversed) for ( ; it_orig != zcorn.end(); it_orig += entries_per_line) { std::vector<double> next_vec(it_orig, it_orig + entries_per_line); std::vector<double> next_reversed = next_vec; reverse(next_reversed.begin(), next_reversed.end()); // Copy old corner-points copy(it_orig, it_orig + entries_per_line, it_new); it_new += entries_per_line; // Add new corner-points copy(next_reversed.begin(), next_reversed.end(), it_new); it_new += entries_per_line; } } else if (direction == "y") { // Total entries in mirrored ZCORN. Eight corners per cell. const int entries = dimensions[0]*dimensions[1]*2*dimensions[2]*8; zcorn_mirrored.assign(entries, 0.0); // Entries per line in x-direction. Two for each cell. const int entries_per_line_x = dimensions[0]*2; // Entries per layer of corner-points. Four for each cell const int entries_per_layer = dimensions[0]*dimensions[1]*4; std::vector<double>::iterator it_new = zcorn_mirrored.begin(); std::vector<double>::iterator it_orig = zcorn.begin(); // Loop through each layer and copy old corner-points and add new (which are the old reordered) for ( ; it_orig != zcorn.end(); it_orig += entries_per_layer) { // Copy old corner-points copy(it_orig, it_orig + entries_per_layer, it_new); it_new += entries_per_layer; // Add new corner-points std::vector<double> next_vec(it_orig, it_orig + entries_per_layer); std::vector<double> next_reordered(entries_per_layer, 0.0); std::vector<double>::iterator it_next = next_vec.end(); std::vector<double>::iterator it_reordered = next_reordered.begin(); // Reorder next entries for ( ; it_reordered != next_reordered.end(); it_reordered += entries_per_line_x) { copy(it_next - entries_per_line_x, it_next, it_reordered); it_next -= entries_per_line_x; } copy(next_reordered.begin(), next_reordered.end(), it_new); it_new += entries_per_layer; } } else { std::cerr << "Direction should be either x or y" << std::endl; exit(1); } // Write new ZCORN values to output file printKeywordValues(out, "ZCORN", zcorn_mirrored, 8); }
/// Mirror keyword COORD in deck void mirror_coord(const Opm::Deck& deck, std::string direction, std::ofstream& out) { // We assume uniform spacing in x and y directions and parallel top and bottom faces const auto& specgridRecord = deck.getKeyword("SPECGRID").getRecord(0); std::vector<int> dimensions(3); dimensions[0] = specgridRecord.getItem("NX").get< int >(0); dimensions[1] = specgridRecord.getItem("NY").get< int >(0); dimensions[2] = specgridRecord.getItem("NZ").get< int >(0); std::vector<double> coord = deck.getKeyword("COORD").getRawDoubleData(); const int entries_per_pillar = 6; std::vector<double> coord_mirrored; // Handle the two directions differently due to ordering of the pillars. if (direction == "x") { // Total entries in mirrored ZCORN. Number of pillars times 6 const int entries = (2*dimensions[0] + 1) * (dimensions[1] + 1) * entries_per_pillar; // Entries per line in x-direction. Number of pillars in x-direction times 6 const int entries_per_line = entries_per_pillar*(dimensions[0] + 1); coord_mirrored.assign(entries, 0.0); // Distance between pillars in x-directiion const double spacing = coord[entries_per_pillar]-coord[0]; std::vector<double>::iterator it_new = coord_mirrored.begin(); std::vector<double>::iterator it_orig; // Loop through each pillar line in the x-direction for (it_orig = coord.begin(); it_orig != coord.end(); it_orig += entries_per_line) { // Copy old pillars copy(it_orig, it_orig + entries_per_line, it_new); // Add new pillars in between it_new += entries_per_line; std::vector<double> next_vec(it_orig + entries_per_line - entries_per_pillar, it_orig + entries_per_line); for (int r=0; r < dimensions[0]; ++r) { next_vec[0] += spacing; next_vec[3] += spacing; copy(next_vec.begin(), next_vec.end(), it_new); it_new += entries_per_pillar; } } } else if (direction == "y") { // Total entries in mirrored ZCORN. Number of pillars times 6 const int entries = (dimensions[0] + 1) * (2*dimensions[1] + 1) * entries_per_pillar; // Entries per line in y-direction. Number of pillars in y-direction times 6 const int entries_per_line = entries_per_pillar*(dimensions[0] + 1); coord_mirrored.assign(entries, 0.0); // Distance between pillars in y-directiion const double spacing = coord[entries_per_line + 1]-coord[1]; std::vector<double>::iterator it_new = coord_mirrored.begin(); // Copy old pillars copy(coord.begin(), coord.end(), it_new); // Add new pillars at the end it_new += coord.size(); std::vector<double> next_vec(coord.end() - entries_per_line, coord.end()); for ( ; it_new != coord_mirrored.end(); it_new += entries_per_line) { for (int i = 1; i < entries_per_line; i += 3) { next_vec[i] += spacing; } copy(next_vec.begin(), next_vec.end(), it_new); } } else { std::cerr << "Direction should be either x or y" << std::endl; exit(1); } // Write new COORD values to output file printKeywordValues(out, "COORD", coord_mirrored, 6); }
/// set the tables which specify the temperature dependence of the oil viscosity void initFromDeck(std::shared_ptr<const PvtInterface> isothermalPvt, const Opm::Deck& deck, const Opm::EclipseState& eclipseState) { isothermalPvt_ = isothermalPvt; int numRegions; auto tables = eclipseState->getTableManager(); if (deck->hasKeyword("PVTO")) numRegions = tables->getPvtoTables().size(); else if (deck->hasKeyword("PVDO")) numRegions = tables->getPvdoTables().size(); else if (deck->hasKeyword("PVCDO")) numRegions = deck->getKeyword("PVCDO").size(); else OPM_THROW(std::runtime_error, "Oil phase was not initialized using a known way"); // viscosity if (deck->hasKeyword("VISCREF")) { oilvisctTables_ = &tables->getOilvisctTables(); const auto& viscrefKeyword = deck->getKeyword("VISCREF"); assert(int(oilvisctTables_->size()) == numRegions); assert(int(viscrefKeyword.size()) == numRegions); viscrefPress_.resize(numRegions); viscrefRs_.resize(numRegions); muRef_.resize(numRegions); for (int regionIdx = 0; regionIdx < numRegions; ++regionIdx) { 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... double Tref = 273.15 + 20; // compute the reference viscosity using the isothermal PVT object. double tmp1, tmp2; isothermalPvt_->mu(1, ®ionIdx, &viscrefPress_[regionIdx], &Tref, &viscrefRs_[regionIdx], &muRef_[regionIdx], &tmp1, &tmp2); } } // quantities required for density. note that we just always use the values // for the first EOS. (since EOS != PVT region.) tref_ = 0.0; if (deck->hasKeyword("THERMEX1")) { oilCompIdx_ = deck->getKeyword("OCOMPIDX").getRecord(0).getItem("OIL_COMPONENT_INDEX").get< int >(0) - 1; // always use the values of the first EOS tref_ = deck->getKeyword("TREF").getRecord(0).getItem("TEMPERATURE").getSIDouble(oilCompIdx_); pref_ = deck->getKeyword("PREF").getRecord(0).getItem("PRESSURE").getSIDouble(oilCompIdx_); cref_ = deck->getKeyword("CREF").getRecord(0).getItem("COMPRESSIBILITY").getSIDouble(oilCompIdx_); thermex1_ = deck->getKeyword("THERMEX1").getRecord(0).getItem("EXPANSION_COEFF").getSIDouble(oilCompIdx_); } }