From 1b3707e56a0098cf60fe0aa77fbf0589116cb6a6 Mon Sep 17 00:00:00 2001 From: Stein Krogstad Date: Tue, 10 Mar 2026 23:03:27 +0100 Subject: [PATCH 1/2] use analytic weights for cprw by default except when solvent is enabled --- .../linalg/FlowLinearSolverParameters.cpp | 3 ++- .../linalg/FlowLinearSolverParameters.hpp | 3 ++- opm/simulators/linalg/ISTLSolver.hpp | 15 +++++++++------ opm/simulators/linalg/setupPropertyTree.cpp | 7 ++++++- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/opm/simulators/linalg/FlowLinearSolverParameters.cpp b/opm/simulators/linalg/FlowLinearSolverParameters.cpp index c5d9c1d12b1..16c62323fb3 100644 --- a/opm/simulators/linalg/FlowLinearSolverParameters.cpp +++ b/opm/simulators/linalg/FlowLinearSolverParameters.cpp @@ -29,7 +29,7 @@ namespace Opm { -void FlowLinearSolverParameters::init(bool cprRequestedInDataFile) +void FlowLinearSolverParameters::init(bool cprRequestedInDataFile, bool cprwUseAnalyticWeights) { // TODO: these parameters have undocumented non-trivial dependencies relaxed_linear_solver_reduction_ = Parameters::Get(); @@ -48,6 +48,7 @@ void FlowLinearSolverParameters::init(bool cprRequestedInDataFile) cpr_reuse_setup_ = Parameters::Get(); cpr_reuse_interval_ = Parameters::Get(); gpu_aware_mpi_ = Parameters::Get(); + cprw_use_analytic_weights_ = cprwUseAnalyticWeights; if (!Parameters::IsSet() && cprRequestedInDataFile) { linsolver_ = "cpr"; diff --git a/opm/simulators/linalg/FlowLinearSolverParameters.hpp b/opm/simulators/linalg/FlowLinearSolverParameters.hpp index 2cbf6e65686..537a4f3010e 100644 --- a/opm/simulators/linalg/FlowLinearSolverParameters.hpp +++ b/opm/simulators/linalg/FlowLinearSolverParameters.hpp @@ -122,10 +122,11 @@ struct FlowLinearSolverParameters bool gpu_aware_mpi_; bool verify_gpu_aware_mpi_; bool cpr_weights_thread_parallel_; + bool cprw_use_analytic_weights_; FlowLinearSolverParameters() { reset(); } - void init(bool cprRequestedInDataFile); + void init(bool cprRequestedInDataFile, bool cprwUseAnalyticWeights = true); static void registerParameters(); diff --git a/opm/simulators/linalg/ISTLSolver.hpp b/opm/simulators/linalg/ISTLSolver.hpp index e55762e8d3d..bac372b6aba 100644 --- a/opm/simulators/linalg/ISTLSolver.hpp +++ b/opm/simulators/linalg/ISTLSolver.hpp @@ -166,9 +166,11 @@ std::unique_ptr blockJacobiAdjacency(const Grid& grid, using ElementChunksType = ElementChunks; constexpr static std::size_t pressureIndex = GetPropType::pressureSwitchIdx; - + enum { enableSolvent = getPropValue()}; enum { enablePolymerMolarWeight = getPropValue() }; - constexpr static bool isIncompatibleWithCprw = enablePolymerMolarWeight; + + static constexpr bool isIncompatibleWithCprw = enablePolymerMolarWeight; + static constexpr bool canUseAnalyticWeightsForCprw = !enableSolvent; #if HAVE_MPI using CommunicationType = Dune::OwnerOverlapCopyCommunication; @@ -212,7 +214,9 @@ std::unique_ptr blockJacobiAdjacency(const Grid& grid, matrix_(nullptr) { parameters_.resize(1); - parameters_[0].init(simulator_.vanguard().eclState().getSimulationConfig().useCPR()); + parameters_[0].init(simulator_.vanguard().eclState().getSimulationConfig().useCPR(), + canUseAnalyticWeightsForCprw); + initialize(); } @@ -228,7 +232,6 @@ std::unique_ptr blockJacobiAdjacency(const Grid& grid, "Choose a different option, for example --linear-solver=ilu0"); } } - if (parameters_[0].linsolver_ == "hybrid") { // Experimental hybrid configuration. // When chosen, will set up two solvers, one with CPRW @@ -238,7 +241,7 @@ std::unique_ptr blockJacobiAdjacency(const Grid& grid, parameters_.clear(); { FlowLinearSolverParameters para; - para.init(false); + para.init(false, canUseAnalyticWeightsForCprw); para.linsolver_ = "cprw"; parameters_.push_back(para); prm_.push_back(setupPropertyTree(parameters_[0], @@ -247,7 +250,7 @@ std::unique_ptr blockJacobiAdjacency(const Grid& grid, } { FlowLinearSolverParameters para; - para.init(false); + para.init(false, canUseAnalyticWeightsForCprw); para.linsolver_ = "ilu0"; parameters_.push_back(para); prm_.push_back(setupPropertyTree(parameters_[1], diff --git a/opm/simulators/linalg/setupPropertyTree.cpp b/opm/simulators/linalg/setupPropertyTree.cpp index 3f7b6919eca..23eba02f4aa 100644 --- a/opm/simulators/linalg/setupPropertyTree.cpp +++ b/opm/simulators/linalg/setupPropertyTree.cpp @@ -290,7 +290,12 @@ setupCPRW(const std::string& /*conf*/, const FlowLinearSolverParameters& p) prm.put("preconditioner.type", "cprw"s); prm.put("preconditioner.use_well_weights", "false"s); prm.put("preconditioner.add_wells", "true"s); - prm.put("preconditioner.weight_type", "trueimpes"s); + // Can't use trueimpesanalytic when e.g., solvent is active + if (p.cprw_use_analytic_weights_) { + prm.put("preconditioner.weight_type", "trueimpesanalytic"s); + } else { + prm.put("preconditioner.weight_type", "trueimpes"s); + } prm.put("preconditioner.pre_smooth", 0); prm.put("preconditioner.post_smooth", 1); prm.put("preconditioner.finesmoother.type", "paroverilu0"s); From baf7aa75ae0ca4a1f6d13612dee6fc14c61ea052 Mon Sep 17 00:00:00 2001 From: Stein Krogstad Date: Fri, 13 Mar 2026 14:36:37 +0100 Subject: [PATCH 2/2] Remove default argument, check EnableSolvent also in ISTLSolverGPUISTL.hpp/BlackoilModelNldd.hpp --- opm/simulators/flow/BlackoilModelNldd.hpp | 5 ++++- opm/simulators/linalg/FlowLinearSolverParameters.hpp | 2 +- opm/simulators/linalg/gpuistl/ISTLSolverGPUISTL.hpp | 7 +++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/opm/simulators/flow/BlackoilModelNldd.hpp b/opm/simulators/flow/BlackoilModelNldd.hpp index 10ca0d0a2ad..d90479decbe 100644 --- a/opm/simulators/flow/BlackoilModelNldd.hpp +++ b/opm/simulators/flow/BlackoilModelNldd.hpp @@ -99,6 +99,9 @@ class BlackoilModelNldd static constexpr int numEq = Indices::numEq; + enum { enableSolvent = getPropValue() }; + static constexpr bool canUseAnalyticWeightsForCprw = !enableSolvent; + //! \brief The constructor sets up the subdomains. //! \param model BlackOil model to solve for //! \param param param Model parameters @@ -203,7 +206,7 @@ class BlackoilModelNldd const auto& eclState = model_.simulator().vanguard().eclState(); FlowLinearSolverParameters loc_param; loc_param.is_nldd_local_solver_ = true; - loc_param.init(eclState.getSimulationConfig().useCPR()); + loc_param.init(eclState.getSimulationConfig().useCPR(), canUseAnalyticWeightsForCprw); // Override solver type with umfpack if small domain. if (domains_[index].cells.size() < 200) { loc_param.linsolver_ = "umfpack"; diff --git a/opm/simulators/linalg/FlowLinearSolverParameters.hpp b/opm/simulators/linalg/FlowLinearSolverParameters.hpp index 537a4f3010e..9e9b17ef31e 100644 --- a/opm/simulators/linalg/FlowLinearSolverParameters.hpp +++ b/opm/simulators/linalg/FlowLinearSolverParameters.hpp @@ -126,7 +126,7 @@ struct FlowLinearSolverParameters FlowLinearSolverParameters() { reset(); } - void init(bool cprRequestedInDataFile, bool cprwUseAnalyticWeights = true); + void init(bool cprRequestedInDataFile, bool cprwUseAnalyticWeights); static void registerParameters(); diff --git a/opm/simulators/linalg/gpuistl/ISTLSolverGPUISTL.hpp b/opm/simulators/linalg/gpuistl/ISTLSolverGPUISTL.hpp index 68c89c86e33..8a57fcf3937 100644 --- a/opm/simulators/linalg/gpuistl/ISTLSolverGPUISTL.hpp +++ b/opm/simulators/linalg/gpuistl/ISTLSolverGPUISTL.hpp @@ -77,7 +77,9 @@ class ISTLSolverGPUISTL : public AbstractISTLSolver using GPUVectorInt = Opm::gpuistl::GpuVector; constexpr static std::size_t pressureIndex = GetPropType::pressureSwitchIdx; - + + enum { enableSolvent = getPropValue() }; + static constexpr bool canUseAnalyticWeightsForCprw = !enableSolvent; #if HAVE_MPI using CommunicationType = Dune::OwnerOverlapCopyCommunication; @@ -119,7 +121,8 @@ class ISTLSolverGPUISTL : public AbstractISTLSolver #else m_comm = std::make_shared(simulator.gridView().comm()); #endif - m_parameters.init(simulator.vanguard().eclState().getSimulationConfig().useCPR()); + m_parameters.init(simulator.vanguard().eclState().getSimulationConfig().useCPR(), + canUseAnalyticWeightsForCprw); m_propertyTree = setupPropertyTree(m_parameters, Parameters::IsSet(), Parameters::IsSet());