int main(int argc, char** argv) { // Set output precision int decimals = 16; // Process input parameters if (argc != 3) { std::cout << "Usage: mirror_grid filename.grdecl direction" << std::endl; std::cout << "(replace direction with either x or y)" << std::endl; exit(1); } const char* eclipsefilename = argv[1]; std::string direction(argv[2]); if ( ! ((direction == "x") || (direction == "y")) ) { std::cerr << "Unrecognized input parameter for direction: '" << direction << "'. Should be either x or y (maybe also z later)." << std::endl; exit(1); } // Parse grdecl file std::cout << "Parsing grid file '" << eclipsefilename << "' ..." << std::endl; Opm::Parser parser; Opm::ParseContext parseContext; const Opm::Deck deck(parser.parseFile(eclipsefilename , parseContext)); if ( ! (deck.hasKeyword("SPECGRID") && deck.hasKeyword("COORD") && deck.hasKeyword("ZCORN")) ) { std::cerr << "Grid file " << eclipsefilename << "are missing keywords SPECGRID, COORD or ZCORN!" << std::endl; exit(1); } // Create new grid file std::string mirrored_eclipsefilename = std::string(eclipsefilename); std::string::size_type last_dot = mirrored_eclipsefilename.find_last_of('.'); mirrored_eclipsefilename = mirrored_eclipsefilename.substr(0, last_dot) + "_mirrored-" + direction + ".grdecl"; std::ofstream outfile; outfile.open(mirrored_eclipsefilename.c_str(), std::ios::out | std::ios::trunc); if (!outfile) { std::cerr << "Can't open output file " << mirrored_eclipsefilename << std::endl; exit(1); } outfile.precision(decimals); outfile.setf(std::ios::fixed); // Print init message printInitMessage(outfile, eclipsefilename, direction); // Mirror keywords mirror_mapaxes(deck, direction, outfile); mirror_specgrid(deck, direction, outfile); mirror_coord(deck, direction, outfile); mirror_zcorn(deck, direction, outfile); mirror_celldata<int>("ACTNUM", deck, direction, outfile); mirror_celldata<double>("PERMX", deck, direction, outfile); mirror_celldata<double>("PERMY", deck, direction, outfile); mirror_celldata<double>("PERMZ", deck, direction, outfile); mirror_celldata<double>("PORO", deck, direction, outfile); mirror_celldata<int>("SATNUM", deck, direction, outfile); mirror_celldata<double>("NTG", deck, direction, outfile); mirror_celldata<double>("SWCR", deck, direction, outfile); mirror_celldata<double>("SOWCR", deck, direction, outfile); }
inline void loadDeck( const char * deck_file) { Opm::ParseContext parseContext; Opm::Parser parser; auto deck = parser.parseFile(deck_file, parseContext); Opm::EclipseState state( deck, parseContext ); Opm::Schedule schedule( deck, state.getInputGrid(), state.get3DProperties(), state.runspec(), parseContext); Opm::SummaryConfig summary( deck, schedule, state.getTableManager( ), parseContext ); { std::stringstream ss; ss << deck; auto deck2 = parser.parseString(ss.str(), parseContext); if (deck.size() != deck2.size()) { std::cerr << "Deck size mismatch original:" << deck.size() << " new: " << deck2.size( ) << std::endl; std::exit( 1 ); } for (size_t index=0; index < deck.size(); index++) { const auto& kw1 = deck.getKeyword( index ); const auto& kw2 = deck2.getKeyword( index ); if (!kw1.equal( kw2 , true , true)) { std::cerr << "Keyword " << index << " different " << kw1.name() << " " << kw2.name() << std::endl; std::cerr << kw1 << std::endl; std::cerr << std::endl << "-----------------------------------------------------------------" << std::endl; std::cerr << kw2 << std::endl; std::exit( 1 ); } } } }
void Opm::initCPGrid(Dune::CpGrid& grid, const Opm::ParameterGroup& param) { std::string fileformat = param.get<std::string>("fileformat"); if (fileformat == "sintef_legacy") { std::string grid_prefix = param.get<std::string>("grid_prefix"); grid.readSintefLegacyFormat(grid_prefix); } else if (fileformat == "eclipse") { std::string filename = param.get<std::string>("filename"); if (param.has("z_tolerance")) { std::cerr << "****** Warning: z_tolerance parameter is obsolete, use PINCH in deck input instead\n"; } bool periodic_extension = param.getDefault<bool>("periodic_extension", false); bool turn_normals = param.getDefault<bool>("turn_normals", false); Opm::Parser parser; auto deck = parser.parseFile(filename); Opm::EclipseGrid inputGrid(deck); grid.processEclipseFormat(inputGrid, periodic_extension , turn_normals ); } else if (fileformat == "cartesian") { std::array<int, 3> dims = {{ param.getDefault<int>("nx", 1), param.getDefault<int>("ny", 1), param.getDefault<int>("nz", 1) }}; std::array<double, 3> cellsz = {{ param.getDefault<double>("dx", 1.0), param.getDefault<double>("dy", 1.0), param.getDefault<double>("dz", 1.0) }}; grid.createCartesian(dims, cellsz); } else { OPM_THROW(std::runtime_error, "Unknown file format string: " << fileformat); } }
SetupMSW() { Opm::ParseContext parse_context; Opm::Parser parser; auto deck = parser.parseFile("msw.data", parse_context); Opm::EclipseState ecl_state(deck , parse_context); // Create grid. const std::vector<double>& porv = ecl_state.get3DProperties().getDoubleGridProperty("PORV").getData(); std::unique_ptr<GridInit> grid_init(new GridInit(ecl_state, porv)); const Grid& grid = grid_init->grid(); // Create material law manager. std::vector<int> compressed_to_cartesianIdx; Opm::createGlobalCellArray(grid, compressed_to_cartesianIdx); std::shared_ptr<MaterialLawManager> material_law_manager(new MaterialLawManager()); material_law_manager->initFromDeck(deck, ecl_state, compressed_to_cartesianIdx); std::unique_ptr<FluidProps> fluidprops(new FluidProps(deck, ecl_state, material_law_manager, grid)); const size_t current_timestep = 0; // dummy_dynamic_list_econ_lmited const Opm::DynamicListEconLimited dummy_dynamic_list; // Create wells. Opm::WellsManager wells_manager(ecl_state, current_timestep, Opm::UgGridHelpers::numCells(grid), Opm::UgGridHelpers::globalCell(grid), Opm::UgGridHelpers::cartDims(grid), Opm::UgGridHelpers::dimensions(grid), Opm::UgGridHelpers::cell2Faces(grid), Opm::UgGridHelpers::beginFaceCentroids(grid), fluidprops->permeability(), dummy_dynamic_list, false // We need to pass the optionaly arguments // as we get the following error otherwise // with c++ (Debian 4.9.2-10) 4.9.2 and -std=c++11 // converting to ‘const std::unordered_set<std::basic_string<char> >’ from initializer list would use explicit constructor , std::vector<double>(), // null well_potentials std::unordered_set<std::string>()); const Wells* wells = wells_manager.c_wells(); const auto wells_ecl = ecl_state.getSchedule().getWells(current_timestep); ms_wells.reset(new Opm::MultisegmentWells(wells, &(wells_manager.wellCollection()), wells_ecl, current_timestep)); };
inline void loadDeck( const char * deck_file) { Opm::ParseContext parseContext; Opm::ErrorGuard errors; Opm::Parser parser; std::cout << "Loading deck: " << deck_file << " ..... "; std::cout.flush(); auto deck = parser.parseFile(deck_file, parseContext, errors); std::cout << "parse complete - creating EclipseState .... "; std::cout.flush(); Opm::EclipseState state( deck, parseContext, errors ); Opm::Schedule schedule( deck, state.getInputGrid(), state.get3DProperties(), state.runspec(), parseContext, errors); Opm::SummaryConfig summary( deck, schedule, state.getTableManager( ), parseContext, errors ); std::cout << "complete." << std::endl; }
SetupTest () { Opm::Parser parser; auto deck = parser.parseFile("TESTWELLMODEL.DATA"); ecl_state.reset(new Opm::EclipseState(deck) ); { const Opm::TableManager table ( deck ); const Opm::Eclipse3DProperties eclipseProperties ( deck , table, ecl_state->getInputGrid()); const Opm::Runspec runspec (deck); schedule.reset( new Opm::Schedule(deck, ecl_state->getInputGrid(), eclipseProperties, runspec)); } // Create grid. const std::vector<double>& porv = ecl_state->get3DProperties().getDoubleGridProperty("PORV").getData(); std::unique_ptr<GridInit> grid_init(new GridInit(*ecl_state, porv)); const Grid& grid = grid_init->grid(); // Create material law manager. std::vector<int> compressed_to_cartesianIdx; Opm::createGlobalCellArray(grid, compressed_to_cartesianIdx); current_timestep = 0; // Create wells. wells_manager.reset(new Opm::WellsManager(*ecl_state, *schedule, current_timestep, Opm::UgGridHelpers::numCells(grid), Opm::UgGridHelpers::globalCell(grid), Opm::UgGridHelpers::cartDims(grid), Opm::UgGridHelpers::dimensions(grid), Opm::UgGridHelpers::cell2Faces(grid), Opm::UgGridHelpers::beginFaceCentroids(grid), false, std::unordered_set<std::string>() ) ); };
// ----------------- Main program ----------------- int main(int argc, char** argv) try { using namespace Opm; // Setup. ParameterGroup param(argc, argv); std::cout << "--------------- Reading parameters ---------------" << std::endl; const std::string deck_filename = param.get<std::string>("deck_filename"); Opm::ParseContext parseContext; Opm::Parser parser; const Opm::Deck& deck = parser.parseFile(deck_filename , parseContext); const Opm::EclipseState eclipseState(deck, parseContext); const double grav = param.getDefault("gravity", unit::gravity); GridManager gm(eclipseState.getInputGrid()); const UnstructuredGrid& grid = *gm.c_grid(); warnIfUnusedParams(param); // Create material law manager. std::vector<int> compressedToCartesianIdx = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); typedef FluidSystems::BlackOil<double> FluidSystem; // Forward declaring the MaterialLawManager template. typedef Opm::ThreePhaseMaterialTraits<double, /*wettingPhaseIdx=*/FluidSystem::waterPhaseIdx, /*nonWettingPhaseIdx=*/FluidSystem::oilPhaseIdx, /*gasPhaseIdx=*/FluidSystem::gasPhaseIdx> MaterialTraits; typedef Opm::EclMaterialLawManager<MaterialTraits> MaterialLawManager; MaterialLawManager materialLawManager = MaterialLawManager(); materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); // Initialisation. //initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); BlackoilState state( UgGridHelpers::numCells(grid) , UgGridHelpers::numFaces(grid), 3); FluidSystem::initFromDeck(deck, eclipseState); PhaseUsage pu = phaseUsageFromDeck(deck); typedef EQUIL::DeckDependent::InitialStateComputer<FluidSystem> ISC; ISC isc(materialLawManager, eclipseState, grid, grav); const bool oil = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx); const int oilpos = FluidSystem::oilPhaseIdx; const int waterpos = FluidSystem::waterPhaseIdx; const int ref_phase = oil ? oilpos : waterpos; state.pressure() = isc.press()[ref_phase]; convertSats<FluidSystem>(state.saturation(), isc.saturation(), pu); state.gasoilratio() = isc.rs(); state.rv() = isc.rv(); // Output. const std::string output_dir = param.getDefault<std::string>("output_dir", "output"); outputData(output_dir, "pressure", state.pressure()); outputData(output_dir, "saturation", state.saturation()); outputData(output_dir, "rs", state.gasoilratio()); outputData(output_dir, "rv", state.rv()); } catch (const std::exception& e) { std::cerr << "Program threw an exception: " << e.what() << "\n"; throw; }
// ----------------- Main program ----------------- int main(int argc, char** argv) try { using namespace Opm; std::cout << "\n================ Test program for fully implicit three-phase black-oil flow ===============\n\n"; parameter::ParameterGroup param(argc, argv, false); std::cout << "--------------- Reading parameters ---------------" << std::endl; // If we have a "deck_filename", grid and props will be read from that. bool use_deck = param.has("deck_filename"); if (!use_deck) { OPM_THROW(std::runtime_error, "This program must be run with an input deck. " "Specify the deck with deck_filename=deckname.data (for example)."); } std::shared_ptr<GridManager> grid; std::shared_ptr<BlackoilPropertiesInterface> props; std::shared_ptr<BlackoilPropsAdFromDeck> new_props; std::shared_ptr<RockCompressibility> rock_comp; std::unique_ptr<PolymerBlackoilState> state; // bool check_well_controls = false; // int max_well_control_iterations = 0; double gravity[3] = { 0.0 }; std::string deck_filename = param.get<std::string>("deck_filename"); // Write parameters used for later reference. bool output = param.getDefault("output", true); std::string output_dir; if (output) { // Create output directory if needed. output_dir = param.getDefault("output_dir", std::string("output")); boost::filesystem::path fpath(output_dir); try { create_directories(fpath); } catch (...) { std::cerr << "Creating directories failed: " << fpath << std::endl; return EXIT_FAILURE; } // Write simulation parameters. param.writeParam(output_dir + "/simulation.param"); } std::string logFile = output_dir + "/LOGFILE.txt"; Opm::ParseContext parseContext({{ ParseContext::PARSE_RANDOM_SLASH , InputError::IGNORE }}); Opm::Parser parser; { std::shared_ptr<Opm::StreamLog> streamLog = std::make_shared<Opm::StreamLog>(logFile , Opm::Log::DefaultMessageTypes); std::shared_ptr<Opm::CounterLog> counterLog = std::make_shared<Opm::CounterLog>(Opm::Log::DefaultMessageTypes); Opm::OpmLog::addBackend( "STREAM" , streamLog ); Opm::OpmLog::addBackend( "COUNTER" , counterLog ); } Deck deck; std::shared_ptr<EclipseState> eclipseState; try { deck = parser.parseFile(deck_filename , parseContext); Opm::checkDeck(deck, parser); eclipseState.reset(new Opm::EclipseState(deck , parseContext)); } catch (const std::invalid_argument& e) { std::cerr << "Failed to create valid ECLIPSESTATE object. See logfile: " << logFile << std::endl; std::cerr << "Exception caught: " << e.what() << std::endl; return EXIT_FAILURE; } // Grid init if (eclipseState->get3DProperties().hasDeckDoubleGridProperty("PORV")) { const auto& porv = eclipseState->get3DProperties().getDoubleGridProperty("PORV").getData(); grid.reset(new GridManager(eclipseState->getInputGrid(), porv)); } else { grid.reset(new GridManager(eclipseState->getInputGrid())); } auto &cGrid = *grid->c_grid(); const PhaseUsage pu = Opm::phaseUsageFromDeck(deck); // Rock and fluid init std::vector<int> compressedToCartesianIdx; Opm::createGlobalCellArray(*grid->c_grid(), compressedToCartesianIdx); typedef BlackoilPropsAdFromDeck::MaterialLawManager MaterialLawManager; auto materialLawManager = std::make_shared<MaterialLawManager>(); materialLawManager->initFromDeck(deck, *eclipseState, compressedToCartesianIdx); props.reset(new BlackoilPropertiesFromDeck( deck, *eclipseState, materialLawManager, Opm::UgGridHelpers::numCells(cGrid), Opm::UgGridHelpers::globalCell(cGrid), Opm::UgGridHelpers::cartDims(cGrid), param)); state.reset( new PolymerBlackoilState( Opm::UgGridHelpers::numCells(cGrid), Opm::UgGridHelpers::numFaces(cGrid), 2)); new_props.reset(new BlackoilPropsAdFromDeck(deck, *eclipseState, materialLawManager, cGrid)); PolymerProperties polymer_props(deck, *eclipseState); PolymerPropsAd polymer_props_ad(polymer_props); // Rock compressibility. rock_comp.reset(new RockCompressibility(*eclipseState)); // Gravity. gravity[2] = deck.hasKeyword("NOGRAV") ? 0.0 : unit::gravity; // Init state variables (saturation and pressure). if (param.has("init_saturation")) { initStateBasic(*grid->c_grid(), *props, param, gravity[2], *state); initBlackoilSurfvol(*grid->c_grid(), *props, *state); } else { initStateFromDeck(*grid->c_grid(), *props, deck, gravity[2], *state); } bool use_gravity = (gravity[0] != 0.0 || gravity[1] != 0.0 || gravity[2] != 0.0); const double *grav = use_gravity ? &gravity[0] : 0; // Solver for Newton iterations. std::unique_ptr<NewtonIterationBlackoilInterface> fis_solver; if (param.getDefault("use_cpr", true)) { fis_solver.reset(new NewtonIterationBlackoilCPR(param)); } else { fis_solver.reset(new NewtonIterationBlackoilSimple(param)); } const auto timeMap = eclipseState->getSchedule().getTimeMap(); SimulatorTimer simtimer; simtimer.init(timeMap); SimulatorReport rep; // With a deck, we may have more epochs etc. WellState well_state; // Check for WPOLYMER presence in last epoch to decide // polymer injection control type. const bool use_wpolymer = deck.hasKeyword("WPOLYMER"); if (use_wpolymer) { if (param.has("poly_start_days")) { OPM_MESSAGE("Warning: Using WPOLYMER to control injection since it was found in deck. " "You seem to be trying to control it via parameter poly_start_days (etc.) as well."); } } std::cout << "\n\n================ Starting main simulation loop ===============\n" << std::flush; std::unique_ptr<Opm::EclipseIO> eclipseWriter(new Opm::EclipseIO(*eclipseState, UgGridHelpers ::createEclipseGrid( cGrid , eclipseState->getInputGrid()))); Opm::BlackoilOutputWriter outputWriter(cGrid, param, *eclipseState, std::move(eclipseWriter), pu); SimulatorReport fullReport; // Create and run simulator. Opm::DerivedGeology geology(*grid->c_grid(), *new_props, *eclipseState, grav); SimulatorFullyImplicitCompressiblePolymer<UnstructuredGrid> simulator(param, *grid->c_grid(), geology, *new_props, polymer_props_ad, rock_comp->isActive() ? rock_comp.get() : 0, eclipseState, outputWriter, deck, *fis_solver, grav); fullReport= simulator.run(simtimer, *state); std::cout << "\n\n================ End of simulation ===============\n\n"; fullReport.report(std::cout); if (output) { std::string filename = output_dir + "/walltime.param"; std::fstream tot_os(filename.c_str(),std::fstream::trunc | std::fstream::out); fullReport.reportParam(tot_os); warnIfUnusedParams(param); } } catch (const std::exception &e) { std::cerr << "Program threw an exception: " << e.what() << "\n"; throw; }
int main(int argc, char** argv) try { using namespace Opm::parameter; using namespace Opm; ParameterGroup parameters(argc, argv, false); std::string file_name = parameters.getDefault<std::string > ("inputdeck", "data.data"); SimulatorTimer simtimer; simtimer.init(parameters); // Read input file ParseContext parseContext; Opm::Parser parser; Opm::Deck deck = parser.parseFile(file_name , parseContext); Opm::EclipseState eclipseState(deck , parseContext); std::cout << "Done!" << std::endl; // Setup grid GridManager grid(eclipseState.getInputGrid()); // Define rock and fluid properties IncompPropertiesFromDeck incomp_properties(deck, eclipseState, *grid.c_grid()); RockCompressibility rock_comp(deck, eclipseState); // Finally handle the wells WellsManager wells(eclipseState , 0 , *grid.c_grid(), incomp_properties.permeability()); double gravity[3] = {0.0, 0.0, parameters.getDefault<double>("gravity", 0.0)}; Opm::LinearSolverFactory linsolver(parameters); double nl_pressure_residual_tolerance = 1e-8; double nl_pressure_change_tolerance = 0.0; int nl_pressure_maxiter = 100; if (rock_comp.isActive()) { nl_pressure_residual_tolerance = parameters.getDefault("nl_pressure_residual_tolerance", 1e-8); nl_pressure_change_tolerance = parameters.getDefault("nl_pressure_change_tolerance", 1.0); // in Pascal nl_pressure_maxiter = parameters.getDefault("nl_pressure_maxiter", 10); } std::vector<double> src; Opm::FlowBCManager bcs; // EXPERIMENT_ISTL IncompTpfa pressure_solver(*grid.c_grid(), incomp_properties, &rock_comp, linsolver, nl_pressure_residual_tolerance, nl_pressure_change_tolerance, nl_pressure_maxiter, gravity, wells.c_wells(), src, bcs.c_bcs()); std::vector<int> all_cells; for (int i = 0; i < grid.c_grid()->number_of_cells; i++) { all_cells.push_back(i); } Opm::TwophaseState state( grid.c_grid()->number_of_cells , grid.c_grid()->number_of_faces ); initStateFromDeck(*grid.c_grid(), incomp_properties, deck, gravity[2], state); Opm::WellState well_state; well_state.init(wells.c_wells(), state); pressure_solver.solve(simtimer.currentStepLength(), state, well_state); const int np = incomp_properties.numPhases(); std::vector<double> fractional_flows(grid.c_grid()->number_of_cells*np, 0.0); computeFractionalFlow(incomp_properties, all_cells, state.saturation(), fractional_flows); // This will be refactored into a separate function once done std::vector<double> well_resflows(wells.c_wells()->number_of_wells*np, 0.0); computePhaseFlowRatesPerWell(*wells.c_wells(), well_state.perfRates(), fractional_flows, well_resflows); // We approximate (for _testing_ that resflows = surfaceflows) for (int wc_iter = 0; wc_iter < 10 && !wells.conditionsMet(well_state.bhp(), well_resflows, well_resflows); ++wc_iter) { std::cout << "Conditions not met for well, trying again" << std::endl; pressure_solver.solve(simtimer.currentStepLength(), state, well_state); std::cout << "Solved" << std::endl; computePhaseFlowRatesPerWell(*wells.c_wells(), well_state.perfRates(), fractional_flows, well_resflows); } #if 0 std::vector<double> porevol; computePorevolume(*grid->c_grid(), incomp_properties, porevol); TwophaseFluid fluid(incomp_properties); TransportContextl model(fluid, *grid->c_grid(), porevol, gravity[2], true); TransportSolver tsolver(model); TransportSource* tsrc = create_transport_source(2, 2); double ssrc[] = {1.0, 0.0}; double ssink[] = {0.0, 1.0}; double zdummy[] = {0.0, 0.0}; { int well_cell_index = 0; for (int well = 0; well < wells.c_wells()->number_of_wells; ++well) { for (int cell = wells.c_wells()->well_connpos[well]; cell < wells.c_wells()->well_connpos[well + 1]; ++cell) { if (well_rate_per_cell[well_cell_index] > 0.0) { append_transport_source(well_cell_index, 2, 0, well_rate_per_cell[well_cell_index], ssrc, zdummy, tsrc); } else if (well_rate_per_cell[well_cell_index] < 0.0) { append_transport_source(well_cell_index, 2, 0, well_rate_per_cell[well_cell_index], ssink, zdummy, tsrc); } } } } tsolver.solve(*grid->c_grid(), tsrc, stepsize, ctrl, state, linsolve, rpt); Opm::computeInjectedProduced(*props, state.saturation(), src, stepsize, injected, produced); #endif return 0; } catch (const std::exception &e) { std::cerr << "Program threw an exception: " << e.what() << "\n"; throw; }
int main(int argc, char** argv) try { if (argc == 1) { std::cout << "Usage: cpregularize gridfilename=filename.grdecl [ires=5] [jres=5] [zres=5] " << std::endl; std::cout << " [imin=] [imax=] [jmin=] [jmax=] [zmin=] [zmax=] " << std::endl; std::cout << " [minperm=1e-9] " << std::endl; std::cout << " [resultgrid=regularizedgrid.grdecl]" << std::endl; exit(1); } Dune::MPIHelper::instance(argc, argv); Opm::parameter::ParameterGroup param(argc, argv); std::string gridfilename = param.get<std::string>("gridfilename"); Opm::CornerPointChopper ch(gridfilename); // The cells with i coordinate in [imin, imax) are included, similar for j. // The z limits may be changed inside the chopper to match actual min/max z. const int* dims = ch.dimensions(); int imin = param.getDefault("imin", 0); int imax = param.getDefault("imax", dims[0]); int jmin = param.getDefault("jmin", 0); int jmax = param.getDefault("jmax", dims[1]); double zmin = param.getDefault("zmin", ch.zLimits().first); double zmax = param.getDefault("zmax", ch.zLimits().second); int ires = param.getDefault("ires", 1); int jres = param.getDefault("jres", 1); int zres = param.getDefault("zres", 1); std::string resultgrid = param.getDefault<std::string>("resultgrid", "regularizedgrid.grdecl"); double minperm = param.getDefault("minperm", 1e-9); double minpermSI = Opm::unit::convert::from(minperm, Opm::prefix::milli*Opm::unit::darcy); if (param.has("z_tolerance")) { std::cerr << "****** Warning: z_tolerance parameter is obsolete, use PINCH in deck input instead\n"; } double residual_tolerance = param.getDefault("residual_tolerance", 1e-8); double linsolver_verbosity = param.getDefault("linsolver_verbosity", 0); double linsolver_type = param.getDefault("linsolver_type", 1); // Check for unused parameters (potential typos). if (param.anyUnused()) { std::cout << "***** WARNING: Unused parameters: *****\n"; param.displayUsage(); } // Check that we do not have any user input // that goes outside the coordinates described in // the cornerpoint file (runtime-exception will be thrown in case of error) // (ilen, jlen and zlen set to zero, does not apply here) ch.verifyInscribedShoebox(imin, 0, imax, jmin, 0, jmax, zmin, 0, zmax); // Storage for properties for regularized cells std::vector<double> poro; std::vector<double> permx; std::vector<double> permy; std::vector<double> permz; Opm::ParseContext parseMode; // Original x/y resolution in terms of coordinate values (not indices) Opm::Parser parser; auto deck = parser.parseFile(gridfilename , parseMode); // TODO: REFACTOR!!!! it is stupid to parse this again Opm::EclipseGridInspector gridinspector(deck); std::array<double, 6> gridlimits=gridinspector.getGridLimits(); double finegridxresolution = (gridlimits[1]-gridlimits[0])/dims[0]; double finegridyresolution = (gridlimits[3]-gridlimits[2])/dims[1]; // Construct mapping from coarse i and j indices to fine // and COORDS values for regularized pillars. std::vector<int> iidx_f, jidx_f; std::vector<double> newcoords_x; int finesprcoarse_i = floor(dims[0] / ires); int remainder_i = dims[0] - ires*finesprcoarse_i; for (int iidx_c=0; iidx_c < remainder_i+1; ++iidx_c) { iidx_f.push_back(iidx_c*(finesprcoarse_i + 1)); // Spread remainder evenly } for (int iidx_c=remainder_i + 1; iidx_c < ires; ++iidx_c) { iidx_f.push_back(iidx_c*finesprcoarse_i + remainder_i); } iidx_f.push_back(imax); // endpoint needed below int finesprcoarse_j = floor(dims[1] / jres); int remainder_j = dims[1] - jres*finesprcoarse_j; for (int jidx_c=0; jidx_c < remainder_j+1; ++jidx_c) { jidx_f.push_back(jidx_c*(finesprcoarse_j + 1)); // Spread remainder evenly } for (int jidx_c=remainder_j + 1; jidx_c < jres; ++jidx_c) { jidx_f.push_back(jidx_c*finesprcoarse_j + remainder_j); } jidx_f.push_back(jmax); // endpoint needed below // Construct new ZCORN for regular grid std::vector<double> zcorn_c; for (int zidx_c=0; zidx_c < zres; ++zidx_c) { zcorn_c.push_back(zmin + zidx_c * (zmax-zmin)/zres); } zcorn_c.push_back(zmax); // Run through the new regular grid to find its properties for (int zidx_c=0; zidx_c < zres; ++zidx_c) { for (int jidx_c=0; jidx_c < jres; ++jidx_c) { for (int iidx_c=0; iidx_c < ires; ++iidx_c) { ch.chop(iidx_f[iidx_c], iidx_f[iidx_c+1], jidx_f[jidx_c], jidx_f[jidx_c+1], zcorn_c[zidx_c], zcorn_c[zidx_c+1], false); OPM_THROW(std::logic_error, "Sub-decks not are not implemented by opm-parser. Refactor the calling code!?"); try { auto subdeck = ch.subDeck(); Opm::SinglePhaseUpscaler upscaler; upscaler.init(subdeck, Opm::SinglePhaseUpscaler::Fixed, minpermSI, residual_tolerance, linsolver_verbosity, linsolver_type, false); Opm::SinglePhaseUpscaler::permtensor_t upscaled_K = upscaler.upscaleSinglePhase(); upscaled_K *= (1.0/(Opm::prefix::milli*Opm::unit::darcy)); poro.push_back(upscaler.upscalePorosity()); permx.push_back(upscaled_K(0,0)); permy.push_back(upscaled_K(1,1)); permz.push_back(upscaled_K(2,2)); } catch (...) { std::cout << "Warning: Upscaling for cell failed to convert, values set to zero\n"; poro.push_back(0.0); permx.push_back(0.0); permy.push_back(0.0); permz.push_back(0.0); } } } } // Write regularized grid to outputfile std::ofstream out(resultgrid.c_str()); if (!out) { std::cerr << "Could not open file " << resultgrid << "\n"; throw std::runtime_error("Could not open output file."); } out << "SPECGRID\n" << ires << ' ' << jres << ' ' << zres << " 1 F\n/\n\n"; out << "COORD\n"; for (int j = 0; j <= jres; ++j) { for (int i = 0; i <= ires; ++i) { out << finegridxresolution*iidx_f[i] << " " << finegridyresolution*jidx_f[j] << " " << zmin << " " << finegridxresolution*iidx_f[i] << " " << finegridyresolution*jidx_f[j] << " " << zmax << "\n"; } } out << "/\n\n"; /* Write ZCORN, that is the Z-coordinates along the pillars, specifying the eight corners of each cell. Each corner is specified for each cell, even though it is the same corner that is used in other cells. We loop over corners in each grid cell, directions: z, y, x (x innermost). The code here *IS* redundant, but the grid is also very redundant for a grid that is really regular.. */ out << "ZCORN\n"; double zlen = zmax-zmin; for (int zidx=0; zidx < zres; ++zidx) { for (int j = 0; j < jres; ++j) { for (int i = 0; i < ires; ++i) { out << zlen/zres*zidx << " " << zlen/zres*zidx << " "; } out << "\n"; for (int i = 0; i < ires; ++i) { out << zlen/zres*zidx << " " << zlen/zres*zidx << " "; } } for (int j = 0; j < jres; ++j) { for (int i = 0; i < ires; ++i) { out << zlen/zres*(zidx+1) << " " << zlen/zres*(zidx+1) << " "; } out << "\n"; for (int i = 0; i < ires; ++i) { out << zlen/zres*(zidx+1) << " " << zlen/zres*(zidx+1) << " "; } } } out << "/\n\n"; out << "PORO\n"; for (size_t idx=0; idx < (size_t)poro.size(); ++idx) { out << poro[idx] << std::endl; } out << "/\n\n"; out << "PERMX\n"; for (size_t idx=0; idx < (size_t)permx.size(); ++idx) { out << permx[idx] << std::endl; } out << "/\n\n"; out << "PERMY\n\n"; for (size_t idx=0; idx < (size_t)permy.size(); ++idx) { out << permy[idx] << std::endl; } out << "/\n\n"; out << "PERMZ\n\n"; for (size_t idx=0; idx < (size_t)permz.size(); ++idx) { out << permz[idx] << std::endl; } out << "/\n"; out.close(); } catch (const std::exception &e) { std::cerr << "Program threw an exception: " << e.what() << "\n"; throw; }
int main(int argc, char** argv) try { Dune::MPIHelper::instance(argc,argv); // Dummy if no MPI. CpGrid grid; if (argc != 2) { std::cout << "Usage: grdecl2vtu filename.grdecl" << std::endl; exit(1); } const char* eclipsefilename = argv[1]; #if HAVE_OPM_PARSER Opm::ParseContext parseContext; Opm::Parser parser; auto deck = parser.parseFile(eclipsefilename, parseContext); // Get logical cartesian grid dimensions. std::array<size_t, 3> dims; if (deck.hasKeyword("SPECGRID")) { const auto& specgridRecord = deck.getKeyword("SPECGRID").getRecord(0); dims[0] = specgridRecord.getItem("NX").get< int >(0); dims[1] = specgridRecord.getItem("NY").get< int >(0); dims[2] = specgridRecord.getItem("NZ").get< int >(0); } else if (deck.hasKeyword("DIMENS")) { const auto& dimensRecord = deck.getKeyword("DIMENS").getRecord(0); dims[0] = dimensRecord.getItem("NX").get< int >(0); dims[1] = dimensRecord.getItem("NY").get< int >(0); dims[2] = dimensRecord.getItem("NZ").get< int >(0); } else { OPM_THROW(std::runtime_error, "Found neither SPECGRID nor DIMENS in file. At least one is needed."); } { const int* actnum = deck.hasKeyword("ACTNUM") ? deck.getKeyword("ACTNUM").getIntData().data() : nullptr; Opm::EclipseGrid ecl_grid(deck , actnum); grid.processEclipseFormat(ecl_grid, false); } #endif VTKWriter<CpGrid::LeafGridView> vtkwriter(grid.leafGridView()); #if HAVE_OPM_PARSER const std::vector<int>& global_cell = grid.globalCell(); std::vector<double> poros; condWriteDoubleField(poros, "PORO", deck, global_cell, dims, vtkwriter); std::vector<double> permxs; condWriteDoubleField(permxs, "PERMX", deck, global_cell, dims, vtkwriter); std::vector<double> permys; condWriteDoubleField(permys, "PERMY", deck, global_cell, dims, vtkwriter); std::vector<double> permzs; condWriteDoubleField(permzs, "PERMZ", deck, global_cell, dims, vtkwriter); std::vector<double> actnums; condWriteIntegerField(actnums, "ACTNUM", deck, global_cell, dims, vtkwriter); std::vector<double> satnums; condWriteIntegerField(satnums, "SATNUM", deck, global_cell, dims, vtkwriter); std::vector<double> regnums; condWriteIntegerField(regnums, "REGNUM", deck, global_cell, dims, vtkwriter); std::vector<double> swats; condWriteDoubleField(swats, "SWAT", deck, global_cell, dims, vtkwriter); #endif // #if HAVE_OPM_PARSER std::string fname(eclipsefilename); std::string fnamebase = fname.substr(0, fname.find_last_of('.')); std::cout << "Writing to filename " << fnamebase << ".vtu" << std::endl; vtkwriter.write(fnamebase, VTK::ascii); } catch (const std::exception &e) { std::cerr << "Program threw an exception: " << e.what() << "\n"; throw; }