Skip to content

Commit 8afbc00

Browse files
baperry2Copilot
andauthored
Add unset capability for ParmParse (#5263)
## Summary For ParmParse, once a variable is set in an input file, there is no way to remove it completely from the command line or subsequently in the input file. For example, you may have specified `amr.keyword = 5` in `inputs.inp` but then want to override it on the command line so a check on `pp.contains("amr.keyword")` comes up as false. Right now, using command line input overrides you can set it to a null value but not completely remove it from the table (pp.remove() can remove from the table in source code). This PR adds an UNSET directive to ParmParse that removes a previously-defined keyword from the parse table. This enables input files to conditionally suppress parameters — for example, an included file can cancel a key set by its parent. ``` amr.keyword = 5 UNSET = amr.keyword # equivalent to never having set amr.keyword ``` Multiple keys can be removed in a single directive: ``` UNSET = key1 key2 key3 ``` ## Additional background Motivated by discussion in Exawind/amr-wind#1897. Code generated by Copilot. Mirrors the design of the existing FILE directive. The new `ParmParse::UnsetKeyword = "UNSET"` static is exposed in the header for symmetry with FileKeyword. The directive is handled in addDefn() by erasing each listed key from the table; keys not present are silently ignored. Tests added to Tests/ParmParse/inputs and Tests/ParmParse/main.cpp cover single-key unset, multi-key unset, and verifying that non-listed keys are unaffected. ## Checklist The proposed changes: - [ ] fix a bug or incorrect behavior in AMReX - [X] add new capabilities to AMReX - [ ] changes answers in the test suite to more than roundoff level - [ ] are likely to significantly affect the results of downstream AMReX users - [X] include documentation in the code and/or rst files, if appropriate --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 80f53a4 commit 8afbc00

File tree

5 files changed

+53
-0
lines changed

5 files changed

+53
-0
lines changed

Docs/sphinx_documentation/source/Basics.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,21 @@ entries in an inputs file:
668668
hydro.cfl = 0.9
669669
my_string = "A String"
670670
671+
You can also remove the effect of having defined an input parameter at all using the
672+
``UNSET`` directive (parameters that are merely overridden will still be caught by
673+
:cpp:`pp.contains()` checks in code). Specifying ``keyword = 5`` in an input file and
674+
then ``UNSET = keyword`` subsequently in the input file or from the command line
675+
completely removes ``keyword`` from the ParmParse table. Multiple keywords can
676+
be removed simultaneously (``UNSET = key1 key2 key3``). if using the ``UNSET``
677+
directive with TOML-like input files, note that full parameter names must be used
678+
even if the UNSET falls within a TOML table:
679+
680+
.. code-block:: none
681+
682+
[x]
683+
a = 1 # Same as x.a = 1 at the root level
684+
685+
UNSET = x.a # full name required to remove x.a entry
671686
672687
Setting Defaults via an Environment Variable
673688
--------------------------------------------

Src/Base/AMReX_ParmParse.H

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,9 @@ public:
17731773
//! keyword for files to load
17741774
static std::string const FileKeyword;
17751775

1776+
//! keyword for removing entries from the table
1777+
static std::string const UnsetKeyword;
1778+
17761779
static std::string ParserPrefix;
17771780

17781781
[[nodiscard]] std::string const& getPrefix () const;

Src/Base/AMReX_ParmParse.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ namespace {
4040
}
4141

4242
std::string const ParmParse::FileKeyword = "FILE";
43+
std::string const ParmParse::UnsetKeyword = "UNSET";
4344
std::string ParmParse::ParserPrefix;
4445

4546
ParmParse::ParmParse (std::string prefix, std::string parser_prefix)
@@ -772,6 +773,15 @@ addDefn (std::string& def, std::vector<std::string>& val,
772773
read_file(fname, tab);
773774
g_toml_table_key = std::move(prev_toml_table_key);
774775
}
776+
//
777+
// Check if this defn is an unset directive.
778+
//
779+
else if ( def == ParmParse::UnsetKeyword )
780+
{
781+
for (auto const& key : val) {
782+
tab.erase(key);
783+
}
784+
}
775785
else
776786
{
777787
std::string key;

Tests/ParmParse/inputs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,13 @@ macro.use_gpu.spacedim = 3
156156
# endif
157157

158158
#endif
159+
160+
# UNSET directive tests
161+
unset_me = 123
162+
UNSET = unset_me
163+
164+
unset_multi_a = 1
165+
unset_multi_b = 2
166+
UNSET = unset_multi_a unset_multi_b
167+
168+
unset_kept = 77

Tests/ParmParse/main.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,21 @@ int main(int argc, char* argv[])
335335
int n = pp.countname("string-for-testing-addfile");
336336
AMREX_ALWAYS_ASSERT(n==3 && s == "string for testing addfile");
337337
}
338+
{ // UNSET directive
339+
ParmParse pp;
340+
// "unset_me" is defined then immediately unset in the inputs file
341+
int v = -1;
342+
int found = pp.query("unset_me", v);
343+
AMREX_ALWAYS_ASSERT(found == 0);
344+
// "unset_multi_a" and "unset_multi_b" are unset together in inputs
345+
found = pp.query("unset_multi_a", v);
346+
AMREX_ALWAYS_ASSERT(found == 0);
347+
found = pp.query("unset_multi_b", v);
348+
AMREX_ALWAYS_ASSERT(found == 0);
349+
// "unset_kept" is NOT unset, so it should still be present
350+
pp.get("unset_kept", v);
351+
AMREX_ALWAYS_ASSERT(v == 77);
352+
}
338353
{
339354
amrex::Print() << "SUCCESS\n";
340355
}

0 commit comments

Comments
 (0)