Skip to content

Commit a64cc96

Browse files
authored
Fixed a bug in distribcell offsets logic (openmc-dev#3424)
1 parent 6f5e134 commit a64cc96

16 files changed

Lines changed: 325 additions & 87 deletions

File tree

include/openmc/cell.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ class Cell {
226226
void set_temperature(
227227
double T, int32_t instance = -1, bool set_contained = false);
228228

229+
int32_t n_instances() const;
230+
229231
//! Set the rotation matrix of a cell instance
230232
//! \param[in] rot The rotation matrix of length 3 or 9
231233
void set_rotation(const vector<double>& rot);
@@ -312,12 +314,11 @@ class Cell {
312314
//----------------------------------------------------------------------------
313315
// Data members
314316

315-
int32_t id_; //!< Unique ID
316-
std::string name_; //!< User-defined name
317-
Fill type_; //!< Material, universe, or lattice
318-
int32_t universe_; //!< Universe # this cell is in
319-
int32_t fill_; //!< Universe # filling this cell
320-
int32_t n_instances_ {0}; //!< Number of instances of this cell
317+
int32_t id_; //!< Unique ID
318+
std::string name_; //!< User-defined name
319+
Fill type_; //!< Material, universe, or lattice
320+
int32_t universe_; //!< Universe # this cell is in
321+
int32_t fill_; //!< Universe # filling this cell
321322

322323
//! \brief Index corresponding to this cell in distribcell arrays
323324
int distribcell_index_ {C_NONE};

include/openmc/geometry_aux.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
namespace openmc {
1616

1717
namespace model {
18-
extern std::unordered_map<int32_t, std::unordered_map<int32_t, int32_t>>
19-
universe_cell_counts;
2018
extern std::unordered_map<int32_t, int32_t> universe_level_counts;
2119
} // namespace model
2220

@@ -80,15 +78,13 @@ void prepare_distribcell(
8078
const std::vector<int32_t>* user_distribcells = nullptr);
8179

8280
//==============================================================================
83-
//! Recursively search through the geometry and count cell instances.
81+
//! Recursively search through the geometry and count universe instances.
8482
//!
85-
//! This function will update the Cell::n_instances value for each cell in the
86-
//! geometry.
87-
//! \param univ_indx The index of the universe to begin searching from (probably
88-
//! the root universe).
83+
//! This function will update Universe.n_instances_ for each
84+
//! universe in the geometry.
8985
//==============================================================================
9086

91-
void count_cell_instances(int32_t univ_indx);
87+
void count_universe_instances();
9288

9389
//==============================================================================
9490
//! Recursively search through universes and count universe instances.

include/openmc/lattice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class Lattice {
7676
}
7777

7878
//! Populate the distribcell offset tables.
79-
int32_t fill_offset_table(int32_t offset, int32_t target_univ_id, int map,
79+
int32_t fill_offset_table(int32_t target_univ_id, int map,
8080
std::unordered_map<int32_t, int32_t>& univ_count_memo);
8181

8282
//! \brief Check lattice indices.

include/openmc/universe.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class Universe {
2929
public:
3030
int32_t id_; //!< Unique ID
3131
vector<int32_t> cells_; //!< Cells within this universe
32+
int32_t n_instances_; //!< Number of instances of this universe
3233

3334
//! \brief Write universe information to an HDF5 group.
3435
//! \param group_id An HDF5 group id.

src/cell.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ vector<unique_ptr<Cell>> cells;
4040
// Cell implementation
4141
//==============================================================================
4242

43+
int32_t Cell::n_instances() const
44+
{
45+
return model::universes[universe_]->n_instances_;
46+
}
47+
4348
void Cell::set_rotation(const vector<double>& rot)
4449
{
4550
if (fill_ == C_NONE) {
@@ -115,8 +120,8 @@ void Cell::set_temperature(double T, int32_t instance, bool set_contained)
115120
if (type_ == Fill::MATERIAL) {
116121
if (instance >= 0) {
117122
// If temperature vector is not big enough, resize it first
118-
if (sqrtkT_.size() != n_instances_)
119-
sqrtkT_.resize(n_instances_, sqrtkT_[0]);
123+
if (sqrtkT_.size() != n_instances())
124+
sqrtkT_.resize(n_instances(), sqrtkT_[0]);
120125

121126
// Set temperature for the corresponding instance
122127
sqrtkT_.at(instance) = std::sqrt(K_BOLTZMANN * T);
@@ -170,7 +175,7 @@ void Cell::import_properties_hdf5(hid_t group)
170175

171176
// Ensure number of temperatures makes sense
172177
auto n_temps = temps.size();
173-
if (n_temps > 1 && n_temps != n_instances_) {
178+
if (n_temps > 1 && n_temps != n_instances()) {
174179
throw std::runtime_error(fmt::format(
175180
"Number of temperatures for cell {} doesn't match number of instances",
176181
id_));
@@ -1618,7 +1623,7 @@ extern "C" int openmc_cell_get_num_instances(
16181623
set_errmsg("Index in cells array is out of bounds.");
16191624
return OPENMC_E_OUT_OF_BOUNDS;
16201625
}
1621-
*num_instances = model::cells[index]->n_instances_;
1626+
*num_instances = model::cells[index]->n_instances();
16221627
return 0;
16231628
}
16241629

src/finalize.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,6 @@ int openmc_finalize()
185185
int openmc_reset()
186186
{
187187

188-
model::universe_cell_counts.clear();
189188
model::universe_level_counts.clear();
190189

191190
for (auto& t : model::tallies) {

src/geometry_aux.cpp

Lines changed: 26 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,9 @@
2525
namespace openmc {
2626

2727
namespace model {
28-
std::unordered_map<int32_t, std::unordered_map<int32_t, int32_t>>
29-
universe_cell_counts;
3028
std::unordered_map<int32_t, int32_t> universe_level_counts;
3129
} // namespace model
3230

33-
// adds the cell counts of universe b to universe a
34-
void update_universe_cell_count(int32_t a, int32_t b)
35-
{
36-
auto& universe_a_counts = model::universe_cell_counts[a];
37-
const auto& universe_b_counts = model::universe_cell_counts[b];
38-
for (const auto& it : universe_b_counts) {
39-
universe_a_counts[it.first] += it.second;
40-
}
41-
}
42-
4331
void read_geometry_xml()
4432
{
4533
// Display output message
@@ -263,7 +251,7 @@ void finalize_geometry()
263251
{
264252
// Perform some final operations to set up the geometry
265253
adjust_indices();
266-
count_cell_instances(model::root_universe);
254+
count_universe_instances();
267255
partition_universes();
268256

269257
// Assign temperatures to cells that don't have temperatures already assigned
@@ -356,35 +344,38 @@ void prepare_distribcell(const std::vector<int32_t>* user_distribcells)
356344
Cell& c {*model::cells[i]};
357345

358346
if (c.material_.size() > 1) {
359-
if (c.material_.size() != c.n_instances_) {
347+
if (c.material_.size() != c.n_instances()) {
360348
fatal_error(fmt::format(
361349
"Cell {} was specified with {} materials but has {} distributed "
362350
"instances. The number of materials must equal one or the number "
363351
"of instances.",
364-
c.id_, c.material_.size(), c.n_instances_));
352+
c.id_, c.material_.size(), c.n_instances()));
365353
}
366354
}
367355

368356
if (c.sqrtkT_.size() > 1) {
369-
if (c.sqrtkT_.size() != c.n_instances_) {
357+
if (c.sqrtkT_.size() != c.n_instances()) {
370358
fatal_error(fmt::format(
371359
"Cell {} was specified with {} temperatures but has {} distributed "
372360
"instances. The number of temperatures must equal one or the number "
373361
"of instances.",
374-
c.id_, c.sqrtkT_.size(), c.n_instances_));
362+
c.id_, c.sqrtkT_.size(), c.n_instances()));
375363
}
376364
}
377365
}
378366

379367
// Search through universes for material cells and assign each one a
380-
// unique distribcell array index.
381-
int distribcell_index = 0;
368+
// distribcell array index according to the containing universe.
382369
vector<int32_t> target_univ_ids;
383370
for (const auto& u : model::universes) {
384371
for (auto idx : u->cells_) {
385372
if (distribcells.find(idx) != distribcells.end()) {
386-
model::cells[idx]->distribcell_index_ = distribcell_index++;
387-
target_univ_ids.push_back(u->id_);
373+
if (!contains(target_univ_ids, u->id_)) {
374+
target_univ_ids.push_back(u->id_);
375+
}
376+
model::cells[idx]->distribcell_index_ =
377+
std::find(target_univ_ids.begin(), target_univ_ids.end(), u->id_) -
378+
target_univ_ids.begin();
388379
}
389380
}
390381
}
@@ -419,8 +410,7 @@ void prepare_distribcell(const std::vector<int32_t>* user_distribcells)
419410
} else if (c.type_ == Fill::LATTICE) {
420411
c.offset_[map] = offset;
421412
Lattice& lat = *model::lattices[c.fill_];
422-
offset +=
423-
lat.fill_offset_table(offset, target_univ_id, map, univ_count_memo);
413+
offset += lat.fill_offset_table(target_univ_id, map, univ_count_memo);
424414
}
425415
}
426416
}
@@ -429,32 +419,12 @@ void prepare_distribcell(const std::vector<int32_t>* user_distribcells)
429419

430420
//==============================================================================
431421

432-
void count_cell_instances(int32_t univ_indx)
422+
void count_universe_instances()
433423
{
434-
const auto univ_counts = model::universe_cell_counts.find(univ_indx);
435-
if (univ_counts != model::universe_cell_counts.end()) {
436-
for (const auto& it : univ_counts->second) {
437-
model::cells[it.first]->n_instances_ += it.second;
438-
}
439-
} else {
440-
for (int32_t cell_indx : model::universes[univ_indx]->cells_) {
441-
Cell& c = *model::cells[cell_indx];
442-
++c.n_instances_;
443-
model::universe_cell_counts[univ_indx][cell_indx] += 1;
444-
445-
if (c.type_ == Fill::UNIVERSE) {
446-
// This cell contains another universe. Recurse into that universe.
447-
count_cell_instances(c.fill_);
448-
update_universe_cell_count(univ_indx, c.fill_);
449-
} else if (c.type_ == Fill::LATTICE) {
450-
// This cell contains a lattice. Recurse into the lattice universes.
451-
Lattice& lat = *model::lattices[c.fill_];
452-
for (auto it = lat.begin(); it != lat.end(); ++it) {
453-
count_cell_instances(*it);
454-
update_universe_cell_count(univ_indx, *it);
455-
}
456-
}
457-
}
424+
for (auto& univ : model::universes) {
425+
std::unordered_map<int32_t, int32_t> univ_count_memo;
426+
univ->n_instances_ = count_universe_instances(
427+
model::root_universe, univ->id_, univ_count_memo);
458428
}
459429
}
460430

@@ -528,19 +498,16 @@ std::string distribcell_path_inner(int32_t target_cell, int32_t map,
528498

529499
// Material cells don't contain other cells so ignore them.
530500
if (c.type_ != Fill::MATERIAL) {
531-
int32_t temp_offset;
532-
if (c.type_ == Fill::UNIVERSE) {
533-
temp_offset =
534-
offset + c.offset_[map]; // TODO: should also apply to lattice fills?
535-
} else {
501+
int32_t temp_offset = offset + c.offset_[map];
502+
if (c.type_ == Fill::LATTICE) {
536503
Lattice& lat = *model::lattices[c.fill_];
537504
int32_t indx = lat.universes_.size() * map + lat.begin().indx_;
538-
temp_offset = offset + lat.offsets_[indx];
505+
temp_offset += lat.offsets_[indx];
539506
}
540507

541508
// The desired cell is the first cell that gives an offset smaller or
542509
// equal to the target offset.
543-
if (temp_offset <= target_offset - c.offset_[map])
510+
if (temp_offset <= target_offset)
544511
break;
545512
}
546513
}
@@ -570,12 +537,12 @@ std::string distribcell_path_inner(int32_t target_cell, int32_t map,
570537
path << "l" << lat.id_;
571538
for (ReverseLatticeIter it = lat.rbegin(); it != lat.rend(); ++it) {
572539
int32_t indx = lat.universes_.size() * map + it.indx_;
573-
int32_t temp_offset = offset + lat.offsets_[indx];
574-
if (temp_offset <= target_offset - c.offset_[map]) {
540+
int32_t temp_offset = offset + lat.offsets_[indx] + c.offset_[map];
541+
if (temp_offset <= target_offset) {
575542
offset = temp_offset;
576543
path << "(" << lat.index_to_string(it.indx_) << ")->";
577-
path << distribcell_path_inner(target_cell, map, target_offset,
578-
*model::universes[*it], offset + c.offset_[map]);
544+
path << distribcell_path_inner(
545+
target_cell, map, target_offset, *model::universes[*it], offset);
579546
return path.str();
580547
}
581548
}

src/lattice.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ void Lattice::adjust_indices()
103103

104104
//==============================================================================
105105

106-
int32_t Lattice::fill_offset_table(int32_t offset, int32_t target_univ_id,
107-
int map, std::unordered_map<int32_t, int32_t>& univ_count_memo)
106+
int32_t Lattice::fill_offset_table(int32_t target_univ_id, int map,
107+
std::unordered_map<int32_t, int32_t>& univ_count_memo)
108108
{
109109
// If the offsets have already been determined for this "map", don't bother
110110
// recalculating all of them and just return the total offset. Note that the
@@ -119,6 +119,7 @@ int32_t Lattice::fill_offset_table(int32_t offset, int32_t target_univ_id,
119119
count_universe_instances(last_univ, target_univ_id, univ_count_memo);
120120
}
121121

122+
int32_t offset = 0;
122123
for (LatticeIter it = begin(); it != end(); ++it) {
123124
offsets_[map * universes_.size() + it.indx_] = offset;
124125
offset += count_universe_instances(*it, target_univ_id, univ_count_memo);

src/random_ray/flat_source_domain.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ FlatSourceDomain::FlatSourceDomain() : negroups_(data::mg.num_energy_groups_)
4646
source_region_offsets_.push_back(-1);
4747
} else {
4848
source_region_offsets_.push_back(base_source_regions);
49-
base_source_regions += c->n_instances_;
49+
base_source_regions += c->n_instances();
5050
}
5151
}
5252

@@ -61,7 +61,7 @@ FlatSourceDomain::FlatSourceDomain() : negroups_(data::mg.num_energy_groups_)
6161
for (int i = 0; i < model::cells.size(); i++) {
6262
Cell& cell = *model::cells[i];
6363
if (cell.type_ == Fill::MATERIAL) {
64-
for (int j = 0; j < cell.n_instances_; j++) {
64+
for (int j = 0; j < cell.n_instances(); j++) {
6565
source_regions_.material(source_region_id++) = cell.material(j);
6666
}
6767
}
@@ -1014,7 +1014,7 @@ void FlatSourceDomain::apply_external_source_to_cell_and_children(
10141014
Cell& cell = *model::cells[i_cell];
10151015

10161016
if (cell.type_ == Fill::MATERIAL) {
1017-
vector<int> instances(cell.n_instances_);
1017+
vector<int> instances(cell.n_instances());
10181018
std::iota(instances.begin(), instances.end(), 0);
10191019
apply_external_source_to_cell_instances(
10201020
i_cell, discrete, strength_factor, target_material_id, instances);
@@ -1343,12 +1343,12 @@ void FlatSourceDomain::apply_mesh_to_cell_and_children(int32_t i_cell,
13431343
Cell& cell = *model::cells[i_cell];
13441344

13451345
if (cell.type_ == Fill::MATERIAL) {
1346-
vector<int> instances(cell.n_instances_);
1346+
vector<int> instances(cell.n_instances());
13471347
std::iota(instances.begin(), instances.end(), 0);
13481348
apply_mesh_to_cell_instances(
13491349
i_cell, mesh_idx, target_material_id, instances, is_target_void);
13501350
} else if (target_material_id == C_NONE && !is_target_void) {
1351-
for (int j = 0; j < cell.n_instances_; j++) {
1351+
for (int j = 0; j < cell.n_instances(); j++) {
13521352
std::unordered_map<int32_t, vector<int32_t>> cell_instance_list =
13531353
cell.get_contained_cells(j, nullptr);
13541354
for (const auto& pair : cell_instance_list) {

src/tallies/filter_distribcell.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void DistribcellFilter::set_cell(int32_t cell)
3434
assert(cell >= 0);
3535
assert(cell < model::cells.size());
3636
cell_ = cell;
37-
n_bins_ = model::cells[cell]->n_instances_;
37+
n_bins_ = model::cells[cell]->n_instances();
3838
}
3939

4040
void DistribcellFilter::get_all_bins(

0 commit comments

Comments
 (0)