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..aa0daa2a718 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 @@ -126,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/.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 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 55d880c8866..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.4 + rev: v0.9.1 hooks: # Run the linter - id: ruff diff --git a/CMakeLists.txt b/CMakeLists.txt index c7a889633da..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) @@ -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/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/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/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/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/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/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/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/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/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/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``. 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/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/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/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/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 bc6b2d74106..9a4d7257a69 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, @@ -96,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 @@ -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): """ 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/Python/setup.py b/Python/setup.py index fa38e14e7ce..a50b467c070 100644 --- a/Python/setup.py +++ b/Python/setup.py @@ -65,12 +65,12 @@ setup( name="pywarpx", - version="24.12", + version="25.01", packages=["pywarpx"], package_dir={"pywarpx": "pywarpx"}, 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/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 +} + 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/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/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; 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/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/Initialization/WarpXInitData.cpp b/Source/Initialization/WarpXInitData.cpp index daecfac8bed..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. @@ -850,7 +853,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/Parallelization/WarpXRegrid.cpp b/Source/Parallelization/WarpXRegrid.cpp index a0a2d4929df..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) { @@ -320,7 +320,7 @@ WarpX::ComputeCostsHeuristic (amrex::Vector 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..96335e10c5e 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, @@ -2101,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); } @@ -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); 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) 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 new file mode 100755 index 00000000000..9dfa178e5b4 --- /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/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 diff --git a/cmake/dependencies/AMReX.cmake b/cmake/dependencies/AMReX.cmake index 0066a3103cd..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 "") @@ -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/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..ad5501371c5 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.", @@ -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,12 +336,13 @@ 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" + "License :: OSI Approved :: BSD License" ), # TODO: use real SPDX: BSD-3-Clause-LBNL ], # new PEP 639 format