EquelleRuntimeCPU::EquelleRuntimeCPU(const Opm::parameter::ParameterGroup& param) : grid_manager_(createGridManager(param)), grid_(*(grid_manager_->c_grid())), ops_(grid_), linsolver_(param), output_to_file_(param.getDefault("output_to_file", false)), verbose_(param.getDefault("verbose", 0)), param_(param), max_iter_(param.getDefault("max_iter", 10)), abs_res_tol_(param.getDefault("abs_res_tol", 1e-6)) { }
virtual void initSources(const Opm::parameter::ParameterGroup& param) { // Zero-initializing first. int nc = this->ginterf_.numberOfCells(); this->injection_rates_ = Opm::SparseVector<double>(nc); this->injection_rates_psolver_.resize(nc, 0.0); // this->injection_rates_.addElement(1.0, 0); // this->injection_rates_psolver_[0] = 1.0; // this->injection_rates_.addElement(-1.0, nc-1); // this->injection_rates_psolver_[nc-1] = -1.0; // Initializing blocks. double total_inj = 0.0; bool has_inj_block = param.getDefault("has_inj_block", false); if (has_inj_block) { Vector low; low[0] = param.getDefault("inj_block_low_x", 0.0); low[1] = param.getDefault("inj_block_low_y", 0.0); low[2] = param.getDefault("inj_block_low_z", 0.0); Vector high; high[0] = param.getDefault("inj_block_high_x", 1.0); high[1] = param.getDefault("inj_block_high_y", 1.0); high[2] = param.getDefault("inj_block_high_z", 1.0); double inj_block_density = param.get<double>("inj_block_density"); total_inj = setSourceBlock(low, high, inj_block_density, true); } double total_prod = 0.0; bool has_prod_block = param.getDefault("has_prod_block", false); if (has_prod_block) { Vector low; low[0] = param.getDefault("prod_block_low_x", 0.0); low[1] = param.getDefault("prod_block_low_y", 0.0); low[2] = param.getDefault("prod_block_low_z", 0.0); Vector high; high[0] = param.getDefault("prod_block_high_x", 1.0); high[1] = param.getDefault("prod_block_high_y", 1.0); high[2] = param.getDefault("prod_block_high_z", 1.0); double prod_block_density = param.get<double>("prod_block_density"); total_prod = setSourceBlock(low, high, prod_block_density, false); } if (has_inj_block || has_prod_block) { std::cout << "Initialized injectors with total rate: " << total_inj << "\nInitialized producers with total rate: " << total_prod << std::endl; } }
inline void setupGridAndProps(const Opm::parameter::ParameterGroup& param, CpGrid& grid, ResProp<3>& res_prop) { // Initialize grid and reservoir properties. // Parts copied from CpGrid::init(). std::string fileformat = param.getDefault<std::string>("fileformat", "cartesian"); if (fileformat == "sintef_legacy") { std::string grid_prefix = param.get<std::string>("grid_prefix"); grid.readSintefLegacyFormat(grid_prefix); MESSAGE("Warning: We do not yet read legacy reservoir properties. Using defaults."); res_prop.init(grid.size(0)); } else if (fileformat == "eclipse") { Opm::EclipseGridParser parser(param.get<std::string>("filename")); double z_tolerance = param.getDefault<double>("z_tolerance", 0.0); bool periodic_extension = param.getDefault<bool>("periodic_extension", false); bool turn_normals = param.getDefault<bool>("turn_normals", false); grid.processEclipseFormat(parser, z_tolerance, periodic_extension, turn_normals); double perm_threshold_md = param.getDefault("perm_threshold_md", 0.0); double perm_threshold = Opm::unit::convert::from(perm_threshold_md, Opm::prefix::milli*Opm::unit::darcy); std::string rock_list = param.getDefault<std::string>("rock_list", "no_list"); std::string* rl_ptr = (rock_list == "no_list") ? 0 : &rock_list; bool use_j = param.getDefault("use_jfunction_scaling", useJ<ResProp<3> >()); double sigma = 1.0; double theta = 0.0; if (use_j) { sigma = param.getDefault("sigma", sigma); theta = param.getDefault("theta", theta); } if (param.has("viscosity1") || param.has("viscosity2")) { double v1 = param.getDefault("viscosity1", 0.001); double v2 = param.getDefault("viscosity2", 0.003); res_prop.setViscosities(v1, v2); } res_prop.init(parser, grid.globalCell(), perm_threshold, rl_ptr, use_j, sigma, theta); } else if (fileformat == "cartesian") { array<int, 3> dims = {{ param.getDefault<int>("nx", 1), param.getDefault<int>("ny", 1), param.getDefault<int>("nz", 1) }}; 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); double default_poro = param.getDefault("default_poro", 0.2); double default_perm_md = param.getDefault("default_perm_md", 100.0); double default_perm = Opm::unit::convert::from(default_perm_md, Opm::prefix::milli*Opm::unit::darcy); MESSAGE("Warning: For generated cartesian grids, we use uniform reservoir properties."); res_prop.init(grid.size(0), default_poro, default_perm); } else { THROW("Unknown file format string: " << fileformat); } if (param.getDefault("use_unique_boundary_ids", false)) { grid.setUniqueBoundaryIds(true); } }
inline void setupRegionBasedConditions(const Opm::parameter::ParameterGroup& param, const GridInterface& g, BCs& bcs) { // Extract region and pressure value for Dirichlet bcs. typedef typename GridInterface::Vector Vector; Vector low; low[0] = param.getDefault("dir_block_low_x", 0.0); low[1] = param.getDefault("dir_block_low_y", 0.0); low[2] = param.getDefault("dir_block_low_z", 0.0); Vector high; high[0] = param.getDefault("dir_block_high_x", 1.0); high[1] = param.getDefault("dir_block_high_y", 1.0); high[2] = param.getDefault("dir_block_high_z", 1.0); double dir_block_pressure = param.get<double>("dir_block_pressure"); // Set flow conditions for that region. // For this to work correctly, unique boundary ids should be used, // otherwise conditions may spread outside the given region, to all // faces with the same bid as faces inside the region. typedef typename GridInterface::CellIterator CI; typedef typename CI::FaceIterator FI; int max_bid = 0; std::vector<int> dir_bids; for (CI c = g.cellbegin(); c != g.cellend(); ++c) { for (FI f = c->facebegin(); f != c->faceend(); ++f) { int bid = f->boundaryId(); max_bid = std::max(bid, max_bid); if (bid != 0 && isInside(low, high, f->centroid())) { dir_bids.push_back(bid); } } } bcs.resize(max_bid + 1); for (std::vector<int>::const_iterator it = dir_bids.begin(); it != dir_bids.end(); ++it) { bcs.flowCond(*it) = FlowBC(FlowBC::Dirichlet, dir_block_pressure); } // Transport BCs are defaulted. }
inline void EulerUpstreamImplicit<GI, RP, BC>::init(const Opm::parameter::ParameterGroup& param) { check_sat_ = param.getDefault("check_sat", check_sat_); clamp_sat_ = param.getDefault("clamp_sat", clamp_sat_); //Opm::ImplicitTransportDetails::NRControl ctrl_; ctrl_.max_it = param.getDefault("transport_nr_max_it", 10); max_repeats_ = param.getDefault("transport_max_rep", 10); ctrl_.atol = param.getDefault("transport_atol", 1.0e-6); ctrl_.rtol = param.getDefault("transport_rtol", 5.0e-7); ctrl_.max_it_ls = param.getDefault("transport_max_it_ls", 20); ctrl_.dxtol = param.getDefault("transport_dxtol", 1e-6); ctrl_.verbosity = param.getDefault("transport_verbosity", 0); }
inline void setupGridAndProps(const Opm::parameter::ParameterGroup& param, Dune::SGrid<3, 3>& grid, ResProp<3>& res_prop) { // Initialize grid and reservoir properties. // Parts copied from Dune::CpGrid::init(). std::string fileformat = param.getDefault<std::string>("fileformat", "cartesian"); 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.~SGrid<3,3>(); new (&grid) Dune::SGrid<3, 3>(&dims[0], &cellsz[0]); double default_poro = param.getDefault("default_poro", 0.2); double default_perm = param.getDefault("default_perm", 100.0*Opm::prefix::milli*Opm::unit::darcy); OPM_MESSAGE("Warning: For generated cartesian grids, we use uniform reservoir properties."); res_prop.init(grid.size(0), default_poro, default_perm); } else { OPM_THROW(std::runtime_error, "Dune::SGrid can only handle cartesian grids, unsupported file format string: " << fileformat); } }
inline void EulerUpstream<GI, RP, BC>::init(const Opm::parameter::ParameterGroup& param) { courant_number_ = param.getDefault("courant_number", courant_number_); method_viscous_ = param.getDefault("method_viscous", method_viscous_); method_gravity_ = param.getDefault("method_gravity", method_gravity_); method_capillary_ = param.getDefault("method_capillary", method_capillary_); use_cfl_viscous_ = param.getDefault("use_cfl_viscous", use_cfl_viscous_); use_cfl_gravity_ = param.getDefault("use_cfl_gravity", use_cfl_gravity_); use_cfl_capillary_ = param.getDefault("use_cfl_capillary", use_cfl_capillary_); minimum_small_steps_ = param.getDefault("minimum_small_steps", minimum_small_steps_); maximum_small_steps_ = param.getDefault("maximum_small_steps", maximum_small_steps_); check_sat_ = param.getDefault("check_sat", check_sat_); clamp_sat_ = param.getDefault("clamp_sat", clamp_sat_); }
void LinearSolverISTL::init(const Opm::parameter::ParameterGroup& param) { linsolver_residual_tolerance_ = param.getDefault("linsolver_residual_tolerance", linsolver_residual_tolerance_); linsolver_verbosity_ = param.getDefault("linsolver_verbosity", linsolver_verbosity_); linsolver_type_ = LinsolverType(param.getDefault("linsolver_type", int(linsolver_type_))); linsolver_save_system_ = param.getDefault("linsolver_save_system", linsolver_save_system_); if (linsolver_save_system_) { linsolver_save_filename_ = param.getDefault("linsolver_save_filename", std::string("linsys")); } linsolver_max_iterations_ = param.getDefault("linsolver_max_iterations", linsolver_max_iterations_); }
inline void ImplicitCapillarity<GI, RP, BC, IP>::init(const Opm::parameter::ParameterGroup& param) { method_viscous_ = param.getDefault("method_viscous", method_viscous_); method_gravity_ = param.getDefault("method_gravity", method_gravity_); check_sat_ = param.getDefault("check_sat", check_sat_); clamp_sat_ = param.getDefault("clamp_sat", clamp_sat_); residual_tolerance_ = param.getDefault("residual_tolerance", residual_tolerance_); linsolver_verbosity_ = param.getDefault("linsolver_verbosity", linsolver_verbosity_); linsolver_type_ = param.getDefault("linsolver_type", linsolver_type_); update_relaxation_ = param.getDefault("update_relaxation", update_relaxation_); }
inline void UpscalerBase<Traits>::initImpl(const Opm::parameter::ParameterGroup& param) { // Request the boundary condition type parameter early since, // depending on the actual type, we may have to manufacture // and insert other parameters into the ParameterGroup prior // to constructing the grid and associated properties. // int bct = param.get<int>("boundary_condition_type"); bctype_ = static_cast<BoundaryConditionType>(bct); // Import control parameters pertaining to reduced physical // dimensionality ("2d_hack = true" precludes periodic // boundary conditions in the Z direction), and linear solves. // twodim_hack_ = param.getDefault("2d_hack", twodim_hack_); residual_tolerance_ = param.getDefault("residual_tolerance", residual_tolerance_); linsolver_verbosity_ = param.getDefault("linsolver_verbosity", linsolver_verbosity_); linsolver_type_ = param.getDefault("linsolver_type", linsolver_type_); linsolver_maxit_ = param.getDefault("linsolver_max_iterations", linsolver_maxit_); linsolver_prolongate_factor_ = param.getDefault("linsolver_prolongate_factor", linsolver_prolongate_factor_); linsolver_smooth_steps_ = param.getDefault("linsolver_smooth_steps", linsolver_smooth_steps_); // Ensure sufficient grid support for requested boundary // condition type. // Opm::parameter::ParameterGroup temp_param = param; if (bctype_ == Linear || bctype_ == Periodic) { if (!temp_param.has("use_unique_boundary_ids")) { temp_param.insertParameter("use_unique_boundary_ids", "true"); } } if (bctype_ == Periodic) { if (!temp_param.has("periodic_extension")) { temp_param.insertParameter("periodic_extension", "true"); } } setupGridAndProps(temp_param, grid_, res_prop_); ginterf_.init(grid_); }
inline void setupBoundaryConditions(const Opm::parameter::ParameterGroup& param, const GridInterface& g, BCs& bcs) { if (param.getDefault("upscaling", false)) { int bct = param.get<int>("boundary_condition_type"); int pddir = param.getDefault("pressure_drop_direction", 0); double pdrop = param.getDefault("boundary_pressuredrop", 1.0e5); double bdy_sat = param.getDefault("boundary_saturation", 1.0); bool twodim_hack = param.getDefault("2d_hack", false); setupUpscalingConditions(g, bct, pddir, pdrop, bdy_sat, twodim_hack, bcs); return; } if (param.getDefault("region_based_bcs", false)) { setupRegionBasedConditions(param, g, bcs); return; } // Make flow equation boundary conditions. // Default is pressure 1.0e5 on the left, 0.0 on the right. // Recall that the boundary ids range from 1 to 6 for the cartesian edges, // and that boundary id 0 means interiour face/intersection. std::string flow_bc_type = param.getDefault<std::string>("flow_bc_type", "dirichlet"); FlowBC::BCType bct = FlowBC::Dirichlet; double leftval = 1.0*Opm::unit::barsa; double rightval = 0.0; if (flow_bc_type == "neumann") { bct = FlowBC::Neumann; leftval = param.get<double>("left_flux"); rightval = param.getDefault<double>("right_flux", -leftval); } else if (flow_bc_type == "dirichlet") { leftval = param.getDefault<double>("left_pressure", leftval); rightval = param.getDefault<double>("right_pressure", rightval); } else if (flow_bc_type == "periodic") { THROW("Periodic conditions not here yet."); } else { THROW("Unknown flow boundary condition type " << flow_bc_type); } bcs.resize(7); bcs.flowCond(1) = FlowBC(bct, leftval); bcs.flowCond(2) = FlowBC(bct, rightval); // Default transport boundary conditions are used. }
inline void setupGridAndProps(const Opm::parameter::ParameterGroup& param, Dune::CpGrid& grid, ResProp<3>& res_prop) { // Initialize grid and reservoir properties. // Parts copied from Dune::CpGrid::init(). std::string fileformat = param.getDefault<std::string>("fileformat", "cartesian"); if (fileformat == "sintef_legacy") { std::string grid_prefix = param.get<std::string>("grid_prefix"); grid.readSintefLegacyFormat(grid_prefix); OPM_MESSAGE("Warning: We do not yet read legacy reservoir properties. Using defaults."); res_prop.init(grid.size(0)); } else if (fileformat == "eclipse") { std::string ecl_file = param.get<std::string>("filename"); Opm::ParseContext parseContext; Opm::ParserPtr parser(new Opm::Parser()); Opm::DeckConstPtr deck(parser->parseFile(ecl_file , parseContext)); 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); grid.processEclipseFormat(deck, periodic_extension, turn_normals); // Save EGRID file in case we are writing ECL output. if (param.getDefault("output_ecl", false)) { OPM_THROW(std::runtime_error, "Saving to EGRID files is not yet implemented"); /* boost::filesystem::path ecl_path(ecl_file); const std::vector<int>& globalCell = grid.globalCell(); ecl_path.replace_extension(".EGRID"); parser.saveEGRID(ecl_path.string() , (int) globalCell.size() , &globalCell[0]); */ } double perm_threshold_md = param.getDefault("perm_threshold_md", 0.0); double perm_threshold = Opm::unit::convert::from(perm_threshold_md, Opm::prefix::milli*Opm::unit::darcy); std::string rock_list = param.getDefault<std::string>("rock_list", "no_list"); std::string* rl_ptr = (rock_list == "no_list") ? 0 : &rock_list; bool use_j = param.getDefault("use_jfunction_scaling", useJ<ResProp<3> >()); double sigma = 1.0; double theta = 0.0; if (use_j) { sigma = param.getDefault("sigma", sigma); theta = param.getDefault("theta", theta); } if (param.has("viscosity1") || param.has("viscosity2")) { double v1 = param.getDefault("viscosity1", 0.001); double v2 = param.getDefault("viscosity2", 0.003); res_prop.setViscosities(v1, v2); } res_prop.init(deck, grid.globalCell(), perm_threshold, rl_ptr, use_j, sigma, theta); } 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); double default_poro = param.getDefault("default_poro", 0.2); double default_perm_md = param.getDefault("default_perm_md", 100.0); double default_perm = Opm::unit::convert::from(default_perm_md, Opm::prefix::milli*Opm::unit::darcy); OPM_MESSAGE("Warning: For generated cartesian grids, we use uniform reservoir properties."); res_prop.init(grid.size(0), default_poro, default_perm); } else { OPM_THROW(std::runtime_error, "Unknown file format string: " << fileformat); } if (param.getDefault("use_unique_boundary_ids", false)) { grid.setUniqueBoundaryIds(true); } }
inline void SteadyStateUpscaler<Traits>::initImpl(const Opm::parameter::ParameterGroup& param) { Super::initImpl(param); use_gravity_ = param.getDefault("use_gravity", use_gravity_); output_vtk_ = param.getDefault("output_vtk", output_vtk_); print_inoutflows_ = param.getDefault("print_inoutflows", print_inoutflows_); simulation_steps_ = param.getDefault("simulation_steps", simulation_steps_); stepsize_ = Opm::unit::convert::from(param.getDefault("stepsize", stepsize_), Opm::unit::day); relperm_threshold_ = param.getDefault("relperm_threshold", relperm_threshold_); maximum_mobility_contrast_ = param.getDefault("maximum_mobility_contrast", maximum_mobility_contrast_); sat_change_threshold_ = param.getDefault("sat_change_threshold", sat_change_threshold_); transport_solver_.init(param); // Set viscosities and densities if given. double v1_default = this->res_prop_.viscosityFirstPhase(); double v2_default = this->res_prop_.viscositySecondPhase(); this->res_prop_.setViscosities(param.getDefault("viscosity1", v1_default), param.getDefault("viscosity2", v2_default)); double d1_default = this->res_prop_.densityFirstPhase(); double d2_default = this->res_prop_.densitySecondPhase(); this->res_prop_.setDensities(param.getDefault("density1", d1_default), param.getDefault("density2", d2_default)); }
virtual void init(const Opm::parameter::ParameterGroup& param, const Grid& grid, const Fluid& fluid, typename Grid::Vector gravity, State& simstate) { typedef typename Fluid::CompVec CompVec; typedef typename Fluid::PhaseVec PhaseVec; if (param.getDefault("heterogenous_initial_mix", false)) { CompVec init_oil(0.0); init_oil[Fluid::Oil] = 1.0; CompVec init_water(0.0); init_water[Fluid::Water] = 1.0; simstate.cell_z_.resize(grid.numCells()); std::fill(simstate.cell_z_.begin(), simstate.cell_z_.begin() + simstate.cell_z_.size()/2, init_oil); std::fill(simstate.cell_z_.begin() + simstate.cell_z_.size()/2, simstate.cell_z_.end(), init_water); OPM_MESSAGE("******* Assuming zero capillary pressures *******"); PhaseVec init_p(100.0*Opm::unit::barsa); simstate.cell_pressure_.resize(grid.numCells(), init_p); // if (gravity.two_norm() != 0.0) { // double ref_gravpot = grid.cellCentroid(0)*gravity; // double rho = init_z*fluid_.surfaceDensities(); // Assuming incompressible, and constant initial z. // for (int cell = 1; cell < grid.numCells(); ++cell) { // double press = rho*(grid.cellCentroid(cell)*gravity - ref_gravpot) + simstate.cell_pressure_[0][0]; // simstate.cell_pressure_[cell] = PhaseVec(press); // } // } } else if (param.getDefault("unstable_initial_mix", false)) { CompVec init_oil(0.0); init_oil[Fluid::Oil] = 1.0; init_oil[Fluid::Gas] = 0.0; CompVec init_water(0.0); init_water[Fluid::Water] = 1.0; CompVec init_gas(0.0); init_gas[Fluid::Gas] = 150.0; simstate.cell_z_.resize(grid.numCells()); std::fill(simstate.cell_z_.begin(), simstate.cell_z_.begin() + simstate.cell_z_.size()/3, init_water); std::fill(simstate.cell_z_.begin() + simstate.cell_z_.size()/3, simstate.cell_z_.begin() + 2*(simstate.cell_z_.size()/3), init_oil); std::fill(simstate.cell_z_.begin() + 2*(simstate.cell_z_.size()/3), simstate.cell_z_.end(), init_gas); OPM_MESSAGE("******* Assuming zero capillary pressures *******"); PhaseVec init_p(100.0*Opm::unit::barsa); simstate.cell_pressure_.resize(grid.numCells(), init_p); if (gravity.two_norm() != 0.0) { typename Fluid::FluidState state = fluid.computeState(simstate.cell_pressure_[0], simstate.cell_z_[0]); simstate.cell_z_[0] *= 1.0/state.total_phase_volume_density_; for (int cell = 1; cell < grid.numCells(); ++cell) { double fluid_vol_dens; int cnt =0; do { double rho = 0.5*((simstate.cell_z_[cell]+simstate.cell_z_[cell-1])*fluid.surfaceDensities()); double press = rho*((grid.cellCentroid(cell) - grid.cellCentroid(cell-1))*gravity) + simstate.cell_pressure_[cell-1][0]; simstate.cell_pressure_[cell] = PhaseVec(press); state = fluid.computeState(simstate.cell_pressure_[cell], simstate.cell_z_[cell]); fluid_vol_dens = state.total_phase_volume_density_; simstate.cell_z_[cell] *= 1.0/fluid_vol_dens; ++cnt; } while (std::fabs((fluid_vol_dens-1.0)) > 1.0e-8 && cnt < 10); } } else { std::cout << "---- Exit - BlackoilSimulator.hpp: No gravity, no fun ... ----" << std::endl; exit(-1); } } else if (param.getDefault("CO2-injection", false)) { CompVec init_water(0.0); // Initially water filled (use Oil-component for water in order // to utilise blackoil mechanisms for brine-co2 interaction) init_water[Fluid::Oil] = 1.0; simstate.cell_z_.resize(grid.numCells()); std::fill(simstate.cell_z_.begin(),simstate.cell_z_.end(),init_water); double datum_pressure_barsa = param.getDefault<double>("datum_pressure", 200.0); double datum_pressure = Opm::unit::convert::from(datum_pressure_barsa, Opm::unit::barsa); PhaseVec init_p(datum_pressure); simstate.cell_pressure_.resize(grid.numCells(), init_p); // Simple initial condition based on "incompressibility"-assumption double zMin = grid.cellCentroid(0)[2]; for (int cell = 1; cell < grid.numCells(); ++cell) { if (grid.cellCentroid(cell)[2] < zMin) zMin = grid.cellCentroid(cell)[2]; } typename Fluid::FluidState state = fluid.computeState(init_p, init_water); simstate.cell_z_[0] *= 1.0/state.total_phase_volume_density_; double density = (init_water*fluid.surfaceDensities())/state.total_phase_volume_density_; for (int cell = 0; cell < grid.numCells(); ++cell) { double pressure(datum_pressure + (grid.cellCentroid(cell)[2] - zMin)*gravity[2]*density); simstate.cell_pressure_[cell] = PhaseVec(pressure); state = fluid.computeState(simstate.cell_pressure_[cell], simstate.cell_z_[cell]); simstate.cell_z_[cell] *= 1.0/state.total_phase_volume_density_; } } else { CompVec init_z(0.0); double initial_mixture_gas = param.getDefault("initial_mixture_gas", 0.0); double initial_mixture_oil = param.getDefault("initial_mixture_oil", 1.0); double initial_mixture_water = param.getDefault("initial_mixture_water", 0.0); init_z[Fluid::Water] = initial_mixture_water; init_z[Fluid::Gas] = initial_mixture_gas; init_z[Fluid::Oil] = initial_mixture_oil; simstate.cell_z_.resize(grid.numCells(), init_z); OPM_MESSAGE("******* Assuming zero capillary pressures *******"); PhaseVec init_p(param.getDefault("initial_pressure", 100.0*Opm::unit::barsa)); simstate.cell_pressure_.resize(grid.numCells(), init_p); if (gravity.two_norm() != 0.0) { double ref_gravpot = grid.cellCentroid(0)*gravity; double rho = init_z*fluid.surfaceDensities(); // Assuming incompressible, and constant initial z. for (int cell = 1; cell < grid.numCells(); ++cell) { double press = rho*(grid.cellCentroid(cell)*gravity - ref_gravpot) + simstate.cell_pressure_[0][0]; simstate.cell_pressure_[cell] = PhaseVec(press); } } } }
virtual void init(const Opm::parameter::ParameterGroup& param, const Grid& grid, const Fluid& fluid, typename Grid::Vector gravity, State& simstate) { typedef typename Fluid::CompVec CompVec; double zeroDepth = param.getDefault("zero_depth", 2743.2); int nx = param.getDefault<int>("nx", 24); int ny = param.getDefault<int>("ny", 25); int nz = param.getDefault<int>("nz", 15); // double datum_depth = param.getDefault<double>("datum_depth", 2753.87) - zeroDepth; double datum_pressure_barsa = param.getDefault<double>("datum_pressure", 248.22); double datum_pressure = Opm::unit::convert::from(datum_pressure_barsa, Opm::unit::barsa); double wo_contact_depth = param.getDefault<double>("wo_contact_depth", 3032.76) - zeroDepth; double go_contact_depth = param.getDefault<double>("go_contact_depth", 2682.24) - zeroDepth; double connate_water_saturation = param.getDefault<double>("connate_water_saturation", 0.151090); double residual_oil_saturation = param.getDefault<double>("residual_oil_saturation", 0.118510); double initial_mixture_gas = param.getDefault("initial_mixture_gas", 247.43); double initial_mixture_oil = param.getDefault("initial_mixture_oil", 1.0); // Initial fluid state CompVec oil_sample(0.0); oil_sample[Fluid::Oil] = initial_mixture_oil; oil_sample[Fluid::Gas] = initial_mixture_gas; CompVec water_sample(0.0); water_sample[Fluid::Water] = 1.0; simstate.cell_z_.resize(grid.numCells()); simstate.cell_pressure_.resize(grid.numCells()); // Datum -cell // For now, assume that datum_depth corresponds the centroid of cell 0 (reasonable approx) simstate.cell_pressure_[0] = datum_pressure; typename Fluid::FluidState state = fluid.computeState(simstate.cell_pressure_[0],oil_sample); simstate.cell_z_[0] = oil_sample; simstate.cell_z_[0] *= (1.0-connate_water_saturation)/state.total_phase_volume_density_; state = fluid.computeState(simstate.cell_pressure_[0],water_sample); simstate.cell_z_[0][Fluid::Water] = water_sample[Fluid::Water]; simstate.cell_z_[0][Fluid::Water] *= connate_water_saturation/state.total_phase_volume_density_; // Rest of the cells -- NOTE: Assume uniform cell properties in y-direction for (int i=0; i<nx; ++i) { int k0=i*nz; for (int k=0; k<nz; ++k) { int kk=k0+k; if (i>0 && k==0) { computeCellState(grid, fluid, gravity, kk, kk-nz, wo_contact_depth, go_contact_depth, connate_water_saturation, residual_oil_saturation, simstate); } else if (k>0) { computeCellState(grid, fluid, gravity, kk, kk-1, wo_contact_depth, go_contact_depth, connate_water_saturation, residual_oil_saturation, simstate); } // Copy cell properties to y-layers for (int j=1; j<ny; ++j) { int jj = j*nx*nz + kk; simstate.cell_z_[jj] = simstate.cell_z_[kk]; simstate.cell_pressure_[jj] = simstate.cell_pressure_[kk]; } } } }
void upscale(const Opm::parameter::ParameterGroup& param) { // Control structure. std::vector<double> saturations; Opm::SparseTable<double> all_pdrops; bool from_file = param.has("sat_pdrop_filename"); if (from_file) { std::string filename = param.get<std::string>("sat_pdrop_filename"); std::ifstream file(filename.c_str()); if (!file) { OPM_THROW(std::runtime_error, "Could not open file " << filename); } readControl(file, saturations, all_pdrops); } else { // Get a linear range of saturations. int num_sats = param.getDefault("num_sats", 4); double min_sat = param.getDefault("min_sat", 0.2); double max_sat = param.getDefault("max_sat", 0.8); saturations.resize(num_sats); for (int i = 0; i < num_sats; ++i) { double factor = num_sats == 1 ? 0 : double(i)/double(num_sats - 1); saturations[i] = (1.0 - factor)*min_sat + factor*max_sat; } // Get a logarithmic range of pressure drops. int num_pdrops = param.getDefault("num_pdrops", 5); double log_min_pdrop = std::log(param.getDefault("min_pdrop", 1e2)); double log_max_pdrop = std::log(param.getDefault("max_pdrop", 1e6)); std::vector<double> pdrops; pdrops.resize(num_pdrops); for (int i = 0; i < num_pdrops; ++i) { double factor = num_pdrops == 1 ? 0 : double(i)/double(num_pdrops - 1); pdrops[i] = std::exp((1.0 - factor)*log_min_pdrop + factor*log_max_pdrop); } // Assign the same pressure drops to all saturations. for (int i = 0; i < num_sats; ++i) { all_pdrops.appendRow(pdrops.begin(), pdrops.end()); } } int flow_direction = param.getDefault("flow_direction", 0); // Print the saturations and pressure drops. // writeControl(std::cout, saturations, all_pdrops); // Initialize upscaler. typedef SteadyStateUpscaler<Traits> Upscaler; typedef typename Upscaler::permtensor_t permtensor_t; Upscaler upscaler; upscaler.init(param); // First, compute an upscaled permeability. permtensor_t upscaled_K = upscaler.upscaleSinglePhase(); permtensor_t upscaled_K_copy = upscaled_K; upscaled_K_copy *= (1.0/(Opm::prefix::milli*Opm::unit::darcy)); std::cout.precision(15); std::cout << "Upscaled K in millidarcy:\n" << upscaled_K_copy << std::endl; std::cout << "Upscaled porosity: " << upscaler.upscalePorosity() << std::endl; // Create output streams for upscaled relative permeabilities std::string kr_filename = param.getDefault<std::string>("kr_filename", "upscaled_relperm"); std::string krw_filename = kr_filename + "_water"; std::string kro_filename = kr_filename + "_oil"; std::ofstream krw_out(krw_filename.c_str()); std::ofstream kro_out(kro_filename.c_str()); krw_out << "# Result from steady state upscaling" << std::endl; krw_out << "# Pressuredrop Sw Krxx Kryy Krzz" << std::endl; kro_out << "# Result from steady state upscaling" << std::endl; kro_out << "# Pressuredrop Sw Krxx Kryy Krzz" << std::endl; krw_out.precision(15); krw_out.setf(std::ios::scientific | std::ios::showpoint); kro_out.precision(15); kro_out.setf(std::ios::scientific | std::ios::showpoint); //#endif // Then, compute some upscaled relative permeabilities. int num_cells = upscaler.grid().size(0); int num_sats = saturations.size(); for (int i = 0; i < num_sats; ++i) { // Starting every computation with a trio of uniform profiles. std::vector<double> init_sat(num_cells, saturations[i]); const Opm::SparseTable<double>::row_type pdrops = all_pdrops[i]; int num_pdrops = pdrops.size(); for (int j = 0; j < num_pdrops; ++j) { double pdrop = pdrops[j]; std::pair<permtensor_t, permtensor_t> lambda = upscaler.upscaleSteadyState(flow_direction, init_sat, saturations[i], pdrop, upscaled_K); double usat = upscaler.lastSaturationUpscaled(); std::cout << "\n\nTensor of upscaled relperms for initial saturation " << saturations[i] << ", real steady-state saturation " << usat << " and pressure drop " << pdrop << ":\n\n[water]\n" << lambda.first << "\n[oil]\n" << lambda.second << std::endl; // Changing initial saturations for next pressure drop to equal the steady state of the last init_sat = upscaler.lastSaturationState(); writeRelPerm(krw_out, lambda.first , usat, pdrop); writeRelPerm(kro_out, lambda.second, usat, pdrop); } } }