Skip to content

Add transformation boundary condition #3402

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

Open
wants to merge 26 commits into
base: develop
Choose a base branch
from

Conversation

connoramoreno
Copy link
Contributor

@connoramoreno connoramoreno commented May 8, 2025

Description

Adds a transformation boundary condition to surfaces through which the user can define affine transformations to particle position and direction upon crossing the surface.

Mathematically, each affine transformation $\textbf{v} \rightarrow \textbf{v}'$ can be expressed as

$$ \textbf{v}' = A\textbf{v} + \textbf{b} $$

where $A$ is a $3 \times 3$ matrix representing a linear map and $\textbf{b}$ is a vector of length 3 representing a translation. This transformation can be described in a single matrix-vector product via an augmented matrix and augmented vector:

$$ \textbf{v}' = \begin{bmatrix} \textbf{a}_1 & \textbf{a}_2 & \textbf{a}_3 & \textbf{b} \end{bmatrix} \begin{bmatrix} \textbf{v} \\ 1 \end{bmatrix} := [A | \textbf{b}] \begin{bmatrix} \textbf{v} \\ 1 \end{bmatrix} $$

where $\textbf{a}_i$ is the $i^{th}$ column of $A$. I'll refer to this 3x4 augmented matrix $[A | \textbf{b}]$ as an "affine transformation matrix".

In the Python API, the affine transformations are defined by a keyword argument transformation of the Surface class that is used only if boundary_type == "transformation". transformation takes the form of a dictionary with two optional keys:

  • "direction": the affine transformation matrix modifying particle direction, given in row-major order
  • "position": the affine transformation matrix modifying particle position, given in row-major order

When boundary_type == "transformation", for each key that is not provided, the affine transformation matrix is defined as $[\mathbb{I}_3 | \textbf{0}_3]$, where $\mathbb{I}_3$ is the $3 \times 3$ identity matrix and $\textbf{0}_3$ is the length-3 zero vector.

A single regression test, transformation_plane has been added that mimics the reflective_plane test, replacing the reflective BCs with transformation BCs that apply those same reflections. The expected results file is copied directly from the reflective_plane directory. I can add additional regression tests that mimic the periodic BC tests for more robust testing.

Fixes #3394

Checklist

  • I have performed a self-review of my own code
  • I have run clang-format (version 15) on any C++ source files (if applicable)
  • I have followed the style guidelines for Python source files (if applicable)
  • I have made corresponding changes to the documentation (if applicable)
  • I have added tests that prove my fix is effective or that my feature works (if applicable)

@connoramoreno connoramoreno marked this pull request as ready for review May 12, 2025 21:31
Copy link
Contributor

@gonuke gonuke left a comment

Choose a reason for hiding this comment

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

A few streamlining suggestions

else:
for key in transformation:
if key not in ["direction", "position"]:
msg = (
Copy link
Contributor

Choose a reason for hiding this comment

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

you need to use this msg

Comment on lines +282 to +283
for key in transformation:
if key not in ["direction", "position"]:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
for key in transformation:
if key not in ["direction", "position"]:
valid_keys = {"direction", "position"}
for key in set(transformation.keys()) - valid_keys:

Comment on lines +289 to +309
if "direction" in transformation.keys():
check_type(
'transformation', transformation["direction"],
Iterable,
Real)
check_length(
'transformation', transformation["direction"], 12)
else:
transformation["direction"] = np.append(
np.identity(3), np.zeros(3,1), axis=1).flatten()

if "position" in transformation.keys():
check_type(
'transformation', transformation["position"],
Iterable,
Real)
check_length(
'transformation', transformation["position"], 12)
else:
transformation["position"] = np.append(
np.identity(3), np.zeros(3,1), axis=1).flatten()
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if "direction" in transformation.keys():
check_type(
'transformation', transformation["direction"],
Iterable,
Real)
check_length(
'transformation', transformation["direction"], 12)
else:
transformation["direction"] = np.append(
np.identity(3), np.zeros(3,1), axis=1).flatten()
if "position" in transformation.keys():
check_type(
'transformation', transformation["position"],
Iterable,
Real)
check_length(
'transformation', transformation["position"], 12)
else:
transformation["position"] = np.append(
np.identity(3), np.zeros(3,1), axis=1).flatten()
for key in valid_keys
if key in transformation:
check_type(
'transformation', transformation[key],
Iterable,
Real)
check_length(
'transformation', transformation[key], 12)
else:
transformation[key] = np.append(
np.identity(3), np.zeros(3,1), axis=1).flatten()

@@ -88,6 +88,38 @@ Surface::Surface(pugi::xml_node surf_node)
bc_ = make_unique<WhiteBC>();
} else if (surf_bc == "periodic") {
// Periodic BCs are handled separately
} else if (surf_bc == "transformation" || surf_bc == "transform") {
Copy link
Contributor

Choose a reason for hiding this comment

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

May not be necessary to support two similar keywords


// Reassign particle's cell and surface
coord(0).cell = cell_last(0);
surface() = -surface();
Copy link
Contributor

Choose a reason for hiding this comment

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

This may require more thought and consideration

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.

New boundary condition to support user-defined particle trajectory transformations at a boundary surface
2 participants