newtonmethod: move parameters to dedicated struct with a translation unit

This commit is contained in:
Arne Morten Kvarving 2024-09-16 08:43:09 +02:00
parent 1b19fa02f4
commit 3ee3dc2b5f
6 changed files with 122 additions and 42 deletions

View File

@ -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}")

View File

@ -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

View File

@ -149,7 +149,7 @@ public:
{
const auto& constraintsMap = this->model().linearizer().constraintsMap();
this->lastError_ = this->error_;
Scalar newtonMaxError = Parameters::Get<Parameters::NewtonMaxError<Scalar>>();
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<Parameters::EclNewtonSumToleranceExponent<Scalar>>();
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_ << ")";

View File

@ -118,9 +118,9 @@ public:
{
lastError_ = 1e100;
error_ = 1e100;
tolerance_ = Parameters::Get<Parameters::NewtonTolerance<Scalar>>();
numIterations_ = 0;
params_.read();
}
/*!
@ -129,23 +129,7 @@ public:
static void registerParameters()
{
LinearSolverBackend::registerParameters();
Parameters::Register<Parameters::NewtonVerbose>
("Specify whether the Newton method should inform "
"the user about its progress or not");
Parameters::Register<Parameters::NewtonWriteConvergence>
("Write the convergence behaviour of the Newton "
"method to a VTK file");
Parameters::Register<Parameters::NewtonTargetIterations>
("The 'optimum' number of Newton iterations per time step");
Parameters::Register<Parameters::NewtonMaxIterations>
("The maximum number of Newton iterations per time step");
Parameters::Register<Parameters::NewtonTolerance<Scalar>>
("The maximum raw error tolerated by the Newton"
"method for considering a solution to be converged");
Parameters::Register<Parameters::NewtonMaxError<Scalar>>
("The maximum error tolerated by the Newton "
"method to which does not cause an abort");
NewtonMethodParams<Scalar>::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<Parameters::NewtonVerbose>() && (comm_.rank() == 0);
return params_.verbose_ && (comm_.rank() == 0);
}
/*!
@ -521,7 +505,7 @@ protected:
{
numIterations_ = 0;
if (Parameters::Get<Parameters::NewtonWriteConvergence>()) {
if (params_.writeConvergence_) {
convergenceWriter_.beginTimeStep();
}
}
@ -574,7 +558,7 @@ protected:
{
const auto& constraintsMap = model().linearizer().constraintsMap();
lastError_ = error_;
Scalar newtonMaxError = Parameters::Get<Parameters::NewtonMaxError<Scalar>>();
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<Parameters::NewtonWriteConvergence>()) {
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<Parameters::NewtonWriteConvergence>()) {
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<Parameters::NewtonTargetIterations>(); }
// maximum number of iterations we do before giving up
int maxIterations_() const
{ return Parameters::Get<Parameters::NewtonMaxIterations>(); }
static bool enableConstraints_()
{ return getPropValue<TypeTag, Properties::EnableConstraints>(); }
@ -853,7 +830,7 @@ protected:
Scalar error_;
Scalar lastError_;
Scalar tolerance_;
NewtonMethodParams<Scalar> params_;
// actual number of iterations done so far
int numIterations_;

View File

@ -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 <http://www.gnu.org/licenses/>.
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 <config.h>
#include <opm/models/nonlinear/newtonmethodparams.hpp>
#include <opm/models/utils/parametersystem.hpp>
#if HAVE_QUAD
#include <opm/material/common/quad.hpp>
#endif
namespace Opm {
template<class Scalar>
void NewtonMethodParams<Scalar>::registerParameters()
{
Parameters::Register<Parameters::NewtonVerbose>
("Specify whether the Newton method should inform "
"the user about its progress or not");
Parameters::Register<Parameters::NewtonWriteConvergence>
("Write the convergence behaviour of the Newton "
"method to a VTK file");
Parameters::Register<Parameters::NewtonTargetIterations>
("The 'optimum' number of Newton iterations per time step");
Parameters::Register<Parameters::NewtonMaxIterations>
("The maximum number of Newton iterations per time step");
Parameters::Register<Parameters::NewtonTolerance<Scalar>>
("The maximum raw error tolerated by the Newton"
"method for considering a solution to be converged");
Parameters::Register<Parameters::NewtonMaxError<Scalar>>
("The maximum error tolerated by the Newton "
"method to which does not cause an abort");
}
template<class Scalar>
void NewtonMethodParams<Scalar>::read()
{
verbose_ = Parameters::Get<Parameters::NewtonVerbose>();
writeConvergence_ = Parameters::Get<Parameters::NewtonWriteConvergence>();
targetIterations_ = Parameters::Get<Parameters::NewtonTargetIterations>();
maxIterations_ = Parameters::Get<Parameters::NewtonMaxIterations>();
tolerance_ = Parameters::Get<Parameters::NewtonTolerance<Scalar>>();
maxError_ = Parameters::Get<Parameters::NewtonMaxError<Scalar>>();
}
template struct NewtonMethodParams<double>;
#if FLOW_INSTANTIATE_FLOAT
template struct NewtonMethodParams<float>;
#endif
#if HAVE_QUAD
template struct NewtonMethodParams<quad>;
#endif
} // namespace Opm

View File

@ -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<class Scalar>
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