mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-10-24 22:57:42 -05:00
Introduce a prototype for solving the reservoir and well degrees of freedom as a single coupled linear system. This complements the existing approach of handling wells separately through Schur complement elimination. Key design choices: - The linear solve operates on the full coupled system (reservoir + well DOFs) to simplify the solver architecture and reduce special-case well handling - The underlying solver uses standard sparse matrices with no well-aware operators, improving modularity and reducing code complexity - The included preconditioner is configurable to reproduce standard CPR behavior, providing a baseline for validation before further performance tuning - An approximate well-block solve is supported for potential performance gains Important changes: - Add linear solver implementation with coupled system support - Configure preconditioner to match existing CPR behavior for correctness - Remove need for separate well-block elimination in the linear solve path - Update solver selection to allow --linear-solver=system_cpr option This implementation serves as a prototype to validate the coupled system approach before further optimization and benchmarking.
91 lines
3.5 KiB
C++
91 lines
3.5 KiB
C++
/*
|
|
Copyright 2025 SINTEF Digital, Mathematics and Cybernetics.
|
|
|
|
This file is part of the Open Porous Media project (OPM).
|
|
|
|
OPM is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
OPM is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#define BOOST_TEST_MODULE TestSetupPropertyTree
|
|
|
|
#ifndef HAVE_MPI
|
|
#define HAVE_MPI 0
|
|
#endif
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
#include <opm/simulators/linalg/PropertyTree.hpp>
|
|
#include <opm/simulators/linalg/setupPropertyTree.hpp>
|
|
|
|
#include <stdexcept>
|
|
|
|
BOOST_AUTO_TEST_SUITE(SystemCPR)
|
|
|
|
// Unit test 1: JSON file with system_cpr but missing well_solver must throw.
|
|
//
|
|
// options_system_cpr_missing_well.json contains reservoir_smoother and
|
|
// reservoir_solver but no well_solver. validateSystemCPRTree must catch this
|
|
// at setup time so the error is clear rather than a cryptic PropertyTree
|
|
// exception from deep inside SystemPreconditioner::initSubSolvers.
|
|
BOOST_AUTO_TEST_CASE(JSONMissingWellSolver)
|
|
{
|
|
Opm::PropertyTree prm("options_system_cpr_missing_well.json");
|
|
BOOST_CHECK_THROW(Opm::validateSystemCPRTree(prm), std::invalid_argument);
|
|
}
|
|
|
|
// Unit test 2: JSON file with system_cpr but missing reservoir_solver must throw.
|
|
BOOST_AUTO_TEST_CASE(JSONMissingReservoirSolver)
|
|
{
|
|
Opm::PropertyTree prm("options_system_cpr_missing_ressolver.json");
|
|
BOOST_CHECK_THROW(Opm::validateSystemCPRTree(prm), std::invalid_argument);
|
|
}
|
|
|
|
// Unit test 3: JSON file with system_cpr but missing reservoir_smoother must throw.
|
|
BOOST_AUTO_TEST_CASE(JSONMissingReservoirSmoother)
|
|
{
|
|
Opm::PropertyTree prm("options_system_cpr_missing_smoother.json");
|
|
BOOST_CHECK_THROW(Opm::validateSystemCPRTree(prm), std::invalid_argument);
|
|
}
|
|
|
|
// Unit test 3: JSON has reservoir_solver but no preconditioner.type (or no preconditioner at all)
|
|
BOOST_AUTO_TEST_CASE(JSONReservoirSolverPreconditionerTypeMissingOrWrong)
|
|
{
|
|
// Test missing type
|
|
Opm::PropertyTree prm("options_system_cpr_missing_precond_type.json");
|
|
BOOST_CHECK_THROW(Opm::validateSystemCPRTree(prm), std::invalid_argument);
|
|
|
|
// Test wrong type (e.g., "ilu")
|
|
Opm::PropertyTree prm2("options_system_cpr_res_precond_not_cpr.json");
|
|
BOOST_CHECK_THROW(Opm::validateSystemCPRTree(prm2), std::invalid_argument);
|
|
}
|
|
|
|
// Regression test: --matrix-add-well-contributions=true is incompatible
|
|
// with system_cpr and must throw in both serial and parallel (MPI) runs.
|
|
//
|
|
// system_cpr handles reservoir-well coupling in the outer three-stage
|
|
// SystemPreconditioner. Enabling matrix well contributions merges well rows
|
|
// into the reservoir block before that preconditioner runs, which would
|
|
// double-count the coupling and corrupt the linear system.
|
|
// ISTLSolverRuntimeOptionProxy::createSolver delegates to this function,
|
|
// making the invariant unit-testable without the full simulator framework.
|
|
BOOST_AUTO_TEST_CASE(MatrixAddWellContributionsIncompatible)
|
|
{
|
|
BOOST_CHECK_THROW(Opm::checkSystemCPRMatrixAddWell(true), std::invalid_argument);
|
|
BOOST_CHECK_NO_THROW(Opm::checkSystemCPRMatrixAddWell(false));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END() // SystemCPR
|