-
Notifications
You must be signed in to change notification settings - Fork 31
Polygon aperture #1199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
ax3l
merged 54 commits into
BLAST-ImpactX:development
from
egstern:egstern-polygon-aperture
Nov 25, 2025
Merged
Polygon aperture #1199
Changes from 3 commits
Commits
Show all changes
54 commits
Select commit
Hold shift + click to select a range
03dc3c3
start of PolygonAperture implementation
egstern 229ab2a
PolygonAperture logic added and builds now.
egstern 680b89c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] a86705d
Update src/elements/PolygonAperture.H
egstern 26da419
Added input file parsing logic.
egstern 42120dc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] f65dd08
Update src/elements/PolygonAperture.H
cemitch99 23e0f40
sense of test was incorrect
egstern 55e8bdf
input file example
egstern 6b9a5b8
some problem merging upstream? I don't know what happened
egstern 8461e9d
examples of aperture with offsets and rotations
egstern e93a870
Rearrange storage of vertices data and min_radius2 so that
egstern d07b51a
script to plot the action of the aperture
egstern 7aa179b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] af944bb
tweaks to plot layout
egstern 3d414ef
tweaks to plot layout
egstern bac3829
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] ef0c3ce
New analysis script that checks tests the results of the aperture, small
egstern 95fe1ee
I don't know why this changed upstream
egstern b3df98f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] d91ed97
python bindings for polygon aperture
egstern 7fde375
python example file for the polygon aperture
egstern 9cd397a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 6a45a42
additional scripts demonstrating absorb, rotate, offset options
egstern 49a3306
add new polygon aperture tests to test suite
egstern f0b9e18
changed upstream
egstern c9994d5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] b84682e
fix python stanza
egstern 800f382
another fix python stanza
egstern 357d067
changed upstream
egstern 2362d07
cleanup comments
egstern 0210e94
Fix type for binding of PolygonAperture class data member definitions.
egstern dbff31c
Added the element to the examples documentation.
egstern d83b435
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] d0a11fb
Added Python and Input-file documentation
egstern 8a430aa
upstream changes
egstern f40e6c0
spelling correction
egstern b39109d
Update examples/polygon_aperture/README.rst
egstern 7462522
Update src/elements/PolygonAperture.H
egstern 725d351
Update examples/polygon_aperture/README.rst
egstern 926e684
Update docs/source/usage/parameters.rst
egstern 5f6ad3c
add comments describing the particle-in-polygon algorithm
egstern 80d7358
Update src/elements/PolygonAperture.H
egstern 863cdcd
Update src/elements/PolygonAperture.H
egstern 5a0943c
update documentation to include additional examples
egstern fbfce19
add test that first and last vertices are equal
egstern 975d424
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 9e5b983
Clarify that the first and last vertices must be identical.
egstern e4c14b3
Add additional example scripts to testing list
egstern 0ce7445
upstream changes
egstern b063331
fix indent and close unterminated literal string to squash sphinx war…
egstern 3a8371f
Merge branch 'development' into egstern-polygon-aperture
egstern 92cc602
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 8f825fb
Check in example plot file and point to it in the documentation.
egstern File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| target_sources(lib | ||
| PRIVATE | ||
| Aperture.cpp | ||
| PolygonAperture.cpp | ||
| Programmable.cpp | ||
| Source.cpp | ||
| ) | ||
|
|
||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,296 @@ | ||
| /* Copyright 2022-2023 The Regents of the University of California, through Lawrence | ||
| * Berkeley National Laboratory (subject to receipt of any required | ||
| * approvals from the U.S. Dept. of Energy). All rights reserved. | ||
| * | ||
| * This file is part of ImpactX. | ||
| * | ||
| * Authors: Eric G. Stern, Chad Mitchell, Axel Huebl | ||
| * License: BSD-3-Clause-LBNL | ||
| */ | ||
| #ifndef IMPACTX_POLYGONAPERTURE_H | ||
| #define IMPACTX_POLYGONAPERTURE_H | ||
|
|
||
|
|
||
| #include "particles/ImpactXParticleContainer.H" | ||
| #include "mixin/alignment.H" | ||
| #include "mixin/beamoptic.H" | ||
| #include "mixin/thin.H" | ||
| #include "mixin/lineartransport.H" | ||
| #include "mixin/named.H" | ||
| #include "mixin/nofinalize.H" | ||
|
|
||
| #include <AMReX_Extension.H> | ||
| #include <AMReX_Math.H> | ||
| #include <AMReX_REAL.H> | ||
| #include <AMReX_SIMD.H> | ||
| #include <ablastr/constant.H> | ||
| #include <cmath> | ||
| #include <stdexcept> | ||
egstern marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| namespace impactx::elements | ||
| { | ||
|
|
||
| /** Dynamic data for the PolygonAperture elements | ||
| * | ||
| * Since we copy the element to the device, we cannot store this data on the element itself. | ||
| * But we can store pointers to this data with the element and keep a lookup table here, | ||
| * which we clean up in the end. | ||
| */ | ||
| namespace PolygonApertureData | ||
| { | ||
| //! last used id for a created ExactMultipole | ||
| inline int next_id = 0; | ||
|
|
||
| //! host: normal multipole coefficients of the magnetic field | ||
| inline std::map<int, std::vector<amrex::ParticleReal>> h_vertices_x = {}; | ||
| //! host: skew multipole coefficients of the magnetic field | ||
| inline std::map<int, std::vector<amrex::ParticleReal>> h_vertices_y = {}; | ||
|
|
||
| //! device: normal multipole coefficients of the magnetic field | ||
| inline std::map<int, amrex::Gpu::DeviceVector<amrex::ParticleReal>> d_vertices_x = {}; | ||
| //! device: skew multipole coefficients of the magnetic field | ||
| inline std::map<int, amrex::Gpu::DeviceVector<amrex::ParticleReal>> d_vertices_y = {}; | ||
|
|
||
| } // namespace PolygonApertureData | ||
|
|
||
| struct PolygonAperture | ||
| : public mixin::Named, | ||
| public mixin::BeamOptic<PolygonAperture>, | ||
| public mixin::LinearTransport<PolygonAperture>, | ||
| public mixin::Thin, | ||
| public mixin::Alignment, | ||
| public mixin::NoFinalize, | ||
| public amrex::simd::Vectorized<amrex::simd::native_simd_size_particlereal> | ||
egstern marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| static constexpr auto type = "PolygonAperture"; | ||
| using PType = ImpactXParticleContainer::ParticleType; | ||
|
|
||
| enum Action | ||
| { | ||
| transmit, | ||
| absorb | ||
| }; | ||
|
|
||
| static std::string | ||
| action_name (Action const & action); | ||
|
|
||
| /** A thin collimator element that applies a transverse aperture boundary defined | ||
| * by points of a polygon vertices. | ||
| * Particles outside the boundary are considered lost. | ||
| * | ||
| * @param action specify action of domain (transmit/absorb) | ||
| * @param vertices_x array of coordinates of the horizontal vertex positions (m) | ||
| * @param vertices_y array of coordinates of the vertical vertex positions (m) | ||
cemitch99 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * @param min_radius2 a minimum radius**2 below which all particles are transmitted | ||
ax3l marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * @param repeat_x horizontal period for repeated masking, optional (m) | ||
| * @param repeat_y vertical period for repeated masking, optional (m) | ||
| * @param shift_odd_x for hexagonal/triangular mask patterns: horizontal shift of every 2nd (odd) vertical period by repeat_x / 2. Use alignment offsets dx,dy to move whole mask as needed. | ||
| * @param dx horizontal translation error in m | ||
| * @param dy vertical translation error in m | ||
| * @param rotation_degree rotation error in the transverse plane [degrees] | ||
| * @param name a user defined and not necessarily unique name of the element | ||
| */ | ||
| PolygonAperture ( | ||
| std::vector< amrex::ParticleReal> vertices_xx, | ||
| std::vector< amrex::ParticleReal> vertices_yy, | ||
| amrex::ParticleReal min_radius2x, | ||
| amrex::ParticleReal repeat_x, | ||
| amrex::ParticleReal repeat_y, | ||
| bool shift_odd_x, | ||
| Action action, | ||
| amrex::ParticleReal dx = 0, | ||
| amrex::ParticleReal dy = 0, | ||
| amrex::ParticleReal rotation_degree = 0, | ||
| std::optional<std::string> name = std::nullopt | ||
| ) | ||
| // | ||
| : Named(std::move(name)), | ||
| Alignment(dx, dy, rotation_degree), | ||
| m_action(action), m_repeat_x(repeat_x), m_repeat_y(repeat_y), m_shift_odd_x(shift_odd_x), | ||
| vertices_x(vertices_xx), vertices_y(vertices_yy), min_radius2(min_radius2x) | ||
egstern marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| using namespace amrex::literals; // for _rt and _prt | ||
|
|
||
| if (m_repeat_y == 0_prt && m_shift_odd_x) { | ||
| throw std::runtime_error("Aperture: shift_odd_x can only be used if repeat_y is set, too!"); | ||
| } | ||
|
|
||
| // next created MulPolygonAperture has another id for its data | ||
| PolygonApertureData::next_id++; | ||
|
|
||
| m_nvert = vertices_x.size(); | ||
| // there must be the same number of horizontal and vertical vertices | ||
| if (m_nvert != vertices_y.size()) { | ||
| throw std::runtime_error("PolygonAperture: horizontal and vertical vertices arrays must have same length!"); | ||
| } | ||
egstern marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // host data | ||
| PolygonApertureData::h_vertices_x[m_id] = vertices_x; | ||
| PolygonApertureData::h_vertices_y[m_id] = vertices_y; | ||
| m_vertices_x_h_data = PolygonApertureData::h_vertices_x[m_id].data(); | ||
| m_vertices_y_h_data = PolygonApertureData::h_vertices_y[m_id].data(); | ||
|
|
||
| // device data | ||
| PolygonApertureData::d_vertices_x.emplace(m_id, amrex::Gpu::DeviceVector<amrex::ParticleReal>(m_nvert)); | ||
| PolygonApertureData::d_vertices_y.emplace(m_id, amrex::Gpu::DeviceVector<amrex::ParticleReal>(m_nvert)); | ||
| amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, | ||
| vertices_x.begin(), vertices_x.end(), | ||
| PolygonApertureData::d_vertices_x[m_id].begin()); | ||
| amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, | ||
| vertices_y.begin(), vertices_y.end(), | ||
| PolygonApertureData::d_vertices_y[m_id].begin()); | ||
| amrex::Gpu::streamSynchronize(); | ||
|
|
||
| // low-level objects we can use on device | ||
| m_vertices_x_d_data = PolygonApertureData::d_vertices_x[m_id].data(); | ||
| m_vertices_y_d_data = PolygonApertureData::d_vertices_y[m_id].data(); | ||
|
|
||
| } | ||
|
|
||
| /** Push all particles */ | ||
| using BeamOptic::operator(); | ||
|
|
||
| /** Compute and cache the constants for the push. | ||
| * | ||
| * In particular, used to pre-compute and cache variables that are | ||
| * independent of the individually tracked particle. | ||
| * | ||
| * @param refpart reference particle (unused) | ||
| */ | ||
| void compute_constants ([[maybe_unused]] RefPart const & refpart) | ||
| { | ||
| Alignment::compute_constants(refpart); | ||
| } | ||
|
|
||
| /** This is an aperture functor, so that a variable of this type can be used like an | ||
| * aperture function. | ||
| * | ||
| * @param x particle position in x | ||
| * @param y particle position in y | ||
| * @param t particle position in t (unused) | ||
| * @param px particle momentum in x | ||
| * @param py particle momentum in y | ||
| * @param pt particle momentum in t (unused) | ||
| * @param idcpu particle global index | ||
| * @param refpart reference particle (unused) | ||
| */ | ||
| template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t> | ||
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE | ||
| void operator() ( | ||
| T_Real & AMREX_RESTRICT x, | ||
| T_Real & AMREX_RESTRICT y, | ||
| [[maybe_unused]] T_Real & AMREX_RESTRICT t, | ||
| T_Real & AMREX_RESTRICT px, | ||
| T_Real & AMREX_RESTRICT py, | ||
| [[maybe_unused]] T_Real & AMREX_RESTRICT pt, | ||
| T_IdCpu & AMREX_RESTRICT idcpu, | ||
| [[maybe_unused]] RefPart const & AMREX_RESTRICT refpart | ||
| ) const | ||
| { | ||
| // a complex type with two T_Real | ||
| using Complex = amrex::GpuComplex<T_Real>; | ||
|
|
||
| using namespace amrex::literals; // for _rt and _prt | ||
| namespace stdx = amrex::simd::stdx; | ||
| using amrex::Math::powi; | ||
| using std::fmod; | ||
| using std::abs; | ||
| using amrex::arg; | ||
| using VBool = decltype(x>0_prt); | ||
|
|
||
| // shift due to alignment errors of the element | ||
| shift_in(x, y, px, py); | ||
|
|
||
| // define intermediate variables | ||
| amrex::ParticleReal const dx = m_repeat_x * 0.5_prt; | ||
| amrex::ParticleReal const dy = m_repeat_y * 0.5_prt; | ||
|
|
||
| // shift every 2nd row by half of m_repeat_x | ||
| T_Real sx = x; | ||
| T_Real const sy = y; | ||
| VBool const shift_x = m_shift_odd_x == false ? VBool{false} : fmod(floor((y+dy)/m_repeat_y), 2) != T_Real{0}; | ||
| #ifdef AMREX_USE_SIMD | ||
| amrex::simd::stdx::where(shift_x, sx) += dx; | ||
| #else | ||
| sx += shift_x ? dx : 0_prt; | ||
| #endif | ||
|
|
||
| // if the aperture is periodic, shift sx,sy coordinates to the fundamental domain | ||
| T_Real u = (m_repeat_x == 0_prt) ? sx : (fmod(abs(sx)+dx, m_repeat_x)-dx); | ||
|
||
| T_Real v = (m_repeat_y == 0_prt) ? sy : (fmod(abs(sy)+dy, m_repeat_y)-dy); | ||
|
||
|
|
||
| // compare against the aperture boundary | ||
| VBool inside_aperture; | ||
|
|
||
| // calculate whether point is inside polygon or not | ||
| T_Real r2 = powi<2>(u) + powi<2>(v); | ||
| // are we inside the minimum radius? | ||
| if (r2 < min_radius2) { | ||
| inside_aperture = VBool(true); // yes! | ||
| } else{ | ||
| // no, we have to do the polygon calculation | ||
| T_Real thetasum = 0.0; | ||
| Complex v1conj, v2; | ||
| // vertices_x and vertices_y must be the same size | ||
| for (size_t i = 0; i <vertices_x.size()-1; ++i) { | ||
| v1conj = Complex(u - vertices_x[i], -(v-vertices_y[i])); | ||
| v2 = Complex(u - vertices_x[i+1], v-vertices_y[i+1]); | ||
| thetasum += arg(v2 * v1conj); | ||
| } | ||
| inside_aperture = abs(thetasum/(2*ablastr::constant::math::pi)) < 1.0e-12_prt; | ||
| } | ||
|
|
||
| // For transmit (default): invalidate if outside aperture | ||
| // For absorb: invalidate if inside aperture | ||
| auto const invalid_mask = m_action == Action::transmit ? !inside_aperture : inside_aperture; | ||
| amrex::ParticleIDWrapper<T_IdCpu>{idcpu}.make_invalid(invalid_mask); | ||
|
|
||
| // undo shift due to alignment errors of the element | ||
| shift_out(x, y, px, py); | ||
| } | ||
|
|
||
| /** This pushes the reference particle. */ | ||
| using Thin::operator(); | ||
|
|
||
| /** This pushes the covariance matrix. */ | ||
| using LinearTransport::operator(); | ||
|
|
||
| /** This function returns the linear transport map. | ||
| * | ||
| * @param[in] refpart reference particle | ||
| * @returns 6x6 transport matrix | ||
| */ | ||
| AMREX_GPU_HOST AMREX_FORCE_INLINE | ||
| Map6x6 | ||
| transport_map ([[maybe_unused]] RefPart const & AMREX_RESTRICT refpart) const | ||
| { | ||
| throw std::runtime_error(std::string(type) + ": Envelope tracking is not yet implemented!"); | ||
| return Map6x6::Identity(); | ||
| } | ||
|
|
||
| /////////////////////////////////////////////////////////////// | ||
| // class data | ||
|
|
||
| Action m_action; //! action type (transmit, absorb) | ||
| amrex::ParticleReal m_repeat_x; //! horizontal period for repeated masking | ||
| amrex::ParticleReal m_repeat_y; //! vertical period for repeated masking | ||
| bool m_shift_odd_x; //! for hexagonal/triangular mask patterns: horizontal shift of every 2nd (odd) vertical period by m_repeat_x / 2. Use Alignment offsets to move whole mask as needed. | ||
|
|
||
| int m_id; //! unique PolygonAperture id used for data lookup map | ||
|
|
||
| std::vector< amrex::ParticleReal> vertices_x; | ||
| std::vector< amrex::ParticleReal> vertices_y; | ||
| amrex::ParticleReal min_radius2; // minimum radius in which all pass squared | ||
|
|
||
| std::vector<double>::size_type m_nvert = 0; //! number of vertices | ||
| amrex::ParticleReal* m_vertices_x_h_data = nullptr; //! non-owning pointer to host cosine coefficients | ||
| amrex::ParticleReal* m_vertices_y_h_data = nullptr; //! non-owning pointer to host sine coefficients | ||
| amrex::ParticleReal* m_vertices_x_d_data = nullptr; //! non-owning pointer to device cosine coefficients | ||
| amrex::ParticleReal* m_vertices_y_d_data = nullptr; //! non-owning pointer to device sine coefficients | ||
|
|
||
| }; | ||
|
|
||
| } // namespace impactx | ||
|
|
||
| #endif // IMPACTX_POLYGONAPERTURE_H | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /* Copyright 2022-2023 The Regents of the University of California, through Lawrence | ||
| * Berkeley National Laboratory (subject to receipt of any required | ||
| * approvals from the U.S. Dept. of Energy). All rights reserved. | ||
| * | ||
| * This file is part of ImpactX. | ||
| * | ||
| * Authors: Eric G. Stern, Chad Mitchell, Axel Huebl | ||
| * License: BSD-3-Clause-LBNL | ||
| */ | ||
| #include "PolygonAperture.H" | ||
|
|
||
| #include <stdexcept> | ||
| #include <string> | ||
|
|
||
| std::string | ||
| impactx::elements::PolygonAperture::action_name (Action const & action) | ||
| { | ||
| switch (action) | ||
| { | ||
| case PolygonAperture::Action::transmit : // default | ||
| return "transmit"; | ||
| case PolygonAperture::Action::absorb : | ||
| return "absorb"; | ||
| default: | ||
| throw std::runtime_error("Unknown action"); | ||
| } | ||
| } |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.