Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add legacy flag for executing timestep execute in fixed point iteration #28932

Open
wants to merge 2 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions framework/include/executioners/Executioner.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ class Executioner : public MooseObject,
virtual PostprocessorValue & addAttributeReporter(const std::string & name,
Real initial_value = 0);

/// Flag to indicate timestep_begin/end objects are to be executed within a fixed point iteration
const bool _legacy_execute_on;

FEProblemBase & _fe_problem;

MooseEnum _iteration_method;
Expand Down
18 changes: 12 additions & 6 deletions framework/include/executioners/FixedPointSolve.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class FixedPointSolve : public SolveObject

static InputParameters validParams();

/// Custom execute flags for fixed point iterations
static const ExecFlagType EXEC_FIXEDPOINT_BEGIN;
static const ExecFlagType EXEC_FIXEDPOINT_END;

/**
* Iteratively solves the FEProblem.
* @return True if solver is converged.
Expand Down Expand Up @@ -143,8 +147,8 @@ class FixedPointSolve : public SolveObject
/**
* Perform one fixed point iteration or a full solve.
*
* @param begin_norm Residual norm after timestep_begin execution
* @param end_norm Residual norm after timestep_end execution
* @param begin_norm Residual norm after fixedpoint_begin execution
* @param end_norm Residual norm after fixedpoint_end execution
* @param transformed_dofs DoFs targetted by the fixed point algorithm
*
* @return True if both nonlinear solve and the execution of multiapps are successful.
Expand Down Expand Up @@ -193,6 +197,8 @@ class FixedPointSolve : public SolveObject
/// Print information about the fixed point convergence
void printFixedPointConvergenceReason();

/// Flag to indicate timestep_begin/end objects are to be executed within a fixed point iteration
const bool _legacy_execute_on;
/// Minimum fixed point iterations
unsigned int _min_fixed_point_its;
/// Maximum fixed point iterations
Expand Down Expand Up @@ -239,10 +245,10 @@ class FixedPointSolve : public SolveObject
unsigned int _main_fixed_point_it;
/// Initial residual norm
Real _fixed_point_initial_norm;
/// Full history of residual norm after evaluation of timestep_begin
std::vector<Real> _fixed_point_timestep_begin_norm;
/// Full history of residual norm after evaluation of timestep_end
std::vector<Real> _fixed_point_timestep_end_norm;
/// Full history of residual norm after evaluation of fixedpoint_begin
std::vector<Real> _fixed_point_begin_norm;
/// Full history of residual norm after evaluation of fixedpoint_end
std::vector<Real> _fixed_point_end_norm;
/// Status of fixed point solve
MooseFixedPointConvergenceReason _fixed_point_status;
///@}
Expand Down
5 changes: 5 additions & 0 deletions framework/src/base/MooseApp.C
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,11 @@ MooseApp::validParams()
"solution modifying objects are executed prior to the initial (0th nonlinear iteration) "
"residual evaluation. The new behavior skips that redundant residual evaluation unless the "
"parameter Executioner/use_pre_SMO_residual is set to true.");
params.addParam<bool>(
"use_legacy_fixed_point_execute_on",
true,
"The legacy behavior executes objects including aux kernels, user objects, postprocessors, "
"MultiApps, transfers, etc. on timestep_begin and timestep_end within a fixed point iteration.");

params.addParam<bool>(
MeshGeneratorSystem::allow_data_driven_param,
Expand Down
14 changes: 14 additions & 0 deletions framework/src/executioners/Eigenvalue.C
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,14 @@ Eigenvalue::execute()
#endif // LIBMESH_ENABLE_AMR
_eigen_problem.timestepSetup();

if (!_legacy_execute_on)
{
_eigen_problem.execute(EXEC_TIMESTEP_BEGIN);
_time = _time_step;
_eigen_problem.outputStep(EXEC_TIMESTEP_BEGIN);
_time = _system_time;
}

_last_solve_converged = _fixed_point_solve->solve();
if (!lastSolveConverged())
{
Expand All @@ -270,6 +278,12 @@ Eigenvalue::execute()
_eigen_problem.computeIndicators();
_eigen_problem.computeMarkers();
}

if (!_legacy_execute_on)
{
_eigen_problem.onTimestepEnd();
_eigen_problem.execute(EXEC_TIMESTEP_END);
}
// need to keep _time in sync with _time_step to get correct output
_time = _time_step;
_eigen_problem.outputStep(EXEC_TIMESTEP_END);
Expand Down
2 changes: 2 additions & 0 deletions framework/src/executioners/Executioner.C
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Executioner::Executioner(const InputParameters & parameters)
PostprocessorInterface(this),
Restartable(this, "Executioners"),
PerfGraphInterface(this),
_legacy_execute_on(_app.parameters().get<bool>("use_legacy_fixed_point_execute_on")),
_fe_problem(*getCheckedPointerParam<FEProblemBase *>(
"_fe_problem_base", "This might happen if you don't have a mesh")),
_iteration_method(getParam<MooseEnum>("fixed_point_algorithm")),
Expand Down Expand Up @@ -91,6 +92,7 @@ Executioner::Executioner(const InputParameters & parameters, bool)
PostprocessorInterface(this),
Restartable(this, "Executioners"),
PerfGraphInterface(this),
_legacy_execute_on(_app.parameters().get<bool>("use_legacy_fixed_point_execute_on")),
_fe_problem(*getCheckedPointerParam<FEProblemBase *>(
"_fe_problem_base", "This might happen if you don't have a mesh")),
_iteration_method(getParam<MooseEnum>("fixed_point_algorithm")),
Expand Down
101 changes: 70 additions & 31 deletions framework/src/executioners/FixedPointSolve.C
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
#include "AllLocalDofIndicesThread.h"
#include "Console.h"
#include "EigenExecutionerBase.h"
#include "ExecFlagRegistry.h"

const ExecFlagType FixedPointSolve::EXEC_FIXEDPOINT_BEGIN = registerDefaultExecFlag("FIXEDPOINT_BEGIN");
const ExecFlagType FixedPointSolve::EXEC_FIXEDPOINT_END = registerDefaultExecFlag("FIXEDPOINT_END");

InputParameters
FixedPointSolve::validParams()
Expand Down Expand Up @@ -51,7 +55,7 @@ FixedPointSolve::validParams()
params.addParam<bool>(
"fixed_point_force_norms",
false,
"Force the evaluation of both the TIMESTEP_BEGIN and TIMESTEP_END norms regardless of the "
"Force the evaluation of residual norms after executing objects and MultiApps on fixedpoint_begin and fixedpoint_end regardless of the "
"existence of active MultiApps with those execute_on flags, default: false.");

// Parameters for using a custom postprocessor for convergence checks
Expand Down Expand Up @@ -116,7 +120,7 @@ FixedPointSolve::validParams()
"Maximum number of times to update XFEM crack topology in a step due to evolving cracks");
params.addParam<bool>("update_xfem_at_timestep_begin",
false,
"Should XFEM update the mesh at the beginning of the timestep");
"Should XFEM update the mesh at the beginning of a fixed point iteration");

params.addParamNamesToGroup("max_xfem_update update_xfem_at_timestep_begin",
"XFEM fixed point iterations");
Expand All @@ -126,6 +130,7 @@ FixedPointSolve::validParams()

FixedPointSolve::FixedPointSolve(Executioner & ex)
: SolveObject(ex),
_legacy_execute_on(_app.parameters().get<bool>("use_legacy_fixed_point_execute_on")),
_min_fixed_point_its(getParam<unsigned int>("fixed_point_min_its")),
_max_fixed_point_its(getParam<unsigned int>("fixed_point_max_its")),
_has_fixed_point_its(_max_fixed_point_its > 1),
Expand Down Expand Up @@ -198,18 +203,23 @@ FixedPointSolve::solve()

Real current_dt = _problem.dt();

_fixed_point_timestep_begin_norm.clear();
_fixed_point_timestep_end_norm.clear();
_fixed_point_timestep_begin_norm.resize(_max_fixed_point_its);
_fixed_point_timestep_end_norm.resize(_max_fixed_point_its);
_fixed_point_begin_norm.clear();
_fixed_point_end_norm.clear();
_fixed_point_begin_norm.resize(_max_fixed_point_its);
_fixed_point_end_norm.resize(_max_fixed_point_its);

bool converged = true;

// need to back up multi-apps even when not doing fixed point iteration for recovering from failed
// multiapp solve
_problem.backupMultiApps(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
_problem.backupMultiApps(EXEC_TIMESTEP_BEGIN);
_problem.backupMultiApps(EXEC_TIMESTEP_END);
if (_legacy_execute_on)
{
_problem.backupMultiApps(EXEC_TIMESTEP_BEGIN);
_problem.backupMultiApps(EXEC_TIMESTEP_END);
}
_problem.backupMultiApps(EXEC_FIXEDPOINT_BEGIN);
_problem.backupMultiApps(EXEC_FIXEDPOINT_END);
_problem.backupMultiApps(EXEC_MULTIAPP_FIXED_POINT_END);

// Prepare to relax variables as a main app
Expand Down Expand Up @@ -273,8 +283,13 @@ FixedPointSolve::solve()
{
// For every iteration other than the first, we need to restore the state of the MultiApps
_problem.restoreMultiApps(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
_problem.restoreMultiApps(EXEC_TIMESTEP_BEGIN);
_problem.restoreMultiApps(EXEC_TIMESTEP_END);
if (_legacy_execute_on)
{
_problem.restoreMultiApps(EXEC_TIMESTEP_BEGIN);
_problem.restoreMultiApps(EXEC_TIMESTEP_END);
}
_problem.restoreMultiApps(EXEC_FIXEDPOINT_BEGIN);
_problem.restoreMultiApps(EXEC_FIXEDPOINT_END);
_problem.restoreMultiApps(EXEC_MULTIAPP_FIXED_POINT_END);
}

Expand All @@ -288,8 +303,8 @@ FixedPointSolve::solve()
_pp_old = *_fixed_point_custom_pp;

// Solve a single application for one time step
bool solve_converged = solveStep(_fixed_point_timestep_begin_norm[_fixed_point_it],
_fixed_point_timestep_end_norm[_fixed_point_it],
bool solve_converged = solveStep(_fixed_point_begin_norm[_fixed_point_it],
_fixed_point_end_norm[_fixed_point_it],
transformed_dofs);

// Get new value and print history for the custom postprocessor convergence criterion
Expand Down Expand Up @@ -335,8 +350,8 @@ FixedPointSolve::solve()
current_dt; // _dt might be smaller than this at this point for multistep methods
}

// Save postprocessors after the solve and their potential timestep_end execution
// The postprocessors could be overwritten at timestep_begin, which is why they are saved
// Save postprocessors after the solve and their potential fixedpoint_end execution
// The postprocessors could be overwritten at fixedpoint_begin, which is why they are saved
// after the solve. They could also be saved right after the transfers.
if (_old_entering_time == _problem.time())
savePostprocessorValues(false);
Expand Down Expand Up @@ -377,13 +392,15 @@ FixedPointSolve::solveStep(Real & begin_norm,
bool auto_advance = autoAdvance();

// Compute previous norms for coloring the norm output
Real begin_norm_old = (_fixed_point_it > 0 ? _fixed_point_timestep_begin_norm[_fixed_point_it - 1]
Real begin_norm_old = (_fixed_point_it > 0 ? _fixed_point_begin_norm[_fixed_point_it - 1]
: std::numeric_limits<Real>::max());
Real end_norm_old = (_fixed_point_it > 0 ? _fixed_point_timestep_end_norm[_fixed_point_it - 1]
Real end_norm_old = (_fixed_point_it > 0 ? _fixed_point_end_norm[_fixed_point_it - 1]
: std::numeric_limits<Real>::max());

_executioner.preSolve();
_problem.execTransfers(EXEC_TIMESTEP_BEGIN);
if (_legacy_execute_on)
_problem.execTransfers(EXEC_TIMESTEP_BEGIN);
_problem.execTransfers(EXEC_FIXEDPOINT_BEGIN);

if (_fixed_point_it == 0)
{
Expand All @@ -397,7 +414,12 @@ FixedPointSolve::solveStep(Real & begin_norm,
_problem.outputStep(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
}

if (!_problem.execMultiApps(EXEC_TIMESTEP_BEGIN, auto_advance))
if (_legacy_execute_on && !_problem.execMultiApps(EXEC_TIMESTEP_BEGIN, auto_advance))
{
_fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP;
return false;
}
if (!_problem.execMultiApps(EXEC_FIXEDPOINT_BEGIN, auto_advance))
{
_fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP;
return false;
Expand All @@ -406,9 +428,11 @@ FixedPointSolve::solveStep(Real & begin_norm,
if (_problem.haveXFEM() && _update_xfem_at_timestep_begin)
_problem.updateMeshXFEM();

_problem.execute(EXEC_TIMESTEP_BEGIN);
if (_legacy_execute_on)
_problem.execute(EXEC_TIMESTEP_BEGIN);
_problem.execute(EXEC_FIXEDPOINT_BEGIN);

// Transform the fixed point postprocessors before solving, but after the timestep_begin transfers
// Transform the fixed point postprocessors before solving, but after the fixedpoint_begin transfers
// have been received
if (_transformed_pps.size() > 0 && useFixedPointAlgorithmUpdateInsteadOfPicard(true))
transformPostprocessors(true);
Expand All @@ -417,16 +441,19 @@ FixedPointSolve::solveStep(Real & begin_norm,
transformPostprocessors(false);

if (_has_fixed_point_its && _has_fixed_point_norm)
if (_problem.hasMultiApps(EXEC_TIMESTEP_BEGIN) || _fixed_point_force_norms)
if ((_legacy_execute_on && _problem.hasMultiApps(EXEC_TIMESTEP_BEGIN)) ||
_problem.hasMultiApps(EXEC_FIXEDPOINT_BEGIN) || _fixed_point_force_norms)
{
begin_norm = _problem.computeResidualL2Norm();

_console << COLOR_MAGENTA << "Fixed point residual norm after TIMESTEP_BEGIN MultiApps: "
_console << COLOR_MAGENTA << "Fixed point residual norm after FIXEDPOINT_BEGIN MultiApps: "
<< Console::outputNorm(begin_norm_old, begin_norm) << std::endl;
}

// Perform output for timestep begin
_problem.outputStep(EXEC_TIMESTEP_BEGIN);
if (_legacy_execute_on)
_problem.outputStep(EXEC_TIMESTEP_BEGIN);
_problem.outputStep(EXEC_FIXEDPOINT_BEGIN);

// Update warehouse active objects
_problem.updateActiveObjects();
Expand Down Expand Up @@ -466,11 +493,22 @@ FixedPointSolve::solveStep(Real & begin_norm,
_console << "\nXFEM did not modify mesh, continuing" << std::endl;
}

_problem.onTimestepEnd();
_problem.execute(EXEC_TIMESTEP_END);
if (_legacy_execute_on)
{
_problem.onTimestepEnd();
_problem.execute(EXEC_TIMESTEP_END);

_problem.execTransfers(EXEC_TIMESTEP_END);
if (!_problem.execMultiApps(EXEC_TIMESTEP_END, auto_advance))
{
_fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP;
return false;
}
}
_problem.execute(EXEC_FIXEDPOINT_END);

_problem.execTransfers(EXEC_TIMESTEP_END);
if (!_problem.execMultiApps(EXEC_TIMESTEP_END, auto_advance))
_problem.execTransfers(EXEC_FIXEDPOINT_END);
if (!_problem.execMultiApps(EXEC_FIXEDPOINT_END, auto_advance))
{
_fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP;
return false;
Expand All @@ -486,11 +524,12 @@ FixedPointSolve::solveStep(Real & begin_norm,
_executioner.postSolve();

if (_has_fixed_point_its && _has_fixed_point_norm)
if (_problem.hasMultiApps(EXEC_TIMESTEP_END) || _fixed_point_force_norms)
if ((_legacy_execute_on && _problem.hasMultiApps(EXEC_TIMESTEP_END)) ||
_problem.hasMultiApps(EXEC_FIXEDPOINT_END) || _fixed_point_force_norms)
{
end_norm = _problem.computeResidualL2Norm();

_console << COLOR_MAGENTA << "Fixed point residual norm after TIMESTEP_END MultiApps: "
_console << COLOR_MAGENTA << "Fixed point residual norm after FIXEDPOINT_END MultiApps: "
<< Console::outputNorm(end_norm_old, end_norm) << std::endl;
}

Expand All @@ -516,8 +555,8 @@ FixedPointSolve::examineFixedPointConvergence(bool & converged)
{
if (_fixed_point_it + 2 > _min_fixed_point_its)
{
Real max_norm = std::max(_fixed_point_timestep_begin_norm[_fixed_point_it],
_fixed_point_timestep_end_norm[_fixed_point_it]);
Real max_norm = std::max(_fixed_point_begin_norm[_fixed_point_it],
_fixed_point_end_norm[_fixed_point_it]);

Real max_relative_drop = max_norm / _fixed_point_initial_norm;

Expand Down
8 changes: 4 additions & 4 deletions framework/src/executioners/PicardSolve.C
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ PicardSolve::validParams()
"picard_max_its",
1,
"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. "
"Mainly used when wanting to do Picard iterations with MultiApps "
"that are set to execute_on fixedpoint_end or fixedpoint_begin. "
"Setting this parameter to 1 turns off the Picard iterations.",
"Deprecated, use fixed_point_max_its");
params.addDeprecatedParam<bool>(
Expand Down Expand Up @@ -60,7 +60,7 @@ PicardSolve::validParams()
params.addDeprecatedParam<bool>(
"picard_force_norms",
false,
"Force the evaluation of both the TIMESTEP_BEGIN and TIMESTEP_END norms regardless of the "
"Force the evaluation of both the FIXEDPOINT_BEGIN and FIXEDPOINT_END norms regardless of the "
"existence of active MultiApps with those execute_on flags, default: false.",
"Deprecated, use fixed_point_force_norms");

Expand Down Expand Up @@ -266,7 +266,7 @@ PicardSolve::printFixedPointConvergenceHistory()
for (unsigned int i = 0; i <= _fixed_point_it; ++i)
{
Real max_norm =
std::max(_fixed_point_timestep_begin_norm[i], _fixed_point_timestep_end_norm[i]);
std::max(_fixed_point_begin_norm[i], _fixed_point_end_norm[i]);
_console << std::setw(2) << i + 1
<< " Picard |R| = " << Console::outputNorm(max_norm_old, max_norm) << '\n';
max_norm_old = max_norm;
Expand Down
8 changes: 4 additions & 4 deletions framework/src/executioners/SecantSolve.C
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ SecantSolve::savePostprocessorValues(const bool primary)
(*transformed_pps_values)[i][2] = (*transformed_pps_values)[i][0];

// Save current value
// Primary: this is done before the timestep's solves and before timestep_begin transfers,
// Primary: this is done before the fixedpoint's solves and before fixedpoint_begin transfers,
// so the value is the result of the previous Secant update (xn_m1)
// Secondary: this is done after the secondary solve, but before timestep_end postprocessors
// are computed, or timestep_end transfers are received.
// Secondary: this is done after the secondary solve, but before fixedpoint_end postprocessors
// are computed, or fixedpoint_end transfers are received.
// This value is the same as before the solve (xn_m1)
(*transformed_pps_values)[i][1] = getPostprocessorValueByName((*transformed_pps)[i]);
}
Expand Down Expand Up @@ -259,7 +259,7 @@ SecantSolve::printFixedPointConvergenceHistory()
for (unsigned int i = 0; i <= _fixed_point_it; ++i)
{
Real max_norm =
std::max(_fixed_point_timestep_begin_norm[i], _fixed_point_timestep_end_norm[i]);
std::max(_fixed_point_begin_norm[i], _fixed_point_end_norm[i]);
std::stringstream secant_prefix;
if (i < 2)
secant_prefix << " Secant initialization |R| = ";
Expand Down
Loading