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 Unused Parameter Warnings #223

Merged
merged 14 commits into from
Sep 28, 2022
14 changes: 14 additions & 0 deletions docs/source/usage/parameters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ Overall simulation parameters
Note that even with this set to ``1`` ImpactX will not catch all out-of-memory events yet when operating close to maximum device memory.
`Please also see the documentation in AMReX <https://amrex-codes.github.io/amrex/docs_html/GPU.html#inputs-parameters>`_.

* ``amrex.abort_on_unused_inputs`` (``0`` or ``1``; default is ``0`` for false)
When set to ``1``, this option causes the simulation to fail *after* its completion if there were unused parameters.
It is mainly intended for continuous integration and automated testing to check that all tests and inputs are adapted to API changes.

* ``impactx.always_warn_immediately`` (``0`` or ``1``; default is ``0`` for false)
If set to ``1``, ImpactX immediately prints every warning message as soon as it is generated.
It is mainly intended for debug purposes, in case a simulation crashes before a global warning report can be printed.

* ``impactx.abort_on_warning_threshold`` (string: ``low``, ``medium`` or ``high``) optional
Optional threshold to abort as soon as a warning is raised.
If the threshold is set, warning messages with priority greater than or equal to the threshold trigger an immediate abort.
It is mainly intended for debug purposes, and is best used with ``impactx.always_warn_immediately=1``.
For more information on the warning logger, see `this section <https://warpx.readthedocs.io/en/latest/developers/warning_logger.html>`_ of the WarpX documentation.

.. _running-cpp-parameters-box:


Expand Down
15 changes: 15 additions & 0 deletions docs/source/usage/python.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,21 @@ General
Access the elements in the accelerator lattice.
See :py:mod:`impactx.elements` for lattice elements.

.. py:property:: abort_on_warning_threshold

(optional) Set to "low", "medium" or "high".
Cause the code to abort if a warning is raised that exceeds the warning threshold.

.. py:property:: abort_on_unused_inputs

Set to ``1`` to cause the simulation to fail *after* its completion if there were unused parameters. (default: ``0`` for false)
It is mainly intended for continuous integration and automated testing to check that all tests and inputs are adapted to API changes.

.. py:property:: always_warn_immediately

If set to ``1``, ImpactX immediately prints every warning message as soon as it is generated. (default: ``0`` for false)
It is mainly intended for debug purposes, in case a simulation crashes before a global warning report can be printed.

.. py:method:: evolve()

Run the main simulation loop for a number of steps.
Expand Down
6 changes: 5 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ function(add_impactx_test name input is_mpi is_python analysis_script plot_scrip
impactx_test_set_pythonpath(${name}.run)
else()
add_test(NAME ${name}.run
COMMAND ${THIS_MPI_TEST_EXE} $<TARGET_FILE:app> ${ImpactX_SOURCE_DIR}/${input}
COMMAND
${THIS_MPI_TEST_EXE} $<TARGET_FILE:app> ${ImpactX_SOURCE_DIR}/${input}
amrex.abort_on_unused_inputs=1
impactx.always_warn_immediately=1
impactx.abort_on_warning_threshold=low
WORKING_DIRECTORY ${THIS_WORKING_DIR}
)
endif()
Expand Down
12 changes: 12 additions & 0 deletions src/ImpactX.H
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,22 @@ namespace impactx
*/
void validate ();

/** Check inputs for unused parameters (e.g. typos) after step 1
*
* @return true if successful
*/
bool early_param_check ();

/** Run the main simulation loop for a number of steps
*/
void evolve ();

/** Query input for warning logger variables and set up warning logger accordingly
*
* Input variables are: ``always_warn_immediately`` and ``abort_on_warning_threshold``.
*/
void init_warning_logger ();

private:
//! Tag cells for refinement. TagBoxArray tags is built on level lev grids.
void ErrorEst (int lev, amrex::TagBoxArray& tags, amrex::Real time,
Expand Down
11 changes: 11 additions & 0 deletions src/ImpactX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "particles/spacecharge/PoissonSolve.H"
#include "particles/transformation/CoordinateTransformation.H"

#include <ablastr/warn_manager/WarnManager.H>

#include <AMReX.H>
#include <AMReX_AmrParGDB.H>
#include <AMReX_BLProfiler.H>
Expand All @@ -36,6 +38,9 @@ namespace impactx

// todo: if charge deposition and/or space charge are requested, require
// amr.n_cells from user inputs

// query input for warning logger variables and set up warning logger accordingly
init_warning_logger();
}

void ImpactX::initGrids ()
Expand Down Expand Up @@ -64,6 +69,9 @@ namespace impactx
// before we start the evolve loop, we are in "step 0" (initial state)
int global_step = 0;

// check typos in inputs after step 1
bool early_params_checked = false;

amrex::ParmParse pp_diag("diag");
bool diag_enable = true;
pp_diag.queryAdd("enable", diag_enable);
Expand Down Expand Up @@ -199,6 +207,9 @@ namespace impactx

}

// inputs: unused parameters (e.g. typos) check after step 1 has finished
if (!early_params_checked) { early_params_checked = early_param_check(); }

} // end in-element space-charge slice-step loop
} // end beamline element loop

Expand Down
1 change: 1 addition & 0 deletions src/initialization/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ target_sources(ImpactX
InitMeshRefinement.cpp
InitParser.cpp
Validate.cpp
Warnings.cpp
)
68 changes: 68 additions & 0 deletions src/initialization/Warnings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* Copyright 2022 The Regents of the University of California, through Lawrence
* Berkeley National Laboratory (subject to receipt of any required
* approvals from the U.S. Dept. of Energy). All rights reserved.
*
* This file is part of ImpactX.
*
* Authors: Marco Garten
* License: BSD-3-Clause-LBNL
*/
#include "ImpactX.H"

#include <ablastr/warn_manager/WarnManager.H>

#include <AMReX_BLProfiler.H>
#include <AMReX_ParmParse.H>

#include <optional>
#include <stdexcept>
#include <string>


namespace impactx
{
void ImpactX::init_warning_logger ()
{
amrex::ParmParse pp_impactx("impactx");
n01r marked this conversation as resolved.
Show resolved Hide resolved

// Set the flag to control if ImpactX has to emit a warning message
// as soon as a warning is recorded
bool always_warn_immediately = false;
pp_impactx.query("always_warn_immediately", always_warn_immediately);
ablastr::warn_manager::GetWMInstance().
SetAlwaysWarnImmediately(always_warn_immediately);

// Set the WarnPriority threshold to decide if ImpactX has to abort
// when a warning is recorded
if(std::string str_abort_on_warning_threshold = "";
n01r marked this conversation as resolved.
Show resolved Hide resolved
pp_impactx.query("abort_on_warning_threshold", str_abort_on_warning_threshold)){
std::optional<ablastr::warn_manager::WarnPriority> abort_on_warning_threshold = std::nullopt;
n01r marked this conversation as resolved.
Show resolved Hide resolved
if (str_abort_on_warning_threshold == "high")
abort_on_warning_threshold = ablastr::warn_manager::WarnPriority::high;
else if (str_abort_on_warning_threshold == "medium" )
abort_on_warning_threshold = ablastr::warn_manager::WarnPriority::medium;
else if (str_abort_on_warning_threshold == "low")
abort_on_warning_threshold = ablastr::warn_manager::WarnPriority::low;
else {
throw std::runtime_error(str_abort_on_warning_threshold
+"is not a valid option for impactx.abort_on_warning_threshold (use: low, medium or high)");
}
ablastr::warn_manager::GetWMInstance().
SetAbortThreshold(abort_on_warning_threshold);
}
}

bool ImpactX::early_param_check ()
{
BL_PROFILE("ImpactX::early_param_check");

amrex::Print() << "\n";
amrex::ParmParse().QueryUnusedInputs();

// Print the warning list right after the first step.
amrex::Print() << ablastr::warn_manager::GetWMInstance()
.PrintGlobalWarnings("FIRST STEP");

n01r marked this conversation as resolved.
Show resolved Hide resolved
return true;
}
n01r marked this conversation as resolved.
Show resolved Hide resolved
} // namespace impactx
48 changes: 48 additions & 0 deletions src/python/ImpactX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,54 @@ void init_ImpactX(py::module& m)
"The minimum number of digits (default: 6) used for the step\n"
"number appended to the diagnostic file names."
)
.def_property("abort_on_warning_threshold",
[](ImpactX & /* ix */){
amrex::ParmParse pp_impactx("impactx");
std::string str_abort_on_warning_threshold;
pp_impactx.get("abort_on_warning_threshold", str_abort_on_warning_threshold);
return str_abort_on_warning_threshold;
},
[](ImpactX & ix, std::string const str_abort_on_warning_threshold) {
amrex::ParmParse pp_impactx("impactx");
pp_impactx.add("abort_on_warning_threshold", str_abort_on_warning_threshold);
// query input for warning logger variables and set up warning logger accordingly
ix.init_warning_logger();
},
"Set WarnPriority threshold to decide if ImpactX\n"
"has to abort when a warning is recorded.\n"
"Valid choices are: ['low', 'medium', 'high']."
)
.def_property("always_warn_immediately",
[](ImpactX & /* ix */){
amrex::ParmParse pp_impactx("impactx");
int always_warn_immediately;
pp_impactx.get("always_warn_immediately", always_warn_immediately);
return always_warn_immediately;
},
[](ImpactX & /* ix */, int const always_warn_immediately) {
amrex::ParmParse pp_impactx("impactx");
pp_impactx.add("always_warn_immediately", always_warn_immediately);
},
"If set to 1, immediately prints every warning message\n"
" as soon as it is generated."
)
// TODO this is an integer with 0 or 1 - can I just make this a boolean here?
.def_property("abort_on_unused_inputs",
[](ImpactX & /* ix */){
amrex::ParmParse pp_amrex("amrex");
int abort_on_unused_inputs;
pp_amrex.get("abort_on_unused_inputs", abort_on_unused_inputs);
return abort_on_unused_inputs;
},
[](ImpactX & ix, int const abort_on_unused_inputs) {
amrex::ParmParse pp_amrex("amrex");
pp_amrex.add("abort_on_unused_inputs", abort_on_unused_inputs);
// query input for warning logger variables and set up warning logger accordingly
ix.init_warning_logger();
},
"Configure simulation to abort AFTER it has run\n"
"if there are unused parameters in the input."
)

.def("init_grids", &ImpactX::initGrids,
"Initialize AMReX blocks/grids for domain decomposition & space charge mesh.\n\n"
Expand Down