Skip to content

Add allocdata Python callback - #6966

Merged
ax3l merged 3 commits into
BLAST-WarpX:developmentfrom
dpgrote:add_allocdata_python_callback
Jun 23, 2026
Merged

Add allocdata Python callback#6966
ax3l merged 3 commits into
BLAST-WarpX:developmentfrom
dpgrote:add_allocdata_python_callback

Conversation

@dpgrote

@dpgrote dpgrote commented Jun 23, 2026

Copy link
Copy Markdown
Member

This adds a new call back to the Python interface. This call back, allocdata, is called during initialization, both from scratch and from restart. New MultiFabs should be allocated at this point.

This is associated with the PR #6954 which allows writing of any MultiFabs to the diagnostics and to checkpoint files. The new MultiFabs would need to be added in the allocdata call back to be included in the diagnostics.

This also implements similar capability from PR #6889.

@dpgrote dpgrote added component: Python Python layer component: initialization Changes related to the initialization of the simulation labels Jun 23, 2026
@ax3l
ax3l self-requested a review June 23, 2026 19:16
Comment thread Source/Diagnostics/WarpXIO.cpp Outdated
Comment thread Source/Initialization/WarpXInitData.cpp Outdated
Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>

@ax3l ax3l 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.

LGTM 👍

@ax3l ax3l self-assigned this Jun 23, 2026
@ax3l
ax3l enabled auto-merge (squash) June 23, 2026 19:18
@ax3l
ax3l merged commit 2c3eb90 into BLAST-WarpX:development Jun 23, 2026
51 of 52 checks passed
@dpgrote
dpgrote deleted the add_allocdata_python_callback branch June 23, 2026 23:09

@n01r n01r 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, @dpgrote!

dpgrote added a commit to dpgrote/WarpX that referenced this pull request Jul 1, 2026
This adds a new call back to the Python interface. This call back,
`allocdata`, is called during initialization, both from scratch and from
restart. New MultiFabs should be allocated at this point.

This is associated with the PR BLAST-WarpX#6954 which allows writing of any
MultiFabs to the diagnostics and to checkpoint files. The new MultiFabs
would need to be added in the `allocdata` call back to be included in
the diagnostics.

---------

Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>
dpgrote added a commit that referenced this pull request Jul 24, 2026
This allows new MultiFabs and user defined MultiFabs to be added to the
checkpoint/restart.

Comments:
- All of the specific writes in `FlushFormatCheckpoint::WriteToFile` and
read in `WarpX::InitFromCheckpoint` could be removed by setting the new
flag on those MultiFabs. However, this would break any existing restart
dumps since the names of the MultiFabs would change.
- The change was not implemented in `Python/pywarpx/fields.py` since
that usage has been deprecated.
- This needs a CI test

This builds on PR #6966, allowing Python defined MultiFabs to be added
to checkpoint/restart.
dpgrote added a commit to dpgrote/WarpX that referenced this pull request Jul 24, 2026
This allows new MultiFabs and user defined MultiFabs to be added to the
checkpoint/restart.

Comments:
- All of the specific writes in `FlushFormatCheckpoint::WriteToFile` and
read in `WarpX::InitFromCheckpoint` could be removed by setting the new
flag on those MultiFabs. However, this would break any existing restart
dumps since the names of the MultiFabs would change.
- The change was not implemented in `Python/pywarpx/fields.py` since
that usage has been deprecated.
- This needs a CI test

This builds on PR BLAST-WarpX#6966, allowing Python defined MultiFabs to be added
to checkpoint/restart.
n01r added a commit to aed-zed/WarpX that referenced this pull request Aug 12, 2026
BLAST-WarpX#7025 ("Allow any MultiFab to be written to the diagnostics"), BLAST-WarpX#7023
(checkpoint_restart flag on the registry) and BLAST-WarpX#6966 (allocdata callback) merged
without a test under Examples/. Nothing in the suite registers a field from
Python and writes it to a diagnostic by its registered name:

  - no Examples/ input uses the "allocdata" callback;
  - the one input that calls alloc_init (rz_spacecraft_charging) uses the fields
    internally via saxpy/copymf and never puts them in a data_list;
  - the one input using additional_fields_to_plot (3d_particle_fields_diags)
    lists rho/rho_electrons/rho_protons, which are matched by explicit branches
    rather than the registry lookup.

Add that coverage to an existing test rather than a new one. The 3D ohm-solver
cylinder-compression case does a 2x uniform Bz compression of a diamagnetic
plasma column, so the magnetic pressure Bz^2/(2 mu0) is a physically meaningful
quantity for it: Bz is excluded from the core and piles up outside, and the
resulting pressure is what confines the column radially against the plasma
pressure the hybrid solver already tracks. (The field is essentially purely
axial -- |B_perp|/|Bz| < 1% -- while the compression it drives is radial; the
field name refers to the component the pressure is built from, not to the
direction of the compression.)

It is registered from Python in an "allocdata" callback, refreshed after each
E-solve, and requested in data_list by its registered name -- so the test
exercises alloc_init, the allocdata hook, and the MultiFabRegister name lookup
in FullDiagnostics together. No new input file and no measurable extra runtime.

The field is registered on the Bz BoxArray, so it inherits that staggering and
is exact where it is computed; the diagnostic's CellCenterFunctor does the
face-to-centre averaging on output, as it does for Bz itself. Note that the
cell-centred output is therefore avg(Bz^2)/(2 mu0), which is >= (avg Bz)^2/(2
mu0) by Jensen's inequality -- the two agree to 1e-16 in the uniform region and
differ by up to 9.7% where Bz varies most sharply. Verified the peak value:
321.06 Pa against Bz_max = 0.0284 T, i.e. Bz_max^2/(2 mu0) = 321.06 Pa.

The step-0 dump shows the allocation value (zeros) because "afterInitEsolve"
fires before AddExternalFields(), so Bfield_fp does not yet hold the applied
compression field, and there is no callback between AddExternalFields() and the
initial diagnostic write. Every dump from step 1 on carries the current value.

The benchmark gains the one new key; every other recorded value is unchanged.

Depends on the preceding commit: without the PICMI pass-through the registered
name is dropped in Python and never reaches the C++ lookup.
aeriforme pushed a commit to pkicsiny/WarpX that referenced this pull request Aug 13, 2026
This adds a new call back to the Python interface. This call back,
`allocdata`, is called during initialization, both from scratch and from
restart. New MultiFabs should be allocated at this point.

This is associated with the PR BLAST-WarpX#6954 which allows writing of any
MultiFabs to the diagnostics and to checkpoint files. The new MultiFabs
would need to be added in the `allocdata` call back to be included in
the diagnostics.

---------

Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>
aeriforme pushed a commit to pkicsiny/WarpX that referenced this pull request Aug 13, 2026
This allows new MultiFabs and user defined MultiFabs to be added to the
checkpoint/restart.

Comments:
- All of the specific writes in `FlushFormatCheckpoint::WriteToFile` and
read in `WarpX::InitFromCheckpoint` could be removed by setting the new
flag on those MultiFabs. However, this would break any existing restart
dumps since the names of the MultiFabs would change.
- The change was not implemented in `Python/pywarpx/fields.py` since
that usage has been deprecated.
- This needs a CI test

This builds on PR BLAST-WarpX#6966, allowing Python defined MultiFabs to be added
to checkpoint/restart.
n01r added a commit to aed-zed/WarpX that referenced this pull request Aug 20, 2026
BLAST-WarpX#7025 ("Allow any MultiFab to be written to the diagnostics"), BLAST-WarpX#7023
(checkpoint_restart flag on the registry) and BLAST-WarpX#6966 (allocdata callback) merged
without a test under Examples/. Nothing in the suite registers a field from
Python and writes it to a diagnostic by its registered name:

  - no Examples/ input uses the "allocdata" callback;
  - the one input that calls alloc_init (rz_spacecraft_charging) uses the fields
    internally via saxpy/copymf and never puts them in a data_list;
  - the one input using additional_fields_to_plot (3d_particle_fields_diags)
    lists rho/rho_electrons/rho_protons, which are matched by explicit branches
    rather than the registry lookup.

Add that coverage to an existing test rather than a new one. The 3D ohm-solver
cylinder-compression case does a 2x uniform Bz compression of a diamagnetic
plasma column, so the magnetic pressure Bz^2/(2 mu0) is a physically meaningful
quantity for it: Bz is excluded from the core and piles up outside, and the
resulting pressure is what confines the column radially against the plasma
pressure the hybrid solver already tracks. (The field is essentially purely
axial -- |B_perp|/|Bz| < 1% -- while the compression it drives is radial; the
field name refers to the component the pressure is built from, not to the
direction of the compression.)

It is registered from Python in an "allocdata" callback, refreshed after each
E-solve, and requested in data_list by its registered name -- so the test
exercises alloc_init, the allocdata hook, and the MultiFabRegister name lookup
in FullDiagnostics together. No new input file and no measurable extra runtime.

The field is registered on the Bz BoxArray, so it inherits that staggering and
is exact where it is computed; the diagnostic's CellCenterFunctor does the
face-to-centre averaging on output, as it does for Bz itself. Note that the
cell-centred output is therefore avg(Bz^2)/(2 mu0), which is >= (avg Bz)^2/(2
mu0) by Jensen's inequality (Jensen, Acta Mathematica 30, 175-193, 1906,
https://doi.org/10.1007/BF02418571) -- the two agree to 1e-16 in the uniform
region and differ by up to 9.7% where Bz varies most sharply. Jensen bounds the
sign of that gap but not its size; for the two-point face average used here the
exact identity is mean(B^2) - mean(B)^2 = (a-b)^2/4, i.e. a ratio of
1 + ((a-b)/(a+b))^2, so 9.7% corresponds to a face-pair contrast of 0.31.
Verified the peak value: 321.06 Pa against Bz_max = 0.0284 T, i.e.
Bz_max^2/(2 mu0) = 321.06 Pa.

The step-0 dump shows the allocation value (zeros) because "afterInitEsolve"
fires before AddExternalFields(), so Bfield_fp does not yet hold the applied
compression field, and there is no callback between AddExternalFields() and the
initial diagnostic write. Every dump from step 1 on carries the current value.

The benchmark gains the one new key; every other recorded value is unchanged.

Depends on the preceding commit: without the PICMI pass-through the registered
name is dropped in Python and never reaches the C++ lookup.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: initialization Changes related to the initialization of the simulation component: Python Python layer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants