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

Diagnostics : EM fields on particles #5637

Open
wants to merge 32 commits into
base: development
Choose a base branch
from

Conversation

grobertdautun
Copy link

@grobertdautun grobertdautun commented Feb 4, 2025

This PR implements the EM option for particles diagnostics output. It is an extension of #4599 and #4839 and works in the same way. It allows the user to output the electromagnetic fields seen by particles.

I added a test case test_2d_particle_EM_diagnostics with its analysis. This case represents a single particle fixed in a box traversed by a laser pulse, and the analysis verifies that the fields are matching the theoretical ones.

I also tested the diagnostics on bigger cases, and I noticed that when writing a lot of timesteps with a lot of particles, reading the diagnostics with adios2 file-based encoding is very slow due to the high number of opening/closing files. Moreover, it appears that openpmd-viewer does not support reading variable-based encoding, so I wrote some scripts to read them directly using the adios2 python API, that I added in Tools/PostProcessing/read_variable_based_adios2.py

There is a small update in the documentation to add the description of both the diagnostics and the script

This diagnostics does not support mesh refinement at the moment, this should be added in a follow up PR

@ax3l ax3l added the component: diagnostics all types of outputs label Feb 4, 2025
Comment on lines 315 to 322
tmp.NewRealComp("Ex");
tmp.NewRealComp("Ey");
tmp.NewRealComp("Ez");
tmp.NewRealComp("Bx");
tmp.NewRealComp("By");
tmp.NewRealComp("Bz");

int const Ex_index = tmp.getParticleComps().at("Ex");
Copy link
Member

Choose a reason for hiding this comment

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

There will be a minimal change we need to add to this PR once we merged #5481 (simplification of named SoA bookkeeping), but it will be easy to update once your PR is ready/out-of-WIP.

@ax3l ax3l requested review from atmyers and RemiLehe February 4, 2025 18:39
@grobertdautun grobertdautun changed the title [WIP] Diagnostics : EM fields on particles Diagnostics : EM fields on particles Feb 6, 2025
@lucafedeli88 lucafedeli88 requested a review from ax3l February 13, 2025 13:11
@@ -2916,9 +2916,9 @@ In-situ capabilities can be used by turning on Sensei or Ascent (provided they a
* ``<diag_name>.<species_name>.variables`` (list of `strings` separated by spaces, optional)
List of particle quantities to write to output.
Choices are ``x``, ``y``, ``z`` for the particle positions (3D and RZ), ``x`` & ``z`` in 2D, ``z`` in 1D,
``w`` for the particle weight and ``ux``, ``uy``, ``uz`` for the particle momenta.
``w`` for the particle weight, ``ux``, ``uy``, ``uz`` for the particle momenta, and ``EM`` for the electromagnetic fields.
Copy link
Member

Choose a reason for hiding this comment

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

Could we instead allow the user to pass Ex, Ey, Bx, etc.

Comment on lines +393 to +395
Ex_particle_arr[ip] = 0._rt;
Ey_particle_arr[ip] = 0._rt;
Ez_particle_arr[ip] = 0._rt;
Copy link
Member

Choose a reason for hiding this comment

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

alignment is off by one whitespace 😅

@@ -0,0 +1,145 @@
import numpy as np
from adios2 import Stream
Copy link
Member

Choose a reason for hiding this comment

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

As discussed: we could use openPMD-api.

I think for openPMD-viewer support, we rely on this upcoming feature: openPMD/openPMD-api#1706

Current ADIOS2 support status:
https://openpmd-api.readthedocs.io/en/0.16.1/backends/adios2.html

@franzpoeschel, @guj @pnorbert can you remind me if we can do variable-based encoding without steps (i.e., can we already set something during write that allows-us to read variable based encoding with random access)?

Choose a reason for hiding this comment

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

(i.e., can we already set something during write that allows-us to read variable based encoding with random access)

Not yet, that is what #1706 (and follow-ups for changing metadata) will bring (setting a flag during write will not be needed though).
Until that point, it's better to continue using file encoding for random access.

@@ -2784,7 +2784,7 @@ In-situ capabilities can be used by turning on Sensei or Ascent (provided they a
* ``<diag_name>.openpmd_encoding`` (optional, ``v`` (variable based), ``f`` (file based) or ``g`` (group based) ) only read if ``<diag_name>.format = openpmd``.
openPMD `file output encoding <https://openpmd-api.readthedocs.io/en/0.16.1/usage/concepts.html#iteration-and-series>`__.
File based: one file per timestep (slower), group/variable based: one file for all steps (faster)).
``variable based`` is an `experimental feature with ADIOS2 <https://openpmd-api.readthedocs.io/en/0.16.1/backends/adios2.html#experimental-new-adios2-schema>`__ and not supported for back-transformed diagnostics.
``variable based`` is an `experimental feature with ADIOS2 <https://openpmd-api.readthedocs.io/en/0.16.1/backends/adios2.html#experimental-new-adios2-schema>`__ and not supported for back-transformed diagnostics. This format is also not supported by OpenPMDTimeSeries at the moment, the script :download:`read_variable_based_adios2.py <../../../Tools/PostProcessing/read_variable_based_adios2.py>` provides basic functions to read variable-based particle diagnostics directly with the ``adios2`` module.
Copy link
Member

Choose a reason for hiding this comment

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

This could go in a separate PR. Could you remove from this one?

@@ -0,0 +1,145 @@
import numpy as np
Copy link
Member

Choose a reason for hiding this comment

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

This file could go in a separate PR. Could you remove from this one?

Ez_particle_arr[ip] = 0._rt;
Bx_particle_arr[ip] = 0._rt;
By_particle_arr[ip] = 0._rt;
Bz_particle_arr[ip] = 0._rt;
Copy link
Member

Choose a reason for hiding this comment

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

Could we add the external fields as part of this call?

Copy link
Member

Choose a reason for hiding this comment

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

Comment on lines +344 to +349
amrex::MultiFab const& Ex = *warpx.m_fields.get(FieldType::Efield_fp, Dir{0}, lev0);
amrex::MultiFab const& Ey = *warpx.m_fields.get(FieldType::Efield_fp, Dir{1}, lev0);
amrex::MultiFab const& Ez = *warpx.m_fields.get(FieldType::Efield_fp, Dir{2}, lev0);
amrex::MultiFab const& Bx = *warpx.m_fields.get(FieldType::Bfield_fp, Dir{0}, lev0);
amrex::MultiFab const& By = *warpx.m_fields.get(FieldType::Bfield_fp, Dir{1}, lev0);
amrex::MultiFab const& Bz = *warpx.m_fields.get(FieldType::Bfield_fp, Dir{2}, lev0);
Copy link
Member

@RemiLehe RemiLehe Feb 13, 2025

Choose a reason for hiding this comment

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

Suggested change
amrex::MultiFab const& Ex = *warpx.m_fields.get(FieldType::Efield_fp, Dir{0}, lev0);
amrex::MultiFab const& Ey = *warpx.m_fields.get(FieldType::Efield_fp, Dir{1}, lev0);
amrex::MultiFab const& Ez = *warpx.m_fields.get(FieldType::Efield_fp, Dir{2}, lev0);
amrex::MultiFab const& Bx = *warpx.m_fields.get(FieldType::Bfield_fp, Dir{0}, lev0);
amrex::MultiFab const& By = *warpx.m_fields.get(FieldType::Bfield_fp, Dir{1}, lev0);
amrex::MultiFab const& Bz = *warpx.m_fields.get(FieldType::Bfield_fp, Dir{2}, lev0);
amrex::MultiFab const& Ex = *warpx.m_fields.get(FieldType::Efield_aux, Dir{0}, lev0);
amrex::MultiFab const& Ey = *warpx.m_fields.get(FieldType::Efield_aux, Dir{1}, lev0);
amrex::MultiFab const& Ez = *warpx.m_fields.get(FieldType::Efield_aux, Dir{2}, lev0);
amrex::MultiFab const& Bx = *warpx.m_fields.get(FieldType::Bfield_aux, Dir{0}, lev0);
amrex::MultiFab const& By = *warpx.m_fields.get(FieldType::Bfield_aux, Dir{1}, lev0);
amrex::MultiFab const& Bz = *warpx.m_fields.get(FieldType::Bfield_aux, Dir{2}, lev0);

Comment on lines 589 to +594
if ( particle_diag.m_plot_phi ) {
storePhiOnParticles( tmp, WarpX::electrostatic_solver_id, !use_pinned_pc );
}
if ( particle_diag.m_plot_EM ) {
storeEMFieldsOnParticles( tmp, WarpX::electromagnetic_solver_id, !use_pinned_pc );
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if ( particle_diag.m_plot_phi ) {
storePhiOnParticles( tmp, WarpX::electrostatic_solver_id, !use_pinned_pc );
}
if ( particle_diag.m_plot_EM ) {
storeEMFieldsOnParticles( tmp, WarpX::electromagnetic_solver_id, !use_pinned_pc );
}
// Detect whether this is a FullDiagnostic (use_pinned_pc = 0) or
// a BoundaryScrapingDiagnostic/BackTransformedDiagnostic (use_pinned_pc=1)
bool const is_full_diagnostic = !use_pinned_pc;
if ( particle_diag.m_plot_phi ) {
storePhiOnParticles( tmp, WarpX::electrostatic_solver_id, is_full_diagnostic);
}
if ( particle_diag.m_plot_EM ) {
storeEMFieldsOnParticles( tmp, WarpX::electromagnetic_solver_id, is_full_diagnostic);
}

Ez_particle_arr[ip] = 0._rt;
Bx_particle_arr[ip] = 0._rt;
By_particle_arr[ip] = 0._rt;
Bz_particle_arr[ip] = 0._rt;
Copy link
Member

Choose a reason for hiding this comment

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: diagnostics all types of outputs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants