/// \brief Get a vector of pressure thresholds from either EclipseState /// or maxDp (for defaulted values) for all Non-neighbour connections (NNCs). /// \param[in] nnc The NNCs, /// \param[in] eclipseState Processed eclipse state, EQLNUM is accessed from it. /// \param[in] maxDp The maximum gravity corrected pressure differences between /// the equilibration regions. /// \return A vector of pressure thresholds, one /// for each NNC in the grid. A value /// of zero means no threshold for that /// particular connection. An empty vector is /// returned if there is no THPRES /// feature used in the deck. std::vector<double> thresholdPressuresNNC(EclipseStateConstPtr eclipseState, const NNC& nnc, const std::map<std::pair<int, int>, double>& maxDp) { const SimulationConfig& simulationConfig = eclipseState->getSimulationConfig(); std::vector<double> thpres_vals; if (simulationConfig.hasThresholdPressure()) { std::shared_ptr<const ThresholdPressure> thresholdPressure = simulationConfig.getThresholdPressure(); const auto& eqlnum = eclipseState->get3DProperties().getIntGridProperty("EQLNUM"); const auto& eqlnumData = eqlnum.getData(); // Set values for each NNC thpres_vals.resize(nnc.numNNC(), 0.0); for (size_t i = 0 ; i < nnc.numNNC(); ++i) { const int gc1 = nnc.nncdata()[i].cell1; const int gc2 = nnc.nncdata()[i].cell2; const int eq1 = eqlnumData[gc1]; const int eq2 = eqlnumData[gc2]; if (thresholdPressure->hasRegionBarrier(eq1,eq2)) { if (thresholdPressure->hasThresholdPressure(eq1,eq2)) { thpres_vals[i] = thresholdPressure->getThresholdPressure(eq1,eq2); } else { // set the threshold pressure for NNC of PVT regions where the third item // has been defaulted to the maximum pressure potential difference between // these regions const auto barrierId = std::make_pair(eq1, eq2); thpres_vals[i] = maxDp.at(barrierId); } } } } return thpres_vals; }
void EclipseIO::Impl::writeEGRIDFile( const NNC& nnc ) const { const auto& ioConfig = this->es.getIOConfig(); std::string egridFile( ERT::EclFilename( this->outputDir, this->baseName, ECL_EGRID_FILE, ioConfig.getFMTOUT() )); { int idx = 0; auto* ecl_grid = const_cast< ecl_grid_type* >( this->grid.c_ptr() ); for (const NNCdata& n : nnc.nncdata()) ecl_grid_add_self_nnc( ecl_grid, n.cell1, n.cell2, idx++); ecl_grid_fwrite_EGRID2(ecl_grid, egridFile.c_str(), this->es.getDeckUnitSystem().getEclType() ); } }
void EclipseIO::Impl::writeINITFile( const data::Solution& simProps, std::map<std::string, std::vector<int> > int_data, const NNC& nnc) const { const auto& units = this->es.getUnits(); const IOConfig& ioConfig = this->es.cfg().io(); std::string initFile( ERT::EclFilename( this->outputDir, this->baseName, ECL_INIT_FILE, ioConfig.getFMTOUT() )); ERT::FortIO fortio( initFile, std::ios_base::out, ioConfig.getFMTOUT(), ECL_ENDIAN_FLIP ); // Write INIT header. Observe that the PORV vector is treated // specially; that is because for this particulat vector we write // a total of nx*ny*nz values, where the PORV vector has been // explicitly set to zero for inactive cells. The convention is // that the active/inactive cell mapping can be inferred by // reading the PORV vector. { const auto& opm_data = this->es.get3DProperties().getDoubleGridProperty("PORV").getData(); auto ecl_data = opm_data; for (size_t global_index = 0; global_index < opm_data.size(); global_index++) if (!this->grid.cellActive( global_index )) ecl_data[global_index] = 0; ecl_init_file_fwrite_header( fortio.get(), this->grid.c_ptr(), NULL, units.getEclType(), this->es.runspec( ).eclPhaseMask( ), this->schedule.posixStartTime( )); units.from_si( UnitSystem::measure::volume, ecl_data ); writeKeyword( fortio, "PORV" , ecl_data ); } // Writing quantities which are calculated by the grid to the INIT file. ecl_grid_fwrite_depth( this->grid.c_ptr() , fortio.get() , units.getEclType( ) ); ecl_grid_fwrite_dims( this->grid.c_ptr() , fortio.get() , units.getEclType( ) ); // Write properties from the input deck. { const auto& properties = this->es.get3DProperties().getDoubleProperties(); using double_kw = std::pair<std::string, UnitSystem::measure>; /* This is a rather arbitrary hardcoded list of 3D keywords which are written to the INIT file, if they are in the current EclipseState. */ std::vector<double_kw> doubleKeywords = {{"PORO" , UnitSystem::measure::identity }, {"PERMX" , UnitSystem::measure::permeability }, {"PERMY" , UnitSystem::measure::permeability }, {"PERMZ" , UnitSystem::measure::permeability }, {"NTG" , UnitSystem::measure::identity }}; // The INIT file should always contain the NTG property, we // therefor invoke the auto create functionality to ensure // that "NTG" is included in the properties container. properties.assertKeyword("NTG"); for (const auto& kw_pair : doubleKeywords) { if (properties.hasKeyword( kw_pair.first)) { const auto& opm_property = properties.getKeyword(kw_pair.first); auto ecl_data = opm_property.compressedCopy( this->grid ); units.from_si( kw_pair.second, ecl_data ); writeKeyword( fortio, kw_pair.first, ecl_data ); } } } // Write properties which have been initialized by the simulator. { for (const auto& prop : simProps) { auto ecl_data = this->grid.compressedVector( prop.second.data ); writeKeyword( fortio, prop.first, ecl_data ); } } // Write tables { Tables tables( this->es.getUnits() ); tables.addPVTO( this->es.getTableManager().getPvtoTables() ); tables.addPVTG( this->es.getTableManager().getPvtgTables() ); tables.addPVTW( this->es.getTableManager().getPvtwTable() ); tables.addDensity( this->es.getTableManager().getDensityTable( ) ); tables.addSatFunc(this->es); fwrite(tables, fortio); } // Write all integer field properties from the input deck. { const auto& properties = this->es.get3DProperties().getIntProperties(); // It seems that the INIT file should always contain these // keywords, we therefor call getKeyword() here to invoke the // autocreation property, and ensure that the keywords exist // in the properties container. properties.assertKeyword("PVTNUM"); properties.assertKeyword("SATNUM"); properties.assertKeyword("EQLNUM"); properties.assertKeyword("FIPNUM"); for (const auto& property : properties) { auto ecl_data = property.compressedCopy( this->grid ); writeKeyword( fortio , property.getKeywordName() , ecl_data ); } } //Write Integer Vector Map { for( const auto& pair : int_data) { const std::string& key = pair.first; const std::vector<int>& int_vector = pair.second; if (key.size() > ECL_STRING8_LENGTH) throw std::invalid_argument("Keyword is too long."); writeKeyword( fortio , key , int_vector ); } } // Write NNC transmissibilities { std::vector<double> tran; for( const NNCdata& nd : nnc.nncdata() ) tran.push_back( nd.trans ); units.from_si( UnitSystem::measure::transmissibility , tran ); writeKeyword( fortio, "TRANNNC" , tran ); } }