Skip to content

Commit 288c0f2

Browse files
author
skywalker_cn
committed
Adds support for virtual lattice geometry handling
Introduces functionality to calculate distances and locate cells within virtual lattice geometries. Refactors existing geometry handling logic to reduce code duplication and improve maintainability. Key updates include: - Addition of `distance_in_virtual_lattice` and `find_cell_in_virtual_lattice` methods for specialized handling. - Integration of virtual lattice checks in standard cell distance computations. - Refactoring of repetitive code in surface crossing handlers for improved clarity. Enhances support for TRISO particle geometries within virtual lattices, ensuring accurate material and cell identification during particle transport.
1 parent 3f69b39 commit 288c0f2

7 files changed

Lines changed: 237 additions & 211 deletions

File tree

include/openmc/cell.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,9 @@ class CSGCell : public Cell {
381381
std::pair<double, int32_t> distance(Position r, Direction u,
382382
int32_t on_surface, GeometryState* p) const override;
383383

384+
std::pair<double, int32_t> distance_in_virtual_lattice(
385+
Position r, Direction u, int32_t on_surface, GeometryState* p) const;
386+
384387
bool contains(Position r, Direction u, int32_t on_surface) const override
385388
{
386389
return region_.contains(r, u, on_surface);

include/openmc/geometry.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ bool exhaustive_find_cell(GeometryState& p, bool verbose = false);
6464
bool neighbor_list_find_cell(
6565
GeometryState& p, bool verbose = false); // Only usable on surface crossings
6666

67+
bool find_cell_in_virtual_lattice(GeometryState& p,
68+
bool verbose =
69+
false); // Only usable on triso surface crossings in virtual lattice
70+
6771
//==============================================================================
6872
//! Move a particle into a new lattice tile.
6973
//==============================================================================

include/openmc/universe.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class Universe {
3838

3939
virtual bool find_cell(GeometryState& p) const;
4040

41+
virtual bool find_cell_in_virtual_lattice(GeometryState& p) const;
42+
4143
BoundingBox bounding_box() const;
4244

4345
/* By default, universes are CSG universes. The DAGMC

src/cell.cpp

Lines changed: 75 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -505,96 +505,101 @@ vector<int32_t>::iterator CSGCell::find_left_parenthesis(
505505
}
506506
std::pair<double, int32_t> CSGCell::distance(
507507
Position r, Direction u, int32_t on_surface, GeometryState* p) const
508+
{
509+
if (virtual_lattice_) {
510+
return distance_in_virtual_lattice(r, u, on_surface, p);
511+
} else {
512+
return region_.distance(r, u, on_surface);
513+
}
514+
}
515+
516+
std::pair<double, int32_t> CSGCell::distance_in_virtual_lattice(
517+
Position r, Direction u, int32_t on_surface, GeometryState* p) const
508518
{
509519
double min_dist {INFTY};
510520
int32_t i_surf {std::numeric_limits<int32_t>::max()};
511521
double min_dis_vl;
512522
int32_t i_surf_vl;
513-
if (virtual_lattice_) {
514-
double max_dis = p->collision_distance();
515-
double tol_dis = 0;
516-
vector<double> dis_to_bou(3), dis_to_bou_max(3);
517-
double u_value = sqrt(pow(u.x, 2) + pow(u.y, 2) +
518-
pow(u.z, 2)); // don't know if u has been normalized
519-
vector<double> norm_u = {u.x / u_value, u.y / u_value, u.z / u_value};
520-
vector<int> lat_ind(3);
521-
vector<double> temp_pos = {r.x, r.y, r.z};
522-
int loop_time;
523-
for (int i = 0; i < 3; i++) {
524-
lat_ind[i] = floor((temp_pos[i] - vl_lower_left_[i]) / vl_pitch_[i]);
525-
if (lat_ind[i] == vl_shape_[i] && norm_u[i] < 0) {
526-
lat_ind[i] = vl_shape_[i] - 1;
527-
}
528-
if (lat_ind[i] == -1 && norm_u[i] > 0) {
529-
lat_ind[i] = 0;
530-
}
523+
524+
double max_dis = p->collision_distance();
525+
double tol_dis = 0;
526+
vector<double> dis_to_bou(3), dis_to_bou_max(3);
527+
double u_value = sqrt(pow(u.x, 2) + pow(u.y, 2) +
528+
pow(u.z, 2)); // don't know if u has been normalized
529+
vector<double> norm_u = {u.x / u_value, u.y / u_value, u.z / u_value};
530+
vector<int> lat_ind(3);
531+
vector<double> temp_pos = {r.x, r.y, r.z};
532+
int loop_time;
533+
for (int i = 0; i < 3; i++) {
534+
lat_ind[i] = floor((temp_pos[i] - vl_lower_left_[i]) / vl_pitch_[i]);
535+
if (lat_ind[i] == vl_shape_[i] && norm_u[i] < 0) {
536+
lat_ind[i] = vl_shape_[i] - 1;
537+
}
538+
if (lat_ind[i] == -1 && norm_u[i] > 0) {
539+
lat_ind[i] = 0;
531540
}
541+
}
532542

533-
dis_to_bou = {INFTY, INFTY, INFTY};
534-
for (int i = 0; i < 3; i++) {
535-
if (norm_u[i] > 0) {
536-
dis_to_bou[i] = std::abs(
537-
((lat_ind[i] + 1) * vl_pitch_[i] + vl_lower_left_[i] - temp_pos[i]) /
538-
norm_u[i]);
539-
dis_to_bou_max[i] = vl_pitch_[i] / norm_u[i];
540-
} else if (norm_u[i] < 0) {
541-
dis_to_bou[i] = std::abs(
542-
(lat_ind[i] * vl_pitch_[i] + vl_lower_left_[i] - temp_pos[i]) /
543-
norm_u[i]);
544-
dis_to_bou_max[i] = -vl_pitch_[i] / norm_u[i];
545-
}
543+
dis_to_bou = {INFTY, INFTY, INFTY};
544+
for (int i = 0; i < 3; i++) {
545+
if (norm_u[i] > 0) {
546+
dis_to_bou[i] = std::abs(
547+
((lat_ind[i] + 1) * vl_pitch_[i] + vl_lower_left_[i] - temp_pos[i]) /
548+
norm_u[i]);
549+
dis_to_bou_max[i] = vl_pitch_[i] / norm_u[i];
550+
} else if (norm_u[i] < 0) {
551+
dis_to_bou[i] =
552+
std::abs((lat_ind[i] * vl_pitch_[i] + vl_lower_left_[i] - temp_pos[i]) /
553+
norm_u[i]);
554+
dis_to_bou_max[i] = -vl_pitch_[i] / norm_u[i];
546555
}
556+
}
547557

548-
while (true) {
549-
if (lat_ind[0] < 0 || lat_ind[0] >= vl_shape_[0] || lat_ind[1] < 0 ||
550-
lat_ind[1] >= vl_shape_[1] || lat_ind[2] < 0 ||
551-
lat_ind[2] >= vl_shape_[2])
552-
break;
558+
while (true) {
559+
if (lat_ind[0] < 0 || lat_ind[0] >= vl_shape_[0] || lat_ind[1] < 0 ||
560+
lat_ind[1] >= vl_shape_[1] || lat_ind[2] < 0 ||
561+
lat_ind[2] >= vl_shape_[2])
562+
break;
553563

554-
for (int token :
555-
vl_triso_distribution_[lat_ind[0] + lat_ind[1] * vl_shape_[0] +
556-
lat_ind[2] * vl_shape_[0] * vl_shape_[1]]) {
557-
bool coincident {std::abs(token) == std::abs(on_surface)};
558-
double d {model::surfaces[abs(token) - 1]->distance(r, u, coincident)};
559-
if (d < min_dist) {
560-
if (min_dist - d >= FP_PRECISION * min_dist) {
561-
min_dist = d;
562-
i_surf = -token;
563-
}
564+
for (int token :
565+
vl_triso_distribution_[lat_ind[0] + lat_ind[1] * vl_shape_[0] +
566+
lat_ind[2] * vl_shape_[0] * vl_shape_[1]]) {
567+
bool coincident {std::abs(token) == std::abs(on_surface)};
568+
double d {model::surfaces[abs(token) - 1]->distance(r, u, coincident)};
569+
if (d < min_dist) {
570+
if (min_dist - d >= FP_PRECISION * min_dist) {
571+
min_dist = d;
572+
i_surf = -token;
564573
}
565574
}
575+
}
566576

567-
int mes_bou_crossed = 0;
568-
if (dis_to_bou[1] < dis_to_bou[0]) {
569-
mes_bou_crossed = 1;
570-
}
571-
if (dis_to_bou[2] < dis_to_bou[mes_bou_crossed]) {
572-
mes_bou_crossed = 2;
573-
}
577+
int mes_bou_crossed = 0;
578+
if (dis_to_bou[1] < dis_to_bou[0]) {
579+
mes_bou_crossed = 1;
580+
}
581+
if (dis_to_bou[2] < dis_to_bou[mes_bou_crossed]) {
582+
mes_bou_crossed = 2;
583+
}
574584

575-
tol_dis = dis_to_bou[mes_bou_crossed];
585+
tol_dis = dis_to_bou[mes_bou_crossed];
576586

577-
if (min_dist < tol_dis) {
578-
break;
579-
}
587+
if (min_dist < tol_dis) {
588+
break;
589+
}
580590

581-
if (norm_u[mes_bou_crossed] > 0) {
582-
lat_ind[mes_bou_crossed] += 1;
583-
} else {
584-
lat_ind[mes_bou_crossed] += -1;
585-
}
591+
if (norm_u[mes_bou_crossed] > 0) {
592+
lat_ind[mes_bou_crossed] += 1;
593+
} else {
594+
lat_ind[mes_bou_crossed] += -1;
595+
}
586596

587-
dis_to_bou[mes_bou_crossed] += dis_to_bou_max[mes_bou_crossed];
597+
dis_to_bou[mes_bou_crossed] += dis_to_bou_max[mes_bou_crossed];
588598

589-
if (tol_dis > max_dis) {
590-
break;
591-
}
599+
if (tol_dis > max_dis) {
600+
break;
592601
}
593-
594-
} else {
595-
return region_.distance(r, u, on_surface);
596602
}
597-
598603
return {min_dist, i_surf};
599604
}
600605

src/geometry.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,98 @@ bool exhaustive_find_cell(GeometryState& p, bool verbose)
294294
return find_cell_inner(p, nullptr, verbose);
295295
}
296296

297+
bool find_cell_in_virtual_lattice(GeometryState& p, bool verbose)
298+
{
299+
int i_surface = std::abs(p.surface());
300+
if (p.surface() > 0) {
301+
for (int i = p.n_coord(); i < model::n_coord_levels; i++) {
302+
p.coord(i).reset();
303+
}
304+
p.coord(p.n_coord() - 1).cell() =
305+
model::cell_map[model::surfaces[i_surface - 1]->triso_base_index_];
306+
} else if (p.surface() < 0) {
307+
for (int i = p.n_coord(); i < model::n_coord_levels; i++) {
308+
p.coord(i).reset();
309+
}
310+
if (model::surfaces[i_surface - 1]->triso_particle_index_ == -1) {
311+
fatal_error(fmt::format("Particle cell of surface {} is not defined",
312+
model::surfaces[i_surface - 1]->id_));
313+
}
314+
p.lowest_coord().cell() =
315+
model::cell_map[model::surfaces[i_surface - 1]->triso_particle_index_];
316+
}
317+
318+
// find material
319+
bool found = true;
320+
int i_cell = p.lowest_coord().cell();
321+
for (;; ++p.n_coord()) {
322+
if (i_cell == C_NONE) {
323+
int i_universe = p.lowest_coord().universe();
324+
const auto& univ {model::universes[i_universe]};
325+
326+
if (univ->filled_with_triso_base_ != -1) {
327+
p.lowest_coord().cell() =
328+
model::cell_map[univ->filled_with_triso_base_];
329+
found = true;
330+
} else {
331+
found = univ->find_cell(p);
332+
}
333+
if (!found) {
334+
return found;
335+
}
336+
}
337+
338+
i_cell = p.lowest_coord().cell();
339+
340+
Cell& c {*model::cells[i_cell]};
341+
if (c.type_ == Fill::MATERIAL) {
342+
// Found a material cell which means this is the lowest coord level.
343+
344+
p.cell_instance() = 0;
345+
// Find the distribcell instance number.
346+
if (c.distribcell_index_ >= 0) {
347+
p.cell_instance() = cell_instance_at_level(p, p.n_coord() - 1);
348+
}
349+
350+
// Set the material and temperature.
351+
p.material_last() = p.material();
352+
if (c.material_.size() > 1) {
353+
p.material() = c.material_[p.cell_instance()];
354+
} else {
355+
p.material() = c.material_[0];
356+
}
357+
p.sqrtkT_last() = p.sqrtkT();
358+
if (c.sqrtkT_.size() > 1) {
359+
p.sqrtkT() = c.sqrtkT_[p.cell_instance()];
360+
} else {
361+
p.sqrtkT() = c.sqrtkT_[0];
362+
}
363+
return found;
364+
365+
} else if (c.type_ == Fill::UNIVERSE) {
366+
//========================================================================
367+
//! Found a lower universe, update this coord level then search the
368+
//! next.
369+
370+
// Set the lower coordinate level universe.
371+
auto& coor {p.coord(p.n_coord())};
372+
coor.universe() = c.fill_;
373+
374+
// Set the position and direction.
375+
coor.r() = p.r_local();
376+
coor.u() = p.u_local();
377+
378+
// Apply translation.
379+
coor.r() -= c.translation_;
380+
381+
// Apply rotation.
382+
if (!c.rotation_.empty()) {
383+
coor.rotate(c.rotation_);
384+
}
385+
i_cell = C_NONE;
386+
}
387+
}
388+
}
297389
//==============================================================================
298390

299391
void cross_lattice(GeometryState& p, const BoundaryInfo& boundary, bool verbose)

0 commit comments

Comments
 (0)