Skip to content

ABLASTR: Warn Manager State is Per AMReX Cycle - #7186

Merged
ax3l merged 3 commits into
BLAST-WarpX:developmentfrom
ax3l:topic-warn-manager-lifetime
Aug 27, 2026
Merged

ABLASTR: Warn Manager State is Per AMReX Cycle#7186
ax3l merged 3 commits into
BLAST-WarpX:developmentfrom
ax3l:topic-warn-manager-lifetime

Conversation

@ax3l

@ax3l ax3l commented Aug 22, 2026

Copy link
Copy Markdown
Member

Summary

WarnManager is a process-lifetime singleton, so the warnings it recorded outlived WarpX::Finalize(). A process that runs more than one simulation (e.g., a parameter scan in Python, or the pytest unit tests) saw the second simulation report the warnings of the first one again.

  • User-facing: a second simulation in the same process starts with a clean warning list. No change for a regular simulation run, which runs exactly one simulation.
  • Internal: new WarnManager::Clear() and ablastr::warn_manager::WMClear(), backed by msg_logger::Logger::clear(), called at the end of WarpX::Finalize(). The singleton and its lifetime are unchanged.
Details and test coverage

Details

An earlier version of this PR gave the singleton a per-AMReX-cycle lifetime instead: a std::unique_ptr created on first use, released from an amrex::ExecOnFinalize hook and guarded by a mutex. That reset more state, but it had to work around amrex::Finalize() draining its finalize stack with top()() before pop(), which silently drops a hook that is registered while the stack is draining. Clearing the message list from WarpX::Finalize() covers the case that actually bites and is much easier to reason about.

The warning settings are not part of the reset. always_warn_immediately is re-set on every WarpX construction, because initialize_warning_manager() always calls SetAlwaysWarnImmediately() with the parsed-or-default value. abort_on_warning_threshold is only assigned when warpx.abort_on_warning_threshold is present in the inputs, so a second simulation that omits it keeps the threshold of the first one.

Test coverage

Source/ablastr/warn_manager/WarnManager.cpp and Source/WarpX.cpp compile clean with the project warning flags.

The behavior itself is not covered by a test on development yet. The natural home is the pytest harness of #7144, which runs several simulations in one process: a test there should assert that the second simulation's warning list starts empty, otherwise this can regress silently.

@ax3l ax3l added bug Something isn't working bug: affects latest release Bug also exists in latest release version component: ABLASTR components shared with other PIC codes labels Aug 22, 2026
@ax3l
ax3l force-pushed the topic-warn-manager-lifetime branch from 5ca33ff to ed2ee54 Compare August 26, 2026 16:31
@ax3l ax3l changed the title [WIP] ABLASTR: Warn Manager State is Per AMReX Cycle ABLASTR: Warn Manager State is Per AMReX Cycle Aug 26, 2026
@ax3l
ax3l force-pushed the topic-warn-manager-lifetime branch from ed2ee54 to 80d9411 Compare August 26, 2026 17:01
@ax3l
ax3l requested a review from dpgrote August 26, 2026 17:03
ax3l added a commit to ax3l/amrex that referenced this pull request Aug 26, 2026
`amrex::Initialize` and `amrex::Finalize` drained their hook stacks with
`top()()` followed by `pop()`. A hook that registers another one with
`ExecOnInitialize`/`ExecOnFinalize` therefore left the *calling* hook on
top of the stack: it ran a second time, and the following `pop()`
silently discarded the newly registered hook without ever running it.

Move the hook off the stack before calling it, so that a hook which
registers another one runs exactly once and the newly registered hook
runs as well.

Found while making the ABLASTR warn manager state per AMReX cycle in
BLAST-WarpX/warpx#7186: a warning recorded from
a finalize hook resurrects the warn manager singleton and loses the
teardown hook that would have released it again.
`WarnManager::GetInstance()` held the singleton in a function-local
`static`, so its state lived for the whole process instead of for one
AMReX initialize/finalize cycle. A process that runs more than one
simulation - a parameter scan in Python, or the pytest unit tests - saw
the second simulation start with the warnings of the first one still in
the list, and with `always_warn_immediately` and
`abort_on_warning_threshold` still set to whatever the first inputs deck
had chosen.

The instance now lives in a `std::unique_ptr` that is created on first
use and released from an `amrex::ExecOnFinalize` hook, so every cycle
starts with a clean warning list, with the default warning settings and
with a freshly sampled `m_rank`.

Tying the reset to `amrex::Finalize()` rather than to
`WarpX::ResetInstance()` keeps ABLASTR independent of WarpX, and covers
the warnings that are recorded outside the lifetime of a WarpX instance,
such as the ones from `check_mpi_thread_level()`.

The teardown must not itself record a warning. The mutex is not
recursive, so the instance is moved out under the lock and destroyed
after the lock is released; and `amrex::Finalize()` calls `top()()`
before `pop()`, so a teardown hook that is registered while the stack
drains is silently discarded and the state would leak into the next cycle
anyway. Neither is reachable today - `~WarnManager` is defaulted, and
`initialize_warning_manager()` registers the teardown ahead of every
other finalize hook - so the second one is only documented in the code.

This follows BLAST-WarpX#7142 and
BLAST-WarpX#7143, which removed the
equivalent process-lifetime state from the WarpX singleton and from the
Python input buckets.
@ax3l
ax3l force-pushed the topic-warn-manager-lifetime branch from 80d9411 to 91791c0 Compare August 26, 2026 17:23
WeiqunZhang pushed a commit to AMReX-Codes/amrex that referenced this pull request Aug 26, 2026
## Summary

`amrex::Initialize` and `amrex::Finalize` drained their hook stacks with
`top()()` followed by `pop()`. A hook that registers another one with
`ExecOnInitialize`/`ExecOnFinalize` therefore left the *calling* hook on
top of the stack: it ran a second time, and the following `pop()`
silently discarded the newly registered hook without ever running it.

Move the hook off the stack before calling it, so that a hook which
registers another one runs exactly once and the newly registered hook
runs as well.

## Additional background

Found while making the ABLASTR warn manager state per AMReX cycle in
BLAST-WarpX/warpx#7186: a warning recorded from
a finalize hook resurrects the warn manager singleton and loses the
teardown hook that would have released it again.


## Checklist

The proposed changes:
- [x] fix a bug or incorrect behavior in AMReX
- [ ] 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
- [ ] include documentation in the code and/or rst files, if appropriate

@lucafedeli88 lucafedeli88 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR, @ax3l !

I would suggest updating the PR description, as it refers to an initial (more complex) implementation of this fix. Besides this, the PR is OK (I also think that this simpler implementation is better)!

@ax3l

ax3l commented Aug 27, 2026

Copy link
Copy Markdown
Member Author

Oh good point, let me fix that description.

@ax3l
ax3l requested a review from lucafedeli88 August 27, 2026 19:03
@ax3l

ax3l commented Aug 27, 2026

Copy link
Copy Markdown
Member Author

All thanks to @dpgrote for the clean implementation.

@lucafedeli88 lucafedeli88 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect ! Thanks, @ax3l

@ax3l
ax3l merged commit ead0dba into BLAST-WarpX:development Aug 27, 2026
50 checks passed
@ax3l
ax3l deleted the topic-warn-manager-lifetime branch August 27, 2026 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug: affects latest release Bug also exists in latest release version bug Something isn't working component: ABLASTR components shared with other PIC codes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants