Add particle BC: angle_threshold (thermalize vs reflective by incidence angle)#862
Add particle BC: angle_threshold (thermalize vs reflective by incidence angle)#862PLASMAsDJ wants to merge 3 commits intoSmileiPIC:masterfrom
Conversation
|
This pull request is opened primarily for review/evaluation and to provide an easy-to-read diff of the proposed changes. |
mccoys
left a comment
There was a problem hiding this comment.
I didn't check fully your code but there are some comments
| namespace { | ||
|
|
||
| // Trim whitespace | ||
| inline std::string strip_spaces( std::string s ) |
There was a problem hiding this comment.
Inline will likely not be used here
| // "angle_threshold:0.05" -> 0.05 radians (default unit) | ||
| // "angle_threshold:0.05rad" -> 0.05 radians | ||
| // If no parameter is provided ("angle_threshold"), defaults to pi/2 (≈ always thermalize). | ||
| inline double parse_angle0_rad_from_bc( const std::string &bc ) |
| // If no parameter is provided ("angle_threshold"), defaults to pi/2 (≈ always thermalize). | ||
| inline double parse_angle0_rad_from_bc( const std::string &bc ) | ||
| { | ||
| const double pi = std::acos( -1.0 ); |
There was a problem hiding this comment.
You can use M_PI, i believe, for pi. To be checked
| std::string s = strip_spaces( bc.substr( pos + 1 ) ); | ||
| bool is_deg = false; | ||
| bool is_rad = false; | ||
|
|
There was a problem hiding this comment.
I suggest not giving the choice of degrees. This makes the input too difficult to benchmark when there are too many possibilities. Users can easily switch from the python script
| #pragma omp declare target | ||
| #endif | ||
|
|
||
| inline double compute_alpha( int direction, |
There was a problem hiding this comment.
Again I am not sure you can defined inline functions here. If needed on gpu, this might cost something
| { | ||
| // Decide alpha0 from the BC string on this side | ||
| const std::string &bc = species->boundary_conditions_[direction][0]; | ||
| const double alpha0 = parse_angle0_rad_from_bc( bc ); |
There was a problem hiding this comment.
These tests should not be done here. Parse the string art the initialization, otherwise this will be to slow
There was a problem hiding this comment.
@mccoys Thanks for the comment. I was able to address the other comments rather straightforwardly, but this one seemed a bit more involved, so I just wanted to check if I understood your suggestion correctly.
Would you recommend parsing the boundary-condition string only once during initialization, then storing the parsed angle-threshold value as a parameter to be reused at runtime, instead of parsing it inside BoundaryConditionType.cpp?
If that is what you mean, I was thinking it might require a small refactor on the initialization side, for example by storing the value in Species and setting it from SpeciesFactory. Would that be the right direction?
There was a problem hiding this comment.
Yes that sounds exactly right
There was a problem hiding this comment.
@mccoys Thanks again for the suggestion. I updated the implementation accordingly, and there have been several revisions to the code. I would be very grateful if you could review it again when you have time.
I agree that optimization is important. At the same time, my main focus here is to implement the intended particle boundary-condition mechanism, where the particle behavior at the boundary is determined by the incidence angle with respect to the boundary normal. I would also appreciate your feedback on whether this mechanism is represented appropriately in the current implementation.
The threshold angle is now parsed once during initialization, stored as a species parameter, and reused at runtime instead of being parsed inside BoundaryConditionType.cpp.
I also updated the PR description and rechecked the behavior with 1D and 2D test runs.
Summary
This PR adds a new particle boundary condition,
angle_threshold, which switches betweenthermalizeandreflectivedepending on the particle incidence angle relative to the outward normal of the boundary.Motivation / reference
This implementation is inspired by the boundary-treatment approach described in:
[Chen, H., et al, Geophysical research letters, 52, e2025GL116478 (2025)]
Definition
Let n be the outward normal vector of the boundary. The particle velocity is decomposed into components parallel and perpendicular to n, and the incidence angle is defined as:
α = tan⁻¹(v⊥ / v∥)
If α ≤ α₀ (user-defined threshold), the particle is handled with
thermalize; otherwise,reflectiveis applied.Implementation
In the updated implementation:
Modified files
src/ParticleBC/BoundaryConditionType.cppsrc/ParticleBC/BoundaryConditionType.hsrc/ParticleBC/PartBoundCond.cppsrc/Python/pyinit.pysrc/Species/Species.hsrc/Species/SpeciesFactory.hTests
I rechecked the basic behavior with 1D and 2D test runs after the refactor.
If needed, I can provide a minimal namelist and a small test to reproduce the results.
Example namelists:
angle_threshold_Test_1D.pyangle_threshold_Test_1D.py
angle_threshold_Test_2D.pyangle_threshold_Test_2D.py
Note
This PR is mainly intended to get feedback on the implementation approach and code structure.
Namelist usage
1D:
boundary_conditions = [
["angle_threshold", "angle_threshold"],
]
threshold_angle = [
[a_xmin, a_xmax],
]
2D (x and y both use
angle_threshold):boundary_conditions = [
["angle_threshold", "angle_threshold"],
["angle_threshold", "angle_threshold"],
]
threshold_angle = [
[a_xmin, a_xmax],
[a_ymin, a_ymax],
]
2D (only y uses
angle_threshold):boundary_conditions = [
["reflective", "reflective"],
["angle_threshold", "angle_threshold"],
]
threshold_angle = [
[a_ymin, a_ymax],
]