New Boundary Conditions and Fixing Bug in Esirkepov Current Deposition#78
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR extends PyPIC3D’s boundary-handling capabilities by introducing absorbing particle boundaries (via a persistent active-mask), adding an unsplit-convolutional PML implementation for FDTD field updates, and correcting Esirkepov current deposition ghost-cell handling for higher-order shapes. It also threads “external-only” prescribed E/B fields through initialization/evolve/diagnostics so particles and energy accounting can include fields that Maxwell does not evolve.
Changes:
- Add absorbing particle BC support by masking inactive particles from pushes, deposition, and energy/moments.
- Introduce PML configuration/state and integrate coordinate-stretched derivatives into the first-order Yee FDTD update.
- Add external-only E/B fields and update energy + openPMD diagnostics (including thin-axis preservation) and tests.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/utils_test.py | Adds unit tests for external-field loading/addition and energy masking behavior. |
| tests/pml_test.py | Adds PML configuration, initialization, and absorption behavior tests. |
| tests/particle_test.py | Adds tests for absorbing particle masks, initialization config acceptance, and masked deposition. |
| tests/openpmd_test.py | Adds tests ensuring thin mesh axes are preserved in openPMD output. |
| tests/first_order_yee_test.py | Updates tests for the new (field, pml_state) return signatures. |
| tests/evolve_test.py | Adds tests for external-field particle pushing and mask survival under JIT. |
| tests/esirkepov_ghost_cells_test.py | Adds regression tests for two-layer ghost folding and halo elimination. |
| PyPIC3D/utils.py | Masks kinetic energy by active particles; adds external-field composition + loading support. |
| PyPIC3D/solvers/first_order_yee.py | Integrates PML-stretched curls and returns/threads pml_state. |
| PyPIC3D/solvers/electrostatic_yee.py | Fixes CG update sign convention for alpha and residual update. |
| PyPIC3D/particles/species_class.py | Implements absorbing masks and ensures inactive particles don’t update position/velocity or moments. |
| PyPIC3D/particles/particle_initialization.py | Allows absorbing as a per-axis particle boundary option in config. |
| PyPIC3D/particles/flat_particles.py | Threads active_mask through flat particle representation and moment/push methods. |
| PyPIC3D/initialization.py | Adds PML loading/state allocation; introduces and routes external-only E/B fields. |
| PyPIC3D/evolve.py | Uses total (evolved+external) fields for particle pushes; threads external fields and pml_state. |
| PyPIC3D/diagnostics/openPMD.py | Preserves thin axes and adds external field outputs; updates array handling. |
| PyPIC3D/diagnostics/fluid_quantities.py | Masks particle-to-grid moments by active particles. |
| PyPIC3D/deposition/rho.py | Prevents inactive particles from depositing charge density. |
| PyPIC3D/deposition/J_from_rhov.py | Prevents inactive particles from depositing current in RHOV deposition. |
| PyPIC3D/deposition/Esirkepov.py | Reworks ghost-layer logic for Esirkepov with two-layer folding and per-species BC handling. |
| PyPIC3D/boundary_conditions/PML.py | Adds PML profile building, ADE memory, stretched derivatives, and PML-safe ghost updates. |
| PyPIC3D/main.py | Updates runtime energy accounting to include external-only fields and new fields tuple layout. |
| docs/particles.rst | Documents absorbing particle boundaries and masking semantics. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+104
to
113
| if ( | ||
| isinstance(extra, (list, tuple)) | ||
| and len(extra) == 2 | ||
| and all(isinstance(memory, (list, tuple)) and len(memory) == 3 for memory in extra) | ||
| ): | ||
| # PML memory is solver state, not a physical diagnostic field. | ||
| continue | ||
| if isinstance(extra, (list, tuple)): | ||
| field_map[f"field_{idx}"] = tuple(comp[interior] for comp in extra) | ||
| else: |
Comment on lines
228
to
+235
| mass = species.get_mass() | ||
| vx, vy, vz = species.get_velocity() | ||
| v2 = vx**2 + vy**2 + vz**2 | ||
| active = species.get_active_mask().astype(v2.dtype) | ||
| gamma = 1.0 / jnp.sqrt(1 - v2 / C**2) | ||
| momentum2 = jnp.square(mass * gamma ) * v2 | ||
| # compute the squared momentum for each particle | ||
| KE = jnp.sum( jnp.sqrt( momentum2 * C**2 + mass**2 * C**4) - mass * C**2 ) | ||
| KE = jnp.sum(active * (jnp.sqrt(momentum2 * C**2 + mass**2 * C**4) - mass * C**2)) |
Comment on lines
+86
to
+88
| rho = jnp.zeros(shape_with_ghosts) | ||
| phi = jnp.zeros(shape_with_ghosts) | ||
| fields = (E, B, J, rho, phi) |
Comment on lines
+488
to
+489
| vertex_grid, center_grid = build_yee_grid(world) | ||
| world["grids"] = {"vertex": vertex_grid, "center": center_grid} |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Comment on lines
+231
to
+235
| active = species.get_active_mask().astype(v2.dtype) | ||
| gamma = 1.0 / jnp.sqrt(1 - v2 / C**2) | ||
| momentum2 = jnp.square(mass * gamma ) * v2 | ||
| # compute the squared momentum for each particle | ||
| KE = jnp.sum( jnp.sqrt( momentum2 * C**2 + mass**2 * C**4) - mass * C**2 ) | ||
| KE = jnp.sum(active * (jnp.sqrt(momentum2 * C**2 + mass**2 * C**4) - mass * C**2)) |
Comment on lines
202
to
207
| x_bc = "periodic" | ||
| if "x_bc" in config[toml_key]: | ||
| assert config[toml_key]["x_bc"] in ["periodic", "reflecting"], ( | ||
| assert config[toml_key]["x_bc"] in ["periodic", "reflecting", "absorbing"], ( | ||
| f"Invalid x boundary condition: {config[toml_key]['x_bc']}" | ||
| ) | ||
| x_bc = config[toml_key]["x_bc"] |
Comment on lines
209
to
214
| y_bc = "periodic" | ||
| if "y_bc" in config[toml_key]: | ||
| assert config[toml_key]["y_bc"] in ["periodic", "reflecting"], ( | ||
| assert config[toml_key]["y_bc"] in ["periodic", "reflecting", "absorbing"], ( | ||
| f"Invalid y boundary condition: {config[toml_key]['y_bc']}" | ||
| ) | ||
| y_bc = config[toml_key]["y_bc"] |
Comment on lines
216
to
221
| z_bc = "periodic" | ||
| if "z_bc" in config[toml_key]: | ||
| assert config[toml_key]["z_bc"] in ["periodic", "reflecting"], ( | ||
| assert config[toml_key]["z_bc"] in ["periodic", "reflecting", "absorbing"], ( | ||
| f"Invalid z boundary condition: {config[toml_key]['z_bc']}" | ||
| ) | ||
| z_bc = config[toml_key]["z_bc"] |
Comment on lines
+488
to
+489
| vertex_grid, center_grid = build_yee_grid(world) | ||
| world["grids"] = {"vertex": vertex_grid, "center": center_grid} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reference for PML: Martin, R., & Komatitsch, D. (2009). An unsplit convolutional perfectly matched layer technique improved at grazing incidence for the viscoelastic wave equation. Geophysical Journal International, 179(1), 333-344.