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

Add the option to throw an exception on MLMG failure rather than #3424

Merged
merged 4 commits into from
Jul 14, 2023
Merged
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
32 changes: 32 additions & 0 deletions Docs/sphinx_documentation/source/LinearSolvers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,38 @@ Available choices are
:cpp:`LPInfo::setConsolidationStrategy(int)`, to give control over how this
process works.


:cpp:`MLMG::setThrowException(bool)` controls whether multigrid failure results
in aborting (default) or throwing an exception, whereby control will return to the calling
application. The application code must catch the exception:

.. highlight:: c++

::

try {
mlmg.solve(...);
} catch (const MLMG::error& e) {
Print()<<e.what()<<std::endl; //Prints description of error

// Do something else...
}

Note that exceptions that are not caught are passed up the calling chain so that
application codes using specialized solvers relying on MLMG can still catch the exception.
For example, using AMReX-Hydro's :cpp:`NodalProjector`

.. highlight:: c++

::

try {
nodal_projector.project(...);
} catch (const MLMG::error& e) {
// Do something else...
}


Boundary Stencils for Cell-Centered Solvers
===========================================

Expand Down
42 changes: 31 additions & 11 deletions Src/LinearSolvers/MLMG/AMReX_MLMG.H
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ class MLMGT
{
public:

class error
: public std::runtime_error
{
public :
using std::runtime_error::runtime_error;
};

template <typename T> friend class MLCGSolverT;

using FAB = typename MF::fab_type;
Expand Down Expand Up @@ -104,6 +111,7 @@ public:
*/
void apply (const Vector<MF*>& out, const Vector<MF*>& in);

void setThrowException (bool t) noexcept { throw_exception = t; }
void setVerbose (int v) noexcept { verbose = v; }
void setMaxIter (int n) noexcept { max_iters = n; }
void setMaxFmgIter (int n) noexcept { max_fmg_iters = n; }
Expand Down Expand Up @@ -211,7 +219,9 @@ public:

private:

bool throw_exception = false;
int verbose = 1;

int max_iters = 200;
int do_fixed_number_of_iters = 0;

Expand Down Expand Up @@ -453,16 +463,21 @@ MLMGT<MF>::solve (const Vector<AMF*>& a_sol, const Vector<AMF const*>& a_rhs,
}
break;
} else {
if (composite_norminf > RT(1.e20)*max_norm)
{
if (verbose > 0) {
amrex::Print() << "MLMG: Failing to converge after " << iter+1 << " iterations."
<< " resid, resid/" << norm_name << " = "
<< composite_norminf << ", "
<< composite_norminf/max_norm << "\n";
}
amrex::Abort("MLMG failing so lets stop here");
}
if (composite_norminf > RT(1.e20)*max_norm)
{
if (verbose > 0) {
amrex::Print() << "MLMG: Failing to converge after " << iter+1 << " iterations."
<< " resid, resid/" << norm_name << " = "
<< composite_norminf << ", "
<< composite_norminf/max_norm << "\n";
}

if ( throw_exception ) {
throw error("MLMG blew up.");
} else {
amrex::Abort("MLMG failing so lets stop here");
}
}
}
}

Expand All @@ -473,7 +488,12 @@ MLMGT<MF>::solve (const Vector<AMF*>& a_sol, const Vector<AMF const*>& a_rhs,
<< composite_norminf << ", "
<< composite_norminf/max_norm << "\n";
}
amrex::Abort("MLMG failed");

if ( throw_exception ) {
throw error("MLMG failed to converge.");
} else {
amrex::Abort("MLMG failed.");
}
}
timer[iter_time] = amrex::second() - iter_start_time;
}
Expand Down
Loading