Skip to content

EM Field Enhancement: local coordinates, dynamic placements and mapped fields#1012

Merged
dsarrut merged 30 commits into
OpenGATE:masterfrom
srmarcballestero:feature/field_enhancement
Jun 4, 2026
Merged

EM Field Enhancement: local coordinates, dynamic placements and mapped fields#1012
dsarrut merged 30 commits into
OpenGATE:masterfrom
srmarcballestero:feature/field_enhancement

Conversation

@srmarcballestero

@srmarcballestero srmarcballestero commented May 5, 2026

Copy link
Copy Markdown
Contributor

Rationale

Enhancement and maintenance of the internal field management infrastructure. Implement mapped fields. User API remains unchanged.

Fixes

  • Previously, fields were defined in global coordinates and didn't follow volume rotation or translation. Fields are now defined in the local coordinate system of the attached logical volume. The world-to-local coordinate transform is computed for every physical placement of that logical volume and applied on each GetFieldValue call, so a field attached to a repeated or rotated volume automatically applies with the correct orientation and position at each placement.
  • The per-placement world-to-local transforms are cached internally and updated between runs, so fields correctly track volumes that are moved or rotated by dynamic geometry changes.

New Features

  • The Geant4 built-in sextupole magnetic field is now exposed to the user.
  • Mapped magnetic, electric or combined electromagnetic fields defined on a regular, complete 3D cartesian grid can now be used.

Internal Changes

The whole C++ field management infrastructure has been rethought and refactored. Now, all field types share a single base class, GateFieldBase, which resolves the physical placement of the volume and manages coordinate transforms. Concrete implementations are minimal.

Tests and Documentation

Tests for the new features have been added, and I have updated the EM fields documentation page.

Cheers,

Marc :)

Copilot AI review requested due to automatic review settings May 5, 2026 08:54
@srmarcballestero srmarcballestero marked this pull request as draft May 5, 2026 08:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This draft PR refactors magnetic-field handling so fields are defined in the local coordinate system of the volume they’re attached to, and introduces infrastructure to cache and refresh placement transforms (including multi-placement logical volumes) across dynamic geometry updates between runs.

Changes:

  • Wraps magnetic fields in a new C++ GateMagneticField (built on GateField) to transform query points world↔local per physical placement and to support transform refreshes.
  • Updates Python magnetic-field classes to construct an “inner” Geant4 field in local coordinates and then wrap it with GateMagneticField.
  • Adds a run-start hook to refresh cached transforms after dynamic geometry changers are applied, and wires the attached volume object into field construction.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
opengate/geometry/fields.py Refactors magnetic fields to create local-coordinate inner fields and wrap them with GateMagneticField; adds refresh_transforms().
opengate/engines.py Passes the attached volume object into field instances before creating field managers.
opengate/actors/dynamicactors.py Refreshes field transforms after dynamic geometry changes at begin-of-run.
core/opengate_core/opengate_lib/GateField.h / GateField.cpp Adds a C++ helper to cache placement transforms and locate the containing placement (with overshoot fallback).
core/opengate_core/opengate_lib/GateMagneticField.h / GateMagneticField.cpp Adds a C++ magnetic-field wrapper that evaluates inner fields in local coords and rotates results back to world.
core/opengate_core/opengate_lib/pyGateMagneticField.cpp Adds pybind11 bindings for GateMagneticField and SetTransforms.
core/opengate_core/opengate_core.cpp Registers GateMagneticField bindings in the Python module init.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread core/opengate_core/opengate_lib/GateFieldBase.cpp
Comment thread opengate/geometry/fields.py Outdated
Comment thread opengate/geometry/fields.py Outdated
Comment thread opengate/engines.py
Comment thread opengate/actors/dynamicactors.py

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread core/opengate_core/opengate_lib/GateField.cpp Outdated
Comment thread opengate/geometry/fields.py Outdated
Comment thread opengate/engines.py Outdated
Comment thread opengate/geometry/fields.py
Comment thread core/opengate_core/opengate_lib/GateField.cpp Outdated
@srmarcballestero srmarcballestero changed the title WIP: EM field support maintenance and enhancement EM Field Enhancement: local coordinates, dynamic placements and mapped fields May 7, 2026
@srmarcballestero srmarcballestero marked this pull request as ready for review May 7, 2026 06:34
@srmarcballestero srmarcballestero requested a review from Copilot May 7, 2026 06:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 47 out of 47 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (1)

docs/source/user_guide/user_guide_fields.rst:165

  • The CustomElectroMagneticField code snippet also uses tesla without defining it in the snippet. Consider adding tesla = gate.g4_units.tesla near the existing volt/m definitions so users can copy-paste the example successfully.
**CustomElectroMagneticField** -- Arbitrary combined field. The callback must return all six components ``[Bx, By, Bz, Ex, Ey, Ez]``.

.. code-block:: python

   def my_EM_field(x, y, z, t):
       return [0, 1 * tesla, 0, 1e6 * volt / m, 0, 0]

Comment thread core/opengate_core/opengate_lib/GateFieldBase.cpp
Comment thread core/opengate_core/opengate_lib/GateFieldBase.cpp
Comment thread opengate/tests/src/geometry/test099_fields_mapped_vs_uniform_E.py
Comment thread opengate/tests/src/geometry/test099_fields_mapped_vs_uniform_E.py
Comment thread opengate/tests/src/geometry/test099_fields_serialization.py
Comment thread docs/source/user_guide/user_guide_fields.rst
@srmarcballestero

Copy link
Copy Markdown
Contributor Author

Fork synced with master and PR ready for review

@srmarcballestero srmarcballestero force-pushed the feature/field_enhancement branch from 9e165ae to 0a5457f Compare May 7, 2026 13:27
@srmarcballestero srmarcballestero force-pushed the feature/field_enhancement branch from 0a5457f to fb0bf93 Compare May 26, 2026 11:31
@dsarrut

dsarrut commented May 29, 2026

Copy link
Copy Markdown
Contributor

Hi Marc, from my side, this PR is ready to be merged, is it ok from your side? It is really one of the main GATE improvement since long time, well done !

@srmarcballestero

Copy link
Copy Markdown
Contributor Author

Hi Marc, from my side, this PR is ready to be merged, is it ok from your side? It is really one of the main GATE improvement since long time, well done !

Hi David,

Thanks for your feedback! :) From my side, I'm also good to go. I've tested the new capabilities and everything has been working well in tests so far. I'd be happy to keep iterating on this feature based on users' feedback!

@nkrah

nkrah commented May 29, 2026

Copy link
Copy Markdown
Collaborator

Hi Marc,
the PR looks good. I have reviewed your code locally, but I think I never pushed my commits. Nothing concerning API - just internal code/architecture. I suggest you rebase and, if tests pass, we merge. I can then suggest my modifications via a separate PR. OK?

srmarcballestero and others added 12 commits May 29, 2026 15:24
- Allows fields to be defined relative to the local coordinate system of the physical volumes.
- Paves the way for the mapped field implementation
…ld definition in local coordinates and updates for dynamic geometry changes
- copilot code review.
- register SextupoleMagneticField in field_types and process_cls
…ns all the common functionality and field-specific implementations are now minimal

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
@srmarcballestero srmarcballestero force-pushed the feature/field_enhancement branch from 72076d6 to 171727e Compare May 29, 2026 13:41
@srmarcballestero

Copy link
Copy Markdown
Contributor Author

Hi Marc, the PR looks good. I have reviewed your code locally, but I think I never pushed my commits. Nothing concerning API - just internal code/architecture. I suggest you rebase and, if tests pass, we merge. I can then suggest my modifications via a separate PR. OK?

Hi Nils,

Thanks for the feedback :) I've just rebased to upstream/master and ran the test suite locally, everything appears to be working. Looking forward to your commits 👍

Thanks,

Marc

@srmarcballestero

Copy link
Copy Markdown
Contributor Author

HI @nkrah @dsarrut ,

After rebasing to upstream/master, all the CI checks have finally passed, so everything on my side is ready for merging.

Cheers,

Marc

@dsarrut

dsarrut commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Hi @srmarcballestero, I re-run the first test error (it is a tolerance I will update later). The second test error is test099_fields_stepper, can you check please ?

@srmarcballestero

Copy link
Copy Markdown
Contributor Author

Hi @srmarcballestero, I re-run the first test error (it is a tolerance I will update later). The second test error is test099_fields_stepper, can you check please ?

Hi @dsarrut. I've updated the tolerance in the test, and now it seems to be passing. I'm not entirely sure of what was the core issue, but my educated guess is that it had to do with floating point differences across compilers.

@dsarrut dsarrut merged commit 217b394 into OpenGATE:master Jun 4, 2026
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants