From 637e04a9ba9ceae8cb09eb66203e1581d465fa56 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 18 Jul 2025 02:51:30 -0500 Subject: [PATCH] Boundary info accessors (#3496) Co-authored-by: Paul Romano --- include/openmc/particle_data.h | 44 ++++++++++++++++++++++++---------- src/event.cpp | 2 +- src/geometry.cpp | 28 +++++++++++----------- src/mesh.cpp | 12 +++++----- src/particle.cpp | 12 +++++----- src/particle_data.cpp | 14 +++++------ src/plot.cpp | 28 +++++++++++----------- src/random_ray/random_ray.cpp | 2 +- src/simulation.cpp | 2 +- 9 files changed, 81 insertions(+), 63 deletions(-) diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index 8dd814a29..1c8f1215a 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -210,23 +210,41 @@ struct CacheDataMG { // Information about nearest boundary crossing //============================================================================== -struct BoundaryInfo { - double distance {INFINITY}; //!< distance to nearest boundary - int surface { - SURFACE_NONE}; //!< surface token, non-zero if boundary is surface - int coord_level; //!< coordinate level after crossing boundary - array - lattice_translation {}; //!< which way lattice indices will change - +class BoundaryInfo { +public: void reset() { - distance = INFINITY; - surface = SURFACE_NONE; - coord_level = 0; - lattice_translation = {0, 0, 0}; + distance_ = INFINITY; + surface_ = SURFACE_NONE; + coord_level_ = 0; + lattice_translation_ = {0, 0, 0}; } + double& distance() { return distance_; } + const double& distance() const { return distance_; } + + int& surface() { return surface_; } + const int& surface() const { return surface_; } + + int coord_level() const { return coord_level_; } + int& coord_level() { return coord_level_; } + + array& lattice_translation() { return lattice_translation_; } + const array& lattice_translation() const + { + return lattice_translation_; + } + // TODO: off-by-one - int surface_index() const { return std::abs(surface) - 1; } + int surface_index() const { return std::abs(surface()) - 1; } + +private: + // Data members + double distance_ {INFINITY}; //!< distance to nearest boundary + int surface_ { + SURFACE_NONE}; //!< surface token, non-zero if boundary is surface + int coord_level_ {0}; //!< coordinate level after crossing boundary + array lattice_translation_ { + 0, 0, 0}; //!< which way lattice indices will change }; /* diff --git a/src/event.cpp b/src/event.cpp index ae914c8be..aa3987504 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -114,7 +114,7 @@ void process_advance_particle_events() p.event_advance(); if (!p.alive()) continue; - if (p.collision_distance() > p.boundary().distance) { + if (p.collision_distance() > p.boundary().distance()) { simulation::surface_crossing_queue.thread_safe_append({p, buffer_idx}); } else { simulation::collision_queue.thread_safe_append({p, buffer_idx}); diff --git a/src/geometry.cpp b/src/geometry.cpp index cefe7d364..df4850891 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -310,9 +310,9 @@ void cross_lattice(GeometryState& p, const BoundaryInfo& boundary, bool verbose) } // Set the lattice indices. - coord.lattice_index()[0] += boundary.lattice_translation[0]; - coord.lattice_index()[1] += boundary.lattice_translation[1]; - coord.lattice_index()[2] += boundary.lattice_translation[2]; + coord.lattice_index()[0] += boundary.lattice_translation()[0]; + coord.lattice_index()[1] += boundary.lattice_translation()[1]; + coord.lattice_index()[2] += boundary.lattice_translation()[2]; // Set the new coordinate position. const auto& upper_coord {p.coord(p.n_coord() - 2)}; @@ -410,7 +410,7 @@ BoundaryInfo distance_to_boundary(GeometryState& p) // If the boundary on this coordinate level is coincident with a boundary on // a higher level then we need to make sure that the higher level boundary // is selected. This logic must consider floating point precision. - double& d = info.distance; + double& d = info.distance(); if (d_surf < d_lat - FP_COINCIDENT) { if (d == INFINITY || (d - d_surf) / d >= FP_REL_PRECISION) { // Update closest distance @@ -421,29 +421,29 @@ BoundaryInfo distance_to_boundary(GeometryState& p) // have to explicitly check which half-space the particle would be // traveling into if the surface is crossed if (c.is_simple() || d == INFTY) { - info.surface = level_surf_cross; + info.surface() = level_surf_cross; } else { Position r_hit = r + d_surf * u; Surface& surf {*model::surfaces[std::abs(level_surf_cross) - 1]}; Direction norm = surf.normal(r_hit); if (u.dot(norm) > 0) { - info.surface = std::abs(level_surf_cross); + info.surface() = std::abs(level_surf_cross); } else { - info.surface = -std::abs(level_surf_cross); + info.surface() = -std::abs(level_surf_cross); } } - info.lattice_translation[0] = 0; - info.lattice_translation[1] = 0; - info.lattice_translation[2] = 0; - info.coord_level = i + 1; + info.lattice_translation()[0] = 0; + info.lattice_translation()[1] = 0; + info.lattice_translation()[2] = 0; + info.coord_level() = i + 1; } } else { if (d == INFINITY || (d - d_lat) / d >= FP_REL_PRECISION) { d = d_lat; - info.surface = SURFACE_NONE; - info.lattice_translation = level_lat_trans; - info.coord_level = i + 1; + info.surface() = SURFACE_NONE; + info.lattice_translation() = level_lat_trans; + info.coord_level() = i + 1; } } } diff --git a/src/mesh.cpp b/src/mesh.cpp index 1b2c71eb2..9147efb95 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -385,7 +385,7 @@ void Mesh::material_volumes(int nx, int ny, int nz, int table_size, BoundaryInfo boundary = distance_to_boundary(p); // Advance particle forward - double distance = std::min(boundary.distance, max_distance); + double distance = std::min(boundary.distance(), max_distance); p.move_distance(distance); // Determine what mesh elements were crossed by particle @@ -416,12 +416,12 @@ void Mesh::material_volumes(int nx, int ny, int nz, int table_size, p.n_coord_last() = p.n_coord(); // Set surface that particle is on and adjust coordinate levels - p.surface() = boundary.surface; - p.n_coord() = boundary.coord_level; + p.surface() = boundary.surface(); + p.n_coord() = boundary.coord_level(); - if (boundary.lattice_translation[0] != 0 || - boundary.lattice_translation[1] != 0 || - boundary.lattice_translation[2] != 0) { + if (boundary.lattice_translation()[0] != 0 || + boundary.lattice_translation()[1] != 0 || + boundary.lattice_translation()[2] != 0) { // Particle crosses lattice boundary cross_lattice(p, boundary); } else { diff --git a/src/particle.cpp b/src/particle.cpp index 4758cded5..f9044b2d7 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -242,7 +242,7 @@ void Particle::event_advance() } // Select smaller of the two distances - double distance = std::min(boundary().distance, collision_distance()); + double distance = std::min(boundary().distance(), collision_distance()); // Advance particle in space and time // Short-term solution until the surface source is revised and we can use @@ -298,12 +298,12 @@ void Particle::event_cross_surface() n_coord_last() = n_coord(); // Set surface that particle is on and adjust coordinate levels - surface() = boundary().surface; - n_coord() = boundary().coord_level; + surface() = boundary().surface(); + n_coord() = boundary().coord_level(); - if (boundary().lattice_translation[0] != 0 || - boundary().lattice_translation[1] != 0 || - boundary().lattice_translation[2] != 0) { + if (boundary().lattice_translation()[0] != 0 || + boundary().lattice_translation()[1] != 0 || + boundary().lattice_translation()[2] != 0) { // Particle crosses lattice boundary bool verbose = settings::verbosity >= 10 || trace(); diff --git a/src/particle_data.cpp b/src/particle_data.cpp index aff2b68ba..370ca12e4 100644 --- a/src/particle_data.cpp +++ b/src/particle_data.cpp @@ -65,22 +65,22 @@ void GeometryState::advance_to_boundary_from_void() for (auto c_i : root_universe->cells_) { auto dist = model::cells.at(c_i)->distance(root_coord.r(), root_coord.u(), 0, this); - if (dist.first < boundary().distance) { - boundary().distance = dist.first; - boundary().surface = dist.second; + if (dist.first < boundary().distance()) { + boundary().distance() = dist.first; + boundary().surface() = dist.second; } } // if no intersection or near-infinite intersection, reset // boundary information - if (boundary().distance > 1e300) { - boundary().distance = INFTY; - boundary().surface = SURFACE_NONE; + if (boundary().distance() > 1e300) { + boundary().distance() = INFTY; + boundary().surface() = SURFACE_NONE; return; } // move the particle up to (and just past) the boundary - move_distance(boundary().distance + TINY_BIT); + move_distance(boundary().distance() + TINY_BIT); } void GeometryState::move_distance(double length) diff --git a/src/plot.cpp b/src/plot.cpp index db10c7600..2cadc48ce 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1634,7 +1634,7 @@ void Ray::trace() break; // if there is no intersection with the model, we're done - if (boundary().surface == SURFACE_NONE) + if (boundary().surface() == SURFACE_NONE) return; event_counter_++; @@ -1646,10 +1646,10 @@ void Ray::trace() // Call the specialized logic for this type of ray. This is for the // intersection for the first intersection if we had one. - if (boundary().surface != SURFACE_NONE) { + if (boundary().surface() != SURFACE_NONE) { // set the geometry state's surface attribute to be used for // surface normal computation - surface() = boundary().surface; + surface() = boundary().surface(); on_intersection(); if (stop_) return; @@ -1674,37 +1674,37 @@ void Ray::trace() // if we hit the edge of the model, so stop // the particle in that case. Also, just exit // if a negative distance was somehow computed. - if (boundary().distance == INFTY || boundary().distance == INFINITY || - boundary().distance < 0) { + if (boundary().distance() == INFTY || boundary().distance() == INFINITY || + boundary().distance() < 0) { return; } // See below comment where call_on_intersection is checked in an // if statement for an explanation of this. bool call_on_intersection {true}; - if (boundary().distance < 10 * TINY_BIT) { + if (boundary().distance() < 10 * TINY_BIT) { call_on_intersection = false; } // DAGMC surfaces expect us to go a little bit further than the advance // distance to properly check cell inclusion. - boundary().distance += TINY_BIT; + boundary().distance() += TINY_BIT; // Advance particle, prepare for next intersection for (int lev = 0; lev < n_coord(); ++lev) { - coord(lev).r() += boundary().distance * coord(lev).u(); + coord(lev).r() += boundary().distance() * coord(lev).u(); } - surface() = boundary().surface; + surface() = boundary().surface(); n_coord_last() = n_coord(); - n_coord() = boundary().coord_level; - if (boundary().lattice_translation[0] != 0 || - boundary().lattice_translation[1] != 0 || - boundary().lattice_translation[2] != 0) { + n_coord() = boundary().coord_level(); + if (boundary().lattice_translation()[0] != 0 || + boundary().lattice_translation()[1] != 0 || + boundary().lattice_translation()[2] != 0) { cross_lattice(*this, boundary(), settings::verbosity >= 10); } // Record how far the ray has traveled - traversal_distance_ += boundary().distance; + traversal_distance_ += boundary().distance(); inside_cell = neighbor_list_find_cell(*this, settings::verbosity >= 10); // Call the specialized logic for this type of ray. Note that we do not diff --git a/src/random_ray/random_ray.cpp b/src/random_ray/random_ray.cpp index 2eca5b0ab..27f674c42 100644 --- a/src/random_ray/random_ray.cpp +++ b/src/random_ray/random_ray.cpp @@ -281,7 +281,7 @@ void RandomRay::event_advance_ray() { // Find the distance to the nearest boundary boundary() = distance_to_boundary(*this); - double distance = boundary().distance; + double distance = boundary().distance(); if (distance < 0.0) { mark_as_lost("Negative transport distance detected for particle " + diff --git a/src/simulation.cpp b/src/simulation.cpp index d9a4fd131..b9986f473 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -790,7 +790,7 @@ void transport_history_based_single_particle(Particle& p) p.event_advance(); } if (p.alive()) { - if (p.collision_distance() > p.boundary().distance) { + if (p.collision_distance() > p.boundary().distance()) { p.event_cross_surface(); } else if (p.alive()) { p.event_collide();