diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 4e27779d2..5206b62de 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -43,6 +43,7 @@ list (APPEND MAIN_SOURCE_FILES opm/simulators/linalg/FlexibleSolver2.cpp opm/simulators/linalg/FlexibleSolver3.cpp opm/simulators/linalg/FlexibleSolver4.cpp + opm/simulators/linalg/PropertyTree.cpp opm/simulators/linalg/setupPropertyTree.cpp opm/simulators/utils/PartiallySupportedFlowKeywords.cpp opm/simulators/utils/readDeck.cpp @@ -261,6 +262,7 @@ list (APPEND PUBLIC_HEADER_FILES opm/simulators/linalg/PressureTransferPolicy.hpp opm/simulators/linalg/PreconditionerFactory.hpp opm/simulators/linalg/PreconditionerWithUpdate.hpp + opm/simulators/linalg/PropertyTree.hpp opm/simulators/linalg/WellOperators.hpp opm/simulators/linalg/WriteSystemMatrixHelper.hpp opm/simulators/linalg/findOverlapRowsAndColumns.hpp diff --git a/opm/simulators/linalg/FlexibleSolver.hpp b/opm/simulators/linalg/FlexibleSolver.hpp index d6383d414..352506a92 100644 --- a/opm/simulators/linalg/FlexibleSolver.hpp +++ b/opm/simulators/linalg/FlexibleSolver.hpp @@ -23,12 +23,11 @@ #define OPM_FLEXIBLE_SOLVER_HEADER_INCLUDED #include +#include #include #include -#include - namespace Dune { @@ -50,14 +49,14 @@ public: /// Create a sequential solver. FlexibleSolver(AbstractOperatorType& op, - const boost::property_tree::ptree& prm, + const Opm::PropertyTree& prm, const std::function& weightsCalculator = std::function()); /// Create a parallel solver (if Comm is e.g. OwnerOverlapCommunication). template FlexibleSolver(AbstractOperatorType& op, const Comm& comm, - const boost::property_tree::ptree& prm, + const Opm::PropertyTree& prm, const std::function& weightsCalculator = std::function()); virtual void apply(VectorType& x, VectorType& rhs, Dune::InverseOperatorResult& res) override; @@ -75,20 +74,20 @@ private: // Machinery for making sequential or parallel operators/preconditioners/scalar products. template - void initOpPrecSp(AbstractOperatorType& op, const boost::property_tree::ptree& prm, + void initOpPrecSp(AbstractOperatorType& op, const Opm::PropertyTree& prm, const std::function weightsCalculator, const Comm& comm); - void initOpPrecSp(AbstractOperatorType& op, const boost::property_tree::ptree& prm, + void initOpPrecSp(AbstractOperatorType& op, const Opm::PropertyTree& prm, const std::function weightsCalculator, const Dune::Amg::SequentialInformation&); - void initSolver(const boost::property_tree::ptree& prm, const bool is_iorank); + void initSolver(const Opm::PropertyTree& prm, const bool is_iorank); // Main initialization routine. // Call with Comm == Dune::Amg::SequentialInformation to get a serial solver. template void init(AbstractOperatorType& op, const Comm& comm, - const boost::property_tree::ptree& prm, + const Opm::PropertyTree& prm, const std::function weightsCalculator); AbstractOperatorType* linearoperator_for_solver_; diff --git a/opm/simulators/linalg/FlexibleSolver_impl.hpp b/opm/simulators/linalg/FlexibleSolver_impl.hpp index 054830540..69fdb1e35 100644 --- a/opm/simulators/linalg/FlexibleSolver_impl.hpp +++ b/opm/simulators/linalg/FlexibleSolver_impl.hpp @@ -32,15 +32,13 @@ #include #include -#include - namespace Dune { /// Create a sequential solver. template FlexibleSolver:: FlexibleSolver(AbstractOperatorType& op, - const boost::property_tree::ptree& prm, + const Opm::PropertyTree& prm, const std::function& weightsCalculator) { init(op, Dune::Amg::SequentialInformation(), prm, weightsCalculator); @@ -52,7 +50,7 @@ namespace Dune FlexibleSolver:: FlexibleSolver(AbstractOperatorType& op, const Comm& comm, - const boost::property_tree::ptree& prm, + const Opm::PropertyTree& prm, const std::function& weightsCalculator) { init(op, comm, prm, weightsCalculator); @@ -97,18 +95,17 @@ namespace Dune void FlexibleSolver:: initOpPrecSp(AbstractOperatorType& op, - const boost::property_tree::ptree& prm, + const Opm::PropertyTree& prm, const std::function weightsCalculator, const Comm& comm) { // Parallel case. - using pt = const boost::property_tree::ptree; using ParOperatorType = Dune::OverlappingSchwarzOperator; linearoperator_for_solver_ = &op; auto op_prec = std::make_shared(op.getmat(), comm); auto child = prm.get_child_optional("preconditioner"); preconditioner_ = Opm::PreconditionerFactory::create(*op_prec, - child ? *child : pt(), + child ? *child : Opm::PropertyTree(), weightsCalculator, comm); scalarproduct_ = Dune::createScalarProduct(comm, op.category()); @@ -119,18 +116,17 @@ namespace Dune void FlexibleSolver:: initOpPrecSp(AbstractOperatorType& op, - const boost::property_tree::ptree& prm, + const Opm::PropertyTree& prm, const std::function weightsCalculator, const Dune::Amg::SequentialInformation&) { // Sequential case. - using pt = const boost::property_tree::ptree; using SeqOperatorType = Dune::MatrixAdapter; linearoperator_for_solver_ = &op; auto op_prec = std::make_shared(op.getmat()); auto child = prm.get_child_optional("preconditioner"); preconditioner_ = Opm::PreconditionerFactory::create(*op_prec, - child ? *child : pt(), + child ? *child : Opm::PropertyTree(), weightsCalculator); scalarproduct_ = std::make_shared>(); linearoperator_for_precond_ = op_prec; @@ -139,7 +135,7 @@ namespace Dune template void FlexibleSolver:: - initSolver(const boost::property_tree::ptree& prm, const bool is_iorank) + initSolver(const Opm::PropertyTree& prm, const bool is_iorank) { const double tol = prm.get("tol", 1e-2); const int maxiter = prm.get("maxiter", 200); @@ -187,7 +183,7 @@ namespace Dune FlexibleSolver:: init(AbstractOperatorType& op, const Comm& comm, - const boost::property_tree::ptree& prm, + const Opm::PropertyTree& prm, const std::function weightsCalculator) { initOpPrecSp(op, prm, weightsCalculator, comm); @@ -219,11 +215,11 @@ template class Dune::FlexibleSolver, BV>; \ template class Dune::FlexibleSolver, BV>; \ template Dune::FlexibleSolver, BV>::FlexibleSolver(AbstractOperatorType& op, \ const Comm& comm, \ - const boost::property_tree::ptree& prm, \ + const Opm::PropertyTree& prm, \ const std::function()>& weightsCalculator); \ template Dune::FlexibleSolver, BV>::FlexibleSolver(AbstractOperatorType& op, \ const Comm& comm, \ - const boost::property_tree::ptree& prm, \ + const Opm::PropertyTree& prm, \ const std::function()>& weightsCalculator); #else // HAVE_MPI diff --git a/opm/simulators/linalg/ISTLSolverEbos.hpp b/opm/simulators/linalg/ISTLSolverEbos.hpp index f176832ad..43119c9c2 100644 --- a/opm/simulators/linalg/ISTLSolverEbos.hpp +++ b/opm/simulators/linalg/ISTLSolverEbos.hpp @@ -182,7 +182,7 @@ namespace Opm if (on_io_rank) { std::ostringstream os; os << "Property tree for linear solver:\n"; - boost::property_tree::write_json(os, prm_, true); + prm_.write_json(os, true); OpmLog::note(os.str()); } } @@ -423,10 +423,12 @@ namespace Opm { std::function weightsCalculator; - auto preconditionerType = prm_.get("preconditioner.type", "cpr"); + using namespace std::string_literals; + + auto preconditionerType = prm_.get("preconditioner.type"s, "cpr"s); if (preconditionerType == "cpr" || preconditionerType == "cprt") { const bool transpose = preconditionerType == "cprt"; - const auto weightsType = prm_.get("preconditioner.weight_type", "quasiimpes"); + const auto weightsType = prm_.get("preconditioner.weight_type"s, "quasiimpes"s); const auto pressureIndex = this->prm_.get("preconditioner.pressure_var_index", 1); if (weightsType == "quasiimpes") { // weighs will be created as default in the solver @@ -514,7 +516,7 @@ namespace Opm size_t interiorCellNum_; FlowLinearSolverParameters parameters_; - boost::property_tree::ptree prm_; + PropertyTree prm_; bool scale_variables_; std::shared_ptr< CommunicationType > comm_; diff --git a/opm/simulators/linalg/ISTLSolverEbosFlexible.hpp b/opm/simulators/linalg/ISTLSolverEbosFlexible.hpp index 4370fac14..9ca7221b4 100644 --- a/opm/simulators/linalg/ISTLSolverEbosFlexible.hpp +++ b/opm/simulators/linalg/ISTLSolverEbosFlexible.hpp @@ -28,8 +28,6 @@ #include -#include - #include #include @@ -123,7 +121,7 @@ public: if (simulator.gridView().comm().rank() == 0) { std::ostringstream os; os << "Property tree for linear solver:\n"; - boost::property_tree::write_json(os, prm_, true); + prm_.write_json(os, true); OpmLog::note(os.str()); } } @@ -266,10 +264,12 @@ protected: { std::function weightsCalculator; - auto preconditionerType = prm_.get("preconditioner.type", "cpr"); + using namespace std::string_literals; + + auto preconditionerType = prm_.get("preconditioner.type", "cpr"s); if (preconditionerType == "cpr" || preconditionerType == "cprt") { const bool transpose = preconditionerType == "cprt"; - const auto weightsType = prm_.get("preconditioner.weight_type", "quasiimpes"); + const auto weightsType = prm_.get("preconditioner.weight_type", "quasiimpes"s); const auto pressureIndex = this->prm_.get("preconditioner.pressure_var_index", 1); if (weightsType == "quasiimpes") { // weighs will be created as default in the solver @@ -340,7 +340,7 @@ protected: std::unique_ptr linear_operator_; std::unique_ptr solver_; FlowLinearSolverParameters parameters_; - boost::property_tree::ptree prm_; + PropertyTree prm_; VectorType rhs_; Dune::InverseOperatorResult res_; std::any parallelInformation_; diff --git a/opm/simulators/linalg/OwningTwoLevelPreconditioner.hpp b/opm/simulators/linalg/OwningTwoLevelPreconditioner.hpp index cedd351a8..fec4493be 100644 --- a/opm/simulators/linalg/OwningTwoLevelPreconditioner.hpp +++ b/opm/simulators/linalg/OwningTwoLevelPreconditioner.hpp @@ -32,8 +32,6 @@ #include #include -#include - #include #include @@ -82,21 +80,20 @@ template { public: - using pt = boost::property_tree::ptree; using MatrixType = typename OperatorType::matrix_type; using PrecFactory = Opm::PreconditionerFactory; - OwningTwoLevelPreconditioner(const OperatorType& linearoperator, const pt& prm, + OwningTwoLevelPreconditioner(const OperatorType& linearoperator, const Opm::PropertyTree& prm, const std::function weightsCalculator) : linear_operator_(linearoperator) , finesmoother_(PrecFactory::create(linearoperator, - prm.get_child_optional("finesmoother")? - prm.get_child("finesmoother"): pt())) + prm.get_child_optional("finesmoother") ? + prm.get_child("finesmoother") : Opm::PropertyTree())) , comm_(nullptr) , weightsCalculator_(weightsCalculator) , weights_(weightsCalculator()) , levelTransferPolicy_(dummy_comm_, weights_, prm.get("pressure_var_index")) - , coarseSolverPolicy_(prm.get_child_optional("coarsesolver")? prm.get_child("coarsesolver") : pt()) + , coarseSolverPolicy_(prm.get_child_optional("coarsesolver")? prm.get_child("coarsesolver") : Opm::PropertyTree()) , twolevel_method_(linearoperator, finesmoother_, levelTransferPolicy_, @@ -115,17 +112,17 @@ public: } } - OwningTwoLevelPreconditioner(const OperatorType& linearoperator, const pt& prm, + OwningTwoLevelPreconditioner(const OperatorType& linearoperator, const Opm::PropertyTree& prm, const std::function weightsCalculator, const Communication& comm) : linear_operator_(linearoperator) , finesmoother_(PrecFactory::create(linearoperator, - prm.get_child_optional("finesmoother")? - prm.get_child("finesmoother"): pt(), comm)) + prm.get_child_optional("finesmoother") ? + prm.get_child("finesmoother"): Opm::PropertyTree(), comm)) , comm_(&comm) , weightsCalculator_(weightsCalculator) , weights_(weightsCalculator()) , levelTransferPolicy_(*comm_, weights_, prm.get("pressure_var_index", 1)) - , coarseSolverPolicy_(prm.get_child_optional("coarsesolver")? prm.get_child("coarsesolver") : pt()) + , coarseSolverPolicy_(prm.get_child_optional("coarsesolver")? prm.get_child("coarsesolver") : Opm::PropertyTree()) , twolevel_method_(linearoperator, finesmoother_, levelTransferPolicy_, @@ -192,7 +189,7 @@ private: { // Parallel case. auto child = prm_.get_child_optional("finesmoother"); - finesmoother_ = PrecFactory::create(linear_operator_, child ? *child : pt(), *comm_); + finesmoother_ = PrecFactory::create(linear_operator_, child ? *child : Opm::PropertyTree(), *comm_); twolevel_method_.updatePreconditioner(finesmoother_, coarseSolverPolicy_); } @@ -200,7 +197,7 @@ private: { // Serial case. auto child = prm_.get_child_optional("finesmoother"); - finesmoother_ = PrecFactory::create(linear_operator_, child ? *child : pt()); + finesmoother_ = PrecFactory::create(linear_operator_, child ? *child : Opm::PropertyTree()); twolevel_method_.updatePreconditioner(finesmoother_, coarseSolverPolicy_); } @@ -212,7 +209,7 @@ private: LevelTransferPolicy levelTransferPolicy_; CoarseSolverPolicy coarseSolverPolicy_; TwoLevelMethod twolevel_method_; - boost::property_tree::ptree prm_; + Opm::PropertyTree prm_; Communication dummy_comm_; }; diff --git a/opm/simulators/linalg/PreconditionerFactory.hpp b/opm/simulators/linalg/PreconditionerFactory.hpp index 89fbf9ca5..9355cd293 100644 --- a/opm/simulators/linalg/PreconditionerFactory.hpp +++ b/opm/simulators/linalg/PreconditionerFactory.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -33,8 +34,6 @@ #include #include -#include - #include #include @@ -58,15 +57,15 @@ public: using PrecPtr = std::shared_ptr>; /// The type of creator functions passed to addCreator(). - using Creator = std::function&)>; - using ParCreator = std::function&, const Comm&)>; + using Creator = std::function&)>; + using ParCreator = std::function&, const Comm&)>; /// Create a new serial preconditioner and return a pointer to it. /// \param op operator to be preconditioned. /// \param prm parameters for the preconditioner, in particular its type. /// \param weightsCalculator Calculator for weights used in CPR. /// \return (smart) pointer to the created preconditioner. - static PrecPtr create(const Operator& op, const boost::property_tree::ptree& prm, + static PrecPtr create(const Operator& op, const PropertyTree& prm, const std::function& weightsCalculator = std::function()) { return instance().doCreate(op, prm, weightsCalculator); @@ -78,7 +77,7 @@ public: /// \param comm communication object (typically OwnerOverlapCopyCommunication). /// \param weightsCalculator Calculator for weights used in CPR. /// \return (smart) pointer to the created preconditioner. - static PrecPtr create(const Operator& op, const boost::property_tree::ptree& prm, + static PrecPtr create(const Operator& op, const PropertyTree& prm, const std::function& weightsCalculator, const Comm& comm) { return instance().doCreate(op, prm, weightsCalculator, comm); @@ -89,7 +88,7 @@ public: /// \param prm parameters for the preconditioner, in particular its type. /// \param comm communication object (typically OwnerOverlapCopyCommunication). /// \return (smart) pointer to the created preconditioner. - static PrecPtr create(const Operator& op, const boost::property_tree::ptree& prm, const Comm& comm) + static PrecPtr create(const Operator& op, const PropertyTree& prm, const Comm& comm) { return instance().doCreate(op, prm, std::function(), comm); } @@ -123,7 +122,7 @@ private: using Criterion = Dune::Amg::CoarsenCriterion; // Helpers for creation of AMG preconditioner. - static Criterion amgCriterion(const boost::property_tree::ptree& prm) + static Criterion amgCriterion(const PropertyTree& prm) { Criterion criterion(15, prm.get("coarsenTarget", 1200)); criterion.setDefaultValuesIsotropic(2); @@ -151,13 +150,13 @@ private: template struct Id { using Type = X; }; template - static auto amgSmootherArgs(const boost::property_tree::ptree& prm) + static auto amgSmootherArgs(const PropertyTree& prm) { return amgSmootherArgs(prm, Id()); } template - static auto amgSmootherArgs(const boost::property_tree::ptree& prm, + static auto amgSmootherArgs(const PropertyTree& prm, Id) { using SmootherArgs = typename Dune::Amg::SmootherTraits::Arguments; @@ -170,7 +169,7 @@ private: return smootherArgs; } - static auto amgSmootherArgs(const boost::property_tree::ptree& prm, + static auto amgSmootherArgs(const PropertyTree& prm, Id>) { using Smoother = Opm::ParallelOverlappingILU0; @@ -189,7 +188,7 @@ private: } template - static PrecPtr makeAmgPreconditioner(const Operator& op, const boost::property_tree::ptree& prm, bool useKamg = false) + static PrecPtr makeAmgPreconditioner(const Operator& op, const PropertyTree& prm, bool useKamg = false) { auto crit = amgCriterion(prm); auto sargs = amgSmootherArgs(prm); @@ -230,7 +229,7 @@ private: } static PrecPtr - createParILU(const Operator& op, const boost::property_tree::ptree& prm, const Comm& comm, const int ilulevel) + createParILU(const Operator& op, const PropertyTree& prm, const Comm& comm, const int ilulevel) { const double w = prm.get("relaxation", 1.0); const bool redblack = prm.get("redblack", false); @@ -256,7 +255,7 @@ private: using O = Operator; using M = Matrix; using V = Vector; - using P = boost::property_tree::ptree; + using P = PropertyTree; using C = Comm; doAddCreator("ILU0", [](const O& op, const P& prm, const std::function&, const C& comm) { return createParILU(op, prm, comm, 0); @@ -325,7 +324,7 @@ private: using O = Operator; using M = Matrix; using V = Vector; - using P = boost::property_tree::ptree; + using P = PropertyTree; doAddCreator("ILU0", [](const O& op, const P& prm, const std::function&) { const double w = prm.get("relaxation", 1.0); return std::make_shared>( @@ -461,7 +460,7 @@ private: } // Actually creates the product object. - PrecPtr doCreate(const Operator& op, const boost::property_tree::ptree& prm, + PrecPtr doCreate(const Operator& op, const PropertyTree& prm, const std::function weightsCalculator) { const std::string& type = prm.get("type", "ParOverILU0"); @@ -478,7 +477,7 @@ private: return it->second(op, prm, weightsCalculator); } - PrecPtr doCreate(const Operator& op, const boost::property_tree::ptree& prm, + PrecPtr doCreate(const Operator& op, const PropertyTree& prm, const std::function weightsCalculator, const Comm& comm) { const std::string& type = prm.get("type", "ParOverILU0"); diff --git a/opm/simulators/linalg/PreconditionerWithUpdate.hpp b/opm/simulators/linalg/PreconditionerWithUpdate.hpp index 00132f31f..ba9111dfd 100644 --- a/opm/simulators/linalg/PreconditionerWithUpdate.hpp +++ b/opm/simulators/linalg/PreconditionerWithUpdate.hpp @@ -22,7 +22,7 @@ #include #include -#include + namespace Dune { diff --git a/opm/simulators/linalg/PressureSolverPolicy.hpp b/opm/simulators/linalg/PressureSolverPolicy.hpp index d37e82601..dde25169e 100644 --- a/opm/simulators/linalg/PressureSolverPolicy.hpp +++ b/opm/simulators/linalg/PressureSolverPolicy.hpp @@ -21,8 +21,7 @@ #define OPM_PRESSURE_SOLVER_POLICY_HEADER_INCLUDED #include - -#include +#include #include #include @@ -31,8 +30,6 @@ namespace Dune { namespace Amg { - namespace pt = boost::property_tree; - template class PressureSolverPolicy { @@ -43,7 +40,7 @@ namespace Amg * @brief Constructs the coarse solver policy. * @param prm Parameter tree specifying the solver details. */ - explicit PressureSolverPolicy(const pt::ptree prm) + explicit PressureSolverPolicy(const Opm::PropertyTree& prm) : prm_(prm) { } @@ -61,7 +58,7 @@ namespace Amg #if HAVE_MPI template PressureInverseOperator(Operator& op, - const boost::property_tree::ptree& prm, + const Opm::PropertyTree& prm, const Dune::OwnerOverlapCopyCommunication& comm) : linsolver_() { @@ -71,7 +68,7 @@ namespace Amg #endif // HAVE_MPI PressureInverseOperator(Operator& op, - const boost::property_tree::ptree& prm, + const Opm::PropertyTree& prm, const SequentialInformation&) : linsolver_() { @@ -132,7 +129,7 @@ namespace Amg private: /** @brief The coarse level operator. */ std::shared_ptr coarseOperator_; - pt::ptree prm_; + Opm::PropertyTree prm_; }; } // namespace Amg } // namespace Dune diff --git a/opm/simulators/linalg/PropertyTree.cpp b/opm/simulators/linalg/PropertyTree.cpp new file mode 100644 index 000000000..39f230fe9 --- /dev/null +++ b/opm/simulators/linalg/PropertyTree.cpp @@ -0,0 +1,115 @@ +/* + Copyright 2019, 2020 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 . +*/ + +#include + +#include + +#include + +namespace Opm +{ + +PropertyTree::PropertyTree() + : tree_(std::make_unique()) +{ +} + +PropertyTree::PropertyTree(const PropertyTree& tree) + : tree_(std::make_unique(*tree.tree_)) +{ +} + +PropertyTree::PropertyTree(const std::string& jsonFile) + : tree_(std::make_unique()) +{ + boost::property_tree::read_json(jsonFile, *tree_); +} + +PropertyTree::PropertyTree(const boost::property_tree::ptree& tree) + : tree_(std::make_unique(tree)) +{ +} + +PropertyTree::~PropertyTree() = default; + +template +T PropertyTree::get(const std::string& key) const +{ + return tree_->get(key); +} + +template +T PropertyTree::get(const std::string& key, const T& defValue) const +{ + return tree_->get(key, defValue); +} + +template +void PropertyTree::put(const std::string& key, const T& value) +{ + tree_->put(key,value); +} + +void PropertyTree::write_json(std::ostream &os, bool pretty) const +{ + boost::property_tree::write_json(os, *tree_, pretty); +} + +PropertyTree +PropertyTree::get_child(const std::string& key) const +{ + auto pt = tree_->get_child(key); + + return PropertyTree(pt); +} + +std::optional +PropertyTree::get_child_optional(const std::string& key) const +{ + auto pt = tree_->get_child_optional(key); + if (!pt) + return std::nullopt; + + return PropertyTree(pt.get()); +} + +PropertyTree& PropertyTree::operator=(const PropertyTree& tree) +{ + tree_ = std::make_unique(*tree.tree_); + return *this; +} + +template std::string PropertyTree::get(const std::string& key) const; +template std::string PropertyTree::get(const std::string& key, const std::string& defValue) const; +template double PropertyTree::get(const std::string& key) const; +template double PropertyTree::get(const std::string& key, const double& defValue) const; +template int PropertyTree::get(const std::string& key) const; +template int PropertyTree::get(const std::string& key, const int& defValue) const; +template size_t PropertyTree::get(const std::string& key) const; +template size_t PropertyTree::get(const std::string& key, const size_t& defValue) const; +template bool PropertyTree::get(const std::string& key) const; +template bool PropertyTree::get(const std::string& key, const bool& defValue) const; + +template void PropertyTree::put(const std::string& key, const std::string& value); +template void PropertyTree::put(const std::string& key, const double& value); +template void PropertyTree::put(const std::string& key, const int& value); + + +} // namespace Opm diff --git a/opm/simulators/linalg/PropertyTree.hpp b/opm/simulators/linalg/PropertyTree.hpp new file mode 100644 index 000000000..238225310 --- /dev/null +++ b/opm/simulators/linalg/PropertyTree.hpp @@ -0,0 +1,70 @@ +/* + Copyright 2019 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 . +*/ + +#ifndef OPM_PROPERTYTREE_HEADER_INCLUDED +#define OPM_PROPERTYTREE_HEADER_INCLUDED + +#include +#include +#include + +namespace boost { +namespace property_tree { + template class basic_ptree; + using ptree = basic_ptree>; +} +} + +namespace Opm +{ + +class PropertyTree { +public: + PropertyTree(); + PropertyTree(const std::string& jsonFile); + PropertyTree(const PropertyTree& tree); + ~PropertyTree(); + + template + void put(const std::string& key, const T& data); + + template + T get(const std::string& key) const; + + template + T get(const std::string& key, const T& defValue) const; + + PropertyTree get_child(const std::string& key) const; + + std::optional get_child_optional(const std::string& key) const; + + PropertyTree& operator=(const PropertyTree& tree); + + void write_json(std::ostream& os, bool pretty) const; + +protected: + PropertyTree(const boost::property_tree::ptree& tree); + + std::unique_ptr tree_; +}; + + +} // namespace Opm + +#endif // OPM_PROPERTYTREE_HEADER_INCLUDED diff --git a/opm/simulators/linalg/setupPropertyTree.cpp b/opm/simulators/linalg/setupPropertyTree.cpp index 67ea84c67..513ef3d74 100644 --- a/opm/simulators/linalg/setupPropertyTree.cpp +++ b/opm/simulators/linalg/setupPropertyTree.cpp @@ -23,9 +23,6 @@ #include -#include -#include - namespace Opm { @@ -34,7 +31,7 @@ namespace Opm /// and preconditioner. If the latter, the parameters --linear-solver-reduction, /// --linear-solver-maxiter and --linear-solver-verbosity are used, but if reading /// from file the data in the JSON file will override any other options. -boost::property_tree::ptree +PropertyTree setupPropertyTree(FlowLinearSolverParameters p, // Note: copying the parameters to potentially override. bool LinearSolverMaxIterSet, bool CprMaxEllIterSet) @@ -48,9 +45,7 @@ setupPropertyTree(FlowLinearSolverParameters p, // Note: copying the parameters OPM_THROW(std::invalid_argument, "JSON file " << conf << " does not exist."); } try { - boost::property_tree::ptree prm; - boost::property_tree::read_json(conf, prm); - return prm; + return PropertyTree(conf); } catch (...) { OPM_THROW(std::invalid_argument, "Failed reading linear solver configuration from JSON file " << conf); @@ -94,29 +89,30 @@ setupPropertyTree(FlowLinearSolverParameters p, // Note: copying the parameters << " Please use ilu0, cpr, cpr_trueimpes, or cpr_quasiimpes"); } -boost::property_tree::ptree +PropertyTree setupCPR(const std::string& conf, const FlowLinearSolverParameters& p) { - boost::property_tree::ptree prm; + using namespace std::string_literals; + PropertyTree prm; prm.put("maxiter", p.linear_solver_maxiter_); prm.put("tol", p.linear_solver_reduction_); prm.put("verbosity", p.linear_solver_verbosity_); - prm.put("solver", "bicgstab"); - prm.put("preconditioner.type", "cpr"); + prm.put("solver", "bicgstab"s); + prm.put("preconditioner.type", "cpr"s); if (conf == "cpr_quasiimpes") { - prm.put("preconditioner.weight_type", "quasiimpes"); + prm.put("preconditioner.weight_type", "quasiimpes"s); } else { - prm.put("preconditioner.weight_type", "trueimpes"); + prm.put("preconditioner.weight_type", "trueimpes"s); } - prm.put("preconditioner.finesmoother.type", "ParOverILU0"); + prm.put("preconditioner.finesmoother.type", "ParOverILU0"s); prm.put("preconditioner.finesmoother.relaxation", 1.0); prm.put("preconditioner.pressure_var_index", 1); prm.put("preconditioner.verbosity", 0); prm.put("preconditioner.coarsesolver.maxiter", 1); prm.put("preconditioner.coarsesolver.tol", 1e-1); - prm.put("preconditioner.coarsesolver.solver", "loopsolver"); + prm.put("preconditioner.coarsesolver.solver", "loopsolver"s); prm.put("preconditioner.coarsesolver.verbosity", 0); - prm.put("preconditioner.coarsesolver.preconditioner.type", "amg"); + prm.put("preconditioner.coarsesolver.preconditioner.type", "amg"s); prm.put("preconditioner.coarsesolver.preconditioner.alpha", 0.333333333333); prm.put("preconditioner.coarsesolver.preconditioner.relaxation", 1.0); prm.put("preconditioner.coarsesolver.preconditioner.iterations", p.cpr_max_ell_iter_); @@ -124,7 +120,7 @@ setupCPR(const std::string& conf, const FlowLinearSolverParameters& p) prm.put("preconditioner.coarsesolver.preconditioner.pre_smooth", 1); prm.put("preconditioner.coarsesolver.preconditioner.post_smooth", 1); prm.put("preconditioner.coarsesolver.preconditioner.beta", 1e-5); - prm.put("preconditioner.coarsesolver.preconditioner.smoother", "ILU0"); + prm.put("preconditioner.coarsesolver.preconditioner.smoother", "ILU0"s); prm.put("preconditioner.coarsesolver.preconditioner.verbosity", 0); prm.put("preconditioner.coarsesolver.preconditioner.maxlevel", 15); prm.put("preconditioner.coarsesolver.preconditioner.skip_isolated", 0); @@ -141,15 +137,16 @@ setupCPR(const std::string& conf, const FlowLinearSolverParameters& p) } -boost::property_tree::ptree +PropertyTree setupAMG([[maybe_unused]] const std::string& conf, const FlowLinearSolverParameters& p) { - boost::property_tree::ptree prm; + using namespace std::string_literals; + PropertyTree prm; prm.put("tol", p.linear_solver_reduction_); prm.put("maxiter", p.linear_solver_maxiter_); prm.put("verbosity", p.linear_solver_verbosity_); - prm.put("solver", "bicgstab"); - prm.put("preconditioner.type", "amg"); + prm.put("solver", "bicgstab"s); + prm.put("preconditioner.type", "amg"s); prm.put("preconditioner.alpha", 0.333333333333); prm.put("preconditioner.relaxation", 1.0); prm.put("preconditioner.iterations", 20); @@ -157,7 +154,7 @@ setupAMG([[maybe_unused]] const std::string& conf, const FlowLinearSolverParamet prm.put("preconditioner.pre_smooth", 1); prm.put("preconditioner.post_smooth", 1); prm.put("preconditioner.beta", 1e-5); - prm.put("preconditioner.smoother", "ILU0"); + prm.put("preconditioner.smoother", "ILU0"s); prm.put("preconditioner.verbosity", 0); prm.put("preconditioner.maxlevel", 15); prm.put("preconditioner.skip_isolated", 0); @@ -174,15 +171,16 @@ setupAMG([[maybe_unused]] const std::string& conf, const FlowLinearSolverParamet } -boost::property_tree::ptree +PropertyTree setupILU([[maybe_unused]] const std::string& conf, const FlowLinearSolverParameters& p) { - boost::property_tree::ptree prm; + using namespace std::string_literals; + PropertyTree prm; prm.put("tol", p.linear_solver_reduction_); prm.put("maxiter", p.linear_solver_maxiter_); prm.put("verbosity", p.linear_solver_verbosity_); - prm.put("solver", "bicgstab"); - prm.put("preconditioner.type", "ParOverILU0"); + prm.put("solver", "bicgstab"s); + prm.put("preconditioner.type", "ParOverILU0"s); prm.put("preconditioner.relaxation", p.ilu_relaxation_); prm.put("preconditioner.ilulevel", p.ilu_fillin_level_); return prm; diff --git a/opm/simulators/linalg/setupPropertyTree.hpp b/opm/simulators/linalg/setupPropertyTree.hpp index fed1ebf66..c5c278d0e 100644 --- a/opm/simulators/linalg/setupPropertyTree.hpp +++ b/opm/simulators/linalg/setupPropertyTree.hpp @@ -21,20 +21,20 @@ #define OPM_SETUPPROPERTYTREE_HEADER_INCLUDED #include +#include -#include -#include +#include namespace Opm { -boost::property_tree::ptree setupPropertyTree(FlowLinearSolverParameters p, - bool LinearSolverMaxIterSet, - bool CprMaxEllIterSet); +PropertyTree setupPropertyTree(FlowLinearSolverParameters p, + bool LinearSolverMaxIterSet, + bool CprMaxEllIterSet); -boost::property_tree::ptree setupCPR(const std::string& conf, const FlowLinearSolverParameters& p); -boost::property_tree::ptree setupAMG(const std::string& conf, const FlowLinearSolverParameters& p); -boost::property_tree::ptree setupILU(const std::string& conf, const FlowLinearSolverParameters& p); +PropertyTree setupCPR(const std::string& conf, const FlowLinearSolverParameters& p); +PropertyTree setupAMG(const std::string& conf, const FlowLinearSolverParameters& p); +PropertyTree setupILU(const std::string& conf, const FlowLinearSolverParameters& p); } // namespace Opm diff --git a/tests/test_blackoil_amg.cpp b/tests/test_blackoil_amg.cpp index 8ef0f09fa..f04740f7d 100644 --- a/tests/test_blackoil_amg.cpp +++ b/tests/test_blackoil_amg.cpp @@ -296,8 +296,9 @@ void runBlackoilAmgLaplace() Dune::OverlappingSchwarzScalarProduct sp(comm); Dune::InverseOperatorResult r; - boost::property_tree::ptree prm; - prm.put("type", "amg"); + using namespace std::string_literals; + Opm::PropertyTree prm; + prm.put("type", "amg"s); std::function weights = [&mat]() { return Opm::Amg::getQuasiImpesWeights(mat, 0, false); }; diff --git a/tests/test_flexiblesolver.cpp b/tests/test_flexiblesolver.cpp index f02e14f4e..c37781a7d 100644 --- a/tests/test_flexiblesolver.cpp +++ b/tests/test_flexiblesolver.cpp @@ -30,20 +30,19 @@ #include #include +#include #include #include #include -#include -#include #include #include template Dune::BlockVector> -testSolver(const boost::property_tree::ptree& prm, const std::string& matrix_filename, const std::string& rhs_filename) +testSolver(const Opm::PropertyTree& prm, const std::string& matrix_filename, const std::string& rhs_filename) { using Matrix = Dune::BCRSMatrix>; using Vector = Dune::BlockVector>; @@ -86,15 +85,8 @@ testSolver(const boost::property_tree::ptree& prm, const std::string& matrix_fil BOOST_AUTO_TEST_CASE(TestFlexibleSolver) { - namespace pt = boost::property_tree; - pt::ptree prm; - // Read parameters. - { - std::ifstream file("options_flexiblesolver.json"); - pt::read_json(file, prm); - // pt::write_json(std::cout, prm); - } + Opm::PropertyTree prm("options_flexiblesolver.json"); // Test with 1x1 block solvers. { diff --git a/tests/test_preconditionerfactory.cpp b/tests/test_preconditionerfactory.cpp index c6c0e18e1..25c065689 100644 --- a/tests/test_preconditionerfactory.cpp +++ b/tests/test_preconditionerfactory.cpp @@ -29,6 +29,7 @@ BOOST_VERSION / 100 % 1000 > 48 #include +#include #include #include @@ -37,9 +38,6 @@ #include #include -#include -#include - #include #include @@ -70,7 +68,7 @@ public: template Dune::BlockVector> -testPrec(const boost::property_tree::ptree& prm, const std::string& matrix_filename, const std::string& rhs_filename) +testPrec(const Opm::PropertyTree& prm, const std::string& matrix_filename, const std::string& rhs_filename) { using Matrix = Dune::BCRSMatrix>; using Vector = Dune::BlockVector>; @@ -113,9 +111,7 @@ testPrec(const boost::property_tree::ptree& prm, const std::string& matrix_filen return x; } -namespace pt = boost::property_tree; - -void test1(const pt::ptree& prm) +void test1(const Opm::PropertyTree& prm) { const int bz = 1; auto sol = testPrec(prm, "matr33.txt", "rhs3.txt"); @@ -136,7 +132,7 @@ void test1(const pt::ptree& prm) } } -void test3(const pt::ptree& prm) +void test3(const Opm::PropertyTree& prm) { const int bz = 3; auto sol = testPrec(prm, "matr33.txt", "rhs3.txt"); @@ -155,13 +151,8 @@ void test3(const pt::ptree& prm) BOOST_AUTO_TEST_CASE(TestDefaultPreconditionerFactory) { - pt::ptree prm; - // Read parameters. - { - std::ifstream file("options_flexiblesolver.json"); - pt::read_json(file, prm); - } + Opm::PropertyTree prm("options_flexiblesolver.json"); // Test with 1x1 block solvers. test1(prm); @@ -183,14 +174,8 @@ using PF = Opm::PreconditionerFactory>; BOOST_AUTO_TEST_CASE(TestAddingPreconditioner) { - namespace pt = boost::property_tree; - pt::ptree prm; - // Read parameters. - { - std::ifstream file("options_flexiblesolver_simple.json"); // Requests "nothing" for preconditioner type. - pt::read_json(file, prm); - } + Opm::PropertyTree prm("options_flexiblesolver_simple.json"); // Test with 1x1 block solvers. { @@ -206,7 +191,7 @@ BOOST_AUTO_TEST_CASE(TestAddingPreconditioner) // Add preconditioner to factory for block size 1. - PF<1>::addCreator("nothing", [](const O<1>&, const pt::ptree&, const std::function()>&) { + PF<1>::addCreator("nothing", [](const O<1>&, const Opm::PropertyTree&, const std::function()>&) { return Dune::wrapPreconditioner>>(); }); @@ -221,7 +206,7 @@ BOOST_AUTO_TEST_CASE(TestAddingPreconditioner) } // Add preconditioner to factory for block size 3. - PF<3>::addCreator("nothing", [](const O<3>&, const pt::ptree&, const std::function()>&) { + PF<3>::addCreator("nothing", [](const O<3>&, const Opm::PropertyTree&, const std::function()>&) { return Dune::wrapPreconditioner>>(); }); @@ -288,7 +273,7 @@ protected: template Dune::BlockVector> -testPrecRepeating(const boost::property_tree::ptree& prm, const std::string& matrix_filename, const std::string& rhs_filename) +testPrecRepeating(const Opm::PropertyTree& prm, const std::string& matrix_filename, const std::string& rhs_filename) { using Matrix = Dune::BCRSMatrix>; using Vector = Dune::BlockVector>; @@ -313,7 +298,7 @@ testPrecRepeating(const boost::property_tree::ptree& prm, const std::string& mat using PrecFactory = Opm::PreconditionerFactory; // Add no-oppreconditioner to factory for block size 1. - PrecFactory::addCreator("nothing", [](const Operator&, const pt::ptree&, const std::function&) { + PrecFactory::addCreator("nothing", [](const Operator&, const Opm::PropertyTree&, const std::function&) { return Dune::wrapPreconditioner>(); }); @@ -325,7 +310,7 @@ testPrecRepeating(const boost::property_tree::ptree& prm, const std::string& mat return x; } -void test1rep(const pt::ptree& prm) +void test1rep(const Opm::PropertyTree& prm) { const int bz = 1; auto sol = testPrecRepeating(prm, "matr33rep.txt", "rhs3rep.txt"); @@ -346,7 +331,7 @@ void test1rep(const pt::ptree& prm) } } -void test3rep(const pt::ptree& prm) +void test3rep(const Opm::PropertyTree& prm) { const int bz = 3; auto sol = testPrecRepeating(prm, "matr33rep.txt", "rhs3rep.txt"); @@ -366,13 +351,8 @@ void test3rep(const pt::ptree& prm) BOOST_AUTO_TEST_CASE(TestWithRepeatingOperator) { - pt::ptree prm; - // Read parameters. - { - std::ifstream file("options_flexiblesolver_simple.json"); - pt::read_json(file, prm); - } + Opm::PropertyTree prm("options_flexiblesolver_simple.json"); // Test with 1x1 block solvers. test1rep(prm);