diff --git a/opm/autodiff/BlackoilMultiSegmentModel.hpp b/opm/autodiff/BlackoilMultiSegmentModel.hpp index 0408aab52..035d3b086 100644 --- a/opm/autodiff/BlackoilMultiSegmentModel.hpp +++ b/opm/autodiff/BlackoilMultiSegmentModel.hpp @@ -119,6 +119,13 @@ namespace Opm { const bool initial_assembly); + /// Compute convergence based on total mass balance (tol_mb) and maximum + /// residual mass balance (tol_cnv). + /// \param[in] dt timestep length + /// \param[in] iteration current iteration number + bool getConvergence(const double dt, const int iteration); + + /// Apply an update to the primary variables, chopped if appropriate. /// \param[in] dx updates to apply to primary variables /// \param[in, out] reservoir_state reservoir state variables @@ -155,6 +162,8 @@ namespace Opm { using Base::has_vapoil_; using Base::primalVariable_; using Base::cells_; + using Base::param_; + using Base::linsolver_; // Diff to the pressure of the related segment. @@ -210,12 +219,14 @@ namespace Opm { using Base::dpMaxRel; using Base::dsMax; using Base::drMaxRel; + using Base::convergenceReduction; + using Base::maxResidualAllowed; + using Base::variableState; const std::vector& wellsMultiSegment() const { return wells_multisegment_; } void updateWellControls(WellState& xw) const; - using Base::variableState; void updateWellState(const V& dwells, WellState& well_state); diff --git a/opm/autodiff/BlackoilMultiSegmentModel_impl.hpp b/opm/autodiff/BlackoilMultiSegmentModel_impl.hpp index f26039bfd..f4e822c51 100644 --- a/opm/autodiff/BlackoilMultiSegmentModel_impl.hpp +++ b/opm/autodiff/BlackoilMultiSegmentModel_impl.hpp @@ -1434,6 +1434,123 @@ namespace Opm { + + + template + bool + BlackoilMultiSegmentModel::getConvergence(const double dt, const int iteration) + { + + const double tol_mb = param_.tolerance_mb_; + const double tol_cnv = param_.tolerance_cnv_; + const double tol_wells = param_.tolerance_wells_; + + const int nc = Opm::AutoDiffGrid::numCells(grid_); + const int nw = wellsMultiSegment().size(); + // no good way to store nseg? + int nseg_total = 0; + for (int w = 0; w < nw; ++w) { + nseg_total += wellsMultiSegment()[w]->numberOfSegments(); + } + + const Opm::PhaseUsage& pu = fluid_.phaseUsage(); + + const V pv = geo_.poreVolume(); + + const std::vector cond = phaseCondition(); + + std::array CNV = {{0., 0., 0.}}; + std::array R_sum = {{0., 0., 0.}}; + std::array B_avg = {{0., 0., 0.}}; + std::array maxCoeff = {{0., 0., 0.}}; + std::array mass_balance_residual = {{0., 0., 0.}}; + std::array well_flux_residual = {{0., 0., 0.}}; + std::size_t cols = MaxNumPhases; // needed to pass the correct type to Eigen + Eigen::Array B(nc, cols); + Eigen::Array R(nc, cols); + Eigen::Array tempV(nc, cols); + std::vector maxNormWell(MaxNumPhases); + + for ( int idx=0; idx maxResidualAllowed() || + std::isnan(mass_balance_residual[Oil]) || mass_balance_residual[Oil] > maxResidualAllowed() || + std::isnan(mass_balance_residual[Gas]) || mass_balance_residual[Gas] > maxResidualAllowed() || + std::isnan(CNV[Water]) || CNV[Water] > maxResidualAllowed() || + std::isnan(CNV[Oil]) || CNV[Oil] > maxResidualAllowed() || + std::isnan(CNV[Gas]) || CNV[Gas] > maxResidualAllowed() || + std::isnan(well_flux_residual[Water]) || well_flux_residual[Water] > maxResidualAllowed() || + std::isnan(well_flux_residual[Oil]) || well_flux_residual[Oil] > maxResidualAllowed() || + std::isnan(well_flux_residual[Gas]) || well_flux_residual[Gas] > maxResidualAllowed() || + std::isnan(residualWell) || residualWell > maxWellResidualAllowed ) + { + OPM_THROW(Opm::NumericalProblem,"One of the residuals is NaN or too large!"); + } + + if ( terminal_output_ ) + { + // Only rank 0 does print to std::cout + if (iteration == 0) { + std::cout << "\nIter MB(WATER) MB(OIL) MB(GAS) CNVW CNVO CNVG W-FLUX(W) W-FLUX(O) W-FLUX(G)\n"; + } + const std::streamsize oprec = std::cout.precision(3); + const std::ios::fmtflags oflags = std::cout.setf(std::ios::scientific); + std::cout << std::setw(4) << iteration + << std::setw(11) << mass_balance_residual[Water] + << std::setw(11) << mass_balance_residual[Oil] + << std::setw(11) << mass_balance_residual[Gas] + << std::setw(11) << CNV[Water] + << std::setw(11) << CNV[Oil] + << std::setw(11) << CNV[Gas] + << std::setw(11) << well_flux_residual[Water] + << std::setw(11) << well_flux_residual[Oil] + << std::setw(11) << well_flux_residual[Gas] + << std::endl; + std::cout.precision(oprec); + std::cout.flags(oflags); + } + return converged; + } + + + + } // namespace Opm #endif // OPM_BLACKOILMODELBASE_IMPL_HEADER_INCLUDED