diff --git a/opm/autodiff/BlackoilReorderingTransportModel.hpp b/opm/autodiff/BlackoilReorderingTransportModel.hpp index 15c442462..1f8b50fd5 100644 --- a/opm/autodiff/BlackoilReorderingTransportModel.hpp +++ b/opm/autodiff/BlackoilReorderingTransportModel.hpp @@ -60,16 +60,16 @@ namespace Opm { /// \param[in] has_vapoil turn on vaporized oil feature /// \param[in] terminal_output request output to cout/cerr BlackoilReorderingTransportModel(const typename Base::ModelParameters& param, - const Grid& grid, - const BlackoilPropsAdInterface& fluid, - const DerivedGeology& geo, - const RockCompressibility* rock_comp_props, - const StandardWells& std_wells, - const NewtonIterationBlackoilInterface& linsolver, - Opm::EclipseStateConstPtr eclState, - const bool has_disgas, - const bool has_vapoil, - const bool terminal_output) + const Grid& grid, + const BlackoilPropsAdInterface& fluid, + const DerivedGeology& geo, + const RockCompressibility* rock_comp_props, + const StandardWells& std_wells, + const NewtonIterationBlackoilInterface& linsolver, + Opm::EclipseStateConstPtr eclState, + const bool has_disgas, + const bool has_vapoil, + const bool terminal_output) : Base(param, grid, fluid, geo, rock_comp_props, std_wells, linsolver, eclState, has_disgas, has_vapoil, terminal_output) , reservoir_state0_(0, 0, 0) @@ -89,6 +89,10 @@ namespace Opm { Base::param_.solve_welleq_initially_ = false; reservoir_state0_ = reservoir_state; well_state0_ = well_state; + // Since pressure is constant, porosity and transmissibility multipliers can + // be computed just once. + const std::vector& p = reservoir_state.pressure(); + Base::pvdt_ *= Base::poroMult(ADB::constant(Eigen::Map(p.data(), p.size()))).value(); } @@ -102,10 +106,11 @@ namespace Opm { ReservoirState& reservoir_state, const WellState& well_state) { - // Extract reservoir and well fluxes. + // Extract reservoir and well fluxes and fields. { DebugTimeReport tr("Extracting fluxes"); extractFluxes(reservoir_state, well_state); + extractFields(reservoir_state); } // Compute cell ordering based on total flux. @@ -153,6 +158,8 @@ namespace Opm { // ============ Data members ============ using Base::grid_; using Base::ops_; + using Vec2 = Dune::FieldVector; + using Mat22 = Dune::FieldMatrix; ReservoirState reservoir_state0_; WellState well_state0_; @@ -161,6 +168,10 @@ namespace Opm { DataBlock comp_wellperf_flux_; std::vector sequence_; std::vector components_; + V sw_; + V sg_; + V rs_; + V rv_; // ============ Member functions ============ @@ -188,6 +199,20 @@ namespace Opm { + void extractFields(const ReservoirState& reservoir_state) + { + assert(numPhases() == 3); + const int n = reservoir_state.pressure().size(); + sw_ = Eigen::Map(reservoir_state.saturation().data(), n, numPhases()).col(0); + sg_ = Eigen::Map(reservoir_state.saturation().data(), n, numPhases()).col(2); + rs_ = Eigen::Map(reservoir_state.gasoilratio().data(), n); + rv_ = Eigen::Map(reservoir_state.rv().data(), n); + } + + + + + void computeOrdering() { static_assert(std::is_same::value, @@ -225,6 +250,19 @@ namespace Opm { void solveSingleCell(const int cell) { + + Vec2 x = getInitialGuess(cell); + Vec2 res; + Mat22 jac; + assembleSingleCell(cell, x, res, jac); + + // Newton loop. + while (!getConvergence(res)) { + Vec2 dx; + jac.solve(dx, res); + x = x - dx; + assembleSingleCell(cell, x, res, jac); + } } @@ -233,6 +271,49 @@ namespace Opm { void solveMultiCell(const int comp_size, const int* cell_array) { + OpmLog::warning("solveMultiCell", "solveMultiCell() called with component size " + std::to_string(comp_size)); + for (int ii = 0; ii < comp_size; ++ii) { + solveSingleCell(cell_array[ii]); + } + } + + + + + + void assembleSingleCell(const int cell, const Vec2& x, Vec2& res, Mat22& jac) + { + // Assemble oil and gas component material balance equations. + const double sw = x[0]; + const double sg = Base::isSg_[cell] ? x[1] : sg_[cell]; + const double so = 1.0 - sw - sg; + const double rs = Base::isRs_[cell] ? x[1] : rs_[cell]; + const double rv = Base::isRv_[cell] ? x[1] : rv_[cell]; + const double bo = 0.0; + const double bg = 0.0; + double mo = (bo*so); + res[0] = Base::pvdt_[cell]*(0.0); + } + + + + + + Vec2 getInitialGuess(const int cell) + { + double xvar = (Base::isSg_[cell]) ? sg_[cell] + : ((Base::isRs_[cell]) ? rs_[cell] : rv_[cell]); + return Vec2{sw_[cell], xvar}; + } + + + + + + bool getConvergence(const Vec2& res) + { + const double tol = 1e-6; + return res[0] < tol && res[1] < tol; } };