@@ -1317,13 +1317,64 @@ struct ParentCellStack {
13171317};
13181318
13191319vector<ParentCell> Cell::find_parent_cells (
1320- int32_t instance, Position* hint) const
1320+ int32_t instance, const Position& r) const {
1321+
1322+ // create a temporary particle
1323+ Particle dummy_particle {};
1324+ dummy_particle.clear ();
1325+ dummy_particle.r () = r;
1326+ dummy_particle.u () = {0 ., 0 ., 1 .};
1327+
1328+ return find_parent_cells (instance, dummy_particle);
1329+ }
1330+
1331+ vector<ParentCell> Cell::find_parent_cells (
1332+ int32_t instance, Particle& p) const {
1333+ // look up the particle's location
1334+ openmc::exhaustive_find_cell (p);
1335+ const auto & coords = p.coord ();
1336+
1337+ // build a parent cell stack from the particle coordinates
1338+ ParentCellStack stack;
1339+ bool cell_found = false ;
1340+ for (auto it = coords.begin (); it != coords.end (); it++) {
1341+ const auto & coord = *it;
1342+ auto & cell = model::cells[coord.cell ];
1343+ // if the cell at this level matches the current cell, stop adding to the stack
1344+ if (coord.cell == model::cell_map[this ->id_ ]) {
1345+ cell_found = true ;
1346+ break ;
1347+ }
1348+
1349+ // if filled with a lattice, get the lattice index from the next
1350+ // level in the coordinates to push to the stack
1351+ int lattice_idx = C_NONE;
1352+ if (cell->type_ == Fill::LATTICE) {
1353+ const auto & next_coord = *(it + 1 );
1354+ lattice_idx = model::lattices[next_coord.lattice ]->get_flat_index (next_coord.lattice_i );
1355+ }
1356+ stack.push (coord.universe , {coord.cell , lattice_idx});
1357+ }
1358+
1359+ // if this loop finished because the cell was found and
1360+ // the instance matches the one requested in the call
1361+ // we have the correct path and can return the stack
1362+ if (cell_found && stack.compute_instance (this ->distribcell_index_ ) == instance) {
1363+ return stack.parent_cells ();
1364+ }
1365+
1366+ // fall back on an exhaustive search for the cell's parents
1367+ return find_parent_cells_exhaustive (instance);
1368+ }
1369+
1370+
1371+ vector<ParentCell> Cell::find_parent_cells_exhaustive (
1372+ int32_t instance) const
13211373{
13221374 ParentCellStack stack;
13231375 // start with this cell's universe
13241376 int32_t prev_univ_idx;
13251377 int32_t univ_idx = this ->universe_ ;
1326- bool hint_used = false ;
13271378
13281379 while (true ) {
13291380 const auto & univ = model::universes[univ_idx];
@@ -1352,38 +1403,26 @@ vector<ParentCell> Cell::find_parent_cells(
13521403 const auto & lattice = model::lattices[cell->fill_ ];
13531404 const auto & lattice_univs = lattice->universes_ ;
13541405
1355- // if a hint position is provided, look up the lattice cell
1356- // for that position
1357- if (hint && !hint_used) {
1358- std::array<int , 3 > hint_idx;
1359- lattice->get_indices (*hint, Direction (0.0 , 0.0 , 0.0 ), hint_idx);
1360- int hint_offset = lattice->get_flat_index (hint_idx);
1361- if (univ_idx == lattice_univs[hint_offset]) {
1362- hint_used = true ;
1363- stack.push (univ_idx, {model::cell_map[cell->id_ ], hint_offset});
1364- }
1365- } else {
1366- // start search for universe
1367- auto lat_it = lattice_univs.begin ();
1368- while (true ) {
1369- // find the next lattice cell with this universe
1370- lat_it = std::find (lat_it, lattice_univs.end (), univ_idx);
1371- if (lat_it == lattice_univs.end ())
1372- break ;
1373-
1374- int lattice_idx = lat_it - lattice_univs.begin ();
1375-
1376- // move iterator forward one to avoid finding the same entry
1377- lat_it++;
1378- if (stack.visited (
1379- univ_idx, {model::cell_map[cell->id_ ], lattice_idx}))
1380- continue ;
1381-
1382- // add this cell and lattice index to the stack and exit loop
1383- stack.push (univ_idx, {model::cell_map[cell->id_ ], lattice_idx});
1384- univ_idx = cell->universe_ ;
1406+ // start search for universe
1407+ auto lat_it = lattice_univs.begin ();
1408+ while (true ) {
1409+ // find the next lattice cell with this universe
1410+ lat_it = std::find (lat_it, lattice_univs.end (), univ_idx);
1411+ if (lat_it == lattice_univs.end ())
13851412 break ;
1386- }
1413+
1414+ int lattice_idx = lat_it - lattice_univs.begin ();
1415+
1416+ // move iterator forward one to avoid finding the same entry
1417+ lat_it++;
1418+ if (stack.visited (
1419+ univ_idx, {model::cell_map[cell->id_ ], lattice_idx}))
1420+ continue ;
1421+
1422+ // add this cell and lattice index to the stack and exit loop
1423+ stack.push (univ_idx, {model::cell_map[cell->id_ ], lattice_idx});
1424+ univ_idx = cell->universe_ ;
1425+ break ;
13871426 }
13881427 }
13891428 // if we've updated the universe, break
@@ -1426,7 +1465,14 @@ std::unordered_map<int32_t, vector<int32_t>> Cell::get_contained_cells(
14261465 return contained_cells;
14271466
14281467 // find the pathway through the geometry to this cell
1429- vector<ParentCell> parent_cells = this ->find_parent_cells (instance, hint);
1468+ vector<ParentCell> parent_cells;
1469+
1470+ // if a positional hint is provided, attempt to do a fast lookup
1471+ // of the parent cells
1472+ if (hint)
1473+ parent_cells = find_parent_cells (instance, *hint);
1474+ else
1475+ parent_cells = find_parent_cells_exhaustive (instance);
14301476
14311477 // if this cell is filled w/ a material, it contains no other cells
14321478 if (type_ != Fill::MATERIAL) {
0 commit comments