diff --git a/CMakeLists.txt b/CMakeLists.txt index 40b6d4d15..89f0cca41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -321,7 +321,8 @@ macro (sources_hook) get_target_property(qm_defs QuadMath::QuadMath INTERFACE_COMPILE_DEFINITIONS) list(APPEND qm_defs HAVE_QUAD=1) get_target_property(qm_options QuadMath::QuadMath INTERFACE_COMPILE_OPTIONS) - set_source_files_properties(opm/models/utils/parametersystem.cpp + set_source_files_properties(opm/models/nonlinear/newtonmethodparams.cpp + opm/models/utils/parametersystem.cpp opm/models/utils/simulatorutils.cpp PROPERTIES COMPILE_DEFINITIONS "${qm_defs}" COMPILE_OPTIONS "${qm_options}") diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 967c98f76..fe4e8ec74 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -77,6 +77,7 @@ list (APPEND MAIN_SOURCE_FILES opm/models/io/vtkptflashparams.cpp opm/models/io/vtktemperatureparams.cpp opm/models/io/restart.cpp + opm/models/nonlinear/newtonmethodparams.cpp opm/models/parallel/mpiutil.cpp opm/models/parallel/tasklets.cpp opm/models/parallel/threadmanager.cpp diff --git a/flowexperimental/FlowExpNewtonMethod.hpp b/flowexperimental/FlowExpNewtonMethod.hpp index 53b599622..831b340b5 100644 --- a/flowexperimental/FlowExpNewtonMethod.hpp +++ b/flowexperimental/FlowExpNewtonMethod.hpp @@ -149,7 +149,7 @@ public: { const auto& constraintsMap = this->model().linearizer().constraintsMap(); this->lastError_ = this->error_; - Scalar newtonMaxError = Parameters::Get>(); + Scalar newtonMaxError = this->params_.maxError_; // calculate the error as the maximum weighted tolerance of // the solution's residual @@ -198,7 +198,7 @@ public: this->error_ = max(std::abs(tmpError), this->error_); - if (std::abs(tmpError) > this->tolerance_) { + if (std::abs(tmpError) > this->params_.tolerance_) { cnvViolated = true; } @@ -231,7 +231,7 @@ public: Scalar y = Parameters::Get>(); sumTolerance_ = x*std::pow(sumPv, y); - this->endIterMsg() << " (max: " << this->tolerance_ + this->endIterMsg() << " (max: " << this->params_.tolerance_ << ", violated for " << errorPvFraction_ * 100 << "% of the pore volume), aggegate error: " << errorSum_ << " (max: " << sumTolerance_ << ")"; diff --git a/opm/models/nonlinear/newtonmethod.hh b/opm/models/nonlinear/newtonmethod.hh index 588d23da8..aefaea00b 100644 --- a/opm/models/nonlinear/newtonmethod.hh +++ b/opm/models/nonlinear/newtonmethod.hh @@ -118,9 +118,9 @@ public: { lastError_ = 1e100; error_ = 1e100; - tolerance_ = Parameters::Get>(); numIterations_ = 0; + params_.read(); } /*! @@ -129,23 +129,7 @@ public: static void registerParameters() { LinearSolverBackend::registerParameters(); - - Parameters::Register - ("Specify whether the Newton method should inform " - "the user about its progress or not"); - Parameters::Register - ("Write the convergence behaviour of the Newton " - "method to a VTK file"); - Parameters::Register - ("The 'optimum' number of Newton iterations per time step"); - Parameters::Register - ("The maximum number of Newton iterations per time step"); - Parameters::Register> - ("The maximum raw error tolerated by the Newton" - "method for considering a solution to be converged"); - Parameters::Register> - ("The maximum error tolerated by the Newton " - "method to which does not cause an abort"); + NewtonMethodParams::registerParameters(); } /*! @@ -210,14 +194,14 @@ public: * be converged. */ Scalar tolerance() const - { return tolerance_; } + { return params_.tolerance_; } /*! * \brief Set the current tolerance at which the Newton method considers itself to * be converged. */ void setTolerance(Scalar value) - { tolerance_ = value; } + { params_.tolerance_ = value; } /*! * \brief Run the Newton method. @@ -451,14 +435,14 @@ public: // conservative when increasing it. the rationale is // that we want to avoid failing in the next time // integration which would be quite expensive - if (numIterations_ > targetIterations_()) { - Scalar percent = Scalar(numIterations_ - targetIterations_())/targetIterations_(); + if (numIterations_ > params_.targetIterations_) { + Scalar percent = Scalar(numIterations_ - params_.targetIterations_) / params_.targetIterations_; Scalar nextDt = std::max(problem().minTimeStepSize(), oldDt / (Scalar{1.0} + percent)); return nextDt; } - Scalar percent = Scalar(targetIterations_() - numIterations_)/targetIterations_(); + Scalar percent = Scalar(params_.targetIterations_ - numIterations_) / params_.targetIterations_; Scalar nextDt = std::max(problem().minTimeStepSize(), oldDt*(Scalar{1.0} + percent / Scalar{1.2})); return nextDt; @@ -508,7 +492,7 @@ protected: */ bool verbose_() const { - return Parameters::Get() && (comm_.rank() == 0); + return params_.verbose_ && (comm_.rank() == 0); } /*! @@ -521,7 +505,7 @@ protected: { numIterations_ = 0; - if (Parameters::Get()) { + if (params_.writeConvergence_) { convergenceWriter_.beginTimeStep(); } } @@ -574,7 +558,7 @@ protected: { const auto& constraintsMap = model().linearizer().constraintsMap(); lastError_ = error_; - Scalar newtonMaxError = Parameters::Get>(); + Scalar newtonMaxError = params_.maxError_; // calculate the error as the maximum weighted tolerance of // the solution's residual @@ -739,7 +723,7 @@ protected: void writeConvergence_(const SolutionVector& currentSolution, const GlobalEqVector& solutionUpdate) { - if (Parameters::Get()) { + if (params_.writeConvergence_) { convergenceWriter_.beginIteration(); convergenceWriter_.writeFields(currentSolution, solutionUpdate); convergenceWriter_.endIteration(); @@ -794,7 +778,7 @@ protected: // do more iterations return false; } - else if (asImp_().numIterations() >= asImp_().maxIterations_()) { + else if (asImp_().numIterations() >= params_.maxIterations_) { // we have exceeded the allowed number of steps. If the // error was reduced by a factor of at least 4, // in the last iterations we proceed even if we are above @@ -811,7 +795,7 @@ protected: */ void end_() { - if (Parameters::Get()) { + if (params_.writeConvergence_) { convergenceWriter_.endTimeStep(); } } @@ -822,7 +806,7 @@ protected: * This method is called _after_ end_() */ void failed_() - { numIterations_ = targetIterations_() * 2; } + { numIterations_ = params_.targetIterations_ * 2; } /*! * \brief Called if the Newton method was successful. @@ -832,13 +816,6 @@ protected: void succeeded_() {} - // optimal number of iterations we want to achieve - int targetIterations_() const - { return Parameters::Get(); } - // maximum number of iterations we do before giving up - int maxIterations_() const - { return Parameters::Get(); } - static bool enableConstraints_() { return getPropValue(); } @@ -853,7 +830,7 @@ protected: Scalar error_; Scalar lastError_; - Scalar tolerance_; + NewtonMethodParams params_; // actual number of iterations done so far int numIterations_; diff --git a/opm/models/nonlinear/newtonmethodparams.cpp b/opm/models/nonlinear/newtonmethodparams.cpp new file mode 100644 index 000000000..9a3eea5df --- /dev/null +++ b/opm/models/nonlinear/newtonmethodparams.cpp @@ -0,0 +1,77 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/* + 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 2 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 . + + Consult the COPYING file in the top-level source directory of this + module for the precise wording of the license and the list of + copyright holders. +*/ + +#include +#include + +#include + +#if HAVE_QUAD +#include +#endif + +namespace Opm { + +template +void NewtonMethodParams::registerParameters() +{ + Parameters::Register + ("Specify whether the Newton method should inform " + "the user about its progress or not"); + Parameters::Register + ("Write the convergence behaviour of the Newton " + "method to a VTK file"); + Parameters::Register + ("The 'optimum' number of Newton iterations per time step"); + Parameters::Register + ("The maximum number of Newton iterations per time step"); + Parameters::Register> + ("The maximum raw error tolerated by the Newton" + "method for considering a solution to be converged"); + Parameters::Register> + ("The maximum error tolerated by the Newton " + "method to which does not cause an abort"); +} + +template +void NewtonMethodParams::read() +{ + verbose_ = Parameters::Get(); + writeConvergence_ = Parameters::Get(); + targetIterations_ = Parameters::Get(); + maxIterations_ = Parameters::Get(); + tolerance_ = Parameters::Get>(); + maxError_ = Parameters::Get>(); +} + +template struct NewtonMethodParams; + +#if FLOW_INSTANTIATE_FLOAT +template struct NewtonMethodParams; +#endif + +#if HAVE_QUAD +template struct NewtonMethodParams; +#endif + +} // namespace Opm diff --git a/opm/models/nonlinear/newtonmethodparams.hpp b/opm/models/nonlinear/newtonmethodparams.hpp index 3b1b47109..b49d17628 100644 --- a/opm/models/nonlinear/newtonmethodparams.hpp +++ b/opm/models/nonlinear/newtonmethodparams.hpp @@ -61,4 +61,28 @@ struct NewtonWriteConvergence { static constexpr bool value = false; }; } // end namespace Opm::Parameters +namespace Opm { + +/*! + * \brief Struct holding the parameters for NewtonMethod. + */ +template +struct NewtonMethodParams +{ + //! \brief Registers the parameters in parameter system. + static void registerParameters(); + + //! \brief Reads the parameter values from the parameter system. + void read(); + + bool verbose_; + bool writeConvergence_; + int targetIterations_; //!< Optimal number of iterations we want to achieve + int maxIterations_; //!< Maximum number of iterations we do before giving up + Scalar tolerance_; + Scalar maxError_; +}; + +} // namespace Opm + #endif // OPM_NEWTON_METHOD_PARAMS_HPP