Skip to content

Commit 56ad087

Browse files
committed
Merge branch 'development' into dependencies_pybind11_picmistandard
2 parents 772d6fb + 08750da commit 56ad087

File tree

52 files changed

+2297
-796
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2297
-796
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,15 @@ repos:
6565

6666
# C++ formatting
6767
- repo: https://github.com/pre-commit/mirrors-clang-format
68-
rev: v21.1.2
68+
rev: v21.1.5
6969
hooks:
7070
- id: clang-format
7171
files: '^Source/main.cpp'
7272

7373
# Python: Ruff linter & formatter
7474
# https://docs.astral.sh/ruff/
7575
- repo: https://github.com/astral-sh/ruff-pre-commit
76-
rev: v0.14.3
76+
rev: v0.14.5
7777
hooks:
7878
# Run the linter
7979
- id: ruff

Docs/source/acknowledge_us.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ If your project leads to a scientific publication, please consider citing all Wa
116116
howpublished = {https://blast-warpx.github.io}
117117
}
118118
119-
Since the WarpX is an actively evolving project, a specific version might be used in your work to ensure reproducibility. You can select a *version-specific DOI* from the `release page <https://github.com/BLAST-WarpX/warpx/releases>`__ and add the version number to the cited title, e.g. for version ``25.10``:
119+
Since WarpX is an actively evolving project, a specific version might be used in your work to ensure reproducibility. You can select a *version-specific DOI* from the `release page <https://github.com/BLAST-WarpX/warpx/releases>`__ and add the version number to the cited title, e.g. for version ``25.10``:
120120

121121
.. tab-set::
122122

Docs/source/highlights.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ Laser-Plasma Interaction
100100

101101
Scientific works in laser-ion acceleration and laser-matter interaction.
102102

103+
#. Lei B, Zhang H, Seipt D, Bonatto A, Qiao B, Resta-López J, Xia G, and Welsch C.
104+
**Coherent Synchrotron Radiation by Excitation of Surface Plasmon Polariton on Near-Critical Solid Microtube Surface**.
105+
Phys. Rev. Lett. **135**, 205001, 2025.
106+
`DOI:10.1103/cnym-16hc <https://doi.org/10.1103/cnym-16hc>`__
107+
103108
#. Garten M, Bulanov S S, Hakimi S, Obst-Huebl L, Mitchell C E, Schroeder C B, Esarey E, Geddes C G R, Vay J-L, Huebl A.
104109
**Laser-plasma ion beam booster based on hollow-channel magnetic vortex acceleration**.
105110
Physical Review Research **6**, 033148, 2024.

Docs/source/usage/parameters.rst

Lines changed: 50 additions & 32 deletions
Large diffs are not rendered by default.

Docs/source/usage/workflows.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This section collects typical user workflows and best practices for WarpX.
1616
workflows/generate_lookup_tables_with_tools
1717
workflows/plot_timestep_duration
1818
workflows/psatd_stencil
19+
workflows/stl_geometry_preparation
1920
workflows/archiving
2021
workflows/ml_dataset_training
2122
workflows/optimas
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
.. _workflows-stl-geometry-preparation:
2+
3+
STL Geometry Preparation for WarpX
4+
==================================
5+
6+
WarpX has the ability to define the embedded boundary (EB) in a simulation using externally provided STL (STereoLithography) files.
7+
STL files are a common format for representing 3D geometries and can be used to define complex embedded boundaries in WarpX simulations, without having to define extensive EB implicit functions.
8+
However, there are some limitations to using STL files which must be resolved, including:
9+
10+
1. Multiple STL files representing different parts of a device must be combined into a single file
11+
2. The STL geometry is "watertight" (The STL file shouldn't have duplicate faces or vertices, overlapping vertices should be merged, and there shouldn't be any gaps or holes in the mesh)
12+
3. The STL file is properly formatted for WarpX input
13+
14+
.. 2. The STL file shouldn't have duplicate faces or vertices, and overlapping vertices should be merged. (issues with vertices can cause the MLMG solver to crash)
15+
16+
Step 1: Combining Multiple STL Files
17+
------------------------------------
18+
19+
If your device consists of multiple parts stored in separate STL files, you'll need to combine them into a single STL file.
20+
21+
Using MeshLab
22+
^^^^^^^^^^^^^
23+
24+
`MeshLab <https://www.meshlab.net/>`__ is a free, open-source tool for processing 3D meshes:
25+
26+
1. Open MeshLab
27+
2. Import the first STL file: ``File -> Import Mesh``
28+
3. Import additional STL files: ``File -> Import Mesh`` (repeat for each file)
29+
4. All parts should now be visible in the same scene
30+
5. Create a union of the two parts, either by ``Filters -> Remeshing, Simplification and Reconstruction -> Mesh Boolean: Union``
31+
or by right-clicking on one of the parts in the Layer Dialog panel on the right and clicking ``Mesh Boolean: Union``
32+
6. Select the union and export the combined mesh: ``File -> Export Mesh As``
33+
7. Choose STL format and save
34+
35+
Using Python with trimesh
36+
^^^^^^^^^^^^^^^^^^^^^^^^^
37+
38+
You can also use Python with the `trimesh <https://github.com/mikedh/trimesh>`__ library:
39+
40+
.. code-block:: python
41+
42+
import trimesh
43+
44+
# Load individual STL files
45+
mesh1 = trimesh.load('part1.stl')
46+
mesh2 = trimesh.load('part2.stl')
47+
48+
# Combine meshes
49+
combined = trimesh.util.concatenate([mesh1, mesh2])
50+
51+
# Export combined mesh
52+
combined.export('device_combined.stl')
53+
54+
Step 2: Making the Geometry Watertight and Removing and Merging Duplicate Faces and Vertices
55+
---------------------------------------------------------------------------------------------------
56+
57+
58+
WarpX requires that STL geometries be "watertight" (manifold), meaning the mesh has no holes, gaps, or open edges.
59+
This ensures that WarpX can properly determine which regions are inside or outside the geometry.
60+
STL files that have overlapping or duplicate faces and vertices can cause the MLMG solver to crash, while a non-manifold file can be inherently leaky for Poynting flux in an EM simulation.
61+
These issues with the mesh might happen while exporting the STL file from a CAD program (such as SolidWorks)
62+
63+
Using MeshLab
64+
^^^^^^^^^^^^^
65+
66+
To check and repair a mesh in MeshLab:
67+
68+
1. **Check for issues:**
69+
70+
* ``Filters -> Quality Measure and Computations -> Compute Topological Measures``
71+
* Look for holes in the output
72+
* Look for non-manifold edges and vertices in the output
73+
74+
2. **Repair the mesh:**
75+
76+
* When loading in the mesh, there is an option to ``Unify Duplicated Vertices in STL files``, this will perform the next steps automatically, but gives the user less control.
77+
* ``Filters -> Cleaning and Repairing -> Remove Duplicate Faces``
78+
* ``Filters -> Cleaning and Repairing -> Remove Duplicate Vertices``
79+
* ``Filters -> Cleaning and Repairing -> Merge Close Vertices``
80+
81+
* This filter gives the user an option to set an absolute or relative tolerance on the distance between the vertices to merge.
82+
83+
.. * ``Filters -> Cleaning and Repairing -> Remove Zero Area Faces``
84+
.. * ``Filters -> Remeshing, Simplification and Reconstruction -> Close Holes``
85+
86+
3. **Verify the mesh is watertight:**
87+
88+
* Run ``Filters -> Quality Measure and Computations -> Compute Topological Measures`` again
89+
* Check that the mesh has no holes
90+
* Check that the mesh is manifold (no warnings about non-manifold edges)
91+
92+
* An STL file with non-manifold edges won't necessarily crash a simulation, but may present other numerical issues.
93+
94+
95+
96+
97+
Step 3: Using STL Files in WarpX
98+
--------------------------------
99+
100+
Once you have a single, watertight STL file, you can use it in WarpX by setting the following parameters in your input file:
101+
102+
.. code-block:: text
103+
104+
# Specify that the embedded boundary comes from an STL file
105+
eb2.geom_type = stl
106+
107+
# Path to your STL file
108+
eb2.stl_file = path/to/device_watertight.stl
109+
110+
You can also optionally set an electric potential on the embedded boundary:
111+
112+
.. code-block:: text
113+
114+
# Define electric potential at the embedded boundary (optional)
115+
warpx.eb_potential(x,y,z,t) = "voltage_function"
116+
117+
For more details on embedded boundary parameters, see:
118+
119+
* `Embedded Boundary Input Parameters <https://warpx.readthedocs.io/en/latest/usage/parameters.html#embedded-boundary-conditions:~:text=in%20this%20case.-,Embedded%20Boundary%20Conditions,-%EF%83%81>`__
120+
* `Embedded Boundary PICMI Input Parameters <https://warpx.readthedocs.io/en/latest/usage/python.html#pywarpx.picmi.EmbeddedBoundary:~:text=Custom%20class%20to,translated%20and%20inverted.>`__
121+
122+
Tips and Best Practices
123+
-----------------------
124+
125+
* *Units:* Ensure your STL file uses the same unit system as your WarpX simulation
126+
* *Scale:* If needed, scale your geometry in your CAD software or mesh editor before exporting
127+
* *Orientation:* Check that your geometry is properly oriented relative to WarpX's coordinate system
128+
* *Resolution:* The STL mesh resolution should be appropriate for your simulation - too coarse may miss important features, too fine may slow down initialization
129+
130+
* It's generally a good idea to simplify your geometery and remove features that are significantly smaller than the WarpX simulation grid
131+
132+
* *Binary vs ASCII:* WarpX can read both binary and ASCII STL files, but binary files are typically smaller and faster to load
133+
134+
135+
Examples
136+
--------
137+
138+
.. note::
139+
140+
**TODO**: WarpX does not yet have examples that use STL files for embedded boundaries.
141+
142+
Current embedded boundary examples in ``Examples/Tests/embedded_boundary_*`` use analytical
143+
functions to define geometries. A complete example demonstrating STL file usage will be
144+
added in the future.

Examples/Tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,4 @@ add_subdirectory(single_particle)
8484
add_subdirectory(space_charge_initialization)
8585
add_subdirectory(subcycling)
8686
add_subdirectory(vay_deposition)
87+
add_subdirectory(virtual_photons)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Add tests (alphabetical order) ##############################################
2+
#
3+
4+
add_warpx_test(
5+
test_3d_virtual_photons # name
6+
3 # dims
7+
1 # nprocs
8+
inputs_test_3d_virtual_photons # inputs
9+
analysis_virtual_photons.py # analysis
10+
"analysis_default_regression.py --path diags/diag1" # checksum
11+
OFF # dependency
12+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../analysis_default_regression.py
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/usr/bin/env python3
2+
3+
# This test generates the population of virtual photons
4+
# of one high-energy electron.
5+
# The total number and spectrum of the virtual photons are
6+
# compared to the theoretical prediction.
7+
# Checks that the photons are in the same position of the electron.
8+
9+
import matplotlib.pyplot as plt
10+
import numpy as np
11+
from numpy import log
12+
from openpmd_viewer import OpenPMDTimeSeries
13+
from scipy.constants import alpha, c, eV, m_e, pi
14+
15+
###########################
16+
### ENERGY AND SPECTRUM ###
17+
###########################
18+
19+
# useful constants
20+
GeV = 1e9 * eV
21+
22+
# electron energy
23+
energy = 125 * GeV
24+
25+
# virtual photons min energy
26+
hw_min = 1e-12 * m_e * c**2
27+
28+
# min fractional energy of the virtual photon wrt electron energy
29+
ymin = hw_min / energy
30+
31+
#############
32+
### WarpX ###
33+
#############
34+
35+
series = OpenPMDTimeSeries("./diags/diag1/")
36+
sampling_factor = 1e7
37+
uz_virtual_photons, w_virtual_photons = series.get_particle(
38+
["uz", "w"], species="virtual_photons", iteration=1
39+
)
40+
w_electrons = series.get_particle(["w"], species="beam", iteration=1)
41+
42+
# fractional photon energy (photon energy / electron energy)
43+
y_warpx = uz_virtual_photons * c / energy
44+
45+
# bins for the fractional photon energy
46+
y = np.geomspace(ymin, 1, 401)
47+
48+
# number of virtual photons per electron obtained with WarpX
49+
N_warpx = np.sum(w_virtual_photons) / np.sum(w_electrons)
50+
51+
# spectrum of the virtual photons per electron
52+
H, b = np.histogram(y_warpx, bins=y, weights=w_virtual_photons)
53+
db = np.diff(b)
54+
b = 0.5 * (b[1:] + b[:-1])
55+
dN_dy_warpx = H / db / np.sum(w_electrons)
56+
57+
##############
58+
### Theory ###
59+
##############
60+
61+
y = b
62+
# spectrum of virtual photons for one electron
63+
dN_dy_theory = alpha / pi / y * (-2 * log(y))
64+
# dN_dy[dN_dy < 0] = 0.0
65+
66+
# number of virtual photons for one electron from theory
67+
N_theory = alpha / pi * log(ymin) ** 2
68+
69+
############
70+
### Plot ###
71+
############
72+
73+
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(5, 4), dpi=200)
74+
ax.plot(y, dN_dy_theory, color="black", lw=6, label="theory")
75+
ax.plot(y, dN_dy_warpx, color="dodgerblue", lw=4, label="WarpX")
76+
ax.legend()
77+
ax.set_yscale("log")
78+
ax.set_xscale("log")
79+
ax.set_xlabel("Fractional photon energy")
80+
ax.set_ylabel("dN/dy")
81+
ax.set_title("Virtual photons spectrum")
82+
fig.savefig("spectrum_virtual_photons.png")
83+
84+
#############
85+
### Error ###
86+
#############
87+
88+
number_rel_error = np.abs(N_warpx - N_theory) / N_theory
89+
spectrum_rel_error = np.abs(dN_dy_warpx - dN_dy_theory) / dN_dy_theory
90+
91+
print("Number of virtual photons per electron:")
92+
print(f"From simulation : {N_warpx}")
93+
print(f"From theory : {N_theory}")
94+
print(f"Relative error : {number_rel_error:.4%}")
95+
96+
print("Spectrum of virtual photons per electron:")
97+
print(f"Max relative error: {spectrum_rel_error.max()}")
98+
99+
assert number_rel_error < 0.02
100+
assert (spectrum_rel_error < 0.04).all()
101+
102+
################
103+
### Position ###
104+
################
105+
106+
x, y, z = series.get_particle(["x", "y", "z"], species="virtual_photons", iteration=1)
107+
x_e, y_e, z_e = series.get_particle(["x", "y", "z"], species="beam", iteration=1)
108+
109+
assert np.unique(x) == x_e
110+
assert np.unique(y) == y_e
111+
assert np.unique(z) == z_e

0 commit comments

Comments
 (0)