Skip to content

Commit

Permalink
Adding user-defined picard convergence postprocessor in PicardSolve i…
Browse files Browse the repository at this point in the history
  • Loading branch information
zachmprince authored and aeslaughter committed Feb 12, 2020
1 parent dce9cbf commit 5099518
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 1 deletion.
6 changes: 6 additions & 0 deletions framework/include/executioners/PicardSolve.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ class PicardSolve : public SolveObject
Real _picard_rel_tol;
/// Absolute tolerance on residual norm
Real _picard_abs_tol;
/// Postprocessor value for user-defined picard convergence check
const PostprocessorValue * _picard_custom_pp;
/// Relative tolerance on postprocessor value
Real _custom_rel_tol;
/// Absolute tolerance on postprocessor value
Real _custom_abs_tol;
/// Whether or not we force evaluation of residual norms even without multiapps
bool _picard_force_norms;
/// Relaxation factor for Picard Iteration
Expand Down
54 changes: 53 additions & 1 deletion framework/src/executioners/PicardSolve.C
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ PicardSolve::validParams()
"during Picard iterations. This check is "
"performed based on the Master app's nonlinear "
"residual.");
params.addParam<PostprocessorName>("picard_custom_pp",
"Postprocessor for custom picard convergence check.");
params.addParam<Real>("custom_rel_tol",
1e-8,
"The relative nonlinear residual drop to shoot for "
"during Picard iterations. This check is "
"performed based on postprocessor defined by "
"picard_custom_pp residual.");
params.addParam<Real>("custom_abs_tol",
1e-50,
"The absolute nonlinear residual to shoot for "
"during Picard iterations. This check is "
"performed based on postprocessor defined by "
"picard_custom_pp residual.");
params.addParam<bool>("direct_pp_value",
false,
"True to use direct postprocessor value "
"(scaled by value on first iteration). "
"False (default) to use difference in postprocessor "
"value between picard iterations.");
params.addParam<bool>(
"picard_force_norms",
false,
Expand All @@ -68,7 +88,7 @@ PicardSolve::validParams()

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

Expand All @@ -91,6 +111,12 @@ PicardSolve::PicardSolve(Executioner * ex)
_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_custom_pp(
isParamValid("picard_custom_pp")
? &_problem.getPostprocessorValue(getParam<PostprocessorName>("picard_custom_pp"))
: nullptr),
_custom_rel_tol(getParam<Real>("custom_rel_tol")),
_custom_abs_tol(getParam<Real>("custom_abs_tol")),
_picard_force_norms(getParam<bool>("picard_force_norms")),
_relax_factor(getParam<Real>("relaxation_factor")),
_relaxed_vars(getParam<std::vector<std::string>>("relaxed_variables")),
Expand Down Expand Up @@ -163,6 +189,8 @@ PicardSolve::solve()
}
}

Real pp_scaling = 1.0;

for (_picard_it = 0; _picard_it < _picard_max_its; ++_picard_it)
{
if (_has_picard_its)
Expand Down Expand Up @@ -192,6 +220,11 @@ PicardSolve::solve()
<< '\n';
}

// Save last postprocessor value as value before solve
Real pp_old = 0.0;
if (_picard_custom_pp && _picard_it > 0 && !getParam<bool>("direct_pp_value"))
pp_old = *_picard_custom_pp;

Real begin_norm_old = (_picard_it > 0 ? _picard_timestep_begin_norm[_picard_it - 1]
: std::numeric_limits<Real>::max());
Real end_norm_old = (_picard_it > 0 ? _picard_timestep_end_norm[_picard_it - 1]
Expand All @@ -203,6 +236,15 @@ PicardSolve::solve()
_picard_timestep_end_norm[_picard_it],
relax,
relaxed_dofs);
// Calculate error from postprocessor values
Real pp_new = std::numeric_limits<Real>::max();
if (_picard_custom_pp)
{
if ((_picard_it == 0 && getParam<bool>("direct_pp_value")) ||
!getParam<bool>("direct_pp_value"))
pp_scaling = *_picard_custom_pp;
pp_new = *_picard_custom_pp;
}

if (solve_converged)
{
Expand Down Expand Up @@ -243,6 +285,16 @@ PicardSolve::solve()
_picard_status = MoosePicardConvergenceReason::CONVERGED_CUSTOM;
break;
}
if (std::abs(pp_new - pp_old) < _custom_abs_tol)
{
_picard_status = MoosePicardConvergenceReason::CONVERGED_CUSTOM;
break;
}
if (std::abs((pp_new - pp_old) / pp_scaling) < _custom_rel_tol)
{
_picard_status = MoosePicardConvergenceReason::CONVERGED_CUSTOM;
break;
}
if (_picard_it + 1 == _picard_max_its)
{
if (_accept_max_it)
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
108 changes: 108 additions & 0 deletions test/tests/multiapps/picard/picard_custom_postprocessor.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
[Mesh]
type = GeneratedMesh
dim = 2
nx = 10
ny = 10
parallel_type = replicated
[]

[Variables]
[./u]
[../]
[]

[AuxVariables]
[./v]
[../]
[]

[Kernels]
[./diff]
type = CoefDiffusion
variable = u
coef = 0.1
[../]
[./force_u]
type = CoupledForce
variable = u
v = v
[../]
[]

[BCs]
[./left]
type = DirichletBC
variable = u
boundary = left
value = 0
[../]
[./right]
type = DirichletBC
variable = u
boundary = right
value = 1
[../]
[]

[Postprocessors]
[./unorm_begin]
type = ElementL2Norm
variable = u
execute_on = 'initial timestep_begin'
outputs = none
[../]
[./unorm]
type = ElementL2Norm
variable = u
execute_on = 'initial timestep_end'
[../]
[./unorm_err]
type = RelativeDifferencePostprocessor
value1 = unorm
value2 = unorm_begin
outputs = none
[../]
[./vnorm]
type = ElementL2Norm
variable = v
execute_on = 'initial timestep_end'
[../]
[]

[Executioner]
type = Steady
petsc_options_iname = '-pc_type -pc_hypre_type'
petsc_options_value = 'hypre boomeramg'
picard_max_its = 30
disable_picard_residual_norm_check = true
picard_custom_pp = unorm_err
[]

[Outputs]
exodus = true
[]

[MultiApps]
[./sub]
type = FullSolveMultiApp
input_files = steady_picard_sub.i
no_backup_and_restore = true
[../]
[]

[Transfers]
[./v_from_sub]
type = MultiAppNearestNodeTransfer
direction = from_multiapp
multi_app = sub
source_variable = v
variable = v
[../]
[./u_to_sub]
type = MultiAppNearestNodeTransfer
direction = to_multiapp
multi_app = sub
source_variable = u
variable = u
[../]
[]
21 changes: 21 additions & 0 deletions test/tests/multiapps/picard/tests
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,25 @@
issues = '#9038'
requirement = "The system shall allow steady-state Picard iteration with pseudo-transient multiapps"
[../]

[./steady_with_postprocessor_convergence]
type = 'Exodiff'
input = 'picard_custom_postprocessor.i'
exodiff = 'picard_custom_postprocessor_out.e picard_custom_postprocessor_out_sub0.e'
cli_args = 'Executioner/direct_pp_value=true Executioner/custom_abs_tol=1e-4'
recover = false
design = 'multiapps/FullSolveMultiApp.md'
issues = '#14642'
requirement = "The system shall allow convergence check with user defined postprocessor directly."
[../]
[./steady_with_postprocessor_diff_convergence]
type = 'Exodiff'
input = 'picard_custom_postprocessor.i'
exodiff = 'picard_custom_diff_out.e picard_custom_diff_out_sub0.e'
cli_args = 'Executioner/picard_custom_pp=unorm Executioner/custom_rel_tol=1e-4 Outputs/file_base=picard_custom_diff_out'
recover = false
design = 'multiapps/FullSolveMultiApp.md'
issues = '#14642'
requirement = "The system shall allow convergence check with the convergence of a user defined postprocessor."
[../]
[]

0 comments on commit 5099518

Please sign in to comment.