From fbc1a56ac5d1cf40572f3acda0213a6eeea7f1d5 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Thu, 2 Jan 2025 09:00:09 -0800 Subject: [PATCH 01/23] Doc: Wave Attenuation Numerics (#5532) Add Yin's latest paper. --- Docs/source/highlights.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Docs/source/highlights.rst b/Docs/source/highlights.rst index 7f613625c55..300d94149f8 100644 --- a/Docs/source/highlights.rst +++ b/Docs/source/highlights.rst @@ -188,6 +188,14 @@ Scientific works in High-Performance Computing, applied mathematics and numerics Please see :ref:`this section `. +Related works using WarpX: + +#. Yan Y., Du F., Tang J., Yu D and Zhao Y., + **Numerical study on wave attenuation via 1D fully kinetic electromagnetic particle-in-cell simulations**. + Plasma Sources Sci. Technol. **33** 115013, 2024 + `DOI:10.1088/1361-6595/ad8c7c `__ + + Nuclear Fusion and Plasma Confinement ************************************* From 98889d69b2166aa7a610cdd6dc8abcd1baafee2a Mon Sep 17 00:00:00 2001 From: Remi Lehe Date: Thu, 2 Jan 2025 09:24:33 -0800 Subject: [PATCH 02/23] Injection from EB: do not create particles outside of user-specified bounds (#5521) When using the injection from embedded boundaries along with `zmin`, `zmax`, `xmin`, `xmax`, etc., we were creating a large number of macroparticles along the EB surface, and then removing the particles that are outside of `zmin`, `zmax`, `xmin`, `xmax`, etc. by setting their ID to an invalid value. In case where the area defined by `zmin`, `zmax`, `xmin`, `xmax`, etc. is a small fraction of the EB surface, it is much more efficient not to create these particles in the first place. In addition, it avoids having to create a large number of particle IDs, which are eventually not used in the simulation. (In some use cases, this unnecessarily lead to a particle ID overflow, i.e. WarpX ended up having to generate particle IDs that were outside the maximum possible range given by the number of bits.) This PR removes this issue. --- Source/Particles/PhysicalParticleContainer.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Source/Particles/PhysicalParticleContainer.cpp b/Source/Particles/PhysicalParticleContainer.cpp index c973e9afafa..baac138dd38 100644 --- a/Source/Particles/PhysicalParticleContainer.cpp +++ b/Source/Particles/PhysicalParticleContainer.cpp @@ -1483,17 +1483,14 @@ PhysicalParticleContainer::AddPlasmaFlux (PlasmaInjector const& plasma_injector, if (eb_flag_arr(i,j,k).isRegular() || eb_flag_arr(i,j,k).isCovered()) { return; } // Scale by the (normalized) area of the EB surface in this cell num_ppc_real_in_this_cell *= eb_bnd_area_arr(i,j,k); - } else + } #else amrex::Real const num_ppc_real_in_this_cell = num_ppc_real; // user input: number of macroparticles per cell #endif - { - // Injection from a plane - auto lo = getCellCoords(overlap_corner, dx, {0._rt, 0._rt, 0._rt}, iv); - auto hi = getCellCoords(overlap_corner, dx, {1._rt, 1._rt, 1._rt}, iv); - // Skip cells that do not overlap with the plane - if (!flux_pos->overlapsWith(lo, hi)) { return; } - } + // Skip cells that do not overlap with the bounds specified by the user (xmin/xmax, ymin/ymax, zmin/zmax) + auto lo = getCellCoords(overlap_corner, dx, {0._rt, 0._rt, 0._rt}, iv); + auto hi = getCellCoords(overlap_corner, dx, {1._rt, 1._rt, 1._rt}, iv); + if (!flux_pos->overlapsWith(lo, hi)) { return; } auto index = overlap_box.index(iv); // Take into account refined injection region From f8b97eb82b0798fd6821b3d7358caa2f748eb083 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 15:07:25 -0800 Subject: [PATCH 03/23] [pre-commit.ci] pre-commit autoupdate (#5529) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.3 → v0.8.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.3...v0.8.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7c396c95b1d..55d880c8866 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -69,7 +69,7 @@ repos: # Python: Ruff linter & formatter # https://docs.astral.sh/ruff/ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.3 + rev: v0.8.4 hooks: # Run the linter - id: ruff From bbf9e0d2d3eae080ded84e15481a975efbed454b Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Fri, 3 Jan 2025 14:02:45 -0800 Subject: [PATCH 04/23] PEC: Fix Uninit Var Warning (GCC) (#5536) GCC 13 throws a compile-time warning in 3D that in some cases, `is_normal_to_boundary` is used as uninitialized. There are a lot of `if`s in its usage, so I simply changed the init value to `false` to silence it. --- Source/BoundaryConditions/PEC_Insulator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/BoundaryConditions/PEC_Insulator.cpp b/Source/BoundaryConditions/PEC_Insulator.cpp index b9926e4bf22..b6b6bcf08ea 100644 --- a/Source/BoundaryConditions/PEC_Insulator.cpp +++ b/Source/BoundaryConditions/PEC_Insulator.cpp @@ -69,7 +69,7 @@ namespace bool GuardCell = false; bool isInsulatorBoundary = false; amrex::Real sign = +1._rt; - bool is_normal_to_boundary; + bool is_normal_to_boundary = false; amrex::Real field_value = 0._rt; bool set_field = false; // Loop over all dimensions From 97aa294586b0268ba0ca3f9f46680d5d52b02736 Mon Sep 17 00:00:00 2001 From: Roelof Groenewald <40245517+roelof-groenewald@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:03:58 -0800 Subject: [PATCH 05/23] Use same MLMG parameters in MS solver as in ES solver (#5517) Fixes #5508. ~~We might not want to set the solver precision with the same values as used for the ES solver but that can be debated in this PR.~~ Note this is a patch fix until we can refactor the MS solver to separate it from the `WarpX` class. --------- Signed-off-by: roelof-groenewald --- .../MagnetostaticSolver/MagnetostaticSolver.cpp | 16 ++++++++-------- Source/WarpX.H | 1 + Source/WarpX.cpp | 1 + 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Source/FieldSolver/MagnetostaticSolver/MagnetostaticSolver.cpp b/Source/FieldSolver/MagnetostaticSolver/MagnetostaticSolver.cpp index 96e92b80359..ce39265e720 100644 --- a/Source/FieldSolver/MagnetostaticSolver/MagnetostaticSolver.cpp +++ b/Source/FieldSolver/MagnetostaticSolver/MagnetostaticSolver.cpp @@ -128,22 +128,22 @@ WarpX::AddMagnetostaticFieldLabFrame() // const amrex::Real magnetostatic_absolute_tolerance = self_fields_absolute_tolerance*PhysConst::c; // temporary fix!!! - const amrex::Real magnetostatic_absolute_tolerance = 0.0; - amrex::Real self_fields_required_precision; + const amrex::Real absolute_tolerance = 0.0; + amrex::Real required_precision; if constexpr (std::is_same::value) { - self_fields_required_precision = 1e-5; + required_precision = 1e-5; } else { - self_fields_required_precision = 1e-11; + required_precision = 1e-11; } - const int self_fields_max_iters = 200; - const int self_fields_verbosity = 2; + const int verbosity = 2; computeVectorPotential( m_fields.get_mr_levels_alldirs(FieldType::current_fp, finest_level), m_fields.get_mr_levels_alldirs(FieldType::vector_potential_fp_nodal, finest_level), - self_fields_required_precision, magnetostatic_absolute_tolerance, self_fields_max_iters, - self_fields_verbosity); + required_precision, absolute_tolerance, magnetostatic_solver_max_iters, + verbosity + ); } /* Compute the vector potential `A` by solving the Poisson equation with `J` as diff --git a/Source/WarpX.H b/Source/WarpX.H index 73998d6faf2..56d4f879de8 100644 --- a/Source/WarpX.H +++ b/Source/WarpX.H @@ -902,6 +902,7 @@ public: // Magnetostatic Solver Interface MagnetostaticSolver::VectorPoissonBoundaryHandler m_vector_poisson_boundary_handler; + int magnetostatic_solver_max_iters = 200; void ComputeMagnetostaticField (); void AddMagnetostaticFieldLabFrame (); void computeVectorPotential (ablastr::fields::MultiLevelVectorField const& curr, diff --git a/Source/WarpX.cpp b/Source/WarpX.cpp index 965235e1078..75aa964da3a 100644 --- a/Source/WarpX.cpp +++ b/Source/WarpX.cpp @@ -684,6 +684,7 @@ WarpX::ReadParameters () poisson_solver_id!=PoissonSolverAlgo::IntegratedGreenFunction, "To use the FFT Poisson solver, compile with WARPX_USE_FFT=ON."); #endif + utils::parser::queryWithParser(pp_warpx, "self_fields_max_iters", magnetostatic_solver_max_iters); WARPX_ALWAYS_ASSERT_WITH_MESSAGE( ( From c13764504103c556bab87288e851ace44c1d2c4d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 Jan 2025 02:01:07 +0000 Subject: [PATCH 06/23] [pre-commit.ci] pre-commit autoupdate (#5539) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.4 → v0.8.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.4...v0.8.6) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 55d880c8866..c07ad07f74a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -69,7 +69,7 @@ repos: # Python: Ruff linter & formatter # https://docs.astral.sh/ruff/ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.4 + rev: v0.8.6 hooks: # Run the linter - id: ruff From 1bff387be15deb55585e0ee529581bd7160b3cb9 Mon Sep 17 00:00:00 2001 From: Marco Garten Date: Wed, 8 Jan 2025 09:29:35 -0800 Subject: [PATCH 07/23] Update CMake version for Perlmutter AY25 (#5535) Update CMake as per NERSC automated message upon loading cmake/3.24.3: _"This module is deprecated and scheduled for removal at the end of AY24 (Jan 14, 2025). Please move to cmake/3.30.2."_ --------- Co-authored-by: Axel Huebl --- .../perlmutter-nersc/perlmutter_cpu_warpx.profile.example | 2 +- .../perlmutter-nersc/perlmutter_gpu_warpx.profile.example | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/machines/perlmutter-nersc/perlmutter_cpu_warpx.profile.example b/Tools/machines/perlmutter-nersc/perlmutter_cpu_warpx.profile.example index 488d53c6af9..a7493ecd4bc 100644 --- a/Tools/machines/perlmutter-nersc/perlmutter_cpu_warpx.profile.example +++ b/Tools/machines/perlmutter-nersc/perlmutter_cpu_warpx.profile.example @@ -7,7 +7,7 @@ if [ -z ${proj-} ]; then echo "WARNING: The 'proj' variable is not yet set in yo # required dependencies module load cpu -module load cmake/3.24.3 +module load cmake/3.30.2 module load cray-fftw/3.3.10.6 # optional: for QED support with detailed tables diff --git a/Tools/machines/perlmutter-nersc/perlmutter_gpu_warpx.profile.example b/Tools/machines/perlmutter-nersc/perlmutter_gpu_warpx.profile.example index 7e76d1366a3..5d413db71e1 100644 --- a/Tools/machines/perlmutter-nersc/perlmutter_gpu_warpx.profile.example +++ b/Tools/machines/perlmutter-nersc/perlmutter_gpu_warpx.profile.example @@ -12,7 +12,7 @@ module load craype module load craype-x86-milan module load craype-accel-nvidia80 module load cudatoolkit -module load cmake/3.24.3 +module load cmake/3.30.2 # optional: for QED support with detailed tables export BOOST_ROOT=/global/common/software/spackecp/perlmutter/e4s-23.08/default/spack/opt/spack/linux-sles15-zen3/gcc-12.3.0/boost-1.83.0-nxqk3hnci5g3wqv75wvsmuke3w74mzxi From 1813753fa362a22df41fbed3ccbe6e38e0914be4 Mon Sep 17 00:00:00 2001 From: Luca Fedeli Date: Wed, 8 Jan 2025 18:30:04 +0100 Subject: [PATCH 08/23] Remove an unnecessary call to WarpX::GetInstance() (#5540) This PR removes an unnecessary call to ` WarpX::GetInstance()` from a member function of the `WarpX` class. --- Source/Parallelization/WarpXRegrid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Parallelization/WarpXRegrid.cpp b/Source/Parallelization/WarpXRegrid.cpp index a0a2d4929df..7adc00ed523 100644 --- a/Source/Parallelization/WarpXRegrid.cpp +++ b/Source/Parallelization/WarpXRegrid.cpp @@ -320,7 +320,7 @@ WarpX::ComputeCostsHeuristic (amrex::Vector Date: Wed, 8 Jan 2025 09:30:49 -0800 Subject: [PATCH 09/23] CI: ignore all `.rst` files in the repository (#5523) Following up on #5387, I think we should also ignore all `.rst` files in the repository when we decide whether or not to run the CI workflows. GitHub Actions syntax taken from the examples [here](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#patterns-to-match-file-paths) (see `'**.js'` example). Azure syntax to be tested. If we merge this before #5522, we can test it (i.e., test that CI is skipped) in #5522 after rebasing there. --- .azure-pipelines.yml | 1 + .github/workflows/clang_sanitizers.yml | 1 + .github/workflows/clang_tidy.yml | 1 + .github/workflows/cuda.yml | 1 + .github/workflows/hip.yml | 1 + .github/workflows/insitu.yml | 1 + .github/workflows/intel.yml | 1 + .github/workflows/macos.yml | 1 + .github/workflows/ubuntu.yml | 1 + .github/workflows/windows.yml | 1 + 10 files changed, 10 insertions(+) diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index d22097a208f..28c4e03d102 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -13,6 +13,7 @@ pr: paths: exclude: - Docs + - '**/*.rst' jobs: - job: diff --git a/.github/workflows/clang_sanitizers.yml b/.github/workflows/clang_sanitizers.yml index d63a329bf64..15dbb00756a 100644 --- a/.github/workflows/clang_sanitizers.yml +++ b/.github/workflows/clang_sanitizers.yml @@ -7,6 +7,7 @@ on: pull_request: paths-ignore: - "Docs/**" + - "**.rst" concurrency: group: ${{ github.ref }}-${{ github.head_ref }}-clangsanitizers diff --git a/.github/workflows/clang_tidy.yml b/.github/workflows/clang_tidy.yml index edb3e8b1988..6e83b07000f 100644 --- a/.github/workflows/clang_tidy.yml +++ b/.github/workflows/clang_tidy.yml @@ -7,6 +7,7 @@ on: pull_request: paths-ignore: - "Docs/**" + - "**.rst" concurrency: group: ${{ github.ref }}-${{ github.head_ref }}-clangtidy diff --git a/.github/workflows/cuda.yml b/.github/workflows/cuda.yml index e4967bea790..404f53a3295 100644 --- a/.github/workflows/cuda.yml +++ b/.github/workflows/cuda.yml @@ -7,6 +7,7 @@ on: pull_request: paths-ignore: - "Docs/**" + - "**.rst" concurrency: group: ${{ github.ref }}-${{ github.head_ref }}-cuda diff --git a/.github/workflows/hip.yml b/.github/workflows/hip.yml index 6ab4e4a8401..f61c8fe1313 100644 --- a/.github/workflows/hip.yml +++ b/.github/workflows/hip.yml @@ -7,6 +7,7 @@ on: pull_request: paths-ignore: - "Docs/**" + - "**.rst" concurrency: group: ${{ github.ref }}-${{ github.head_ref }}-hip diff --git a/.github/workflows/insitu.yml b/.github/workflows/insitu.yml index 50b482d28d3..3d3942174a7 100644 --- a/.github/workflows/insitu.yml +++ b/.github/workflows/insitu.yml @@ -7,6 +7,7 @@ on: pull_request: paths-ignore: - "Docs/**" + - "**.rst" concurrency: group: ${{ github.ref }}-${{ github.head_ref }}-insituvis diff --git a/.github/workflows/intel.yml b/.github/workflows/intel.yml index 9b98c6e5990..25819e188e3 100644 --- a/.github/workflows/intel.yml +++ b/.github/workflows/intel.yml @@ -7,6 +7,7 @@ on: pull_request: paths-ignore: - "Docs/**" + - "**.rst" concurrency: group: ${{ github.ref }}-${{ github.head_ref }}-intel diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 0ddfcf38b41..87482cc6166 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -7,6 +7,7 @@ on: pull_request: paths-ignore: - "Docs/**" + - "**.rst" concurrency: group: ${{ github.ref }}-${{ github.head_ref }}-macos diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index bbe20679781..d657daf5793 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -7,6 +7,7 @@ on: pull_request: paths-ignore: - "Docs/**" + - "**.rst" concurrency: group: ${{ github.ref }}-${{ github.head_ref }}-ubuntu diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index ae4843e0536..7f964239a02 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -7,6 +7,7 @@ on: pull_request: paths-ignore: - "Docs/**" + - "**.rst" concurrency: group: ${{ github.ref }}-${{ github.head_ref }}-windows From 9fdc6ecab5462d21a17ae943e7f9e0f319daead5 Mon Sep 17 00:00:00 2001 From: Edoardo Zoni <59625522+EZoni@users.noreply.github.com> Date: Wed, 8 Jan 2025 09:31:47 -0800 Subject: [PATCH 10/23] Docs: fix bugs (broken links, missing examples) (#5522) Just fixing a few errors and warnings I found while working on another documentation PR. Mostly broken links and missing examples. Merge #5523 first, see https://github.com/ECP-WarpX/WarpX/pull/5522#issuecomment-2555975093 below. --- Docs/source/developers/checksum.rst | 5 ----- Docs/source/developers/fields.rst | 4 ++-- Docs/source/developers/particles.rst | 2 +- Docs/source/install/hpc/dane.rst | 6 +++--- Docs/source/install/hpc/lawrencium.rst | 2 +- Docs/source/refs.bib | 1 + Docs/source/theory/multiphysics/collisions.rst | 2 +- Docs/source/usage/examples.rst | 8 -------- Docs/source/usage/examples/thomson_parabola_spectrometer | 1 + .../thomson_parabola_spectrometer/README.rst | 2 +- 10 files changed, 11 insertions(+), 22 deletions(-) create mode 120000 Docs/source/usage/examples/thomson_parabola_spectrometer diff --git a/Docs/source/developers/checksum.rst b/Docs/source/developers/checksum.rst index ccbea3408ef..1e71ee3ddae 100644 --- a/Docs/source/developers/checksum.rst +++ b/Docs/source/developers/checksum.rst @@ -22,11 +22,6 @@ This relies on the function ``evaluate_checksum``: .. autofunction:: checksumAPI.evaluate_checksum -Here's an example: - -.. literalinclude:: ../../../Examples/Tests/embedded_circle/analysis.py - :language: python - This can also be included as part of an existing analysis script. How to evaluate checksums from the command line diff --git a/Docs/source/developers/fields.rst b/Docs/source/developers/fields.rst index bd6a886ae2a..ee782570bad 100644 --- a/Docs/source/developers/fields.rst +++ b/Docs/source/developers/fields.rst @@ -119,9 +119,9 @@ Bilinear filter The multi-pass bilinear filter (applied on the current density) is implemented in ``Source/Filter/``, and class ``WarpX`` holds an instance of this class in member variable ``WarpX::bilinear_filter``. For performance reasons (to avoid creating too many guard cells), this filter is directly applied in communication routines, see ``WarpX::AddCurrentFromFineLevelandSumBoundary`` above and -.. doxygenfunction:: WarpX::ApplyFilterMF(const amrex::Vector, 3>> &mfvec, int lev, int idim) +.. doxygenfunction:: WarpX::ApplyFilterMF(const ablastr::fields::MultiLevelVectorField &mfvec, int lev, int idim) -.. doxygenfunction:: WarpX::SumBoundaryJ(const amrex::Vector, 3>> ¤t, int lev, int idim, const amrex::Periodicity &period) +.. doxygenfunction:: WarpX::SumBoundaryJ(const ablastr::fields::MultiLevelVectorField ¤t, int lev, int idim, const amrex::Periodicity &period) Godfrey's anti-NCI filter for FDTD simulations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Docs/source/developers/particles.rst b/Docs/source/developers/particles.rst index 1f1e2eab606..45a92107ae9 100644 --- a/Docs/source/developers/particles.rst +++ b/Docs/source/developers/particles.rst @@ -83,7 +83,7 @@ Main functions .. doxygenfunction:: PhysicalParticleContainer::PushPX -.. doxygenfunction:: WarpXParticleContainer::DepositCurrent(amrex::Vector, 3>> &J, amrex::Real dt, amrex::Real relative_time) +.. doxygenfunction:: WarpXParticleContainer::DepositCurrent(ablastr::fields::MultiLevelVectorField const &J, amrex::Real dt, amrex::Real relative_time) .. note:: The current deposition is used both by ``PhysicalParticleContainer`` and ``LaserParticleContainer``, so it is in the parent class ``WarpXParticleContainer``. diff --git a/Docs/source/install/hpc/dane.rst b/Docs/source/install/hpc/dane.rst index 2e0efc99391..9c3c9077df5 100644 --- a/Docs/source/install/hpc/dane.rst +++ b/Docs/source/install/hpc/dane.rst @@ -3,7 +3,7 @@ Dane (LLNL) ============= -The `Dane Intel CPU cluster `_ is located at LLNL. +The `Dane Intel CPU cluster `__ is located at LLNL. Introduction @@ -11,9 +11,9 @@ Introduction If you are new to this system, **please see the following resources**: -* `LLNL user account `__ (login required) * `Jupyter service `__ (`documentation `__, login required) -* `Production directories `_: +* `Production directories `__: * ``/p/lustre1/$(whoami)`` and ``/p/lustre2/$(whoami)``: personal directory on the parallel filesystem * Note that the ``$HOME`` directory and the ``/usr/workspace/$(whoami)`` space are NFS mounted and *not* suitable for production quality data generation. diff --git a/Docs/source/install/hpc/lawrencium.rst b/Docs/source/install/hpc/lawrencium.rst index 2217c5a31ce..f163531a29a 100644 --- a/Docs/source/install/hpc/lawrencium.rst +++ b/Docs/source/install/hpc/lawrencium.rst @@ -69,7 +69,7 @@ And since Lawrencium does not yet provide a module for them, install ADIOS2, BLA cmake -S src/lapackpp -B src/lapackpp-v100-build -DCMAKE_CXX_STANDARD=17 -Dgpu_backend=cuda -Dbuild_tests=OFF -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON -DCMAKE_INSTALL_PREFIX=$HOME/sw/v100/lapackpp-master -Duse_cmake_find_lapack=ON -DBLAS_LIBRARIES=${LAPACK_DIR}/lib/libblas.a -DLAPACK_LIBRARIES=${LAPACK_DIR}/lib/liblapack.a cmake --build src/lapackpp-v100-build --target install --parallel 12 -Optionally, download and install Python packages for :ref:`PICMI ` or dynamic ensemble optimizations (:ref:`libEnsemble `): +Optionally, download and install Python packages for :ref:`PICMI ` or dynamic ensemble optimizations (`libEnsemble `__): .. code-block:: bash diff --git a/Docs/source/refs.bib b/Docs/source/refs.bib index 02251c433d5..d6c81c34404 100644 --- a/Docs/source/refs.bib +++ b/Docs/source/refs.bib @@ -458,6 +458,7 @@ @misc{Fallahi2020 @article{VayFELA2009, title = {FULL ELECTROMAGNETIC SIMULATION OF FREE-ELECTRON LASER AMPLIFIER PHYSICS VIA THE LORENTZ-BOOSTED FRAME APPROACH}, author = {Fawley, William M and Vay, Jean-Luc}, + journal = {}, abstractNote = {Numerical simulation of some systems containing charged particles with highly relativistic directed motion can by speeded up by orders of magnitude by choice of the proper Lorentz-boosted frame[1]. A particularly good example is that of short wavelength free-electron lasers (FELs) in which a high energy electron beam interacts with a static magnetic undulator. In the optimal boost frame with Lorentz factor gamma_F , the red-shifted FEL radiation and blue shifted undulator have identical wavelengths and the number of required time-steps (presuming the Courant condition applies) decreases by a factor of 2(gamma_F)**2 for fully electromagnetic simulation. We have adapted the WARP code [2]to apply this method to several FEL problems involving coherent spontaneous emission (CSE) from pre-bunched ebeams, including that in a biharmonic undulator.}, url = {https://www.osti.gov/biblio/964405}, place = {United States}, diff --git a/Docs/source/theory/multiphysics/collisions.rst b/Docs/source/theory/multiphysics/collisions.rst index 08485345a13..a2b11bf42a2 100644 --- a/Docs/source/theory/multiphysics/collisions.rst +++ b/Docs/source/theory/multiphysics/collisions.rst @@ -131,7 +131,7 @@ The process is also the same as for elastic scattering except the excitation ene Benchmarks ---------- -See the :ref:`MCC example ` for a benchmark of the MCC +See the :ref:`MCC example ` for a benchmark of the MCC implementation against literature results. Particle cooling due to elastic collisions diff --git a/Docs/source/usage/examples.rst b/Docs/source/usage/examples.rst index fa3e674edd3..4ac80a8bab0 100644 --- a/Docs/source/usage/examples.rst +++ b/Docs/source/usage/examples.rst @@ -65,14 +65,6 @@ Microelectronics * `ARTEMIS manual `__ -Nuclear Fusion --------------- - -.. note:: - - TODO - - Fundamental Plasma Physics -------------------------- diff --git a/Docs/source/usage/examples/thomson_parabola_spectrometer b/Docs/source/usage/examples/thomson_parabola_spectrometer new file mode 120000 index 00000000000..8e72fba4100 --- /dev/null +++ b/Docs/source/usage/examples/thomson_parabola_spectrometer @@ -0,0 +1 @@ +../../../../Examples/Physics_applications/thomson_parabola_spectrometer \ No newline at end of file diff --git a/Examples/Physics_applications/thomson_parabola_spectrometer/README.rst b/Examples/Physics_applications/thomson_parabola_spectrometer/README.rst index b033ee8c1dd..10009008714 100644 --- a/Examples/Physics_applications/thomson_parabola_spectrometer/README.rst +++ b/Examples/Physics_applications/thomson_parabola_spectrometer/README.rst @@ -28,7 +28,7 @@ The PICMI input file is not available for this example yet. For `MPI-parallel `__ runs, prefix these lines with ``mpiexec -n 4 ...`` or ``srun -n 4 ...``, depending on the system. -.. literalinclude:: inputs +.. literalinclude:: inputs_test_3d_thomson_parabola_spectrometer :language: ini :caption: You can copy this file from ``Examples/Physics_applications/thomson_parabola_spectrometer/inputs_test_3d_thomson_parabola_spectrometer``. From 499fcb07944cadd6d11358bac3de7142d23b590d Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 8 Jan 2025 11:52:56 -0800 Subject: [PATCH 11/23] Python 3.13 Support, 3.8 EOL (#5361) Add support for Python 3.13. Remove 3.8 because it is EOL as of Oct 2024. Bump to pybind11 2.13.0+, which add Python 3.13 support in CI. --- CMakeLists.txt | 2 +- Docs/source/developers/gnumake/python.rst | 2 +- Docs/source/install/dependencies.rst | 2 +- Python/setup.py | 2 +- cmake/dependencies/pybind11.cmake | 4 ++-- setup.py | 5 +++-- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c7a889633da..ff5d156fb8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -480,7 +480,7 @@ foreach(D IN LISTS WarpX_DIMS) warpx_enable_IPO(pyWarpX_${SD}) else() # conditionally defined target in pybind11 - # https://github.com/pybind/pybind11/blob/v2.12.0/tools/pybind11Common.cmake#L397-L403 + # https://github.com/pybind/pybind11/blob/v2.13.0/tools/pybind11Common.cmake#L407-L413 target_link_libraries(pyWarpX_${SD} PRIVATE pybind11::lto) endif() endif() diff --git a/Docs/source/developers/gnumake/python.rst b/Docs/source/developers/gnumake/python.rst index 543b80d5ddd..06dbd5ac737 100644 --- a/Docs/source/developers/gnumake/python.rst +++ b/Docs/source/developers/gnumake/python.rst @@ -3,7 +3,7 @@ Installing WarpX as a Python package ==================================== -A full Python installation of WarpX can be done, which includes a build of all of the C++ code, or a pure Python version can be made which only installs the Python scripts. WarpX requires Python version 3.8 or newer. +A full Python installation of WarpX can be done, which includes a build of all of the C++ code, or a pure Python version can be made which only installs the Python scripts. WarpX requires Python version 3.9 or newer. For a full Python installation of WarpX --------------------------------------- diff --git a/Docs/source/install/dependencies.rst b/Docs/source/install/dependencies.rst index 13e2377d568..200677807d7 100644 --- a/Docs/source/install/dependencies.rst +++ b/Docs/source/install/dependencies.rst @@ -37,7 +37,7 @@ Optional dependencies include: - `SENSEI 4.0.0+ `__: for in situ analysis and visualization - `CCache `__: to speed up rebuilds (For CUDA support, needs version 3.7.9+ and 4.2+ is recommended) - `Ninja `__: for faster parallel compiles -- `Python 3.8+ `__ +- `Python 3.9+ `__ - `mpi4py `__ - `numpy `__ diff --git a/Python/setup.py b/Python/setup.py index fa38e14e7ce..c119917631e 100644 --- a/Python/setup.py +++ b/Python/setup.py @@ -71,6 +71,6 @@ description="""Wrapper of WarpX""", package_data=package_data, install_requires=["numpy", "picmistandard==0.33.0", "periodictable"], - python_requires=">=3.8", + python_requires=">=3.8", # left for CI, truly ">=3.9" zip_safe=False, ) diff --git a/cmake/dependencies/pybind11.cmake b/cmake/dependencies/pybind11.cmake index 50b00013f7a..e90b56b2d38 100644 --- a/cmake/dependencies/pybind11.cmake +++ b/cmake/dependencies/pybind11.cmake @@ -37,7 +37,7 @@ function(find_pybind11) mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_FETCHEDpybind11) endif() else() - find_package(pybind11 2.12.0 CONFIG REQUIRED) + find_package(pybind11 2.13.0 CONFIG REQUIRED) message(STATUS "pybind11: Found version '${pybind11_VERSION}'") endif() endfunction() @@ -52,7 +52,7 @@ option(WarpX_pybind11_internal "Download & build pybind11" ON) set(WarpX_pybind11_repo "https://github.com/pybind/pybind11.git" CACHE STRING "Repository URI to pull and build pybind11 from if(WarpX_pybind11_internal)") -set(WarpX_pybind11_branch "v2.12.0" +set(WarpX_pybind11_branch "v2.13.6" CACHE STRING "Repository branch for WarpX_pybind11_repo if(WarpX_pybind11_internal)") diff --git a/setup.py b/setup.py index 0feb0a710d4..cb98d6371f5 100644 --- a/setup.py +++ b/setup.py @@ -307,7 +307,7 @@ def build_extension(self, ext): cmdclass=cmdclass, # scripts=['warpx_1d', 'warpx_2d', 'warpx_rz', 'warpx_3d'], zip_safe=False, - python_requires=">=3.8", + python_requires=">=3.8", # left for CI, truly ">=3.9" # tests_require=['pytest'], install_requires=install_requires, # see: src/bindings/python/cli @@ -336,10 +336,11 @@ def build_extension(self, ext): "Topic :: Scientific/Engineering :: Physics", "Programming Language :: C++", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ( "License :: OSI Approved :: " "BSD License" ), # TODO: use real SPDX: BSD-3-Clause-LBNL From a56ca8d91e359ce2bad970b7017813e83a51fb02 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 8 Jan 2025 21:52:47 -0800 Subject: [PATCH 12/23] Release 25.01 (#5544) Prepare the January release of WarpX: ```bash # update dependencies ./Tools/Release/updateAMReX.py ./Tools/Release/updatePICSAR.py # no changes, still 24.09 ./Tools/Release/updatepyAMReX.py # bump version number ./Tools/Release/newVersion.sh ``` Following this workflow: https://warpx.readthedocs.io/en/latest/maintenance/release.html --- .github/workflows/cuda.yml | 2 +- CMakeLists.txt | 2 +- Docs/source/conf.py | 4 +- Docs/source/maintenance/release.rst | 5 +- Python/setup.py | 2 +- Tools/Release/releasePR.py | 200 ++++++++++++++++++++++++++++ cmake/dependencies/AMReX.cmake | 4 +- cmake/dependencies/pyAMReX.cmake | 4 +- setup.py | 2 +- 9 files changed, 214 insertions(+), 11 deletions(-) create mode 100755 Tools/Release/releasePR.py diff --git a/.github/workflows/cuda.yml b/.github/workflows/cuda.yml index 404f53a3295..aa0daa2a718 100644 --- a/.github/workflows/cuda.yml +++ b/.github/workflows/cuda.yml @@ -127,7 +127,7 @@ jobs: which nvcc || echo "nvcc not in PATH!" git clone https://github.com/AMReX-Codes/amrex.git ../amrex - cd ../amrex && git checkout --detach b3f67385e62f387b548389222840486c0fffca57 && cd - + cd ../amrex && git checkout --detach 25.01 && cd - make COMP=gcc QED=FALSE USE_MPI=TRUE USE_GPU=TRUE USE_OMP=FALSE USE_FFT=TRUE USE_CCACHE=TRUE -j 4 ccache -s diff --git a/CMakeLists.txt b/CMakeLists.txt index ff5d156fb8a..90771cbbb29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Preamble #################################################################### # cmake_minimum_required(VERSION 3.24.0) -project(WarpX VERSION 24.12) +project(WarpX VERSION 25.01) include(${WarpX_SOURCE_DIR}/cmake/WarpXFunctions.cmake) diff --git a/Docs/source/conf.py b/Docs/source/conf.py index e54a6cc23ba..247e11faa4f 100644 --- a/Docs/source/conf.py +++ b/Docs/source/conf.py @@ -107,9 +107,9 @@ def __init__(self, *args, **kwargs): # built documents. # # The short X.Y version. -version = "24.12" +version = "25.01" # The full version, including alpha/beta/rc tags. -release = "24.12" +release = "25.01" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/Docs/source/maintenance/release.rst b/Docs/source/maintenance/release.rst index f25b8c313e4..9c6dbcc3f82 100644 --- a/Docs/source/maintenance/release.rst +++ b/Docs/source/maintenance/release.rst @@ -28,7 +28,7 @@ In order to create a GitHub release, you need to: 1. Create a new branch from ``development`` and update the version number in all source files. We usually wait for the AMReX release to be tagged first, then we also point to its tag. - There is a script for updating core dependencies of WarpX and the WarpX version: + There are scripts for updating core dependencies of WarpX and the WarpX version: .. code-block:: sh @@ -42,6 +42,9 @@ In order to create a GitHub release, you need to: Then open a PR, wait for tests to pass and then merge. + The maintainer script ``Tools/Release/releasePR.py`` automates the steps above. + Please read through the instructions in the script before running. + 2. **Local Commit** (Optional): at the moment, ``@ax3l`` is managing releases and signs tags (naming: ``YY.MM``) locally with his GPG key before uploading them to GitHub. **Publish**: On the `GitHub Release page `__, create a new release via ``Draft a new release``. diff --git a/Python/setup.py b/Python/setup.py index c119917631e..a50b467c070 100644 --- a/Python/setup.py +++ b/Python/setup.py @@ -65,7 +65,7 @@ setup( name="pywarpx", - version="24.12", + version="25.01", packages=["pywarpx"], package_dir={"pywarpx": "pywarpx"}, description="""Wrapper of WarpX""", diff --git a/Tools/Release/releasePR.py b/Tools/Release/releasePR.py new file mode 100755 index 00000000000..3fd1b016efd --- /dev/null +++ b/Tools/Release/releasePR.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python3 +# +# Copyright 2025 The WarpX Community +# +# This file is part of WarpX. +# +# Authors: Axel Huebl +# + +# This file is a maintainer tool to open a release PR for WarpX. +# It is highly automated and does a few assumptions, e.g., that you +# are releasing for the current month. +# +# You also need to have git and the GitHub CLI tool "gh" installed and properly +# configured for it to work: +# https://cli.github.com/ +# +import subprocess +import sys +from datetime import datetime +from pathlib import Path + +# Maintainer Inputs ########################################################### + +print("""Hi there, this is a WarpX maintainer tool to ...\n. +For it to work, you need write access on the source directory and +you should be working in a clean git branch without ongoing +rebase/merge/conflict resolves and without unstaged changes.""") + +# check source dir +REPO_DIR = Path(__file__).parent.parent.parent.absolute() +print(f"\nYour current source directory is: {REPO_DIR}") + +REPLY = input("Are you sure you want to continue? [y/N] ") +print() +if REPLY not in ["Y", "y"]: + print("You did not confirm with 'y', aborting.") + sys.exit(1) + +release_repo = input("What is the name of your git remote? (e.g., ax3l) ") +commit_sign = input("How to sign the commit? (e.g., -sS) ") + + +# Helpers ##################################################################### + + +def concat_answers(answers): + return "\n".join(answers) + "\n" + + +# Stash current work ########################################################## + +subprocess.run(["git", "stash"], capture_output=True, text=True) + + +# Git Branch ################################################################## + +WarpX_version_yr = f"{datetime.now().strftime('%y')}" +WarpX_version_mn = f"{datetime.now().strftime('%m')}" +WarpX_version = f"{WarpX_version_yr}.{WarpX_version_mn}" +release_branch = f"release-{WarpX_version}" +subprocess.run(["git", "checkout", "development"], capture_output=True, text=True) +subprocess.run(["git", "fetch"], capture_output=True, text=True) +subprocess.run(["git", "pull", "--ff-only"], capture_output=True, text=True) +subprocess.run(["git", "branch", "-D", release_branch], capture_output=True, text=True) +subprocess.run( + ["git", "checkout", "-b", release_branch], capture_output=True, text=True +) + + +# AMReX New Version ########################################################### + +AMReX_version = f"{datetime.now().strftime('%y')}.{datetime.now().strftime('%m')}" +answers = concat_answers(["y", AMReX_version, AMReX_version, "y"]) + +process = subprocess.Popen( + [Path(REPO_DIR).joinpath("Tools/Release/updateAMReX.py")], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, +) + +process.communicate(answers) +del process + +# commit +subprocess.run(["git", "add", "-u"], capture_output=True, text=True) +subprocess.run( + ["git", "commit", commit_sign, "-m", f"AMReX: {AMReX_version}"], text=True +) + + +# PICSAR New Version ########################################################## + +PICSAR_version = "24.09" +answers = concat_answers(["y", PICSAR_version, PICSAR_version, "y"]) + +process = subprocess.Popen( + [Path(REPO_DIR).joinpath("Tools/Release/updatePICSAR.py")], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, +) + +process.communicate(answers) +del process + +# commit +subprocess.run(["git", "add", "-u"], capture_output=True, text=True) +subprocess.run( + ["git", "commit", commit_sign, "-m", f"PICSAR: {PICSAR_version}"], text=True +) + + +# pyAMReX New Version ######################################################### + +pyAMReX_version = f"{datetime.now().strftime('%y')}.{datetime.now().strftime('%m')}" +answers = concat_answers(["y", pyAMReX_version, pyAMReX_version, "y"]) + +process = subprocess.Popen( + [Path(REPO_DIR).joinpath("Tools/Release/updatepyAMReX.py")], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, +) + +process.communicate(answers) +del process + +# commit +subprocess.run(["git", "add", "-u"], capture_output=True, text=True) +subprocess.run( + ["git", "commit", commit_sign, "-m", f"pyAMReX: {pyAMReX_version}"], text=True +) + + +# WarpX New Version ########################################################### + +answers = concat_answers(["y", WarpX_version_yr, WarpX_version_mn, "", "", "y"]) + +process = subprocess.Popen( + [Path(REPO_DIR).joinpath("Tools/Release/newVersion.sh")], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, +) + +process.communicate(answers) +del process + +# commit +subprocess.run(["git", "add", "-u"], capture_output=True, text=True) +subprocess.run( + ["git", "commit", commit_sign, "-m", f"WarpX: {WarpX_version}"], text=True +) + + +# GitHub PR ################################################################### + +subprocess.run(["git", "push", "-u", release_repo, release_branch], text=True) + +subprocess.run( + [ + "gh", + "pr", + "create", + "--title", + f"Release {WarpX_version}", + "--body", + f"""Prepare the {datetime.now().strftime('%B')} release of WarpX: +```bash +# update dependencies +./Tools/Release/updateAMReX.py +./Tools/Release/updatePICSAR.py # no changes, still {PICSAR_version} +./Tools/Release/updatepyAMReX.py +# bump version number +./Tools/Release/newVersion.sh +``` + +Following this workflow: https://warpx.readthedocs.io/en/latest/maintenance/release.html +""", + "--label", + "component: documentation", + "--label", + "component: third party", + "--web", + ], + text=True, +) + + +# Epilogue #################################################################### + +print("""Done. Please check your source, e.g. via + git diff +now and commit the changes if no errors occurred.""") diff --git a/cmake/dependencies/AMReX.cmake b/cmake/dependencies/AMReX.cmake index 0066a3103cd..88df1f82fe8 100644 --- a/cmake/dependencies/AMReX.cmake +++ b/cmake/dependencies/AMReX.cmake @@ -271,7 +271,7 @@ macro(find_amrex) endif() set(COMPONENT_PRECISION ${WarpX_PRECISION} P${WarpX_PARTICLE_PRECISION}) - find_package(AMReX 24.12 CONFIG REQUIRED COMPONENTS ${COMPONENT_ASCENT} ${COMPONENT_CATALYST} ${COMPONENT_DIMS} ${COMPONENT_EB} ${COMPONENT_FFT} PARTICLES ${COMPONENT_PIC} ${COMPONENT_PRECISION} ${COMPONENT_SENSEI} LSOLVERS) + find_package(AMReX 25.01 CONFIG REQUIRED COMPONENTS ${COMPONENT_ASCENT} ${COMPONENT_CATALYST} ${COMPONENT_DIMS} ${COMPONENT_EB} ${COMPONENT_FFT} PARTICLES ${COMPONENT_PIC} ${COMPONENT_PRECISION} ${COMPONENT_SENSEI} LSOLVERS) # note: TINYP skipped because user-configured and optional # AMReX CMake helper scripts @@ -294,7 +294,7 @@ set(WarpX_amrex_src "" set(WarpX_amrex_repo "https://github.com/AMReX-Codes/amrex.git" CACHE STRING "Repository URI to pull and build AMReX from if(WarpX_amrex_internal)") -set(WarpX_amrex_branch "b3f67385e62f387b548389222840486c0fffca57" +set(WarpX_amrex_branch "25.01" CACHE STRING "Repository branch for WarpX_amrex_repo if(WarpX_amrex_internal)") diff --git a/cmake/dependencies/pyAMReX.cmake b/cmake/dependencies/pyAMReX.cmake index 93c4cc63e5a..777b75e2ed3 100644 --- a/cmake/dependencies/pyAMReX.cmake +++ b/cmake/dependencies/pyAMReX.cmake @@ -59,7 +59,7 @@ function(find_pyamrex) endif() elseif(NOT WarpX_pyamrex_internal) # TODO: MPI control - find_package(pyAMReX 24.12 CONFIG REQUIRED) + find_package(pyAMReX 25.01 CONFIG REQUIRED) message(STATUS "pyAMReX: Found version '${pyAMReX_VERSION}'") endif() endfunction() @@ -74,7 +74,7 @@ option(WarpX_pyamrex_internal "Download & build pyAMReX" ON) set(WarpX_pyamrex_repo "https://github.com/AMReX-Codes/pyamrex.git" CACHE STRING "Repository URI to pull and build pyamrex from if(WarpX_pyamrex_internal)") -set(WarpX_pyamrex_branch "cba1ca5098fd4edc83b2ae630c0391140fac55f4" +set(WarpX_pyamrex_branch "25.01" CACHE STRING "Repository branch for WarpX_pyamrex_repo if(WarpX_pyamrex_internal)") diff --git a/setup.py b/setup.py index cb98d6371f5..c3f2e730726 100644 --- a/setup.py +++ b/setup.py @@ -280,7 +280,7 @@ def build_extension(self, ext): setup( name="pywarpx", # note PEP-440 syntax: x.y.zaN but x.y.z.devN - version="24.12", + version="25.01", packages=["pywarpx"], package_dir={"pywarpx": "Python/pywarpx"}, author="Jean-Luc Vay, David P. Grote, Maxence Thévenet, Rémi Lehe, Andrew Myers, Weiqun Zhang, Axel Huebl, et al.", From 09ab371649e35fd8f17c2f1c6f59613e035c5d5b Mon Sep 17 00:00:00 2001 From: Luca Fedeli Date: Thu, 9 Jan 2025 18:52:19 +0100 Subject: [PATCH 13/23] Make `do_subcycling` a private variable of the WarpX class (#5546) This PR makes `do_subcycling` (renamed `m_do_subcycling`) a private member variable of the `WarpX` class. This is part of the effort towards making WarpX class less static. --- Source/Evolve/WarpXComputeDt.cpp | 2 +- Source/Evolve/WarpXEvolve.cpp | 6 +++--- Source/Initialization/WarpXInitData.cpp | 2 +- Source/WarpX.H | 4 +++- Source/WarpX.cpp | 11 +++++------ 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Source/Evolve/WarpXComputeDt.cpp b/Source/Evolve/WarpXComputeDt.cpp index b82cb6aff26..9645f7edbe2 100644 --- a/Source/Evolve/WarpXComputeDt.cpp +++ b/Source/Evolve/WarpXComputeDt.cpp @@ -94,7 +94,7 @@ WarpX::ComputeDt () dt.resize(0); dt.resize(max_level+1,deltat); - if (do_subcycling) { + if (m_do_subcycling) { for (int lev = max_level-1; lev >= 0; --lev) { dt[lev] = dt[lev+1] * refRatio(lev)[0]; } diff --git a/Source/Evolve/WarpXEvolve.cpp b/Source/Evolve/WarpXEvolve.cpp index 163138ca572..c9e363879a6 100644 --- a/Source/Evolve/WarpXEvolve.cpp +++ b/Source/Evolve/WarpXEvolve.cpp @@ -187,7 +187,7 @@ WarpX::Evolve (int numsteps) OneStep_multiJ(cur_time); } // Electromagnetic case: no subcycling or no mesh refinement - else if ( !do_subcycling || (finest_level == 0)) + else if ( !m_do_subcycling || (finest_level == 0)) { OneStep_nosub(cur_time); // E: guard cells are up-to-date @@ -195,14 +195,14 @@ WarpX::Evolve (int numsteps) // F: guard cells are NOT up-to-date } // Electromagnetic case: subcycling with one level of mesh refinement - else if (do_subcycling && (finest_level == 1)) + else if (m_do_subcycling && (finest_level == 1)) { OneStep_sub1(cur_time); } else { WARPX_ABORT_WITH_MESSAGE( - "do_subcycling = " + std::to_string(do_subcycling) + "do_subcycling = " + std::to_string(m_do_subcycling) + " is an unsupported do_subcycling type."); } diff --git a/Source/Initialization/WarpXInitData.cpp b/Source/Initialization/WarpXInitData.cpp index daecfac8bed..71c773c0669 100644 --- a/Source/Initialization/WarpXInitData.cpp +++ b/Source/Initialization/WarpXInitData.cpp @@ -850,7 +850,7 @@ WarpX::computeMaxStepBoostAccelerator() { const Real interaction_time_boost = (len_plasma_boost-zmin_domain_boost_step_0)/ (moving_window_v-v_plasma_boost); // Divide by dt, and update value of max_step. - const auto computed_max_step = (do_subcycling)? + const auto computed_max_step = (m_do_subcycling)? static_cast(interaction_time_boost/dt[0]): static_cast(interaction_time_boost/dt[maxLevel()]); max_step = computed_max_step; diff --git a/Source/WarpX.H b/Source/WarpX.H index 56d4f879de8..2c949cb514a 100644 --- a/Source/WarpX.H +++ b/Source/WarpX.H @@ -391,7 +391,6 @@ public: //! Specifies the type of grid used for the above sorting, i.e. cell-centered, nodal, or mixed static amrex::IntVect sort_idx_type; - static bool do_subcycling; static bool do_multi_J; static int do_multi_J_n_depositions; @@ -1454,6 +1453,9 @@ private: std::optional m_const_dt; std::optional m_max_dt; + // whether to use subcycling + bool m_do_subcycling = false; + // Macroscopic properties std::unique_ptr m_macroscopic_properties; diff --git a/Source/WarpX.cpp b/Source/WarpX.cpp index 75aa964da3a..3f53decbb83 100644 --- a/Source/WarpX.cpp +++ b/Source/WarpX.cpp @@ -179,7 +179,6 @@ amrex::IntVect WarpX::sort_idx_type(AMREX_D_DECL(0,0,0)); bool WarpX::do_dynamic_scheduling = true; -bool WarpX::do_subcycling = false; bool WarpX::do_multi_J = false; int WarpX::do_multi_J_n_depositions; bool WarpX::safe_guard_cells = false; @@ -448,7 +447,7 @@ WarpX::WarpX () // (e.g., use_fdtd_nci_corr) if (WarpX::electromagnetic_solver_id == ElectromagneticSolverAlgo::PSATD) { AMREX_ALWAYS_ASSERT(use_fdtd_nci_corr == 0); - AMREX_ALWAYS_ASSERT(do_subcycling == 0); + AMREX_ALWAYS_ASSERT(m_do_subcycling == 0); } if (WarpX::current_deposition_algo != CurrentDepositionAlgo::Esirkepov) { @@ -622,7 +621,7 @@ WarpX::ReadParameters () utils::parser::queryWithParser(pp_warpx, "cfl", cfl); pp_warpx.query("verbose", verbose); utils::parser::queryWithParser(pp_warpx, "regrid_int", regrid_int); - pp_warpx.query("do_subcycling", do_subcycling); + pp_warpx.query("do_subcycling", m_do_subcycling); pp_warpx.query("do_multi_J", do_multi_J); if (do_multi_J) { @@ -636,7 +635,7 @@ WarpX::ReadParameters () override_sync_intervals = utils::parser::IntervalsParser(override_sync_intervals_string_vec); - WARPX_ALWAYS_ASSERT_WITH_MESSAGE(do_subcycling != 1 || max_level <= 1, + WARPX_ALWAYS_ASSERT_WITH_MESSAGE(m_do_subcycling != 1 || max_level <= 1, "Subcycling method 1 only works for 2 levels."); ReadBoostedFrameParameters(gamma_boost, beta_boost, boost_direction); @@ -2045,7 +2044,7 @@ WarpX::AllocLevelData (int lev, const BoxArray& ba, const DistributionMapping& d guard_cells.Init( dt[lev], dx, - do_subcycling, + m_do_subcycling, WarpX::use_fdtd_nci_corr, grid_type, do_moving_window, @@ -2408,7 +2407,7 @@ WarpX::AllocLevelMFs (int lev, const BoxArray& ba, const DistributionMapping& dm ncomps, ngPhi, 0.0_rt ); } - if (do_subcycling && lev == 0) + if (m_do_subcycling && lev == 0) { m_fields.alloc_init(FieldType::current_store, Direction{0}, lev, amrex::convert(ba,jx_nodal_flag), dm, ncomps, ngJ, 0.0_rt); m_fields.alloc_init(FieldType::current_store, Direction{1}, lev, amrex::convert(ba,jy_nodal_flag), dm, ncomps, ngJ, 0.0_rt); From 17b0c3d1667493f724e3923c3acadd0c47bf08e5 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Thu, 9 Jan 2025 13:53:04 -0800 Subject: [PATCH 14/23] CMake: ABLASTR FFT AMReX (#5548) Complete the control for AMReX_FFT through pure ABLASTR super-builds. --- cmake/dependencies/AMReX.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/dependencies/AMReX.cmake b/cmake/dependencies/AMReX.cmake index 88df1f82fe8..82d56d98a5f 100644 --- a/cmake/dependencies/AMReX.cmake +++ b/cmake/dependencies/AMReX.cmake @@ -51,7 +51,7 @@ macro(find_amrex) set(AMReX_OMP OFF CACHE INTERNAL "") endif() - if(WarpX_FFT) + if(WarpX_FFT OR ABLASTR_FFT) set(AMReX_FFT ON CACHE INTERNAL "") else() set(AMReX_FFT OFF CACHE INTERNAL "") From 16347e6f9aaa95fc28211c21ece913e2d0b7e0a1 Mon Sep 17 00:00:00 2001 From: Revathi Jambunathan <41089244+RevathiJambunathan@users.noreply.github.com> Date: Fri, 10 Jan 2025 00:04:40 -0800 Subject: [PATCH 15/23] python callback at restart (#5549) This PR adds a python callback option after initialization at restart, enabling users to read user-defined checkpoint vars that could be written using the python call afterdiagnostics that already exists --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- Python/pywarpx/callbacks.py | 11 +++++++++++ Source/Initialization/WarpXInitData.cpp | 3 +++ 2 files changed, 14 insertions(+) diff --git a/Python/pywarpx/callbacks.py b/Python/pywarpx/callbacks.py index 45c9b63a082..d12293e699b 100644 --- a/Python/pywarpx/callbacks.py +++ b/Python/pywarpx/callbacks.py @@ -280,6 +280,7 @@ def callfuncsinlist(self, *args, **kw): "loadExternalFields": {}, "beforeInitEsolve": {}, "afterInitEsolve": {}, + "afterInitatRestart": {}, "afterinit": {}, "beforecollisions": {}, "aftercollisions": {}, @@ -406,6 +407,16 @@ def installafterInitEsolve(f): installcallback("afterInitEsolve", f) +# ---------------------------------------------------------------------------- +def callfromafterInitatRestart(f): + installcallback("afterInitatRestart", f) + return f + + +def installafterInitatRestart(f): + installcallback("afterInitatRestart", f) + + # ---------------------------------------------------------------------------- def callfromafterinit(f): installcallback("afterinit", f) diff --git a/Source/Initialization/WarpXInitData.cpp b/Source/Initialization/WarpXInitData.cpp index 71c773c0669..5de8912be6a 100644 --- a/Source/Initialization/WarpXInitData.cpp +++ b/Source/Initialization/WarpXInitData.cpp @@ -610,6 +610,9 @@ WarpX::InitData () AddExternalFields(lev); } } + else { + ExecutePythonCallback("afterInitatRestart"); + } if (restart_chkfile.empty() || write_diagnostics_on_restart) { // Write full diagnostics before the first iteration. From 555f4351a0c53b2b36ebdce641d8f3c52c71c509 Mon Sep 17 00:00:00 2001 From: Thomas Marks Date: Fri, 10 Jan 2025 19:42:58 -0500 Subject: [PATCH 16/23] Python: useful error when `initialize_warpx` not called before creating `ParticleContainerWrapper` (#5412) Currently, WarpX is initialized when `sim.step` is called, or when the user calls `initialize_warpx`. However, if the user tries to create a `ParticleContainerWrapper` before this point, they get an error along the following lines: ``` File "/home/marksta/projects/warpx-ionization/picmi.py", line 185, in sim.run() File "/home/marksta/projects/warpx-ionization/picmi.py", line 179, in run self.elec_wrapper = particle_containers.ParticleContainerWrapper(self.electrons.name) File "/home/marksta/.local/lib/python3.10/site-packages/pywarpx/particle_containers.py", line 29, in __init__ mypc = libwarpx.warpx.multi_particle_container() File "/home/marksta/.local/lib/python3.10/site-packages/pywarpx/_libwarpx.py", line 46, in __getattr__ return self.__getattribute__(attribute) AttributeError: 'LibWarpX' object has no attribute 'warpx' ``` This is confusing. When I got this, I assumed I had maybe installed WarpX wrong. I added a catch for this exception that re-raises it with some additional context that should help direct the user to call `initialize_warpx` --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- Python/pywarpx/particle_containers.py | 30 +++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Python/pywarpx/particle_containers.py b/Python/pywarpx/particle_containers.py index bc6b2d74106..db5dfda883e 100644 --- a/Python/pywarpx/particle_containers.py +++ b/Python/pywarpx/particle_containers.py @@ -24,10 +24,21 @@ class ParticleContainerWrapper(object): def __init__(self, species_name): self.name = species_name + self._particle_container = None + + @property + def particle_container(self): + if self._particle_container is None: + try: + mypc = libwarpx.warpx.multi_particle_container() + self._particle_container = mypc.get_particle_container_from_name( + self.name + ) + except AttributeError as e: + msg = "This is likely caused by attempting to access a ParticleContainerWrapper before initialize_warpx has been called" + raise AttributeError(msg) from e - # grab the desired particle container - mypc = libwarpx.warpx.multi_particle_container() - self.particle_container = mypc.get_particle_container_from_name(self.name) + return self._particle_container def add_particles( self, @@ -758,7 +769,18 @@ class ParticleBoundaryBufferWrapper(object): """ def __init__(self): - self.particle_buffer = libwarpx.warpx.get_particle_boundary_buffer() + self._particle_buffer = None + + @property + def particle_buffer(self): + if self._particle_buffer is None: + try: + self._particle_buffer = libwarpx.warpx.get_particle_boundary_buffer() + except AttributeError as e: + msg = "This is likely caused by attempting to access a ParticleBoundaryBufferWrapper before initialize_warpx has been called" + raise AttributeError(msg) from e + + return self._particle_buffer def get_particle_boundary_buffer_size(self, species_name, boundary, local=False): """ From 2ec6c1364986718c239a6cfe8a2b5ed313c70d88 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 00:58:14 +0000 Subject: [PATCH 17/23] [pre-commit.ci] pre-commit autoupdate (#5553) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.6 → v0.9.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.6...v0.9.1) --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- .../ml_materials/run_warpx_training.py | 2 +- .../usage/workflows/ml_materials/train.py | 2 +- .../inputs_base_1d_picmi.py | 2 +- .../laser_acceleration/analysis_openpmd_rz.py | 24 +++++----- .../Physics_applications/laser_ion/plot_2d.py | 4 +- .../spacecraft_charging/analysis.py | 6 +-- .../Tests/accelerator_lattice/analysis.py | 6 ++- Examples/Tests/boundaries/analysis.py | 12 ++--- .../analysis.py | 2 +- ...effective_potential_electrostatic_picmi.py | 6 +-- ...test_2d_ohm_solver_landau_damping_picmi.py | 2 +- ...nputs_test_1d_ohm_solver_ion_beam_picmi.py | 2 +- ..._ohm_solver_magnetic_reconnection_picmi.py | 14 +++--- .../particle_boundary_interaction/analysis.py | 6 +-- .../Tests/pass_mpi_communicator/analysis.py | 6 +-- Examples/Tests/plasma_lens/analysis.py | 12 +++-- Python/pywarpx/fields.py | 4 +- Python/pywarpx/particle_containers.py | 48 +++++++++---------- Python/pywarpx/picmi.py | 16 +++---- Regression/Checksum/checksum.py | 3 +- .../post_processing_utils.py | 2 +- Tools/Algorithms/psatd.ipynb | 6 +-- Tools/Algorithms/stencil.py | 4 +- Tools/Release/releasePR.py | 2 +- setup.py | 2 +- 26 files changed, 100 insertions(+), 97 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c07ad07f74a..9279bcd038d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -69,7 +69,7 @@ repos: # Python: Ruff linter & formatter # https://docs.astral.sh/ruff/ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.6 + rev: v0.9.1 hooks: # Run the linter - id: ruff diff --git a/Docs/source/usage/workflows/ml_materials/run_warpx_training.py b/Docs/source/usage/workflows/ml_materials/run_warpx_training.py index 9e6b5682ec7..9a246de1cc2 100644 --- a/Docs/source/usage/workflows/ml_materials/run_warpx_training.py +++ b/Docs/source/usage/workflows/ml_materials/run_warpx_training.py @@ -260,7 +260,7 @@ def get_laser(antenna_z, profile_t_peak, fill_in=True): diag_particle_list = ["weighting", "position", "momentum"] coarse_btd_end = int((L_plasma_bulk + 0.001 + stage_spacing * (N_stage - 1)) * 100000) stage_end_snapshots = [ - f"{int((L_plasma_bulk+stage_spacing*ii)*100000)}:{int((L_plasma_bulk+stage_spacing*ii)*100000+50)}:5" + f"{int((L_plasma_bulk + stage_spacing * ii) * 100000)}:{int((L_plasma_bulk + stage_spacing * ii) * 100000 + 50)}:5" for ii in range(1) ] btd_particle_diag = picmi.LabFrameParticleDiagnostic( diff --git a/Docs/source/usage/workflows/ml_materials/train.py b/Docs/source/usage/workflows/ml_materials/train.py index 957a652e0c4..35b02c5cd44 100644 --- a/Docs/source/usage/workflows/ml_materials/train.py +++ b/Docs/source/usage/workflows/ml_materials/train.py @@ -180,7 +180,7 @@ def test_dataset(model, test_source, test_target, loss_fun): ) # Manual: Training loop END t4 = time.time() -print(f"total training time: {t4-t3:.3f}s") +print(f"total training time: {t4 - t3:.3f}s") ######### save model ######### diff --git a/Examples/Physics_applications/capacitive_discharge/inputs_base_1d_picmi.py b/Examples/Physics_applications/capacitive_discharge/inputs_base_1d_picmi.py index 3de88f3b3cb..a03cf1954ad 100644 --- a/Examples/Physics_applications/capacitive_discharge/inputs_base_1d_picmi.py +++ b/Examples/Physics_applications/capacitive_discharge/inputs_base_1d_picmi.py @@ -423,7 +423,7 @@ def run_sim(self): assert hasattr(self.solver, "phi") if libwarpx.amr.ParallelDescriptor.MyProc() == 0: - np.save(f"ion_density_case_{self.n+1}.npy", self.ion_density_array) + np.save(f"ion_density_case_{self.n + 1}.npy", self.ion_density_array) # query the particle z-coordinates if this is run during CI testing # to cover that functionality diff --git a/Examples/Physics_applications/laser_acceleration/analysis_openpmd_rz.py b/Examples/Physics_applications/laser_acceleration/analysis_openpmd_rz.py index f136ffeb1d4..1449e54d8ee 100755 --- a/Examples/Physics_applications/laser_acceleration/analysis_openpmd_rz.py +++ b/Examples/Physics_applications/laser_acceleration/analysis_openpmd_rz.py @@ -20,15 +20,15 @@ # this is in C (Python) order; r is the fastest varying index (Nm, Nz, Nr) = jt.shape -assert ( - Nm == 3 -), "Wrong number of angular modes stored or possible incorrect ordering when flushed" -assert ( - Nr == 64 -), "Wrong number of radial points stored or possible incorrect ordering when flushed" -assert ( - Nz == 512 -), "Wrong number of z points stored or possible incorrect ordering when flushed" +assert Nm == 3, ( + "Wrong number of angular modes stored or possible incorrect ordering when flushed" +) +assert Nr == 64, ( + "Wrong number of radial points stored or possible incorrect ordering when flushed" +) +assert Nz == 512, ( + "Wrong number of z points stored or possible incorrect ordering when flushed" +) assert ii.meshes["part_per_grid"][io.Mesh_Record_Component.SCALAR].shape == [ 512, @@ -60,6 +60,6 @@ electron_meanz = np.sum(np.dot(zlist, rhoe0)) / np.sum(rhoe0) beam_meanz = np.sum(np.dot(zlist, rhob0)) / np.sum(rhob0) -assert ( - (electron_meanz > 0) and (beam_meanz < 0) -), "problem with openPMD+RZ. Maybe openPMD+RZ mixed up the order of rho_ diagnostics?" +assert (electron_meanz > 0) and (beam_meanz < 0), ( + "problem with openPMD+RZ. Maybe openPMD+RZ mixed up the order of rho_ diagnostics?" +) diff --git a/Examples/Physics_applications/laser_ion/plot_2d.py b/Examples/Physics_applications/laser_ion/plot_2d.py index b3aefb80606..87b2d76c8f7 100644 --- a/Examples/Physics_applications/laser_ion/plot_2d.py +++ b/Examples/Physics_applications/laser_ion/plot_2d.py @@ -120,7 +120,7 @@ def visualize_density_iteration(ts, iteration, out_dir): for ax in axs[:-1]: ax.set_xticklabels([]) axs[2].set_xlabel(r"$z$ ($\mu$m)") - fig.suptitle(f"Iteration: {it}, Time: {time/1e-15:.1f} fs") + fig.suptitle(f"Iteration: {it}, Time: {time / 1e-15:.1f} fs") plt.tight_layout() @@ -190,7 +190,7 @@ def visualize_field_iteration(ts, iteration, out_dir): for ax in axs[:-1]: ax.set_xticklabels([]) axs[2].set_xlabel(r"$z$ ($\mu$m)") - fig.suptitle(f"Iteration: {it}, Time: {time/1e-15:.1f} fs") + fig.suptitle(f"Iteration: {it}, Time: {time / 1e-15:.1f} fs") plt.tight_layout() diff --git a/Examples/Physics_applications/spacecraft_charging/analysis.py b/Examples/Physics_applications/spacecraft_charging/analysis.py index 8e13657b62e..9e4b9e8219f 100755 --- a/Examples/Physics_applications/spacecraft_charging/analysis.py +++ b/Examples/Physics_applications/spacecraft_charging/analysis.py @@ -68,6 +68,6 @@ def func(x, v0, tau): print("percentage error for v0 = " + str(diff_v0 * 100) + "%") print("percentage error for tau = " + str(diff_tau * 100) + "%") -assert (diff_v0 < tolerance_v0) and ( - diff_tau < tolerance_tau -), "Test spacecraft_charging did not pass" +assert (diff_v0 < tolerance_v0) and (diff_tau < tolerance_tau), ( + "Test spacecraft_charging did not pass" +) diff --git a/Examples/Tests/accelerator_lattice/analysis.py b/Examples/Tests/accelerator_lattice/analysis.py index f53d54cbe12..331c5322e03 100755 --- a/Examples/Tests/accelerator_lattice/analysis.py +++ b/Examples/Tests/accelerator_lattice/analysis.py @@ -118,9 +118,11 @@ def applylens(x0, vx0, vz0, gamma, lens_length, lens_strength): xx = xx + dt * vx # Compare the analytic to the simulated final values -print(f"Error in x position is {abs(np.abs((xx - xx_sim)/xx))}, which should be < 0.01") print( - f"Error in x velocity is {abs(np.abs((ux - ux_sim)/ux))}, which should be < 0.002" + f"Error in x position is {abs(np.abs((xx - xx_sim) / xx))}, which should be < 0.01" +) +print( + f"Error in x velocity is {abs(np.abs((ux - ux_sim) / ux))}, which should be < 0.002" ) assert abs(np.abs((xx - xx_sim) / xx)) < 0.01, Exception("error in x particle position") diff --git a/Examples/Tests/boundaries/analysis.py b/Examples/Tests/boundaries/analysis.py index 9630c07d0ab..29de2bb37cb 100755 --- a/Examples/Tests/boundaries/analysis.py +++ b/Examples/Tests/boundaries/analysis.py @@ -101,9 +101,9 @@ def do_periodic(x): assert len(a_id) == 1, "Absorbing particles not absorbed" assert np.all(vx == -vx0), "Reflecting particle velocity not correct" assert np.all(vz == +vz0), "Periodic particle velocity not correct" -assert np.all( - np.abs((xx - xxa) / xx) < 1.0e-15 -), "Reflecting particle position not correct" -assert np.all( - np.abs((zz - zza) / zz) < 1.0e-15 -), "Periodic particle position not correct" +assert np.all(np.abs((xx - xxa) / xx) < 1.0e-15), ( + "Reflecting particle position not correct" +) +assert np.all(np.abs((zz - zza) / zz) < 1.0e-15), ( + "Periodic particle position not correct" +) diff --git a/Examples/Tests/effective_potential_electrostatic/analysis.py b/Examples/Tests/effective_potential_electrostatic/analysis.py index b51cd129252..20998e0a066 100755 --- a/Examples/Tests/effective_potential_electrostatic/analysis.py +++ b/Examples/Tests/effective_potential_electrostatic/analysis.py @@ -66,7 +66,7 @@ def get_radial_function(field, info): ) plt.plot(r_grid, n_e_analytic, "k--", alpha=0.6) - plt.plot(r_grid, n_e, label=f"t = {ts.t[ii]*1e6:.2f} $\mu$s") + plt.plot(r_grid, n_e, label=f"t = {ts.t[ii] * 1e6:.2f} $\mu$s") print("RMS error (%) in density: ", rms_errors) assert np.all(rms_errors < 0.05) diff --git a/Examples/Tests/effective_potential_electrostatic/inputs_test_3d_effective_potential_electrostatic_picmi.py b/Examples/Tests/effective_potential_electrostatic/inputs_test_3d_effective_potential_electrostatic_picmi.py index 27b1728b7b2..018739aa682 100644 --- a/Examples/Tests/effective_potential_electrostatic/inputs_test_3d_effective_potential_electrostatic_picmi.py +++ b/Examples/Tests/effective_potential_electrostatic/inputs_test_3d_effective_potential_electrostatic_picmi.py @@ -102,13 +102,13 @@ print( f"Plasma parameters:\n" f"\tlambda_e = {lambda_e:.1e} m\n" - f"\tt_pe = {1.0/f_pe:.1e} s\n" + f"\tt_pe = {1.0 / f_pe:.1e} s\n" f"\tv_ti = {v_ti:.1e} m/s\n" ) print( f"Numerical parameters:\n" - f"\tdz/lambda_e = {dz/lambda_e:.2f}\n" - f"\tdt*w_pe = {dt*f_pe*2.0*np.pi:.2f}\n" + f"\tdz/lambda_e = {dz / lambda_e:.2f}\n" + f"\tdt*w_pe = {dt * f_pe * 2.0 * np.pi:.2f}\n" f"\tdiag steps = {diag_steps:d}\n" f"\ttotal steps = {total_steps:d}\n" ) diff --git a/Examples/Tests/ohm_solver_ion_Landau_damping/inputs_test_2d_ohm_solver_landau_damping_picmi.py b/Examples/Tests/ohm_solver_ion_Landau_damping/inputs_test_2d_ohm_solver_landau_damping_picmi.py index 7c1709d059f..320d36785db 100644 --- a/Examples/Tests/ohm_solver_ion_Landau_damping/inputs_test_2d_ohm_solver_landau_damping_picmi.py +++ b/Examples/Tests/ohm_solver_ion_Landau_damping/inputs_test_2d_ohm_solver_landau_damping_picmi.py @@ -93,7 +93,7 @@ def __init__(self, test, dim, m, T_ratio, verbose): if comm.rank == 0: print( f"Initializing simulation with input parameters:\n" - f"\tT = {self.T_plasma*1e-3:.1f} keV\n" + f"\tT = {self.T_plasma * 1e-3:.1f} keV\n" f"\tn = {self.n_plasma:.1e} m^-3\n" f"\tB0 = {self.B0:.2f} T\n" f"\tM/m = {self.m_ion:.0f}\n" diff --git a/Examples/Tests/ohm_solver_ion_beam_instability/inputs_test_1d_ohm_solver_ion_beam_picmi.py b/Examples/Tests/ohm_solver_ion_beam_instability/inputs_test_1d_ohm_solver_ion_beam_picmi.py index 19569a04e5b..52160038831 100644 --- a/Examples/Tests/ohm_solver_ion_beam_instability/inputs_test_1d_ohm_solver_ion_beam_picmi.py +++ b/Examples/Tests/ohm_solver_ion_beam_instability/inputs_test_1d_ohm_solver_ion_beam_picmi.py @@ -110,7 +110,7 @@ def __init__(self, test, dim, resonant, verbose): if comm.rank == 0: print( f"Initializing simulation with input parameters:\n" - f"\tT = {self.T_plasma*1e-3:.1f} keV\n" + f"\tT = {self.T_plasma * 1e-3:.1f} keV\n" f"\tn = {self.n_plasma:.1e} m^-3\n" f"\tB0 = {self.B0:.2f} T\n" f"\tM/m = {self.m_ion:.0f}\n" diff --git a/Examples/Tests/ohm_solver_magnetic_reconnection/inputs_test_2d_ohm_solver_magnetic_reconnection_picmi.py b/Examples/Tests/ohm_solver_magnetic_reconnection/inputs_test_2d_ohm_solver_magnetic_reconnection_picmi.py index f074c81cbb3..2ddbd0df93d 100644 --- a/Examples/Tests/ohm_solver_magnetic_reconnection/inputs_test_2d_ohm_solver_magnetic_reconnection_picmi.py +++ b/Examples/Tests/ohm_solver_magnetic_reconnection/inputs_test_2d_ohm_solver_magnetic_reconnection_picmi.py @@ -83,14 +83,14 @@ def __init__(self, test, verbose): self.Bg *= self.B0 self.dB *= self.B0 self.Bx = ( - f"{self.B0}*tanh(z*{1.0/self.l_i})" - f"+{-self.dB*self.Lx/(2.0*self.Lz)}*cos({2.0*np.pi/self.Lx}*x)" - f"*sin({np.pi/self.Lz}*z)" + f"{self.B0}*tanh(z*{1.0 / self.l_i})" + f"+{-self.dB * self.Lx / (2.0 * self.Lz)}*cos({2.0 * np.pi / self.Lx}*x)" + f"*sin({np.pi / self.Lz}*z)" ) self.By = ( - f"sqrt({self.Bg**2 + self.B0**2}-" f"({self.B0}*tanh(z*{1.0/self.l_i}))**2)" + f"sqrt({self.Bg**2 + self.B0**2}-({self.B0}*tanh(z*{1.0 / self.l_i}))**2)" ) - self.Bz = f"{self.dB}*sin({2.0*np.pi/self.Lx}*x)*cos({np.pi/self.Lz}*z)" + self.Bz = f"{self.dB}*sin({2.0 * np.pi / self.Lx}*x)*cos({np.pi / self.Lz}*z)" self.J0 = self.B0 / constants.mu0 / self.l_i @@ -103,7 +103,7 @@ def __init__(self, test, verbose): if comm.rank == 0: print( f"Initializing simulation with input parameters:\n" - f"\tTi = {self.Ti*1e-3:.1f} keV\n" + f"\tTi = {self.Ti * 1e-3:.1f} keV\n" f"\tn0 = {self.n_plasma:.1e} m^-3\n" f"\tB0 = {self.B0:.2f} T\n" f"\tM/m = {self.m_ion:.0f}\n" @@ -117,7 +117,7 @@ def __init__(self, test, verbose): ) print( f"Numerical parameters:\n" - f"\tdz = {self.Lz/self.NZ:.1e} m\n" + f"\tdz = {self.Lz / self.NZ:.1e} m\n" f"\tdt = {self.dt:.1e} s\n" f"\tdiag steps = {self.diag_steps:d}\n" f"\ttotal steps = {self.total_steps:d}\n" diff --git a/Examples/Tests/particle_boundary_interaction/analysis.py b/Examples/Tests/particle_boundary_interaction/analysis.py index 062569d5553..edf9d463f98 100755 --- a/Examples/Tests/particle_boundary_interaction/analysis.py +++ b/Examples/Tests/particle_boundary_interaction/analysis.py @@ -43,6 +43,6 @@ print("percentage error for x = %5.4f %%" % (diff_x * 100)) print("percentage error for z = %5.4f %%" % (diff_z * 100)) -assert ( - (diff_x < tolerance) and (y[0] < 1e-8) and (diff_z < tolerance) -), "Test particle_boundary_interaction did not pass" +assert (diff_x < tolerance) and (y[0] < 1e-8) and (diff_z < tolerance), ( + "Test particle_boundary_interaction did not pass" +) diff --git a/Examples/Tests/pass_mpi_communicator/analysis.py b/Examples/Tests/pass_mpi_communicator/analysis.py index 041687c4775..cfac572c1b9 100755 --- a/Examples/Tests/pass_mpi_communicator/analysis.py +++ b/Examples/Tests/pass_mpi_communicator/analysis.py @@ -37,7 +37,7 @@ # Dictionaries have same outer keys (levels, species)? if checksum1.data.keys() != checksum2.data.keys(): - print("ERROR: plotfile 1 and plotfile 2 checksums " "have different outer keys:") + print("ERROR: plotfile 1 and plotfile 2 checksums have different outer keys:") print("Plot1: %s" % checksum1.data.keys()) print("Plot2: %s" % checksum2.data.keys()) sys.exit(1) @@ -45,9 +45,7 @@ # Dictionaries have same inner keys (field and particle quantities)? for key1 in checksum1.data.keys(): if checksum1.data[key1].keys() != checksum2.data[key1].keys(): - print( - "ERROR: plotfile 1 and plotfile 2 checksums have " "different inner keys:" - ) + print("ERROR: plotfile 1 and plotfile 2 checksums have different inner keys:") print("Common outer keys: %s" % checksum2.data.keys()) print("Plotfile 1 inner keys in %s: %s" % (key1, checksum1.data[key1].keys())) print("Plotfile 2 inner keys in %s: %s" % (key1, checksum2.data[key1].keys())) diff --git a/Examples/Tests/plasma_lens/analysis.py b/Examples/Tests/plasma_lens/analysis.py index 44671eea791..ed7ee653af6 100755 --- a/Examples/Tests/plasma_lens/analysis.py +++ b/Examples/Tests/plasma_lens/analysis.py @@ -160,13 +160,17 @@ def applylens(x0, vx0, vz0, gamma, lens_length, lens_strength): xx = xx + dt0 * vx yy = yy + dt1 * vy -print(f"Error in x position is {abs(np.abs((xx - xx_sim)/xx))}, which should be < 0.02") -print(f"Error in y position is {abs(np.abs((yy - yy_sim)/yy))}, which should be < 0.02") print( - f"Error in x velocity is {abs(np.abs((ux - ux_sim)/ux))}, which should be < 0.002" + f"Error in x position is {abs(np.abs((xx - xx_sim) / xx))}, which should be < 0.02" ) print( - f"Error in y velocity is {abs(np.abs((uy - uy_sim)/uy))}, which should be < 0.002" + f"Error in y position is {abs(np.abs((yy - yy_sim) / yy))}, which should be < 0.02" +) +print( + f"Error in x velocity is {abs(np.abs((ux - ux_sim) / ux))}, which should be < 0.002" +) +print( + f"Error in y velocity is {abs(np.abs((uy - uy_sim) / uy))}, which should be < 0.002" ) if plasma_lens_lengths[0] < 0.01: diff --git a/Python/pywarpx/fields.py b/Python/pywarpx/fields.py index 5d3b892b543..9beef1de5c8 100644 --- a/Python/pywarpx/fields.py +++ b/Python/pywarpx/fields.py @@ -284,10 +284,10 @@ def _find_start_stop(self, ii, imin, imax, d): iistart = ii iistop = ii + 1 assert imin <= iistart <= imax, Exception( - f"Dimension {d+1} lower index is out of bounds" + f"Dimension {d + 1} lower index is out of bounds" ) assert imin <= iistop <= imax, Exception( - f"Dimension {d+1} upper index is out of bounds" + f"Dimension {d + 1} upper index is out of bounds" ) return iistart, iistop diff --git a/Python/pywarpx/particle_containers.py b/Python/pywarpx/particle_containers.py index db5dfda883e..9a4d7257a69 100644 --- a/Python/pywarpx/particle_containers.py +++ b/Python/pywarpx/particle_containers.py @@ -107,31 +107,31 @@ def add_particles( maxlen = max(maxlen, lenw) # --- Make sure that the lengths of the input parameters are consistent - assert ( - x is None or lenx == maxlen or lenx == 1 - ), "Length of x doesn't match len of others" - assert ( - y is None or leny == maxlen or leny == 1 - ), "Length of y doesn't match len of others" - assert ( - z is None or lenz == maxlen or lenz == 1 - ), "Length of z doesn't match len of others" - assert ( - ux is None or lenux == maxlen or lenux == 1 - ), "Length of ux doesn't match len of others" - assert ( - uy is None or lenuy == maxlen or lenuy == 1 - ), "Length of uy doesn't match len of others" - assert ( - uz is None or lenuz == maxlen or lenuz == 1 - ), "Length of uz doesn't match len of others" - assert ( - w is None or lenw == maxlen or lenw == 1 - ), "Length of w doesn't match len of others" + assert x is None or lenx == maxlen or lenx == 1, ( + "Length of x doesn't match len of others" + ) + assert y is None or leny == maxlen or leny == 1, ( + "Length of y doesn't match len of others" + ) + assert z is None or lenz == maxlen or lenz == 1, ( + "Length of z doesn't match len of others" + ) + assert ux is None or lenux == maxlen or lenux == 1, ( + "Length of ux doesn't match len of others" + ) + assert uy is None or lenuy == maxlen or lenuy == 1, ( + "Length of uy doesn't match len of others" + ) + assert uz is None or lenuz == maxlen or lenuz == 1, ( + "Length of uz doesn't match len of others" + ) + assert w is None or lenw == maxlen or lenw == 1, ( + "Length of w doesn't match len of others" + ) for key, val in kwargs.items(): - assert ( - np.size(val) == 1 or len(val) == maxlen - ), f"Length of {key} doesn't match len of others" + assert np.size(val) == 1 or len(val) == maxlen, ( + f"Length of {key} doesn't match len of others" + ) # --- Broadcast scalars into appropriate length arrays # --- If the parameter was not supplied, use the default value diff --git a/Python/pywarpx/picmi.py b/Python/pywarpx/picmi.py index d464c44726f..f8261cd7847 100644 --- a/Python/pywarpx/picmi.py +++ b/Python/pywarpx/picmi.py @@ -2556,7 +2556,7 @@ def __init__( **kw, ): assert stl_file is None or implicit_function is None, Exception( - "Only one between implicit_function and " "stl_file can be specified" + "Only one between implicit_function and stl_file can be specified" ) self.implicit_function = implicit_function @@ -2666,9 +2666,9 @@ def __init__( self.strengths_E = strengths_E self.strengths_B = strengths_B - assert (self.strengths_E is not None) or ( - self.strengths_B is not None - ), Exception("One of strengths_E or strengths_B must be supplied") + assert (self.strengths_E is not None) or (self.strengths_B is not None), ( + Exception("One of strengths_E or strengths_B must be supplied") + ) self.handle_init(kw) @@ -3011,9 +3011,9 @@ def initialize_inputs(self): particle_shape = self.particle_shape for s in self.species: if s.particle_shape is not None: - assert ( - particle_shape is None or particle_shape == s.particle_shape - ), Exception("WarpX only supports one particle shape for all species") + assert particle_shape is None or particle_shape == s.particle_shape, ( + Exception("WarpX only supports one particle shape for all species") + ) # --- If this was set for any species, use that value. particle_shape = s.particle_shape @@ -4102,7 +4102,7 @@ def __init__( kw = self._handle_charge_on_eb(**kw) else: raise RuntimeError( - f"{self.type} reduced diagnostic is not yet supported " "in pywarpx." + f"{self.type} reduced diagnostic is not yet supported in pywarpx." ) self.handle_init(kw) diff --git a/Regression/Checksum/checksum.py b/Regression/Checksum/checksum.py index b2f327e36e3..8c93f4ea6ea 100644 --- a/Regression/Checksum/checksum.py +++ b/Regression/Checksum/checksum.py @@ -238,8 +238,7 @@ def evaluate(self, rtol=1.0e-9, atol=1.0e-40): # Dictionaries have same outer keys (levels, species)? if self.data.keys() != ref_benchmark.data.keys(): print( - "ERROR: Benchmark and output file checksum " - "have different outer keys:" + "ERROR: Benchmark and output file checksum have different outer keys:" ) print("Benchmark: %s" % ref_benchmark.data.keys()) print("Test file: %s" % self.data.keys()) diff --git a/Regression/PostProcessingUtils/post_processing_utils.py b/Regression/PostProcessingUtils/post_processing_utils.py index 55bc357c28b..cbd55c433d3 100644 --- a/Regression/PostProcessingUtils/post_processing_utils.py +++ b/Regression/PostProcessingUtils/post_processing_utils.py @@ -164,6 +164,6 @@ def check_random_filter(fn, filtered_fn, random_fraction, dim, species_name): ## Dirty trick to find particles with the same ID + same CPU (does not work with more than 10 ## MPI ranks) random_filter_expression = ( - "np.isin(ids + 0.1*cpus," "ids_filtered_warpx + 0.1*cpus_filtered_warpx)" + "np.isin(ids + 0.1*cpus,ids_filtered_warpx + 0.1*cpus_filtered_warpx)" ) check_particle_filter(fn, filtered_fn, random_filter_expression, dim, species_name) diff --git a/Tools/Algorithms/psatd.ipynb b/Tools/Algorithms/psatd.ipynb index 3e8b2a82d2e..6153b904968 100644 --- a/Tools/Algorithms/psatd.ipynb +++ b/Tools/Algorithms/psatd.ipynb @@ -64,9 +64,9 @@ " Wd[i, j] = Wd[i, j].expand().simplify()\n", " diff = W[i, j] - Wd[i, j]\n", " diff = diff.expand().simplify()\n", - " assert (\n", - " diff == 0\n", - " ), f\"Diagonalization failed: W[{i},{j}] - Wd[{i},{j}] = {diff} is not zero\"\n", + " assert diff == 0, (\n", + " f\"Diagonalization failed: W[{i},{j}] - Wd[{i},{j}] = {diff} is not zero\"\n", + " )\n", "\n", "\n", "def simple_mat(W):\n", diff --git a/Tools/Algorithms/stencil.py b/Tools/Algorithms/stencil.py index 2fe67d1c681..1fafd3837a7 100644 --- a/Tools/Algorithms/stencil.py +++ b/Tools/Algorithms/stencil.py @@ -361,10 +361,10 @@ def run_main( print("\nCell size:") print(f"- dx = {dx_boosted}") if dims > 1: - print(f"- dx[1:]/dx[0] = {dx_boosted[1:]/dx_boosted[0]}") + print(f"- dx[1:]/dx[0] = {dx_boosted[1:] / dx_boosted[0]}") print("\nTime step:") print(f"- dt = {dt}") - print(f"- c*dt/dx = {c*dt/dx_boosted}") + print(f"- c*dt/dx = {c * dt / dx_boosted}") print("\nSpectral order:") print(f"- order = {psatd_order}") print("\nLorentz boost, Galilean velocity:") diff --git a/Tools/Release/releasePR.py b/Tools/Release/releasePR.py index 3fd1b016efd..9dfa178e5b4 100755 --- a/Tools/Release/releasePR.py +++ b/Tools/Release/releasePR.py @@ -171,7 +171,7 @@ def concat_answers(answers): "--title", f"Release {WarpX_version}", "--body", - f"""Prepare the {datetime.now().strftime('%B')} release of WarpX: + f"""Prepare the {datetime.now().strftime("%B")} release of WarpX: ```bash # update dependencies ./Tools/Release/updateAMReX.py diff --git a/setup.py b/setup.py index c3f2e730726..ad5501371c5 100644 --- a/setup.py +++ b/setup.py @@ -342,7 +342,7 @@ def build_extension(self, ext): "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", ( - "License :: OSI Approved :: " "BSD License" + "License :: OSI Approved :: BSD License" ), # TODO: use real SPDX: BSD-3-Clause-LBNL ], # new PEP 639 format From 188e401c9b944c6d87b33447e7a841998f2f3abc Mon Sep 17 00:00:00 2001 From: Arianna Formenti Date: Tue, 14 Jan 2025 09:57:09 -0800 Subject: [PATCH 18/23] Add doxygen documentation regarding `is_igf_2d_slices` (#5556) This is a boolean flag that lets the user select between two types of FFT-based Poisson solver: * fully 3D: solves Poisson equation in 3D geometry * quasi-3D: solves many 2D Poisson equations, one for each `z` slice, independently one another --- Source/FieldSolver/ElectrostaticSolvers/ElectrostaticSolver.H | 3 ++- Source/ablastr/fields/IntegratedGreenFunctionSolver.H | 1 + Source/ablastr/fields/PoissonSolver.H | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/FieldSolver/ElectrostaticSolvers/ElectrostaticSolver.H b/Source/FieldSolver/ElectrostaticSolvers/ElectrostaticSolver.H index f57cfff6080..0a0b0e2be48 100755 --- a/Source/FieldSolver/ElectrostaticSolvers/ElectrostaticSolver.H +++ b/Source/FieldSolver/ElectrostaticSolvers/ElectrostaticSolver.H @@ -76,14 +76,15 @@ public: * \f[ * \vec{\nabla}^2 r \phi - (\vec{\beta}\cdot\vec{\nabla})^2 r \phi = -\frac{r \rho}{\epsilon_0} * \f] - * \param[out] phi The potential to be computed by this function * \param[in] rho The charge density for a given species (relativistic solver) * or total charge density (labframe solver) + * \param[out] phi The potential to be computed by this function * \param[in] beta Represents the velocity of the source of `phi` * \param[in] required_precision The relative convergence threshold for the MLMG solver * \param[in] absolute_tolerance The absolute convergence threshold for the MLMG solver * \param[in] max_iters The maximum number of iterations allowed for the MLMG solver * \param[in] verbosity The verbosity setting for the MLMG solver + * \param[in] is_igf_2d_slices boolean to select between fully 3D Poisson solver and quasi-3D, i.e. one 2D Poisson solve on every z slice (default: false) */ void computePhi ( ablastr::fields::MultiLevelScalarField const& rho, diff --git a/Source/ablastr/fields/IntegratedGreenFunctionSolver.H b/Source/ablastr/fields/IntegratedGreenFunctionSolver.H index 9492cff885e..b34678055a8 100755 --- a/Source/ablastr/fields/IntegratedGreenFunctionSolver.H +++ b/Source/ablastr/fields/IntegratedGreenFunctionSolver.H @@ -124,6 +124,7 @@ namespace ablastr::fields * @param[out] phi the electrostatic potential amrex::MultiFab * @param[in] cell_size an arreay of 3 reals dx dy dz * @param[in] ba amrex::BoxArray with the grid of a given level + * @param[in] is_igf_2d boolean to select between fully 3D Poisson solver and quasi-3D, i.e. one 2D Poisson solve on every z slice (default: false) */ void computePhiIGF (amrex::MultiFab const & rho, diff --git a/Source/ablastr/fields/PoissonSolver.H b/Source/ablastr/fields/PoissonSolver.H index 1cc7d39e9b0..c79736e0d1b 100755 --- a/Source/ablastr/fields/PoissonSolver.H +++ b/Source/ablastr/fields/PoissonSolver.H @@ -179,6 +179,7 @@ inline void interpolatePhiBetweenLevels ( * \param[in] grids the grids per level (e.g., from AmrMesh) * \param[in] grid_type Integer that corresponds to the type of grid used in the simulation (collocated, staggered, hybrid) * \param[in] is_solver_igf_on_lev0 boolean to select the Poisson solver: 1 for FFT on level 0 & Multigrid on other levels, 0 for Multigrid on all levels + * \param[in] is_igf_2d boolean to select between fully 3D Poisson solver and quasi-3D, i.e. one 2D Poisson solve on every z slice (default: false) * \param[in] eb_enabled solve with embedded boundaries * \param[in] do_single_precision_comms perform communications in single precision * \param[in] rel_ref_ratio mesh refinement ratio between levels (default: 1) From a20365520d143814f3d18bb9fa97198a750a810a Mon Sep 17 00:00:00 2001 From: Arianna Formenti Date: Tue, 14 Jan 2025 10:15:02 -0800 Subject: [PATCH 19/23] Update differential luminosity test (#5555) Fixes the species in the test: `test_3d_diff_lumi_diag_photons` from `electron` and `positron` to `photons`. Updates checksums consequently. (Off Topic: it's 5555!) --- .../inputs_test_3d_diff_lumi_diag_photons | 6 +++-- .../test_3d_diff_lumi_diag_photons.json | 25 ++++++++++--------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Examples/Tests/diff_lumi_diag/inputs_test_3d_diff_lumi_diag_photons b/Examples/Tests/diff_lumi_diag/inputs_test_3d_diff_lumi_diag_photons index f0ef254d911..90d66938a4a 100644 --- a/Examples/Tests/diff_lumi_diag/inputs_test_3d_diff_lumi_diag_photons +++ b/Examples/Tests/diff_lumi_diag/inputs_test_3d_diff_lumi_diag_photons @@ -3,7 +3,9 @@ FILE = inputs_base_3d # Test with electrons/positrons: use parse_density_function -beam1.species_type = electron +particles.photon_species = beam1 beam2 + +beam1.species_type = photon beam1.injection_style = "NUniformPerCell" beam1.num_particles_per_cell_each_dim = 1 1 1 beam1.profile = parse_density_function @@ -15,7 +17,7 @@ beam1.ymax = 4*sigmay beam1.zmin =-muz-4*sigmaz beam1.zmax =-muz+4*sigmaz -beam2.species_type = positron +beam2.species_type = photon beam2.injection_style = "NUniformPerCell" beam2.num_particles_per_cell_each_dim = 1 1 1 beam2.profile = parse_density_function diff --git a/Regression/Checksum/benchmarks_json/test_3d_diff_lumi_diag_photons.json b/Regression/Checksum/benchmarks_json/test_3d_diff_lumi_diag_photons.json index 09b2031cdd2..86659bafd79 100644 --- a/Regression/Checksum/benchmarks_json/test_3d_diff_lumi_diag_photons.json +++ b/Regression/Checksum/benchmarks_json/test_3d_diff_lumi_diag_photons.json @@ -1,24 +1,25 @@ { "lev=0": { - "rho_beam1": 656097367.2335038, - "rho_beam2": 656097367.2335038 + "rho_beam1": 0.0, + "rho_beam2": 0.0 }, - "beam1": { + "beam2": { "particle_momentum_x": 0.0, "particle_momentum_y": 0.0, - "particle_momentum_z": 1.7512476113279403e-11, + "particle_momentum_z": 1.7511853009715152e-11, "particle_position_x": 0.2621440000000001, - "particle_position_y": 0.005242880000000001, - "particle_position_z": 314572.79999473685, - "particle_weight": 11997744756.90957 + "particle_position_y": 0.005242880000000004, + "particle_position_z": 314572.8000000002, + "particle_weight": 11997744756.909575 }, - "beam2": { + "beam1": { "particle_momentum_x": 0.0, "particle_momentum_y": 0.0, - "particle_momentum_z": 1.7513431895752007e-11, + "particle_momentum_z": 1.75121641230803e-11, "particle_position_x": 0.2621440000000001, - "particle_position_y": 0.005242880000000001, - "particle_position_z": 314572.79999472946, + "particle_position_y": 0.005242880000000004, + "particle_position_z": 314572.8000000004, "particle_weight": 11997744756.909573 } -} \ No newline at end of file +} + From c666e75508fef6adb2a25a756546cf11b1e290d8 Mon Sep 17 00:00:00 2001 From: Luca Fedeli Date: Tue, 14 Jan 2025 20:18:08 +0100 Subject: [PATCH 20/23] Pass `gamma_boost` as argument to `AcceleratorLattice`, `LatticeElementFinder` (#5541) This PR is a small step towards the goal of reducing the usage of static variables in the WarpX class. --------- Co-authored-by: Edoardo Zoni <59625522+EZoni@users.noreply.github.com> --- Source/AcceleratorLattice/AcceleratorLattice.H | 7 ++++++- Source/AcceleratorLattice/AcceleratorLattice.cpp | 6 ++++-- Source/AcceleratorLattice/LatticeElementFinder.H | 4 +++- Source/AcceleratorLattice/LatticeElementFinder.cpp | 7 ++++--- Source/Parallelization/WarpXRegrid.cpp | 2 +- Source/WarpX.cpp | 2 +- 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Source/AcceleratorLattice/AcceleratorLattice.H b/Source/AcceleratorLattice/AcceleratorLattice.H index 4b3eff46094..e8acc2c8743 100644 --- a/Source/AcceleratorLattice/AcceleratorLattice.H +++ b/Source/AcceleratorLattice/AcceleratorLattice.H @@ -42,10 +42,15 @@ public: * \brief Initialize the element finder instance at the given level of refinement * * @param[in] lev the level of refinement + * @param[in] gamma_boost the Lorentz factor of the boosted frame * @param[in] ba the box array at the level of refinement * @param[in] dm the distribution map at the level of refinement */ - void InitElementFinder (int lev, amrex::BoxArray const & ba, amrex::DistributionMapping const & dm); + void InitElementFinder ( + int lev, + amrex::Real gamma_boost, + amrex::BoxArray const & ba, + amrex::DistributionMapping const & dm); /** * \brief Update the element finder, needed when the simulation frame has moved relative to the lab frame diff --git a/Source/AcceleratorLattice/AcceleratorLattice.cpp b/Source/AcceleratorLattice/AcceleratorLattice.cpp index edccae9374a..b0513f767a0 100644 --- a/Source/AcceleratorLattice/AcceleratorLattice.cpp +++ b/Source/AcceleratorLattice/AcceleratorLattice.cpp @@ -76,13 +76,15 @@ AcceleratorLattice::ReadLattice (std::string const & root_name, amrex::ParticleR } void -AcceleratorLattice::InitElementFinder (int const lev, amrex::BoxArray const & ba, amrex::DistributionMapping const & dm) +AcceleratorLattice::InitElementFinder ( + int const lev, amrex::Real const gamma_boost, + amrex::BoxArray const & ba, amrex::DistributionMapping const & dm) { if (m_lattice_defined) { m_element_finder = std::make_unique>(ba, dm); for (amrex::MFIter mfi(*m_element_finder); mfi.isValid(); ++mfi) { - (*m_element_finder)[mfi].InitElementFinder(lev, mfi, *this); + (*m_element_finder)[mfi].InitElementFinder(lev, gamma_boost, mfi, *this); } } } diff --git a/Source/AcceleratorLattice/LatticeElementFinder.H b/Source/AcceleratorLattice/LatticeElementFinder.H index 6773ed56a65..f7eb5c66531 100644 --- a/Source/AcceleratorLattice/LatticeElementFinder.H +++ b/Source/AcceleratorLattice/LatticeElementFinder.H @@ -30,10 +30,12 @@ struct LatticeElementFinder * \brief Initialize the element finder at the level and grid * * @param[in] lev the refinement level + * @param[in] gamma_boost the Lorentz factor of the boosted frame * @param[in] a_mfi specifies the grid where the finder is defined * @param[in] accelerator_lattice a reference to the accelerator lattice at the refinement level */ - void InitElementFinder (int lev, amrex::MFIter const& a_mfi, + void InitElementFinder (int lev, amrex::Real gamma_boost, + amrex::MFIter const& a_mfi, AcceleratorLattice const& accelerator_lattice); /** diff --git a/Source/AcceleratorLattice/LatticeElementFinder.cpp b/Source/AcceleratorLattice/LatticeElementFinder.cpp index ec784049760..64e593aee30 100644 --- a/Source/AcceleratorLattice/LatticeElementFinder.cpp +++ b/Source/AcceleratorLattice/LatticeElementFinder.cpp @@ -15,7 +15,8 @@ using namespace amrex::literals; void -LatticeElementFinder::InitElementFinder (int const lev, amrex::MFIter const& a_mfi, +LatticeElementFinder::InitElementFinder (int const lev, const amrex::Real gamma_boost, + amrex::MFIter const& a_mfi, AcceleratorLattice const& accelerator_lattice) { @@ -26,8 +27,8 @@ LatticeElementFinder::InitElementFinder (int const lev, amrex::MFIter const& a_m m_dz = WarpX::CellSize(lev)[2]; - m_gamma_boost = WarpX::gamma_boost; - m_uz_boost = std::sqrt(WarpX::gamma_boost*WarpX::gamma_boost - 1._prt)*PhysConst::c; + m_gamma_boost = gamma_boost; + m_uz_boost = std::sqrt(m_gamma_boost*m_gamma_boost - 1._prt)*PhysConst::c; AllocateIndices(accelerator_lattice); diff --git a/Source/Parallelization/WarpXRegrid.cpp b/Source/Parallelization/WarpXRegrid.cpp index 7adc00ed523..81cbb55c2c7 100644 --- a/Source/Parallelization/WarpXRegrid.cpp +++ b/Source/Parallelization/WarpXRegrid.cpp @@ -285,7 +285,7 @@ WarpX::RemakeLevel (int lev, Real /*time*/, const BoxArray& ba, const Distributi } // Re-initialize the lattice element finder with the new ba and dm. - m_accelerator_lattice[lev]->InitElementFinder(lev, ba, dm); + m_accelerator_lattice[lev]->InitElementFinder(lev, gamma_boost, ba, dm); if (costs[lev] != nullptr) { diff --git a/Source/WarpX.cpp b/Source/WarpX.cpp index 3f53decbb83..96335e10c5e 100644 --- a/Source/WarpX.cpp +++ b/Source/WarpX.cpp @@ -2100,7 +2100,7 @@ WarpX::AllocLevelData (int lev, const BoxArray& ba, const DistributionMapping& d guard_cells.ng_alloc_Rho, guard_cells.ng_alloc_F, guard_cells.ng_alloc_G, aux_is_nodal); m_accelerator_lattice[lev] = std::make_unique(); - m_accelerator_lattice[lev]->InitElementFinder(lev, ba, dm); + m_accelerator_lattice[lev]->InitElementFinder(lev, gamma_boost, ba, dm); } From 57703f8fc25a4c05ed887fd75ea68306f694a99f Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Tue, 14 Jan 2025 12:29:37 -0800 Subject: [PATCH 21/23] Use `amrex::getParticleCell` More (#5557) One leftover occurance in `ParticleReductionFunctor`. Follow-up to #5118 --- .../ParticleReductionFunctor.cpp | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/Source/Diagnostics/ComputeDiagFunctors/ParticleReductionFunctor.cpp b/Source/Diagnostics/ComputeDiagFunctors/ParticleReductionFunctor.cpp index d6cd27f7cc0..abc3fb2c8cf 100644 --- a/Source/Diagnostics/ComputeDiagFunctors/ParticleReductionFunctor.cpp +++ b/Source/Diagnostics/ComputeDiagFunctors/ParticleReductionFunctor.cpp @@ -69,6 +69,9 @@ ParticleReductionFunctor::operator() (amrex::MultiFab& mf_dst, const int dcomp, get_particle_position(p, xw, yw, zw); // Get position in AMReX convention to calculate corresponding index. + // Ideally this will be replaced with the AMReX NGP interpolator + // Always do x direction. No RZ case because it's not implemented, and code + // will have aborted const auto [ii, jj, kk] = amrex::getParticleCell(p, plo, dxi).dim3(); // Fix dimensions since parser assumes u = gamma * v / c @@ -97,20 +100,8 @@ ParticleReductionFunctor::operator() (amrex::MultiFab& mf_dst, const int dcomp, // Ideally this will be replaced with the AMReX NGP interpolator // Always do x direction. No RZ case because it's not implemented, and code // will have aborted - int ii = 0, jj = 0, kk = 0; - const amrex::ParticleReal x = p.pos(0); - const amrex::Real lx = (x - plo[0]) * dxi[0]; - ii = static_cast(amrex::Math::floor(lx)); -#if defined(WARPX_DIM_XZ) || defined(WARPX_DIM_3D) - const amrex::ParticleReal y = p.pos(1); - const amrex::Real ly = (y - plo[1]) * dxi[1]; - jj = static_cast(amrex::Math::floor(ly)); -#endif -#if defined(WARPX_DIM_3D) - const amrex::ParticleReal z = p.pos(2); - const amrex::Real lz = (z - plo[2]) * dxi[2]; - kk = static_cast(amrex::Math::floor(lz)); -#endif + const auto [ii, jj, kk] = amrex::getParticleCell(p, plo, dxi).dim3(); + // Fix dimensions since parser assumes u = gamma * v / c const amrex::ParticleReal ux = p.rdata(PIdx::ux) / PhysConst::c; const amrex::ParticleReal uy = p.rdata(PIdx::uy) / PhysConst::c; From ce487f93832919bfc34979e04a31f3c0020d7a22 Mon Sep 17 00:00:00 2001 From: U Sinha <46874465+sinha-r@users.noreply.github.com> Date: Wed, 15 Jan 2025 14:39:49 -0800 Subject: [PATCH 22/23] Containerfile (#5141) Containerfile to run WarpX at NERSC # To Do - [x] GPU-aware MPI is needed: we need to use `shifter` instead of podman - [x] heFFTe has been disabled as of now due to compilation errors (this can be skipped for now and added in a follow-up PR later on, we do not use heFFTe extensively yet) --------- Co-authored-by: Axel Huebl --- Tools/machines/perlmutter-nersc/Containerfile | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Tools/machines/perlmutter-nersc/Containerfile diff --git a/Tools/machines/perlmutter-nersc/Containerfile b/Tools/machines/perlmutter-nersc/Containerfile new file mode 100644 index 00000000000..5a8553c2619 --- /dev/null +++ b/Tools/machines/perlmutter-nersc/Containerfile @@ -0,0 +1,167 @@ +# Build this container from its current directory: +# podman build --build-arg NJOBS=6 -t warpx-perlmutter-dev . +# Adjust NJOBS to the number of processes to use for parallel compilation. +# +# Run from the via WarpX source directory +# podman run -v ${PWD}:/opt/warpx -it warpx-perlmutter-dev +# then +# cd /opt/warpx +# and compile. + +# Base System and Essential Tools Installation +FROM nvidia/cuda:12.6.0-devel-ubuntu22.04 AS base + +# parallel builds +ARG NJOBS +ENV NJOBS=$NJOBS + +# Set up environment variables +ENV DEBIAN_FRONTEND=noninteractive \ + SW_DIR=/opt/software \ + FORCE_UNSAFE_CONFIGURE=1 + +# Perlmutter A100 compilation optimization +ENV AMREX_CUDA_ARCH=8.0 \ + CUDAARCHS=80 \ + CXXFLAGS="-march=znver3" \ + CFLAGS="-march=znver3" + +# Install essential system dependencies including MPI libraries +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + autoconf \ + build-essential \ + ca-certificates \ + coreutils \ + curl \ + environment-modules \ + gfortran \ + git \ + openssh-server \ + python3 \ + python3-pip \ + python3-dev \ + python3-venv \ + unzip \ + vim \ + libmpich-dev \ + cmake \ + libblas-dev \ + liblapack-dev \ + g++ \ + pkg-config \ + libbz2-dev \ + zlib1g-dev \ + libpng-dev \ + libzstd-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install c-blosc from source +FROM base AS c-blosc + +RUN git clone -b v1.21.1 https://github.com/Blosc/c-blosc.git /tmp/c-blosc && \ + cmake \ + -S /tmp/c-blosc \ + -B /tmp/c-blosc-build \ + -DCMAKE_INSTALL_PREFIX=/usr .. && \ + cmake --build /tmp/c-blosc-build \ + --target install \ + -j${NJOBS} && \ + rm -rf /tmp/c-blosc* + +# Install ADIOS2 from source +FROM base AS adios2 + +# Ensure c-blosc is installed before ADIOS2 +COPY --from=c-blosc /usr /usr + +# Verify the location of Blosc library +RUN find /usr -name 'libblosc*' + +# Ensure Blosc library paths are correctly configured +ENV BLOSC_LIBRARY=/usr/lib/libblosc.so.1.21.1 +ENV BLOSC_INCLUDE_DIR=/usr/include + +# Install ADIOS2 +RUN git clone -b v2.8.3 https://github.com/ornladios/ADIOS2.git /tmp/adios2 && \ + cd /tmp/adios2 && \ + cmake -S . -B build \ + -DADIOS2_USE_Blosc=ON \ + -DBLOSC_LIBRARY=${BLOSC_LIBRARY} \ + -DBLOSC_INCLUDE_DIR=${BLOSC_INCLUDE_DIR} \ + -DADIOS2_USE_Fortran=OFF \ + -DADIOS2_USE_Python=OFF \ + -DADIOS2_USE_ZeroMQ=OFF \ + -DADIOS2_USE_BZip2=ON \ + -DADIOS2_USE_ZFP=OFF \ + -DADIOS2_USE_SZ=OFF \ + -DADIOS2_USE_MGARD=OFF \ + -DADIOS2_USE_PNG=ON \ + -DCMAKE_INSTALL_PREFIX=/usr .. && \ + cmake --build build --target install -j${NJOBS} && \ + rm -rf /tmp/adios2 + +# Install BLAS++ and LAPACK++ +FROM base AS blaspp_lapackpp + +RUN git clone -b v2024.05.31 https://github.com/icl-utk-edu/blaspp.git /tmp/blaspp && \ + cd /tmp/blaspp && \ + cmake -S . -B build \ + -Duse_openmp=OFF \ + -Dgpu_backend=cuda \ + -DCMAKE_CXX_STANDARD=17 \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DBLAS_LIBRARIES=/usr/lib/x86_64-linux-gnu/libblas.so \ + -DLAPACK_LIBRARIES=/usr/lib/x86_64-linux-gnu/liblapack.so .. && \ + cmake --build build \ + --target install \ + -j${NJOBS} && \ + rm -rf /tmp/blaspp + +RUN git clone -b v2024.05.31 https://github.com/icl-utk-edu/lapackpp.git /tmp/lapackpp && \ + cd /tmp/lapackpp && \ + cmake -S . -B build \ + -DCMAKE_CXX_STANDARD=17 \ + -Dbuild_tests=OFF \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DLAPACK_LIBRARIES=/usr/lib/x86_64-linux-gnu/liblapack.so .. && \ + cmake --build build \ + --target install -j${NJOBS} && \ + rm -rf /tmp/lapackpp + +# Final Image +FROM base AS final + +# Copy installed software from previous stages +COPY --from=c-blosc /usr /usr +COPY --from=adios2 /usr /usr +COPY --from=blaspp_lapackpp /usr /usr + +# Create and activate Python virtual environment +RUN python3 -m venv /opt/venv && \ + /opt/venv/bin/pip install --no-cache-dir \ + wheel \ + numpy \ + pandas \ + scipy \ + matplotlib \ + jupyter \ + scikit-learn \ + openpmd-api \ + yt \ + cupy-cuda12x \ + torch \ + optimas[all] \ + cython \ + packaging \ + build \ + setuptools + +# Set up the environment for the virtual environment +ENV PATH="/opt/venv/bin:${PATH}" + +# Set up entrypoint +ENTRYPOINT ["/bin/bash", "-c"] + +# Default command +CMD ["/bin/bash"] From a053457086a82092e85b6afcf501236f1a32ff25 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Thu, 16 Jan 2025 08:01:31 -0800 Subject: [PATCH 23/23] AMReX/pyAMReX/PICSAR: Weekly Update (#5564) Weekly update to latest AMReX. Weekly update to latest pyAMReX. Weekly update to latest PICSAR (no changes). ```console ./Tools/Release/updateAMReX.py ./Tools/Release/updatepyAMReX.py ./Tools/Release/updatePICSAR.py ``` --------- Signed-off-by: Axel Huebl --- .github/workflows/cuda.yml | 2 +- cmake/dependencies/AMReX.cmake | 2 +- cmake/dependencies/pyAMReX.cmake | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cuda.yml b/.github/workflows/cuda.yml index aa0daa2a718..1309dc4bb81 100644 --- a/.github/workflows/cuda.yml +++ b/.github/workflows/cuda.yml @@ -127,7 +127,7 @@ jobs: which nvcc || echo "nvcc not in PATH!" git clone https://github.com/AMReX-Codes/amrex.git ../amrex - cd ../amrex && git checkout --detach 25.01 && cd - + cd ../amrex && git checkout --detach e761abff95afbfa442cbe108027094bbddef5b11 && cd - make COMP=gcc QED=FALSE USE_MPI=TRUE USE_GPU=TRUE USE_OMP=FALSE USE_FFT=TRUE USE_CCACHE=TRUE -j 4 ccache -s diff --git a/cmake/dependencies/AMReX.cmake b/cmake/dependencies/AMReX.cmake index 82d56d98a5f..6bde3785176 100644 --- a/cmake/dependencies/AMReX.cmake +++ b/cmake/dependencies/AMReX.cmake @@ -294,7 +294,7 @@ set(WarpX_amrex_src "" set(WarpX_amrex_repo "https://github.com/AMReX-Codes/amrex.git" CACHE STRING "Repository URI to pull and build AMReX from if(WarpX_amrex_internal)") -set(WarpX_amrex_branch "25.01" +set(WarpX_amrex_branch "e761abff95afbfa442cbe108027094bbddef5b11" CACHE STRING "Repository branch for WarpX_amrex_repo if(WarpX_amrex_internal)") diff --git a/cmake/dependencies/pyAMReX.cmake b/cmake/dependencies/pyAMReX.cmake index 777b75e2ed3..c9ee2732b62 100644 --- a/cmake/dependencies/pyAMReX.cmake +++ b/cmake/dependencies/pyAMReX.cmake @@ -74,7 +74,7 @@ option(WarpX_pyamrex_internal "Download & build pyAMReX" ON) set(WarpX_pyamrex_repo "https://github.com/AMReX-Codes/pyamrex.git" CACHE STRING "Repository URI to pull and build pyamrex from if(WarpX_pyamrex_internal)") -set(WarpX_pyamrex_branch "25.01" +set(WarpX_pyamrex_branch "47331d7891bda9b02e75cf452d2c55fe76c77d06" CACHE STRING "Repository branch for WarpX_pyamrex_repo if(WarpX_pyamrex_internal)")