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
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ddf1042
Add transformation BC to C++ files
connoramoreno May 5, 2025
dcd5df1
Add transformation BC to surface.py, update documentation
connoramoreno May 6, 2025
62648f8
Modify input to C++ code
connoramoreno May 6, 2025
c1aea5b
Fix implementation
connoramoreno May 7, 2025
aaa7743
Fix transformation_matrix input handling
connoramoreno May 7, 2025
4db0578
Improve handling in Surface.from_hdf5
connoramoreno May 7, 2025
00a73ce
Add regression test for transformation BC
connoramoreno May 7, 2025
7054410
Add optional translation vectors
connoramoreno May 8, 2025
5371d02
Modify translation implementation
connoramoreno May 8, 2025
d126be2
Finalize translation implementation on Python side
connoramoreno May 8, 2025
62b7b5a
Add translation to C++ code
connoramoreno May 8, 2025
7d6b6d4
Fix Python implementation
connoramoreno May 8, 2025
2e419ec
Update regression test
connoramoreno May 8, 2025
4a3ef0e
Apply C++ formatting
connoramoreno May 8, 2025
e947328
Clean up transformation inputs and documentation
connoramoreno May 9, 2025
c9f5c46
Improve warning handling
connoramoreno May 9, 2025
0ec5f5d
Modify XML reading of transformation parameters in C++ code
connoramoreno May 9, 2025
ec36581
Fix warning
connoramoreno May 9, 2025
afaab4d
Modify inputs and update code
connoramoreno May 12, 2025
3d89fbc
Update data type for transformation matrices and input checking
connoramoreno May 12, 2025
b112c02
Fix default arrays and update test
connoramoreno May 12, 2025
ac72fa3
Apply formatting
connoramoreno May 12, 2025
01cec5a
Reformat surface.cpp
connoramoreno May 12, 2025
4170115
Update documentation
connoramoreno May 12, 2025
3f5f8c6
Fix default matrices
connoramoreno May 12, 2025
2fc68ae
Remove formatting from pre-existing code
connoramoreno May 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions include/openmc/boundary_condition.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,24 @@ class RotationalPeriodicBC : public PeriodicBC {
double angle_;
};

//==============================================================================
//! A BC that transforms particle trajectory by a matrix.
//==============================================================================

class TransformationBC : public BoundaryCondition {
public:
TransformationBC(vector<double> dir_trans, vector<double> pos_trans);

void handle_particle(Particle& p, const Surface& surf) const override;

std::string type() const override { return "transformation"; }

protected:
//! Matrix by which particle directions are transformed
vector<double> dir_trans_;
//! Matrix by which particle positions are transformed
vector<double> pos_trans_;
};

} // namespace openmc
#endif // OPENMC_BOUNDARY_CONDITION_H
9 changes: 9 additions & 0 deletions include/openmc/particle.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ class Particle : public ParticleData {
void cross_periodic_bc(
const Surface& surf, Position new_r, Direction new_u, int new_surface);

//! Cross a transformation boundary condition.
//
//! \param surf The surface (with the transformation boundary condition) that
//! the particle struck.
//! \param new_r The position of the particle after transformation.
//! \param new_u The direction of the particle after transformation.
void cross_transformation_bc(
const Surface& surf, Position new_r, Direction new_u);

//! mark a particle as lost and create a particle restart file
//! \param message A warning message to display
virtual void mark_as_lost(const char* message) override;
Expand Down
253 changes: 193 additions & 60 deletions openmc/surface.py

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions src/boundary_condition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,4 +290,41 @@ void RotationalPeriodicBC::handle_particle(
p.cross_periodic_bc(surf, new_r, new_u, new_surface);
}

//==============================================================================
// TransformationBC implementation
//==============================================================================

TransformationBC::TransformationBC(
vector<double> dir_trans, vector<double> pos_trans)
{
// Set the transformation matrices
dir_trans_ = dir_trans;
pos_trans_ = pos_trans;
}

void TransformationBC::handle_particle(Particle& p, const Surface& surf) const
{
Position r = p.r();
Direction u = p.u();

Position new_r = {r.x * pos_trans_[0] + r.y * pos_trans_[1] +
r.z * pos_trans_[2] + pos_trans_[3],
r.x * pos_trans_[4] + r.y * pos_trans_[5] + r.z * pos_trans_[6] +
pos_trans_[7],
r.x * pos_trans_[8] + r.y * pos_trans_[9] + r.z * pos_trans_[10] +
pos_trans_[11]};

Position new_u = {u.x * dir_trans_[0] + u.y * dir_trans_[1] +
u.z * dir_trans_[2] + dir_trans_[3],
u.x * dir_trans_[4] + u.y * dir_trans_[5] + u.z * dir_trans_[6] +
dir_trans_[7],
u.x * dir_trans_[8] + u.y * dir_trans_[9] + u.z * dir_trans_[10] +
dir_trans_[11]};

// Handle the effects of the surface albedo on the particle's weight.
BoundaryCondition::handle_albedo(p, surf);

p.cross_transformation_bc(surf, new_r, new_u);
}

} // namespace openmc
57 changes: 57 additions & 0 deletions src/particle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,63 @@ void Particle::cross_periodic_bc(
}
}

void Particle::cross_transformation_bc(
const Surface& surf, Position new_r, Direction new_u)
{
// Do not handle transformation boundary conditions on lower universes
if (n_coord() != 1) {
mark_as_lost("Cannot transform particle " + std::to_string(id()) +
" off surface in a lower universe.");
return;
}

// Score surface currents since transformation causes the direction of the
// particle to change. For surface filters, we need to score the tallies
// twice, once before the particle's surface attribute has changed and
// once after. For mesh surface filters, we need to artificially move
// the particle slightly back in case the surface crossing is coincident
// with a mesh boundary

if (!model::active_surface_tallies.empty()) {
score_surface_tally(*this, model::active_surface_tallies);
}

if (!model::active_meshsurf_tallies.empty()) {
Position r {this->r()};
this->r() -= TINY_BIT * u();
score_surface_tally(*this, model::active_meshsurf_tallies);
this->r() = r;
}

// Adjust the particle's location and direction.
r() = new_r;
u() = new_u;

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

// If a transformation surface is coincident with a lattice or universe
// boundary, it is necessary to redetermine the particle's coordinates in
// the lower universes.
// (unless we're using a dagmc model, which has exactly one universe)
n_coord() = 1;
if (surf.geom_type() != GeometryType::DAG &&
!neighbor_list_find_cell(*this)) {
mark_as_lost("Couldn't find particle after transforming from surface " +
std::to_string(surf.id_) + ".");
return;
}

// Set previous coordinate going slightly past surface crossing
r_last_current() = r() + TINY_BIT * u();

// Diagnostic message
if (settings::verbosity >= 10 || trace()) {
write_message(1, " Transformed from surface {}", surf.id_);
}
}

void Particle::mark_as_lost(const char* message)
{
// Print warning and write lost particle file
Expand Down
32 changes: 32 additions & 0 deletions src/surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
int vector_size_exp = 12;
vector<double> dir_trans(vector_size_exp);
vector<double> pos_trans(vector_size_exp);

if (check_for_node(surf_node, "direction_transformation")) {
dir_trans =
get_node_array<double>(surf_node, "direction_transformation");
if (dir_trans.size() != vector_size_exp) {
fatal_error(fmt::format(
"Transformation on surface {} expects direction matrix size {} "
"but was given size {}",
id_, vector_size_exp, dir_trans.size()));
}
} else {
dir_trans = {
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0};
}
if (check_for_node(surf_node, "position_transformation")) {
pos_trans =
get_node_array<double>(surf_node, "position_transformation");
if (pos_trans.size() != vector_size_exp) {
fatal_error(
fmt::format("Transformation on surface {} expects position matrix "
"size {} but was given size {}",
id_, vector_size_exp, pos_trans.size()));
}
} else {
pos_trans = {
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0};
}
bc_ = make_unique<TransformationBC>(dir_trans, pos_trans);
} else {
fatal_error(fmt::format("Unknown boundary condition \"{}\" specified "
"on surface {}",
Expand Down
Empty file.
11 changes: 11 additions & 0 deletions tests/regression_tests/transformation_plane/geometry.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version='1.0' encoding='UTF-8'?>
<geometry>
<!-- Reflective box using transformation BCs -->
<cell id="1" material="1" region="1 -2 3 -4 5 -6" universe="1"/>
<surface boundary="transformation" coeffs="-5.0" id="1" direction_transformation="-1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0" type="x-plane"/>
<surface boundary="transformation" coeffs="5.0" id="2" direction_transformation="-1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0" type="x-plane"/>
<surface boundary="transformation" coeffs="-5.0" id="3" direction_transformation="1.0 0.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 1.0 0.0" type="y-plane"/>
<surface boundary="transformation" coeffs="5.0" id="4" direction_transformation="1.0 0.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 1.0 0.0" type="y-plane"/>
<surface boundary="transformation" coeffs="-5.0" id="5" direction_transformation="1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 -1.0 0.0" type="z-plane"/>
<surface boundary="transformation" coeffs="5.0" id="6" direction_transformation="1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 -1.0 0.0" type="z-plane"/>
</geometry>
7 changes: 7 additions & 0 deletions tests/regression_tests/transformation_plane/materials.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material id="1">
<density units="g/cc" value="4.5"/>
<nuclide ao="1.0" name="U235"/>
</material>
</materials>
2 changes: 2 additions & 0 deletions tests/regression_tests/transformation_plane/results_true.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
k-combined:
2.276857E+00 8.776678E-03
12 changes: 12 additions & 0 deletions tests/regression_tests/transformation_plane/settings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version='1.0' encoding='UTF-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>1000</particles>
<batches>10</batches>
<inactive>5</inactive>
<source particle="neutron" strength="1.0" type="independent">
<space type="box">
<parameters>-4.0 -4.0 -4.0 4.0 4.0 4.0</parameters>
</space>
</source>
</settings>
6 changes: 6 additions & 0 deletions tests/regression_tests/transformation_plane/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from tests.testing_harness import TestHarness


def test_reflective_plane():
harness = TestHarness('statepoint.10.h5')
harness.main()