Skip to content
Permalink
Browse files

Merge pull request #12940 from YaqiWang/new_param_for_picard

Add two new params for Picard iteration and more tests
  • Loading branch information...
permcody committed Feb 22, 2019
2 parents 08ce4a1 + f9a745f commit 2ed7285465617268dc41bf626da7b9eb368469dd
@@ -39,6 +39,7 @@ class PicardSolve : public MooseObject, public PerfGraphInterface
CONVERGED_ABS = 2,
CONVERGED_RELATIVE = 3,
CONVERGED_CUSTOM = 4,
REACH_MAX_ITS = 5,
DIVERGED_MAX_ITS = -1,
DIVERGED_NONLINEAR = -2,
DIVERGED_FAILED_MULTIAPP = -3
@@ -110,6 +111,10 @@ class PicardSolve : public MooseObject, public PerfGraphInterface
unsigned int _picard_max_its;
/// Whether or not we activate Picard iteration
bool _has_picard_its;
/// Whether or not to treat reaching maximum number of Picard iteration as converged
bool _accept_max_it;
/// Whether or not to use residual norm to check the Picard convergence
bool _has_picard_norm;
/// Relative tolerance on residual norm
Real _picard_rel_tol;
/// Absolute tolerance on residual norm
@@ -90,10 +90,18 @@ validParams<Executioner>()
params.addParam<unsigned int>(
"picard_max_its",
1,
"Maximum number of times each timestep will be solved. Mainly used when "
"Specifies the maximum number of Picard iterations. Mainly used when "
"wanting to do Picard iterations with MultiApps that are set to "
"execute_on timestep_end or timestep_begin. Setting this parameter to 1 turns off the Picard "
"iterations.");
params.addParam<bool>(
"accept_on_max_picard_iteration",
false,
"True to treat reaching the maximum number of Picard iterations as converged.");
params.addParam<bool>("disable_picard_residual_norm_check",
false,
"Disable the Picard residual norm evaluation thus the three parameters "
"picard_rel_tol, picard_abs_tol and picard_force_norms.");
params.addParam<Real>("picard_rel_tol",
1e-8,
"The relative nonlinear residual drop to shoot for "
@@ -121,7 +129,9 @@ validParams<Executioner>()
std::vector<std::string>(),
"List of variables to relax during Picard Iteration");

params.addParamNamesToGroup("picard_max_its picard_rel_tol picard_abs_tol picard_force_norms "
params.addParamNamesToGroup("picard_max_its accept_on_max_picard_iteration "
"disable_picard_residual_norm_check picard_rel_tol "
"picard_abs_tol picard_force_norms "
"relaxation_factor relaxed_variables",
"Picard");

@@ -25,6 +25,8 @@ PicardSolve::PicardSolve(Executioner * ex)
_nl(_problem.getNonlinearSystemBase()),
_picard_max_its(getParam<unsigned int>("picard_max_its")),
_has_picard_its(_picard_max_its > 1),
_accept_max_it(getParam<bool>("accept_on_max_picard_iteration")),
_has_picard_norm(!getParam<bool>("disable_picard_residual_norm_check")),
_picard_rel_tol(getParam<Real>("picard_rel_tol")),
_picard_abs_tol(getParam<Real>("picard_abs_tol")),
_picard_force_norms(getParam<bool>("picard_force_norms")),
@@ -50,6 +52,8 @@ PicardSolve::solve()

Real current_dt = _problem.dt();

_picard_timestep_begin_norm.clear();
_picard_timestep_end_norm.clear();
_picard_timestep_begin_norm.resize(_picard_max_its);
_picard_timestep_end_norm.resize(_picard_max_its);

@@ -93,21 +97,23 @@ PicardSolve::solve()
}
}

_picard_it = 0;
for (_picard_it = 0; _picard_it < _picard_max_its; ++_picard_it)
{
if (_has_picard_its)
{
if (_picard_it == 0)
{
// First Picard iteration - need to save off the initial nonlinear residual
_picard_initial_norm = _problem.computeResidualL2Norm();
_console << COLOR_MAGENTA << "Initial Picard Norm: " << COLOR_DEFAULT;
if (_picard_initial_norm == std::numeric_limits<Real>::max())
_console << " MAX ";
else
_console << std::scientific << _picard_initial_norm;
_console << COLOR_DEFAULT << "\n\n";
if (_has_picard_norm)
{
// First Picard iteration - need to save off the initial nonlinear residual
_picard_initial_norm = _problem.computeResidualL2Norm();
_console << COLOR_MAGENTA << "Initial Picard Norm: " << COLOR_DEFAULT;
if (_picard_initial_norm == std::numeric_limits<Real>::max())
_console << " MAX ";
else
_console << std::scientific << _picard_initial_norm;
_console << COLOR_DEFAULT << "\n\n";
}
}
else
{
@@ -136,32 +142,35 @@ PicardSolve::solve()
{
if (_has_picard_its)
{
_console << "\n 0 Picard |R| = "
<< Console::outputNorm(std::numeric_limits<Real>::max(), _picard_initial_norm)
<< '\n';

for (unsigned int i = 0; i <= _picard_it; ++i)
if (_has_picard_norm)
{
Real max_norm = std::max(_picard_timestep_begin_norm[i], _picard_timestep_end_norm[i]);
_console << std::setw(2) << i + 1
<< " Picard |R| = " << Console::outputNorm(_picard_initial_norm, max_norm)
_console << "\n 0 Picard |R| = "
<< Console::outputNorm(std::numeric_limits<Real>::max(), _picard_initial_norm)
<< '\n';
}

Real max_norm = std::max(_picard_timestep_begin_norm[_picard_it],
_picard_timestep_end_norm[_picard_it]);

Real max_relative_drop = max_norm / _picard_initial_norm;

if (max_norm < _picard_abs_tol)
{
_picard_status = MoosePicardConvergenceReason::CONVERGED_ABS;
break;
}
if (max_relative_drop < _picard_rel_tol)
{
_picard_status = MoosePicardConvergenceReason::CONVERGED_RELATIVE;
break;
for (unsigned int i = 0; i <= _picard_it; ++i)
{
Real max_norm = std::max(_picard_timestep_begin_norm[i], _picard_timestep_end_norm[i]);
_console << std::setw(2) << i + 1
<< " Picard |R| = " << Console::outputNorm(_picard_initial_norm, max_norm)
<< '\n';
}

Real max_norm = std::max(_picard_timestep_begin_norm[_picard_it],
_picard_timestep_end_norm[_picard_it]);

Real max_relative_drop = max_norm / _picard_initial_norm;

if (max_norm < _picard_abs_tol)
{
_picard_status = MoosePicardConvergenceReason::CONVERGED_ABS;
break;
}
if (max_relative_drop < _picard_rel_tol)
{
_picard_status = MoosePicardConvergenceReason::CONVERGED_RELATIVE;
break;
}
}
if (_executioner.augmentedPicardConvergenceCheck())
{
@@ -170,8 +179,16 @@ PicardSolve::solve()
}
if (_picard_it + 1 == _picard_max_its)
{
_picard_status = MoosePicardConvergenceReason::DIVERGED_MAX_ITS;
converged = false;
if (_accept_max_it)
{
_picard_status = MoosePicardConvergenceReason::REACH_MAX_ITS;
converged = true;
}
else
{
_picard_status = MoosePicardConvergenceReason::DIVERGED_MAX_ITS;
converged = false;
}
break;
}
}
@@ -217,6 +234,9 @@ PicardSolve::solve()
case MoosePicardConvergenceReason::CONVERGED_CUSTOM:
_console << "CONVERGED_CUSTOM";
break;
case MoosePicardConvergenceReason::REACH_MAX_ITS:
_console << "REACH_MAX_ITS";
break;
case MoosePicardConvergenceReason::DIVERGED_MAX_ITS:
_console << "DIVERGED_MAX_ITS";
break;
@@ -261,7 +281,7 @@ PicardSolve::solveStep(Real begin_norm_old,

_problem.execute(EXEC_TIMESTEP_BEGIN);

if (_has_picard_its)
if (_has_picard_its && _has_picard_norm)
if (_problem.hasMultiApps(EXEC_TIMESTEP_BEGIN) || _picard_force_norms)
{
begin_norm = _problem.computeResidualL2Norm();
@@ -342,7 +362,7 @@ PicardSolve::solveStep(Real begin_norm_old,

_executioner.postSolve();

if (_has_picard_its)
if (_has_picard_its && _has_picard_norm)
if (_problem.hasMultiApps(EXEC_TIMESTEP_END) || _picard_force_norms)
{
end_norm = _problem.computeResidualL2Norm();
@@ -0,0 +1,51 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#ifndef STEADYWITHPICARDCHECK_H
#define STEADYWITHPICARDCHECK_H

#include "Steady.h"

class SteadyWithPicardCheck;

template <>
InputParameters validParams<SteadyWithPicardCheck>();

/**
* Test executioner to show custom convergence check of Picard iterations
*/
class SteadyWithPicardCheck : public Steady
{
public:
SteadyWithPicardCheck(const InputParameters & parameters);

virtual void init() override;

/**
* Calls at the beginning of every Picard iterations
*/
virtual void preSolve() override;

/**
* Additional convergence check to be honored by PicardSolve
*/
virtual bool augmentedPicardConvergenceCheck() const override;

private:
/// Absolute step tolerance on a designated postprocessor
Real _pp_step_tol;

/// The postprocessor value saved after execute
PostprocessorValue _pp_value_old;

/// Reference to the postprocessor value
const PostprocessorValue * _pp_value;
};

#endif /* STEADYWITHPICARDCHECK_H */
@@ -0,0 +1,59 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "SteadyWithPicardCheck.h"

registerMooseObject("MooseTestApp", SteadyWithPicardCheck);

template <>
InputParameters
validParams<SteadyWithPicardCheck>()
{
InputParameters params = validParams<Steady>();

params.addRequiredParam<PostprocessorName>(
"pp_name", "Postprocessor used to control the Picard convergence");
params.addParam<Real>("pp_step_tol", 1e-6, "Relative step tolerance on the postprocessor");
return params;
}

SteadyWithPicardCheck::SteadyWithPicardCheck(const InputParameters & parameters)
: Steady(parameters), _pp_step_tol(getParam<Real>("pp_step_tol"))
{
}

void
SteadyWithPicardCheck::init()
{
_pp_value = &getPostprocessorValue("pp_name");
Steady::init();
}

bool
SteadyWithPicardCheck::augmentedPicardConvergenceCheck() const
{
Real rel_err = std::abs((*_pp_value - _pp_value_old) / *_pp_value);

std::ostringstream os;
os << std::setprecision(10);
os << " Old: " << _pp_value_old << " New: " << *_pp_value;
os << std::scientific << std::setprecision(3) << " Error: " << rel_err;
_console << COLOR_MAGENTA << os.str() << COLOR_DEFAULT << std::endl;
if (rel_err < _pp_step_tol)
return true;
else
return false;
}

void
SteadyWithPicardCheck::preSolve()
{
Steady::preSolve();
_pp_value_old = *_pp_value;
}
Oops, something went wrong.

0 comments on commit 2ed7285

Please sign in to comment.
You can’t perform that action at this time.