From be5318fdb0fbb7a447e68fad6787e2b6e221a20d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 8 Jul 2020 21:16:36 -0500 Subject: [PATCH 01/93] Reorganizing some of the DAGMC-related code and using shared pointers instead. --- include/openmc/cell.h | 17 ++++++++++++++++- include/openmc/dagmc.h | 4 ++-- include/openmc/surface.h | 2 +- src/cell.cpp | 16 ++++++++++++++++ src/dagmc.cpp | 17 +++++++---------- src/finalize.cpp | 3 --- 6 files changed, 42 insertions(+), 17 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index c7ba0ab137..282f00fff8 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -75,6 +75,20 @@ public: unique_ptr partitioner_; }; +#ifdef DAGMC + +class DAGUniverse : public Universe { + +public: + explicit DAGUniverse(std::string filename); + + + // Data Members + std::shared_ptr dag_instance_; //! DAGMC Instance for this universe +}; + +#endif + //============================================================================== //============================================================================== @@ -271,7 +285,7 @@ public: void to_hdf5(hid_t group_id) const; - moab::DagMC* dagmc_ptr_; //!< Pointer to DagMC instance + std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance int32_t dag_index_; //!< DagMC index of cell }; #endif @@ -343,6 +357,7 @@ struct CellInstanceHash { void read_cells(pugi::xml_node node); #ifdef DAGMC +void read_dagmc_universes(pugi::xml_node node); int32_t next_cell(DAGCell* cur_cell, DAGSurface* surf_xed); #endif diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 9f409d8730..81aa163dc3 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -15,7 +15,7 @@ extern "C" const bool DAGMC_ENABLED; namespace openmc { namespace model { - extern moab::DagMC* DAG; + extern std::shared_ptr DAG; } //============================================================================== @@ -23,7 +23,7 @@ namespace model { //============================================================================== void load_dagmc_geometry(); -void free_memory_dagmc(); +void create_dagmc_universe(const std::string& filename); void read_geometry_dagmc(); bool read_uwuw_materials(pugi::xml_document& doc); bool get_uwuw_materials_xml(std::string& s); diff --git a/include/openmc/surface.h b/include/openmc/surface.h index 5a8a88aa41..b729514b9e 100644 --- a/include/openmc/surface.h +++ b/include/openmc/surface.h @@ -168,7 +168,7 @@ public: void to_hdf5(hid_t group_id) const; - moab::DagMC* dagmc_ptr_; //!< Pointer to DagMC instance + std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance int32_t dag_index_; //!< DagMC index of surface }; #endif diff --git a/src/cell.cpp b/src/cell.cpp index 6b88a67803..733b70f056 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -1013,6 +1013,11 @@ void read_cells(pugi::xml_node node) } } +#ifdef DAGMC + // read any DAGMC universes + read_dagmc_universes(node); +#endif + // Populate the Universe vector and map. for (int i = 0; i < model::cells.size(); i++) { int32_t uid = model::cells[i]->universe_; @@ -1034,6 +1039,17 @@ void read_cells(pugi::xml_node node) } } +void read_dagmc_universes(pugi::xml_node node) { + + // determine the max cell id + int32_t next_cell_id = 0; + for (const auto& c : model::cells) { + if (c->id_ > next_cell_id) next_cell_id = c->id_; + } + next_cell_id++; + +} + //============================================================================== // C-API functions //============================================================================== diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 0c2768834a..5b8a61f7ea 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -41,7 +41,7 @@ const std::string DAGMC_FILENAME = "dagmc.h5m"; namespace model { -moab::DagMC* DAG; +std::shared_ptr DAG; } // namespace model @@ -151,14 +151,17 @@ void legacy_assign_material(std::string mat_string, DAGCell* c) void load_dagmc_geometry() { + create_dagmc_universe(dagmc_file()); +} + +void create_dagmc_universe(const std::string& filename) { if (!model::DAG) { - model::DAG = new moab::DagMC(); + model::DAG = std::make_shared(); } // --- Materials --- // create uwuw instance - auto filename = dagmc_file(); UWUW uwuw(filename.c_str()); // check for uwuw material definitions @@ -180,7 +183,7 @@ void load_dagmc_geometry() MB_CHK_ERR_CONT(rval); // parse model metadata - dagmcMetaData DMD(model::DAG, false, false); + dagmcMetaData DMD(model::DAG.get(), false, false); DMD.load_property_data(); vector keywords {"temp"}; @@ -346,11 +349,5 @@ void read_geometry_dagmc() model::root_universe = find_root_universe(); } -void free_memory_dagmc() -{ - delete model::DAG; -} - - } #endif diff --git a/src/finalize.cpp b/src/finalize.cpp index 22dc671836..54a8d681dc 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -51,9 +51,6 @@ void free_memory() if (settings::event_based) { free_event_queues(); } -#ifdef DAGMC - free_memory_dagmc(); -#endif } } From ef21ec493be10b4b68d5b303aaa0097be67ff244 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 8 Jul 2020 21:32:56 -0500 Subject: [PATCH 02/93] Returning universe index from the original dagmc function now. --- include/openmc/dagmc.h | 2 +- src/dagmc.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 81aa163dc3..1e66d8f170 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -23,7 +23,7 @@ namespace model { //============================================================================== void load_dagmc_geometry(); -void create_dagmc_universe(const std::string& filename); +int32_t create_dagmc_universe(const std::string& filename); void read_geometry_dagmc(); bool read_uwuw_materials(pugi::xml_document& doc); bool get_uwuw_materials_xml(std::string& s); diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 5b8a61f7ea..a3567ebe1e 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -151,10 +151,10 @@ void legacy_assign_material(std::string mat_string, DAGCell* c) void load_dagmc_geometry() { - create_dagmc_universe(dagmc_file()); + int32_t univ_idx = create_dagmc_universe(dagmc_file()); } -void create_dagmc_universe(const std::string& filename) { +int32_t create_dagmc_universe(const std::string& filename) { if (!model::DAG) { model::DAG = std::make_shared(); } @@ -338,7 +338,7 @@ void create_dagmc_universe(const std::string& filename) { model::surface_map[s->id_] = i; } - return; + return model::universes.size() - 1; } void read_geometry_dagmc() From a16c0916dae5fd8f6137bb6ea1f96d3c2992248f Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 8 Jul 2020 22:38:06 -0500 Subject: [PATCH 03/93] Using the DAGUniverse constructor to setup the DAGMC instance. --- include/openmc/cell.h | 4 +- include/openmc/dagmc.h | 3 +- src/dagmc.cpp | 213 +++++++++++++++++- .../dagmc/refl/inputs_true.dat | 2 +- tests/regression_tests/dagmc/refl/test.py | 2 +- 5 files changed, 217 insertions(+), 7 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 282f00fff8..5b0b595608 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -80,11 +80,11 @@ public: class DAGUniverse : public Universe { public: - explicit DAGUniverse(std::string filename); + explicit DAGUniverse(const std::string& filename); // Data Members - std::shared_ptr dag_instance_; //! DAGMC Instance for this universe + std::shared_ptr dagmc_instance_; //! DAGMC Instance for this universe }; #endif diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 1e66d8f170..417cedebd7 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -9,8 +9,9 @@ extern "C" const bool DAGMC_ENABLED; #ifdef DAGMC #include "DagMC.hpp" -#include "openmc/xml_interface.h" + #include "openmc/position.h" +#include "openmc/xml_interface.h" namespace openmc { diff --git a/src/dagmc.cpp b/src/dagmc.cpp index a3567ebe1e..37de2d0c6e 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -151,7 +151,215 @@ void legacy_assign_material(std::string mat_string, DAGCell* c) void load_dagmc_geometry() { - int32_t univ_idx = create_dagmc_universe(dagmc_file()); + model::universes.push_back(std::make_unique(dagmc_file())); + model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; +} + +DAGUniverse::DAGUniverse(const std::string& filename) { + + // determine the next cell id + int32_t next_cell_id = 0; + for (const auto& c : model::cells) { + if (c->id_ > next_cell_id) next_cell_id = c->id_; + } + next_cell_id++; + + // determine the next surface id + int32_t next_surf_id = 0; + for (const auto& s : model::surfaces) { + if (s->id_ > next_surf_id) next_surf_id = s->id_; + } + next_surf_id++; + + // determine the next universe id + int32_t next_univ_id = 0; + for (const auto& u : model::universes) { + if (u->id_ > next_univ_id) next_univ_id = u->id_; + } + next_univ_id++; + + // set the universe id + id_ = next_univ_id; + + // create a new DAGMC instance + dagmc_instance_ = std::make_shared(); + + // --- Materials --- + + // create uwuw instance + UWUW uwuw(filename.c_str()); + + // check for uwuw material definitions + bool using_uwuw = !uwuw.material_library.empty(); + + // notify user if UWUW materials are going to be used + if (using_uwuw) { + write_message("Found UWUW Materials in the DAGMC geometry file.", 6); + } + + // load the DAGMC geometry + moab::ErrorCode rval = dagmc_instance_->load_file(filename.c_str()); + MB_CHK_ERR_CONT(rval); + + // initialize acceleration data structures + rval = dagmc_instance_->init_OBBTree(); + MB_CHK_ERR_CONT(rval); + + // parse model metadata + dagmcMetaData DMD(dagmc_instance_.get(), false, false); + DMD.load_property_data(); + + std::vector keywords {"temp"}; + std::map dum; + std::string delimiters = ":/"; + rval = dagmc_instance_->parse_properties(keywords, dum, delimiters.c_str()); + MB_CHK_ERR_CONT(rval); + + // --- Cells (Volumes) --- + + // initialize cell objects + int n_cells = dagmc_instance_->num_entities(3); + moab::EntityHandle graveyard = 0; + for (int i = 0; i < n_cells; i++) { + moab::EntityHandle vol_handle = dagmc_instance_->entity_by_index(3, i + 1); + + // set cell ids using global IDs + DAGCell* c = new DAGCell(); + c->dag_index_ = i + 1; + std::cout << "Cell id: " << next_cell_id << std::endl; + c->id_ = next_cell_id++; + // c->id_ = model::DAG->id_by_index(3, c->dag_index_); + c->dagmc_ptr_ = dagmc_instance_; + c->universe_ = id_; // set to zero for now + c->fill_ = C_NONE; // no fill, single universe + + model::cells.emplace_back(c); + model::cell_map[c->id_] = model::cells.size() - 1; + cells_.push_back(model::cell_map[c->id_]); + + // Populate the Universe vector and dict + // auto it = model::universe_map.find(dagmc_univ_id); + // if (it == model::universe_map.end()) { + // model::universes.push_back(std::make_unique()); + // model::universes.back()->id_ = dagmc_univ_id; + // model::universes.back()->cells_.push_back(i); + // model::universe_map[id_] = model::universes.size() - 1; + // } else { + // model::universes[it->second]->cells_.push_back(i); + // } + + // MATERIALS + + // determine volume material assignment + std::string mat_str = DMD.get_volume_property("material", vol_handle); + + if (mat_str.empty()) { + fatal_error(fmt::format("Volume {} has no material assignment.", c->id_)); + } + + to_lower(mat_str); + + if (mat_str == "graveyard") { + graveyard = vol_handle; + } + + // material void checks + if (mat_str == "void" || mat_str == "vacuum" || mat_str == "graveyard") { + c->material_.push_back(MATERIAL_VOID); + } else { + if (using_uwuw) { + // lookup material in uwuw if present + std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle]; + if (uwuw.material_library.count(uwuw_mat) != 0) { + // Note: material numbers are set by UWUW + int mat_number = uwuw.material_library[uwuw_mat].metadata["mat_number"].asInt(); + c->material_.push_back(mat_number); + } else { + fatal_error(fmt::format("Material with value {} not found in the " + "UWUW material library", mat_str)); + } + } else { + legacy_assign_material(mat_str, c); + } + } + + // check for temperature assignment + std::string temp_value; + + // no temperature if void + if (c->material_[0] == MATERIAL_VOID) continue; + + // assign cell temperature + const auto& mat = model::materials[model::material_map.at(c->material_[0])]; + if (dagmc_instance_->has_prop(vol_handle, "temp")) { + rval = dagmc_instance_->prop_value(vol_handle, "temp", temp_value); + MB_CHK_ERR_CONT(rval); + double temp = std::stod(temp_value); + c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * temp)); + } else if (mat->temperature_ > 0.0) { + c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * mat->temperature_)); + } else { + c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * settings::temperature_default)); + } + + } + + // allocate the cell overlap count if necessary + if (settings::check_overlaps) { + model::overlap_check_count.resize(model::cells.size(), 0); + } + + if (!graveyard) { + warning("No graveyard volume found in the DagMC model." + "This may result in lost particles and rapid simulation failure."); + } + + // --- Surfaces --- + + // initialize surface objects + int n_surfaces = dagmc_instance_->num_entities(2); + + for (int i = 0; i < n_surfaces; i++) { + moab::EntityHandle surf_handle = dagmc_instance_->entity_by_index(2, i+1); + + // set cell ids using global IDs + DAGSurface* s = new DAGSurface(); + s->dag_index_ = i+1; + s->id_ = next_surf_id++; + s->dagmc_ptr_ = dagmc_instance_; + + // set BCs + std::string bc_value = DMD.get_surface_property("boundary", surf_handle); + to_lower(bc_value); + if (bc_value.empty() || bc_value == "transmit" || bc_value == "transmission") { + // set to transmission by default + s->bc_ = Surface::BoundaryType::TRANSMIT; + } else if (bc_value == "vacuum") { + s->bc_ = Surface::BoundaryType::VACUUM; + } else if (bc_value == "reflective" || bc_value == "reflect" || bc_value == "reflecting") { + s->bc_ = Surface::BoundaryType::REFLECT; + } else if (bc_value == "periodic") { + fatal_error("Periodic boundary condition not supported in DAGMC."); + } else { + fatal_error(fmt::format("Unknown boundary condition \"{}\" specified " + "on surface {}", bc_value, s->id_)); + } + + // graveyard check + moab::Range parent_vols; + rval = dagmc_instance_->moab_instance()->get_parent_meshsets(surf_handle, parent_vols); + MB_CHK_ERR_CONT(rval); + + // if this surface belongs to the graveyard + if (graveyard && parent_vols.find(graveyard) != parent_vols.end()) { + // set graveyard surface BC's to vacuum + s->bc_ = Surface::BoundaryType::VACUUM; + } + + // add to global array and map + model::surfaces.emplace_back(s); + model::surface_map[s->id_] = model::surfaces.size() - 1; + } } int32_t create_dagmc_universe(const std::string& filename) { @@ -204,6 +412,7 @@ int32_t create_dagmc_universe(const std::string& filename) { DAGCell* c = new DAGCell(); c->dag_index_ = i+1; c->id_ = model::DAG->id_by_index(3, c->dag_index_); + std::cout << "Cell id: " << c->id_ << std::endl; c->dagmc_ptr_ = model::DAG; c->universe_ = dagmc_univ_id; // set to zero for now c->fill_ = C_NONE; // no fill, single universe @@ -346,7 +555,7 @@ void read_geometry_dagmc() write_message("Reading DAGMC geometry...", 5); load_dagmc_geometry(); - model::root_universe = find_root_universe(); + model::root_universe = 0; } } diff --git a/tests/regression_tests/dagmc/refl/inputs_true.dat b/tests/regression_tests/dagmc/refl/inputs_true.dat index 87ceb944d8..2732730010 100644 --- a/tests/regression_tests/dagmc/refl/inputs_true.dat +++ b/tests/regression_tests/dagmc/refl/inputs_true.dat @@ -14,7 +14,7 @@ - 1 + 2 1 diff --git a/tests/regression_tests/dagmc/refl/test.py b/tests/regression_tests/dagmc/refl/test.py index c451b61250..305e18ed5c 100644 --- a/tests/regression_tests/dagmc/refl/test.py +++ b/tests/regression_tests/dagmc/refl/test.py @@ -30,7 +30,7 @@ class UWUWTest(PyAPITestHarness): # tally tally = openmc.Tally() tally.scores = ['total'] - tally.filters = [openmc.CellFilter(1)] + tally.filters = [openmc.CellFilter(2)] model.tallies = [tally] model.tallies.export_to_xml() From 249a5bb51142808774d736824473513c6ef68260 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 8 Jul 2020 23:18:12 -0500 Subject: [PATCH 04/93] Adding an XML node constructor for the DAGUniverse. --- include/openmc/cell.h | 3 +++ src/dagmc.cpp | 60 ++++++++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 5b0b595608..52d6e9fdc6 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -80,10 +80,13 @@ public: class DAGUniverse : public Universe { public: + explicit DAGUniverse(pugi::xml_node node); explicit DAGUniverse(const std::string& filename); + void initialize(); //!< Sets up the DAGMC instance and OpenMC internals // Data Members + std::string filename_; std::shared_ptr dagmc_instance_; //! DAGMC Instance for this universe }; diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 37de2d0c6e..395372a58d 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -155,7 +155,37 @@ void load_dagmc_geometry() model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; } -DAGUniverse::DAGUniverse(const std::string& filename) { +DAGUniverse::DAGUniverse(pugi::xml_node node) { + if (check_for_node(node, "id")) { + id_ = std::stoi(get_node_value(node, "id")); + } else { + fatal_error("Must specify the id of the DAGMC universe"); + } + + if (check_for_node(node, "filename")) { + filename_ = get_node_value(node, "filename"); + } else { + fatal_error("Must specify a file for the DAGMC universe"); + } + + initialize(); +} + +DAGUniverse::DAGUniverse(const std::string& filename) : filename_(filename) { + // determine the next universe id + int32_t next_univ_id = 0; + for (const auto& u : model::universes) { + if (u->id_ > next_univ_id) next_univ_id = u->id_; + } + next_univ_id++; + + // set the universe id + id_ = next_univ_id; + + initialize(); +} + +void DAGUniverse::initialize() { // determine the next cell id int32_t next_cell_id = 0; @@ -171,23 +201,13 @@ DAGUniverse::DAGUniverse(const std::string& filename) { } next_surf_id++; - // determine the next universe id - int32_t next_univ_id = 0; - for (const auto& u : model::universes) { - if (u->id_ > next_univ_id) next_univ_id = u->id_; - } - next_univ_id++; - - // set the universe id - id_ = next_univ_id; - // create a new DAGMC instance dagmc_instance_ = std::make_shared(); // --- Materials --- // create uwuw instance - UWUW uwuw(filename.c_str()); + UWUW uwuw(filename_.c_str()); // check for uwuw material definitions bool using_uwuw = !uwuw.material_library.empty(); @@ -198,7 +218,7 @@ DAGUniverse::DAGUniverse(const std::string& filename) { } // load the DAGMC geometry - moab::ErrorCode rval = dagmc_instance_->load_file(filename.c_str()); + moab::ErrorCode rval = dagmc_instance_->load_file(filename_.c_str()); MB_CHK_ERR_CONT(rval); // initialize acceleration data structures @@ -237,17 +257,6 @@ DAGUniverse::DAGUniverse(const std::string& filename) { model::cell_map[c->id_] = model::cells.size() - 1; cells_.push_back(model::cell_map[c->id_]); - // Populate the Universe vector and dict - // auto it = model::universe_map.find(dagmc_univ_id); - // if (it == model::universe_map.end()) { - // model::universes.push_back(std::make_unique()); - // model::universes.back()->id_ = dagmc_univ_id; - // model::universes.back()->cells_.push_back(i); - // model::universe_map[id_] = model::universes.size() - 1; - // } else { - // model::universes[it->second]->cells_.push_back(i); - // } - // MATERIALS // determine volume material assignment @@ -554,8 +563,7 @@ void read_geometry_dagmc() { write_message("Reading DAGMC geometry...", 5); load_dagmc_geometry(); - - model::root_universe = 0; + model::root_universe = find_root_universe(); } } From c35c8dae43484e71231edb6372df6dbaa8a532ff Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 8 Jul 2020 23:39:06 -0500 Subject: [PATCH 05/93] Reading DAGMC universes from the geometry.xml now. --- include/openmc/cell.h | 1 + src/cell.cpp | 20 +++++++------------- src/dagmc.cpp | 2 +- src/geometry_aux.cpp | 9 +-------- src/surface.cpp | 7 ++++--- 5 files changed, 14 insertions(+), 25 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 52d6e9fdc6..0aa14e523c 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -358,6 +358,7 @@ struct CellInstanceHash { //============================================================================== void read_cells(pugi::xml_node node); +void read_dagmc_universes(pugi::xml_node node); #ifdef DAGMC void read_dagmc_universes(pugi::xml_node node); diff --git a/src/cell.cpp b/src/cell.cpp index 733b70f056..ffbb7dae7c 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -992,9 +992,6 @@ void read_cells(pugi::xml_node node) // Count the number of cells. int n_cells = 0; for (pugi::xml_node cell_node: node.children("cell")) {n_cells++;} - if (n_cells == 0) { - fatal_error("No cells found in geometry.xml!"); - } // Loop over XML cell elements and populate the array. model::cells.reserve(n_cells); @@ -1013,10 +1010,7 @@ void read_cells(pugi::xml_node node) } } -#ifdef DAGMC - // read any DAGMC universes read_dagmc_universes(node); -#endif // Populate the Universe vector and map. for (int i = 0; i < model::cells.size(); i++) { @@ -1037,17 +1031,17 @@ void read_cells(pugi::xml_node node) if (settings::check_overlaps) { model::overlap_check_count.resize(model::cells.size(), 0); } + + if (model::cells.size() == 0) { + fatal_error("No cells were found in the geometry.xml file"); + } } void read_dagmc_universes(pugi::xml_node node) { - - // determine the max cell id - int32_t next_cell_id = 0; - for (const auto& c : model::cells) { - if (c->id_ > next_cell_id) next_cell_id = c->id_; + for (pugi::xml_node dag_node : node.children("dagmc")) { + model::universes.push_back(std::make_unique(dag_node)); + model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; } - next_cell_id++; - } //============================================================================== diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 395372a58d..93d9b222a2 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -367,7 +367,7 @@ void DAGUniverse::initialize() { // add to global array and map model::surfaces.emplace_back(s); - model::surface_map[s->id_] = model::surfaces.size() - 1; +// model::surface_map[s->id_] = model::surfaces.size() - 1; } } diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index 17000129d3..94365428fd 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -42,13 +42,6 @@ void update_universe_cell_count(int32_t a, int32_t b) { void read_geometry_xml() { -#ifdef DAGMC - if (settings::dagmc) { - read_geometry_dagmc(); - return; - } -#endif - // Display output message write_message("Reading geometry XML file...", 5); @@ -69,8 +62,8 @@ void read_geometry_xml() pugi::xml_node root = doc.document_element(); // Read surfaces, cells, lattice - read_surfaces(root); read_cells(root); + read_surfaces(root); read_lattices(root); // Allocate universes, universe cell arrays, and assign base universe diff --git a/src/surface.cpp b/src/surface.cpp index 76542fcd86..caa3b9ba8f 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -1036,9 +1036,6 @@ void read_surfaces(pugi::xml_node node) // Count the number of surfaces int n_surfaces = 0; for (pugi::xml_node surf_node : node.children("surface")) {n_surfaces++;} - if (n_surfaces == 0) { - fatal_error("No surfaces found in geometry.xml!"); - } // Loop over XML surface elements and populate the array. Keep track of // periodic surfaces. @@ -1196,6 +1193,10 @@ void read_surfaces(pugi::xml_node node) if (settings::run_mode != RunMode::PLOTTING && !boundary_exists) { fatal_error("No boundary conditions were applied to any surfaces!"); } + + if (model::surfaces.size() == 0) { + fatal_error("No surfaces found in geometry.xml!"); + } } void free_memory_surfaces() From a736756d9bbfcbccdf33cce90b593ed6881197a2 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 9 Jul 2020 00:10:36 -0500 Subject: [PATCH 06/93] Adjusting some geometry checks. Reading surfaces before cells. Combines with other CSG objects so far! --- src/geometry_aux.cpp | 2 +- src/surface.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index 94365428fd..d45cdcb23a 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -62,8 +62,8 @@ void read_geometry_xml() pugi::xml_node root = doc.document_element(); // Read surfaces, cells, lattice - read_cells(root); read_surfaces(root); + read_cells(root); read_lattices(root); // Allocate universes, universe cell arrays, and assign base universe diff --git a/src/surface.cpp b/src/surface.cpp index caa3b9ba8f..9114b65adb 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -1190,13 +1190,13 @@ void read_surfaces(pugi::xml_node node) break; } } - if (settings::run_mode != RunMode::PLOTTING && !boundary_exists) { - fatal_error("No boundary conditions were applied to any surfaces!"); - } + // if (settings::run_mode != RunMode::PLOTTING && !boundary_exists) { + // fatal_error("No boundary conditions were applied to any surfaces!"); + // } - if (model::surfaces.size() == 0) { - fatal_error("No surfaces found in geometry.xml!"); - } + // if (model::surfaces.size() == 0) { + // fatal_error("No surfaces found in geometry.xml!"); + // } } void free_memory_surfaces() From 108c2a2f35c846c32f3d29afd28d42e77f85d53e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 9 Jul 2020 18:26:21 -0500 Subject: [PATCH 07/93] Adding surface and cell offsets to the DAGUniverse to recover surface and cell indices. --- include/openmc/cell.h | 3 +++ src/cell.cpp | 7 ++++++- src/dagmc.cpp | 6 ++++-- src/particle.cpp | 36 ++++++++++++++++++------------------ 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 0aa14e523c..f87e594eaa 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -63,6 +63,7 @@ namespace model { class Universe { public: + int32_t id_; //!< Unique ID vector cells_; //!< Cells within this universe @@ -88,6 +89,8 @@ public: // Data Members std::string filename_; std::shared_ptr dagmc_instance_; //! DAGMC Instance for this universe + int32_t cell_idx_offset_; + int32_t surf_idx_offset_; }; #endif diff --git a/src/cell.cpp b/src/cell.cpp index ffbb7dae7c..3fb2050d19 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -793,6 +793,11 @@ DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) cons p->last_dir() = u; } + const auto& univ = model::universes[p->coord_[p->n_coord_ - 1].universe]; + + DAGUniverse* dag_univ = static_cast(univ.get()); + if (!dag_univ) fatal_error("DAGMC call made for particle in a non-DAGMC universe"); + moab::ErrorCode rval; moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); moab::EntityHandle hit_surf; @@ -803,7 +808,7 @@ DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) cons MB_CHK_ERR_CONT(rval); int surf_idx; if (hit_surf != 0) { - surf_idx = dagmc_ptr_->index_by_handle(hit_surf); + surf_idx = dag_univ->surf_idx_offset_ + dagmc_ptr_->index_by_handle(hit_surf); } else { // indicate that particle is lost surf_idx = -1; diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 93d9b222a2..f79215c116 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -171,7 +171,7 @@ DAGUniverse::DAGUniverse(pugi::xml_node node) { initialize(); } -DAGUniverse::DAGUniverse(const std::string& filename) : filename_(filename) { +DAGUniverse::DAGUniverse(const std::string& filename): filename_(filename) { // determine the next universe id int32_t next_univ_id = 0; for (const auto& u : model::universes) { @@ -192,6 +192,7 @@ void DAGUniverse::initialize() { for (const auto& c : model::cells) { if (c->id_ > next_cell_id) next_cell_id = c->id_; } + cell_idx_offset_ = model::cells.size(); next_cell_id++; // determine the next surface id @@ -199,6 +200,7 @@ void DAGUniverse::initialize() { for (const auto& s : model::surfaces) { if (s->id_ > next_surf_id) next_surf_id = s->id_; } + surf_idx_offset_ = model::surfaces.size(); next_surf_id++; // create a new DAGMC instance @@ -367,7 +369,7 @@ void DAGUniverse::initialize() { // add to global array and map model::surfaces.emplace_back(s); -// model::surface_map[s->id_] = model::surfaces.size() - 1; + model::surface_map[s->id_] = model::surfaces.size() - 1; } } diff --git a/src/particle.cpp b/src/particle.cpp index fe2579593e..755330808f 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -386,24 +386,24 @@ Particle::cross_surface() // ========================================================================== // SEARCH NEIGHBOR LISTS FOR NEXT CELL -#ifdef DAGMC - if (settings::dagmc) { - auto cellp = dynamic_cast(model::cells[cell_last(0)].get()); - // TODO: off-by-one - auto surfp = - dynamic_cast(model::surfaces[std::abs(surface()) - 1].get()); - int32_t i_cell = next_cell(cellp, surfp) - 1; - // save material and temp - material_last() = material(); - sqrtkT_last() = sqrtkT(); - // set new cell value - coord(0).cell = i_cell; - cell_instance() = 0; - material() = model::cells[i_cell]->material_[0]; - sqrtkT() = model::cells[i_cell]->sqrtkT_[0]; - return; - } -#endif + +// #ifdef DAGMC +// if (settings::dagmc) { +// auto cellp = dynamic_cast(model::cells[cell_last_[0]].get()); +// // TODO: off-by-one +// auto surfp = dynamic_cast(model::surfaces[std::abs(surface_) - 1].get()); +// int32_t i_cell = next_cell(cellp, surfp) - 1; +// // save material and temp +// material_last_ = material_; +// sqrtkT_last_ = sqrtkT_; +// // set new cell value +// coord_[0].cell = i_cell; +// cell_instance_ = 0; +// material_ = model::cells[i_cell]->material_[0]; +// sqrtkT_ = model::cells[i_cell]->sqrtkT_[0]; +// return; +// } +// #endif if (neighbor_list_find_cell(*this)) return; From 0a463be15e82443f7019cec103bf186e3da6c632 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 19 Jul 2020 22:34:20 -0500 Subject: [PATCH 08/93] Adding universe types again. --- include/openmc/cell.h | 18 ++++-- include/openmc/settings.h | 1 - include/openmc/surface.h | 8 +-- src/cell.cpp | 132 ++++++++++++++++++++++---------------- src/cross_sections.cpp | 15 ----- src/dagmc.cpp | 4 +- src/material.cpp | 22 ++----- src/particle.cpp | 43 +++++++------ src/summary.cpp | 8 --- src/surface.cpp | 17 ++--- 10 files changed, 135 insertions(+), 133 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index f87e594eaa..bef55690a2 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -31,6 +31,11 @@ enum class Fill { LATTICE }; +enum class UniverseType { + CSG, + DAG +}; + // TODO: Convert to enum constexpr int32_t OP_LEFT_PAREN {std::numeric_limits::max()}; constexpr int32_t OP_RIGHT_PAREN {std::numeric_limits::max() - 1}; @@ -73,6 +78,7 @@ public: BoundingBox bounding_box() const; + UniverseType type_ = UniverseType::CSG; unique_ptr partitioner_; }; @@ -138,7 +144,9 @@ public: //! Write all information needed to reconstruct the cell to an HDF5 group. //! \param group_id An HDF5 group id. - virtual void to_hdf5(hid_t group_id) const = 0; + virtual void to_hdf5(hid_t group_id) const; + + virtual void to_hdf5_inner(hid_t group_id) const = 0; //! Get the BoundingBox for this cell. virtual BoundingBox bounding_box() const = 0; @@ -169,6 +177,8 @@ public: //! \param[in] name Cell name void set_name(const std::string& name) { name_ = name; }; + + //! Get all cell instances contained by this cell //! \return Map with cell indexes as keys and instances as values std::unordered_map> get_contained_cells() const; @@ -245,7 +255,7 @@ public: std::pair distance(Position r, Direction u, int32_t on_surface, Particle* p) const; - void to_hdf5(hid_t group_id) const; + void to_hdf5_inner(hid_t group_id) const; BoundingBox bounding_box() const; @@ -289,7 +299,7 @@ public: BoundingBox bounding_box() const; - void to_hdf5(hid_t group_id) const; + void to_hdf5_inner(hid_t group_id) const; std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance int32_t dag_index_; //!< DagMC index of cell @@ -365,7 +375,7 @@ void read_dagmc_universes(pugi::xml_node node); #ifdef DAGMC void read_dagmc_universes(pugi::xml_node node); -int32_t next_cell(DAGCell* cur_cell, DAGSurface* surf_xed); +int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed); #endif } // namespace openmc diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 384f629b0f..cc3887f8f8 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -29,7 +29,6 @@ extern bool check_overlaps; //!< check overlaps in geometry? extern bool confidence_intervals; //!< use confidence intervals for results? extern bool create_fission_neutrons; //!< create fission neutrons (fixed source)? extern "C" bool cmfd_run; //!< is a CMFD run? -extern "C" bool dagmc; //!< indicator of DAGMC geometry extern bool delayed_photon_scaling; //!< Scale fission photon yield to include delayed extern "C" bool entropy_on; //!< calculate Shannon entropy? extern bool event_based; //!< use event-based mode (instead of history-based) diff --git a/include/openmc/surface.h b/include/openmc/surface.h index b729514b9e..8b4e416052 100644 --- a/include/openmc/surface.h +++ b/include/openmc/surface.h @@ -138,6 +138,9 @@ public: //! Get the BoundingBox for this surface. virtual BoundingBox bounding_box(bool /*pos_side*/) const { return {}; } + + protected: + virtual void to_hdf5_inner(hid_t group_id) const = 0; }; class CSGSurface : public Surface @@ -147,9 +150,6 @@ public: CSGSurface(); void to_hdf5(hid_t group_id) const; - -protected: - virtual void to_hdf5_inner(hid_t group_id) const = 0; }; //============================================================================== @@ -166,7 +166,7 @@ public: Direction normal(Position r) const; Direction reflect(Position r, Direction u, Particle* p) const; - void to_hdf5(hid_t group_id) const; + void to_hdf5_inner(hid_t group_id) const override; std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance int32_t dag_index_; //!< DagMC index of surface diff --git a/src/cell.cpp b/src/cell.cpp index 3fb2050d19..ec8c5e0e7d 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -194,6 +194,15 @@ Universe::to_hdf5(hid_t universes_group) const // Create a group for this universe. auto group = create_group(universes_group, fmt::format("universe {}", id_)); + switch(type_) { + case UniverseType::CSG : + write_string(group, "geom_type", "csg", false); + break; + case UniverseType::DAG : + write_string(group, "geom_type", "dagmc", false); + break; + } + // Write the contained cells. if (cells_.size() > 0) { vector cell_ids; @@ -282,6 +291,66 @@ Cell::set_temperature(double T, int32_t instance, bool set_contained) } } +void +Cell::to_hdf5(hid_t cell_group) const { + + // Create a group for this cell. + auto group = create_group(cell_group, fmt::format("cell {}", id_)); + + if (!name_.empty()) { + write_string(group, "name", name_, false); + } + + write_dataset(group, "universe", model::universes[universe_]->id_); + + + to_hdf5_inner(group); + + // Write fill information. + if (type_ == Fill::MATERIAL) { + write_dataset(group, "fill_type", "material"); + std::vector mat_ids; + for (auto i_mat : material_) { + if (i_mat != MATERIAL_VOID) { + mat_ids.push_back(model::materials[i_mat]->id_); + } else { + mat_ids.push_back(MATERIAL_VOID); + } + } + if (mat_ids.size() == 1) { + write_dataset(group, "material", mat_ids[0]); + } else { + write_dataset(group, "material", mat_ids); + } + + std::vector temps; + for (auto sqrtkT_val : sqrtkT_) + temps.push_back(sqrtkT_val * sqrtkT_val / K_BOLTZMANN); + write_dataset(group, "temperature", temps); + + } else if (type_ == Fill::UNIVERSE) { + write_dataset(group, "fill_type", "universe"); + write_dataset(group, "fill", model::universes[fill_]->id_); + if (translation_ != Position(0, 0, 0)) { + write_dataset(group, "translation", translation_); + } + if (!rotation_.empty()) { + if (rotation_.size() == 12) { + std::array rot {rotation_[9], rotation_[10], rotation_[11]}; + write_dataset(group, "rotation", rot); + } else { + write_dataset(group, "rotation", rotation_); + } + } + + } else if (type_ == Fill::LATTICE) { + write_dataset(group, "fill_type", "lattice"); + write_dataset(group, "lattice", model::lattices[fill_]->id_); + } + + close_group(group); +} + //============================================================================== // CSGCell implementation //============================================================================== @@ -526,16 +595,10 @@ CSGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) cons //============================================================================== void -CSGCell::to_hdf5(hid_t cell_group) const +CSGCell::to_hdf5_inner(hid_t group_id) const { - // Create a group for this cell. - auto group = create_group(cell_group, fmt::format("cell {}", id_)); - if (!name_.empty()) { - write_string(group, "name", name_, false); - } - - write_dataset(group, "universe", model::universes[universe_]->id_); + write_string(group_id, "geom_type", "csg", false); // Write the region specification. if (!region_.empty()) { @@ -556,52 +619,9 @@ CSGCell::to_hdf5(hid_t cell_group) const region_spec << " " << ((token > 0) ? surf_id : -surf_id); } } - write_string(group, "region", region_spec.str(), false); + write_string(group_id, "region", region_spec.str(), false); } - // Write fill information. - if (type_ == Fill::MATERIAL) { - write_dataset(group, "fill_type", "material"); - vector mat_ids; - for (auto i_mat : material_) { - if (i_mat != MATERIAL_VOID) { - mat_ids.push_back(model::materials[i_mat]->id_); - } else { - mat_ids.push_back(MATERIAL_VOID); - } - } - if (mat_ids.size() == 1) { - write_dataset(group, "material", mat_ids[0]); - } else { - write_dataset(group, "material", mat_ids); - } - - vector temps; - for (auto sqrtkT_val : sqrtkT_) - temps.push_back(sqrtkT_val * sqrtkT_val / K_BOLTZMANN); - write_dataset(group, "temperature", temps); - - } else if (type_ == Fill::UNIVERSE) { - write_dataset(group, "fill_type", "universe"); - write_dataset(group, "fill", model::universes[fill_]->id_); - if (translation_ != Position(0, 0, 0)) { - write_dataset(group, "translation", translation_); - } - if (!rotation_.empty()) { - if (rotation_.size() == 12) { - array rot {rotation_[9], rotation_[10], rotation_[11]}; - write_dataset(group, "rotation", rot); - } else { - write_dataset(group, "rotation", rotation_); - } - } - - } else if (type_ == Fill::LATTICE) { - write_dataset(group, "fill_type", "lattice"); - write_dataset(group, "lattice", model::lattices[fill_]->id_); - } - - close_group(group); } BoundingBox CSGCell::bounding_box_simple() const { @@ -831,7 +851,9 @@ bool DAGCell::contains(Position r, Direction u, int32_t on_surface) const return result; } -void DAGCell::to_hdf5(hid_t group_id) const { return; } +void DAGCell::to_hdf5_inner(hid_t group_id) const { + write_string(group_id, "geom_type", "dagmc", false); +} BoundingBox DAGCell::bounding_box() const { @@ -1306,7 +1328,7 @@ openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end) } #ifdef DAGMC -int32_t next_cell(DAGCell* cur_cell, DAGSurface* surf_xed) +int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed) { moab::EntityHandle surf = surf_xed->dagmc_ptr_->entity_by_index(2, surf_xed->dag_index_); @@ -1316,7 +1338,7 @@ int32_t next_cell(DAGCell* cur_cell, DAGSurface* surf_xed) moab::EntityHandle new_vol; cur_cell->dagmc_ptr_->next_vol(surf, vol, new_vol); - return cur_cell->dagmc_ptr_->index_by_handle(new_vol); + return cur_cell->dagmc_ptr_->index_by_handle(new_vol) + dag_univ->cell_idx_offset_; } #endif diff --git a/src/cross_sections.cpp b/src/cross_sections.cpp index ea8d0cfbba..942b088d90 100644 --- a/src/cross_sections.cpp +++ b/src/cross_sections.cpp @@ -96,27 +96,12 @@ void read_cross_sections_xml() { pugi::xml_document doc; std::string filename = settings::path_input + "materials.xml"; -#ifdef DAGMC - std::string s; - bool found_uwuw_mats = false; - if (settings::dagmc) { - found_uwuw_mats = get_uwuw_materials_xml(s); - } - - if (found_uwuw_mats) { - // if we found uwuw materials, load those - doc.load_file(s.c_str()); - } else { -#endif // Check if materials.xml exists if (!file_exists(filename)) { fatal_error("Material XML file '" + filename + "' does not exist."); } // Parse materials.xml file doc.load_file(filename.c_str()); -#ifdef DAGMC - } -#endif auto root = doc.document_element(); diff --git a/src/dagmc.cpp b/src/dagmc.cpp index f79215c116..e9070b1646 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -186,6 +186,7 @@ DAGUniverse::DAGUniverse(const std::string& filename): filename_(filename) { } void DAGUniverse::initialize() { + type_ = UniverseType::DAG; // determine the next cell id int32_t next_cell_id = 0; @@ -336,7 +337,7 @@ void DAGUniverse::initialize() { // set cell ids using global IDs DAGSurface* s = new DAGSurface(); s->dag_index_ = i+1; - s->id_ = next_surf_id++; + s->id_ = dagmc_instance_->id_by_index(2, i+1); s->dagmc_ptr_ = dagmc_instance_; // set BCs @@ -564,7 +565,6 @@ int32_t create_dagmc_universe(const std::string& filename) { void read_geometry_dagmc() { write_message("Reading DAGMC geometry...", 5); - load_dagmc_geometry(); model::root_universe = find_root_universe(); } diff --git a/src/material.cpp b/src/material.cpp index 59d2f954e4..a1aa6ea5f8 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -1223,24 +1223,14 @@ void read_materials_xml() pugi::xml_document doc; - bool using_dagmc_mats = false; -#ifdef DAGMC - if (settings::dagmc) { - using_dagmc_mats = read_uwuw_materials(doc); + // Check if materials.xml exists + std::string filename = settings::path_input + "materials.xml"; + if (!file_exists(filename)) { + fatal_error("Material XML file '" + filename + "' does not exist!"); } -#endif - - if (!using_dagmc_mats) { - // Check if materials.xml exists - std::string filename = settings::path_input + "materials.xml"; - if (!file_exists(filename)) { - fatal_error("Material XML file '" + filename + "' does not exist!"); - } - - // Parse materials.xml file and get root element - doc.load_file(filename.c_str()); - } + // Parse materials.xml file and get root element + doc.load_file(filename.c_str()); // Loop over XML material elements and populate the array. pugi::xml_node root = doc.document_element(); diff --git a/src/particle.cpp b/src/particle.cpp index 755330808f..73cdb3dd6a 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -285,6 +285,8 @@ Particle::event_collide() // Score flux derivative accumulators for differential tallies. if (!model::active_tallies.empty()) score_collision_derivative(*this); + + history_.reset(); } void @@ -318,9 +320,8 @@ void Particle::event_death() { #ifdef DAGMC - if (settings::dagmc) - history().reset(); -#endif + history_.reset(); + #endif // Finish particle track output. if (write_track()) { @@ -387,23 +388,25 @@ Particle::cross_surface() // SEARCH NEIGHBOR LISTS FOR NEXT CELL -// #ifdef DAGMC -// if (settings::dagmc) { -// auto cellp = dynamic_cast(model::cells[cell_last_[0]].get()); -// // TODO: off-by-one -// auto surfp = dynamic_cast(model::surfaces[std::abs(surface_) - 1].get()); -// int32_t i_cell = next_cell(cellp, surfp) - 1; -// // save material and temp -// material_last_ = material_; -// sqrtkT_last_ = sqrtkT_; -// // set new cell value -// coord_[0].cell = i_cell; -// cell_instance_ = 0; -// material_ = model::cells[i_cell]->material_[0]; -// sqrtkT_ = model::cells[i_cell]->sqrtkT_[0]; -// return; -// } -// #endif +#ifdef DAGMC + auto surfp = dynamic_cast(model::surfaces[std::abs(surface_) - 1].get()); + if (surfp) { + auto cellp = dynamic_cast(model::cells[cell_last_[n_coord_ - 1]].get()); + // TODO: off-by-one + auto univp = static_cast(model::universes[coord_[n_coord_ - 1].universe].get()); + + int32_t i_cell = next_cell(univp, cellp, surfp) - 1; + // save material and temp + material_last_ = material_; + sqrtkT_last_ = sqrtkT_; + // set new cell value + coord_[n_coord_ - 1].cell = i_cell; + cell_instance_ = 0; + material_ = model::cells[i_cell]->material_[0]; + sqrtkT_ = model::cells[i_cell]->sqrtkT_[0]; + return; + } +#endif if (neighbor_list_find_cell(*this)) return; diff --git a/src/summary.cpp b/src/summary.cpp index 3d2c6816b4..e43982a6a3 100644 --- a/src/summary.cpp +++ b/src/summary.cpp @@ -89,14 +89,6 @@ void write_geometry(hid_t file) { auto geom_group = create_group(file, "geometry"); -#ifdef DAGMC - if (settings::dagmc) { - write_attribute(geom_group, "dagmc", 1); - close_group(geom_group); - return; - } -#endif - write_attribute(geom_group, "n_cells", model::cells.size()); write_attribute(geom_group, "n_surfaces", model::surfaces.size()); write_attribute(geom_group, "n_universes", model::universes.size()); diff --git a/src/surface.cpp b/src/surface.cpp index 9114b65adb..c2c20d0bfa 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -198,16 +198,12 @@ Surface::diffuse_reflect(Position r, Direction u, uint64_t* seed) const return u/u.norm(); } -CSGSurface::CSGSurface() : Surface{} {}; -CSGSurface::CSGSurface(pugi::xml_node surf_node) : Surface{surf_node} {}; - void -CSGSurface::to_hdf5(hid_t group_id) const +Surface::to_hdf5(hid_t group_id) const { - std::string group_name {"surface "}; - group_name += std::to_string(id_); + hid_t surf_group = create_group(group_id, fmt::format("surface {}", id_)); - hid_t surf_group = create_group(group_id, group_name); + write_string(surf_group, "geom_type", "csg", false); if (bc_) { write_string(surf_group, "boundary_type", bc_->type(), false); @@ -224,6 +220,9 @@ CSGSurface::to_hdf5(hid_t group_id) const close_group(surf_group); } +CSGSurface::CSGSurface() : Surface{} {}; +CSGSurface::CSGSurface(pugi::xml_node surf_node) : Surface{surf_node} {}; + //============================================================================== // DAGSurface implementation //============================================================================== @@ -275,7 +274,9 @@ Direction DAGSurface::reflect(Position r, Direction u, Particle* p) const return p->last_dir(); } -void DAGSurface::to_hdf5(hid_t group_id) const {} +void DAGSurface::to_hdf5_inner(hid_t group_id) const { + write_string(group_id, "geom_type", "dagmc", false); +} #endif From 674327e4a7f7ed663dd49d03a0c645ab7e76c7ee Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 8 Oct 2020 22:30:02 -0500 Subject: [PATCH 09/93] Using temperature accessor for material temperatures. --- src/dagmc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index e9070b1646..ad50d85d5a 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -308,8 +308,8 @@ void DAGUniverse::initialize() { MB_CHK_ERR_CONT(rval); double temp = std::stod(temp_value); c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * temp)); - } else if (mat->temperature_ > 0.0) { - c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * mat->temperature_)); + } else if (mat->temperature() > 0.0) { + c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * mat->temperature())); } else { c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * settings::temperature_default)); } From 0f216bc5354705b800e0bef9f6c3eebc3ade1628 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 8 Oct 2020 22:30:28 -0500 Subject: [PATCH 10/93] Removing old DAGMC variable reset during simulation finalize. --- src/finalize.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/finalize.cpp b/src/finalize.cpp index 54a8d681dc..6d207bd7a2 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -71,7 +71,6 @@ int openmc_finalize() settings::confidence_intervals = false; settings::create_fission_neutrons = true; settings::electron_treatment = ElectronTreatment::LED; - settings::dagmc = false; settings::delayed_photon_scaling = true; settings::energy_cutoff = {0.0, 1000.0, 0.0, 0.0}; settings::entropy_on = false; From d94710996f66951e197de5a94fb94b928c1c507a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 9 Oct 2020 00:00:14 -0500 Subject: [PATCH 11/93] Abstracting the Python Universe class. Adding a DAGMC Universe. --- openmc/geometry.py | 3 +- openmc/universe.py | 266 +++++++++++++++++++++++++++++---------------- 2 files changed, 177 insertions(+), 92 deletions(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index e7d981d7b8..30decd9ff8 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -50,7 +50,8 @@ class Geometry: @root_universe.setter def root_universe(self, root_universe): - check_type('root universe', root_universe, openmc.Universe) + check_type('root universe', root_universe, + (openmc.Universe, openmc.DAGMCUniverse)) self._root_universe = root_universe def add_volume_information(self, volume_calc): diff --git a/openmc/universe.py b/openmc/universe.py index 2dfbf9cd75..be6aa00fd7 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -1,3 +1,4 @@ +from abc import ABC, abstractmethod from collections import OrderedDict from collections.abc import Iterable from copy import copy, deepcopy @@ -12,7 +13,119 @@ from .mixin import IDManagerMixin from .plots import _SVG_COLORS -class Universe(IDManagerMixin): +class UniverseBase(ABC, IDManagerMixin): + """A collection of cells that can be repeated. + + Attributes + ---------- + id : int + Unique identifier of the universe + name : str + Name of the universe + """ + + next_id = 1 + used_ids = set() + + def __init__(self, universe_id=None, name=''): + # Initialize Universe class attributes + self.id = universe_id + self.name = name + self._volume = None + self._atoms = {} + + def __repr__(self): + string = 'Universe\n' + string += '{: <16}=\t{}\n'.format('\tID', self._id) + string += '{: <16}=\t{}\n'.format('\tName', self._name) + return string + + @property + def name(self): + return self._name + + @property + def volume(self): + return self._volume + + @name.setter + def name(self, name): + if name is not None: + cv.check_type('universe name', name, str) + self._name = name + else: + self._name = '' + + @volume.setter + def volume(self, volume): + if volume is not None: + cv.check_type('universe volume', volume, Real) + self._volume = volume + + def add_volume_information(self, volume_calc): + """Add volume information to a universe. + + Parameters + ---------- + volume_calc : openmc.VolumeCalculation + Results from a stochastic volume calculation + + """ + if volume_calc.domain_type == 'universe': + if self.id in volume_calc.volumes: + self._volume = volume_calc.volumes[self.id].n + self._atoms = volume_calc.atoms[self.id] + else: + raise ValueError('No volume information found for this universe.') + else: + raise ValueError('No volume information found for this universe.') + + @abstractmethod + def create_xml_subelement(self, xml_element, memo=None): + """Add the universe xml representation to an incoming xml element + + Parameters + ---------- + xml_element : xml.etree.ElementTree.Element + XML element to be added to + + memo : set or None + A set of object id's representing geometry entities already + written to the xml_element. This parameter is used internally + and should not be specified by users. + + Returns + ------- + None + + """ + + @abstractmethod + def clone(self, clone_materials=True, clone_regions=True, memo=None): + """Create a copy of this universe with a new unique ID, and clones + all cells within this universe. + + Parameters + ---------- + clone_materials : bool + Whether to create separates copies of the materials filling cells + contained in this universe. + clone_regions : bool + Whether to create separates copies of the regions bounding cells + contained in this universe. + memo : dict or None + A nested dictionary of previously cloned objects. This parameter + is used internally and should not be specified by the user. + + Returns + ------- + clone : openmc.Universe + The clone of this universe + + """ + + +class Universe(UniverseBase): """A collection of cells that can be repeated. Parameters @@ -44,15 +157,8 @@ class Universe(IDManagerMixin): """ - next_id = 1 - used_ids = set() - def __init__(self, universe_id=None, name='', cells=None): - # Initialize Cell class attributes - self.id = universe_id - self.name = name - self._volume = None - self._atoms = {} + super().__init__(universe_id, name) # Keys - Cell IDs # Values - Cells @@ -62,24 +168,15 @@ class Universe(IDManagerMixin): self.add_cells(cells) def __repr__(self): - string = 'Universe\n' - string += '{: <16}=\t{}\n'.format('\tID', self._id) - string += '{: <16}=\t{}\n'.format('\tName', self._name) + string = super().__repr__() + string += '{: <16}=\t{}\n'.format('\tGeom', 'CSG') string += '{: <16}=\t{}\n'.format('\tCells', list(self._cells.keys())) return string - @property - def name(self): - return self._name - @property def cells(self): return self._cells - @property - def volume(self): - return self._volume - @property def bounding_box(self): regions = [c.region for c in self.cells.values() @@ -90,20 +187,6 @@ class Universe(IDManagerMixin): # Infinite bounding box return openmc.Intersection([]).bounding_box - @name.setter - def name(self, name): - if name is not None: - cv.check_type('universe name', name, str) - self._name = name - else: - self._name = '' - - @volume.setter - def volume(self, volume): - if volume is not None: - cv.check_type('universe volume', volume, Real) - self._volume = volume - @classmethod def from_hdf5(cls, group, cells): """Create universe from HDF5 group @@ -133,24 +216,6 @@ class Universe(IDManagerMixin): return universe - def add_volume_information(self, volume_calc): - """Add volume information to a universe. - - Parameters - ---------- - volume_calc : openmc.VolumeCalculation - Results from a stochastic volume calculation - - """ - if volume_calc.domain_type == 'universe': - if self.id in volume_calc.volumes: - self._volume = volume_calc.volumes[self.id].n - self._atoms = volume_calc.atoms[self.id] - else: - raise ValueError('No volume information found for this universe.') - else: - raise ValueError('No volume information found for this universe.') - def find(self, point): """Find cells/universes/lattices which contain a given point @@ -481,28 +546,6 @@ class Universe(IDManagerMixin): return universes def clone(self, clone_materials=True, clone_regions=True, memo=None): - """Create a copy of this universe with a new unique ID, and clones - all cells within this universe. - - Parameters - ---------- - clone_materials : bool - Whether to create separates copies of the materials filling cells - contained in this universe. - clone_regions : bool - Whether to create separates copies of the regions bounding cells - contained in this universe. - memo : dict or None - A nested dictionary of previously cloned objects. This parameter - is used internally and should not be specified by the user. - - Returns - ------- - clone : openmc.Universe - The clone of this universe - - """ - if memo is None: memo = {} @@ -523,23 +566,6 @@ class Universe(IDManagerMixin): return memo[self] def create_xml_subelement(self, xml_element, memo=None): - """Add the universe xml representation to an incoming xml element - - Parameters - ---------- - xml_element : xml.etree.ElementTree.Element - XML element to be added to - - memo : set or None - A set of object id's representing geometry entities already - written to the xml_element. This parameter is used internally - and should not be specified by users. - - Returns - ------- - None - - """ # Iterate over all Cells for cell in self._cells.values(): @@ -600,3 +626,61 @@ class Universe(IDManagerMixin): cell._num_instances += 1 if not instances_only: cell._paths.append(cell_path) + + +class DAGMCUniverse(UniverseBase): + """A reference to a DAGMC file to be used in the model. + + Parameters + ---------- + filename : str + Path to the DAGMC file used to represent this universe. + universe_id : int, optional + Unique identifier of the universe. If not specified, an identifier will + automatically be assigned + name : str, optional + Name of the universe. If not specified, the name is the empty string. + cells : Iterable of openmc.Cell, optional + Cells to add to the universe. By default no cells are added. + + Attributes + ---------- + id : int + Unique identifier of the universe + name : str + Name of the universe + filename : str + Path to the DAGMC file used to represent this universe. + """ + + def __init__(self, filename, universe_id=None, name=''): + super().__init__(universe_id, name) + # Initialize class attributes + self.filename = filename + + def __repr__(self): + fmt_str = '{: <16}=\t{}\n' + string = super().__repr__() + string += fmt_str.format('\tGeom', 'DAGMC') + string += fmt_str.format('\tFile', self.filename) + return string + + @property + def filename(self): + return self._filename + + @filename.setter + def filename(self, val): + cv.check_type('DAGMC file', val, str) + self._filename = val + + def clone(self, clone_materials=True, clone_regions=True, memo=None): + pass + + def create_xml_subelement(self, xml_element, memo=None): + # Set xml element values + dagmc_element = ET.Element('dagmc') + dagmc_element.set('id', self.id) + dagmc_element.set('name', self.name) + dagmc_element.set('filename', self.filename) + xml_element.append(dagmc_element) From afaf3b04bf82e37e36c0c3a0466d1fd2f36d8d20 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 13 Oct 2020 11:40:07 -0500 Subject: [PATCH 12/93] Updates to the Python API to support model generation with DAGMC universes. --- openmc/cell.py | 9 ++++----- openmc/filter.py | 10 +++++----- openmc/geometry.py | 9 ++++----- openmc/lattice.py | 2 +- openmc/universe.py | 13 ++++++++++++- 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index c55238df86..af1a07f9a9 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -27,7 +27,7 @@ class Cell(IDManagerMixin): automatically be assigned. name : str, optional Name of the cell. If not specified, the name is the empty string. - fill : openmc.Material or openmc.Universe or openmc.Lattice or None or iterable of openmc.Material, optional + fill : openmc.Material or openmc.UniverseBase or openmc.Lattice or None or iterable of openmc.Material, optional Indicates what the region of space is filled with region : openmc.Region, optional Region of space that is assigned to the cell. @@ -38,7 +38,7 @@ class Cell(IDManagerMixin): Unique identifier for the cell name : str Name of the cell - fill : openmc.Material or openmc.Universe or openmc.Lattice or None or iterable of openmc.Material + fill : openmc.Material or openmc.UniverseBase or openmc.Lattice or None or iterable of openmc.Material Indicates what the region of space is filled with. If None, the cell is treated as a void. An iterable of materials is used to fill repeated instances of a cell with different materials. @@ -156,7 +156,7 @@ class Cell(IDManagerMixin): def fill_type(self): if isinstance(self.fill, openmc.Material): return 'material' - elif isinstance(self.fill, openmc.Universe): + elif isinstance(self.fill, openmc.UniverseBase): return 'universe' elif isinstance(self.fill, openmc.Lattice): return 'lattice' @@ -278,11 +278,10 @@ class Cell(IDManagerMixin): cv.check_type('cell.fill[i]', f, openmc.Material) elif not isinstance(fill, (openmc.Material, openmc.Lattice, - openmc.Universe)): + openmc.UniverseBase)): msg = ('Unable to set Cell ID="{0}" to use a non-Material or ' 'Universe fill "{1}"'.format(self._id, fill)) raise ValueError(msg) - self._fill = fill # Info about atom content can now be invalid diff --git a/openmc/filter.py b/openmc/filter.py index 8da3cf78f6..f0ea7d7215 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -15,7 +15,7 @@ from .cell import Cell from .material import Material from .mixin import IDManagerMixin from .surface import Surface -from .universe import Universe +from .universe import UniverseBase _FILTER_TYPES = ( @@ -408,8 +408,8 @@ class UniverseFilter(WithIDFilter): Parameters ---------- - bins : openmc.Universe, int, or iterable thereof - The Universes to tally. Either openmc.Universe objects or their + bins : openmc.UniverseBase, int, or iterable thereof + The Universes to tally. Either openmc.UniverseBase objects or their Integral ID numbers can be used. filter_id : int Unique identifier for the filter @@ -417,14 +417,14 @@ class UniverseFilter(WithIDFilter): Attributes ---------- bins : Iterable of Integral - openmc.Universe IDs. + openmc.UniverseBase IDs. id : int Unique identifier for the filter num_bins : Integral The number of filter bins """ - expected_type = Universe + expected_type = UniverseBase class MaterialFilter(WithIDFilter): diff --git a/openmc/geometry.py b/openmc/geometry.py index 30decd9ff8..36cff94e30 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -14,13 +14,13 @@ class Geometry: Parameters ---------- - root : openmc.Universe or Iterable of openmc.Cell, optional + root : openmc.UniverseBase or Iterable of openmc.Cell, optional Root universe which contains all others, or an iterable of cells that should be used to create a root universe. Attributes ---------- - root_universe : openmc.Universe + root_universe : openmc.UniverseBase Root universe which contains all others bounding_box : 2-tuple of numpy.array Lower-left and upper-right coordinates of an axis-aligned bounding box @@ -32,7 +32,7 @@ class Geometry: self._root_universe = None self._offsets = {} if root is not None: - if isinstance(root, openmc.Universe): + if isinstance(root, openmc.UniverseBase): self.root_universe = root else: univ = openmc.Universe() @@ -50,8 +50,7 @@ class Geometry: @root_universe.setter def root_universe(self, root_universe): - check_type('root universe', root_universe, - (openmc.Universe, openmc.DAGMCUniverse)) + check_type('root universe', root_universe, openmc.UniverseBase) self._root_universe = root_universe def add_volume_information(self, volume_calc): diff --git a/openmc/lattice.py b/openmc/lattice.py index 252fbf3274..5112dde05a 100644 --- a/openmc/lattice.py +++ b/openmc/lattice.py @@ -488,7 +488,7 @@ class RectLattice(Lattice): @Lattice.universes.setter def universes(self, universes): - cv.check_iterable_type('lattice universes', universes, openmc.Universe, + cv.check_iterable_type('lattice universes', universes, openmc.UniverseBase, min_depth=2, max_depth=3) self._universes = np.asarray(universes) diff --git a/openmc/universe.py b/openmc/universe.py index be6aa00fd7..f71aec664a 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -4,6 +4,7 @@ from collections.abc import Iterable from copy import copy, deepcopy from numbers import Real import random +from xml.etree import ElementTree as ET import numpy as np @@ -677,10 +678,20 @@ class DAGMCUniverse(UniverseBase): def clone(self, clone_materials=True, clone_regions=True, memo=None): pass + def get_all_cells(self, memo=None): + return OrderedDict() + def create_xml_subelement(self, xml_element, memo=None): + + if memo and self in memo: + return + + if memo is not None: + memo.add(self) + # Set xml element values dagmc_element = ET.Element('dagmc') - dagmc_element.set('id', self.id) + dagmc_element.set('id', str(self.id)) dagmc_element.set('name', self.name) dagmc_element.set('filename', self.filename) xml_element.append(dagmc_element) From 70ec716c1f9fb51401587f8a55e6f9d1b2fb9fb3 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 13 Oct 2020 11:40:29 -0500 Subject: [PATCH 13/93] Fixed to automatic ID generation for DAGMC universes. --- src/cell.cpp | 4 ++-- src/dagmc.cpp | 20 ++++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index ec8c5e0e7d..eba407ed9b 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -1026,6 +1026,8 @@ void read_cells(pugi::xml_node node) model::cells.push_back(make_unique(cell_node)); } + read_dagmc_universes(node); + // Fill the cell map. for (int i = 0; i < model::cells.size(); i++) { int32_t id = model::cells[i]->id_; @@ -1037,8 +1039,6 @@ void read_cells(pugi::xml_node node) } } - read_dagmc_universes(node); - // Populate the Universe vector and map. for (int i = 0; i < model::cells.size(); i++) { int32_t uid = model::cells[i]->universe_; diff --git a/src/dagmc.cpp b/src/dagmc.cpp index ad50d85d5a..8768eac1b1 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -257,8 +257,6 @@ void DAGUniverse::initialize() { c->fill_ = C_NONE; // no fill, single universe model::cells.emplace_back(c); - model::cell_map[c->id_] = model::cells.size() - 1; - cells_.push_back(model::cell_map[c->id_]); // MATERIALS @@ -330,14 +328,14 @@ void DAGUniverse::initialize() { // initialize surface objects int n_surfaces = dagmc_instance_->num_entities(2); - for (int i = 0; i < n_surfaces; i++) { moab::EntityHandle surf_handle = dagmc_instance_->entity_by_index(2, i+1); // set cell ids using global IDs DAGSurface* s = new DAGSurface(); s->dag_index_ = i+1; - s->id_ = dagmc_instance_->id_by_index(2, i+1); + s->id_ = next_surf_id++; + // s->id_ = dagmc_instance_->id_by_index(2, i+1); s->dagmc_ptr_ = dagmc_instance_; // set BCs @@ -369,11 +367,21 @@ void DAGUniverse::initialize() { } // add to global array and map + + auto in_map = model::surface_map.find(s->id_); + if (in_map == model::surface_map.end()) { + model::surface_map[s->id_] = model::surfaces.size(); + } else { + fatal_error(fmt::format( + "Two or more surfaces use the same unique ID: {}", s->id_)); + } model::surfaces.emplace_back(s); - model::surface_map[s->id_] = model::surfaces.size() - 1; - } + + } // end surface loop + } + int32_t create_dagmc_universe(const std::string& filename) { if (!model::DAG) { model::DAG = std::make_shared(); From f63ba31b55c01883135fbdb78b0bfaa82c2df057 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 13 Oct 2020 19:54:00 -0500 Subject: [PATCH 14/93] Adding an option for reporting ID overlap between DAGMC and CSG geometry. --- include/openmc/cell.h | 3 +- openmc/universe.py | 19 ++++++++++-- src/cell.cpp | 3 +- src/dagmc.cpp | 71 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 82 insertions(+), 14 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index bef55690a2..0738fe9aab 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -88,7 +88,7 @@ class DAGUniverse : public Universe { public: explicit DAGUniverse(pugi::xml_node node); - explicit DAGUniverse(const std::string& filename); + explicit DAGUniverse(const std::string& filename, bool auto_ids = false); void initialize(); //!< Sets up the DAGMC instance and OpenMC internals @@ -97,6 +97,7 @@ public: std::shared_ptr dagmc_instance_; //! DAGMC Instance for this universe int32_t cell_idx_offset_; int32_t surf_idx_offset_; + bool adjust_ids_; }; #endif diff --git a/openmc/universe.py b/openmc/universe.py index f71aec664a..f7ae0390ac 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -652,12 +652,16 @@ class DAGMCUniverse(UniverseBase): Name of the universe filename : str Path to the DAGMC file used to represent this universe. + auto_ids : bool + Set IDs automatically on initialization (True) or report overlaps + in ID space between CSG and DAGMC (False) """ - def __init__(self, filename, universe_id=None, name=''): + def __init__(self, filename, universe_id=None, name='', auto_ids=False): super().__init__(universe_id, name) # Initialize class attributes self.filename = filename + self.auto_ids = auto_ids def __repr__(self): fmt_str = '{: <16}=\t{}\n' @@ -672,9 +676,18 @@ class DAGMCUniverse(UniverseBase): @filename.setter def filename(self, val): - cv.check_type('DAGMC file', val, str) + cv.check_type('DAGMC filename', val, str) self._filename = val + @property + def auto_ids(self): + return self._auto_ids + + @auto_ids.setter + def auto_ids(self, val): + cv.check_type('DAGMC auto ids', val, bool) + self._auto_ids = val + def clone(self, clone_materials=True, clone_regions=True, memo=None): pass @@ -693,5 +706,7 @@ class DAGMCUniverse(UniverseBase): dagmc_element = ET.Element('dagmc') dagmc_element.set('id', str(self.id)) dagmc_element.set('name', self.name) + if self.auto_ids: + dagmc_element.set('auto_ids', 'true') dagmc_element.set('filename', self.filename) xml_element.append(dagmc_element) diff --git a/src/cell.cpp b/src/cell.cpp index eba407ed9b..39f7361576 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -1026,7 +1026,6 @@ void read_cells(pugi::xml_node node) model::cells.push_back(make_unique(cell_node)); } - read_dagmc_universes(node); // Fill the cell map. for (int i = 0; i < model::cells.size(); i++) { @@ -1039,6 +1038,8 @@ void read_cells(pugi::xml_node node) } } + read_dagmc_universes(node); + // Populate the Universe vector and map. for (int i = 0; i < model::cells.size(); i++) { int32_t uid = model::cells[i]->universe_; diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 8768eac1b1..6e9aac2667 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -54,6 +54,46 @@ std::string dagmc_file() { return filename; } +std::string dagmc_ids_for_dim(std::shared_ptr& dagmc_instance, + int dim) { + // generate a vector of ids + std::vector id_vec; + int n_cells = dagmc_instance->num_entities(dim); + for (int i = 1; i <= n_cells; i++) { + id_vec.push_back(dagmc_instance->id_by_index(dim, i)); + } + + // sort the vector of ids + std::sort(id_vec.begin(), id_vec.end()); + + // generate a string representation of the range + std::stringstream out; + + int i = 0; + int start_id = id_vec[0]; + int stop_id; + while (i < n_cells) { + stop_id = id_vec[i]; + + if (id_vec[i + 1] > stop_id + 1) { + if (start_id != stop_id) { + // there are several IDs in a row, print condensed version + out << start_id << "-" << stop_id; + } else { + // only one ID in this contiguous block + out << start_id; + } + if (i < n_cells - 1) { out << ", "; } + start_id = id_vec[++i]; + stop_id = start_id; + } + + i++; + } + + return out.str(); +} + bool get_uwuw_materials_xml(std::string& s) { std::string filename = dagmc_file(); UWUW uwuw(filename.c_str()); @@ -168,10 +208,15 @@ DAGUniverse::DAGUniverse(pugi::xml_node node) { fatal_error("Must specify a file for the DAGMC universe"); } + adjust_ids_ = false; + if (check_for_node(node, "auto_ids")) { + adjust_ids_ = get_node_value_bool(node, "auto_ids"); + } initialize(); } -DAGUniverse::DAGUniverse(const std::string& filename): filename_(filename) { +DAGUniverse::DAGUniverse(const std::string& filename, bool auto_ids) +: filename_(filename), adjust_ids_(auto_ids) { // determine the next universe id int32_t next_univ_id = 0; for (const auto& u : model::universes) { @@ -249,13 +294,21 @@ void DAGUniverse::initialize() { // set cell ids using global IDs DAGCell* c = new DAGCell(); c->dag_index_ = i + 1; - std::cout << "Cell id: " << next_cell_id << std::endl; - c->id_ = next_cell_id++; - // c->id_ = model::DAG->id_by_index(3, c->dag_index_); + c->id_ = adjust_ids_ ? next_cell_id++ : dagmc_instance_->id_by_index(3, c->dag_index_); c->dagmc_ptr_ = dagmc_instance_; c->universe_ = id_; // set to zero for now c->fill_ = C_NONE; // no fill, single universe + + auto in_map = model::cell_map.find(c->id_); + if (in_map == model::cell_map.end()) { + model::cell_map[c->id_] = model::cells.size(); + } else { + warning(fmt::format("DAGMC Cell IDs: {}", dagmc_ids_for_dim(dagmc_instance_, 3))); + fatal_error(fmt::format("Cell ID {} exists in both DAGMC Universe {} " + "and the CSG geometry.", c->id_, this->id_)); + } + model::cells.emplace_back(c); // MATERIALS @@ -334,8 +387,7 @@ void DAGUniverse::initialize() { // set cell ids using global IDs DAGSurface* s = new DAGSurface(); s->dag_index_ = i+1; - s->id_ = next_surf_id++; - // s->id_ = dagmc_instance_->id_by_index(2, i+1); + s->id_ = adjust_ids_ ? next_surf_id++ : dagmc_instance_->id_by_index(2, i+1); s->dagmc_ptr_ = dagmc_instance_; // set BCs @@ -372,8 +424,9 @@ void DAGUniverse::initialize() { if (in_map == model::surface_map.end()) { model::surface_map[s->id_] = model::surfaces.size(); } else { - fatal_error(fmt::format( - "Two or more surfaces use the same unique ID: {}", s->id_)); + warning(fmt::format("DAGMC Surface IDs: {}", dagmc_ids_for_dim(dagmc_instance_, 2))); + fatal_error(fmt::format("Surface ID {} exists in both Universe {} " + "and the CSG geometry.", s->id_, this->id_)); } model::surfaces.emplace_back(s); @@ -427,12 +480,10 @@ int32_t create_dagmc_universe(const std::string& filename) { moab::EntityHandle graveyard = 0; for (int i = 0; i < n_cells; i++) { moab::EntityHandle vol_handle = model::DAG->entity_by_index(3, i+1); - // set cell ids using global IDs DAGCell* c = new DAGCell(); c->dag_index_ = i+1; c->id_ = model::DAG->id_by_index(3, c->dag_index_); - std::cout << "Cell id: " << c->id_ << std::endl; c->dagmc_ptr_ = model::DAG; c->universe_ = dagmc_univ_id; // set to zero for now c->fill_ = C_NONE; // no fill, single universe From 28153780a7cea321249b115dd9b58170a52ce8b0 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 6 Nov 2020 08:07:16 -0600 Subject: [PATCH 15/93] Moving the read_dagmc_universes function into the dagmc files. --- include/openmc/cell.h | 3 +-- include/openmc/dagmc.h | 1 + src/cell.cpp | 9 ++------- src/dagmc.cpp | 10 ++++++++++ 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 0738fe9aab..d8de483867 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -372,10 +372,9 @@ struct CellInstanceHash { //============================================================================== void read_cells(pugi::xml_node node); -void read_dagmc_universes(pugi::xml_node node); + #ifdef DAGMC -void read_dagmc_universes(pugi::xml_node node); int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed); #endif diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 417cedebd7..91755ed146 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -26,6 +26,7 @@ namespace model { void load_dagmc_geometry(); int32_t create_dagmc_universe(const std::string& filename); void read_geometry_dagmc(); +void read_dagmc_universes(pugi::xml_node node); bool read_uwuw_materials(pugi::xml_document& doc); bool get_uwuw_materials_xml(std::string& s); diff --git a/src/cell.cpp b/src/cell.cpp index 39f7361576..10c1669cba 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -1038,7 +1038,9 @@ void read_cells(pugi::xml_node node) } } + #ifdef DAGMC read_dagmc_universes(node); + #endif // Populate the Universe vector and map. for (int i = 0; i < model::cells.size(); i++) { @@ -1065,13 +1067,6 @@ void read_cells(pugi::xml_node node) } } -void read_dagmc_universes(pugi::xml_node node) { - for (pugi::xml_node dag_node : node.children("dagmc")) { - model::universes.push_back(std::make_unique(dag_node)); - model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; - } -} - //============================================================================== // C-API functions //============================================================================== diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 6e9aac2667..e0bc322eea 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -195,6 +195,16 @@ void load_dagmc_geometry() model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; } +#ifdef DAGMC +void read_dagmc_universes(pugi::xml_node node) { + for (pugi::xml_node dag_node : node.children("dagmc")) { + model::universes.push_back(std::make_unique(dag_node)); + model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; + } +} +#endif + + DAGUniverse::DAGUniverse(pugi::xml_node node) { if (check_for_node(node, "id")) { id_ = std::stoi(get_node_value(node, "id")); From 0f08cfe3d01cf8443f2cc9a60bb11be0870b5f4b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 6 Nov 2020 08:22:01 -0600 Subject: [PATCH 16/93] Now writing a geometry file regardless CSG/CAD geometry use. --- openmc/model/model.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 7d6acb281c..0501f03f3a 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -179,8 +179,7 @@ class Model: d.mkdir(parents=True) self.settings.export_to_xml(d) - if not self.settings.dagmc: - self.geometry.export_to_xml(d) + self.geometry.export_to_xml(d) # If a materials collection was specified, export it. Otherwise, look # for all materials in the geometry and use that to automatically build From 4b5aa24a1e8c4f9e2dc021e37d6a4abde80d3d4e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 6 Nov 2020 08:34:02 -0600 Subject: [PATCH 17/93] Removing dagmc property and related methods from the settings class. --- openmc/settings.py | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index 615e6365aa..7696aee9fc 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -44,8 +44,6 @@ class Settings: weight assigned to particles that are not killed after Russian roulette. Value of energy should be a float indicating energy in eV below which particle type will be killed. - dagmc : bool - Indicate that a CAD-based DAGMC geometry will be used. delayed_photon_scaling : bool Indicate whether to scale the fission photon yield by (EGP + EGD)/EGP where EGP is the energy release of prompt photons and EGD is the energy @@ -269,8 +267,6 @@ class Settings: self._material_cell_offsets = None self._log_grid_bins = None - self._dagmc = False - self._event_based = None self._max_particles_in_flight = None @@ -434,10 +430,6 @@ class Settings: def log_grid_bins(self): return self._log_grid_bins - @property - def dagmc(self): - return self._dagmc - @property def event_based(self): return self._event_based @@ -633,11 +625,6 @@ class Settings: cv.check_type('photon transport', photon_transport, bool) self._photon_transport = photon_transport - @dagmc.setter - def dagmc(self, dagmc): - cv.check_type('dagmc geometry', dagmc, bool) - self._dagmc = dagmc - @ptables.setter def ptables(self, ptables): cv.check_type('probability tables', ptables, bool) @@ -1125,11 +1112,6 @@ class Settings: elem = ET.SubElement(root, "log_grid_bins") elem.text = str(self._log_grid_bins) - def _create_dagmc_subelement(self, root): - if self._dagmc: - elem = ET.SubElement(root, "dagmc") - elem.text = str(self._dagmc).lower() - def _eigenvalue_from_xml_element(self, root): elem = root.find('eigenvalue') if elem is not None: @@ -1407,11 +1389,6 @@ class Settings: if text is not None: self.log_grid_bins = int(text) - def _dagmc_from_xml_element(self, root): - text = get_text(root, 'dagmc') - if text is not None: - self.dagmc = text in ('true', '1') - def export_to_xml(self, path='settings.xml'): """Export simulation settings to an XML file. @@ -1465,7 +1442,6 @@ class Settings: self._create_max_particles_in_flight_subelement(root_element) self._create_material_cell_offsets_subelement(root_element) self._create_log_grid_bins_subelement(root_element) - self._create_dagmc_subelement(root_element) # Clean the indentation in the file to be user-readable clean_indentation(root_element) @@ -1539,7 +1515,6 @@ class Settings: settings._max_particles_in_flight_from_xml_element(root) settings._material_cell_offsets_from_xml_element(root) settings._log_grid_bins_from_xml_element(root) - settings._dagmc_from_xml_element(root) # TODO: Get volume calculations From 956cf08481c1d712ecd05494fb57eff6a686a561 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 6 Nov 2020 10:56:59 -0600 Subject: [PATCH 18/93] Relying on the same enum to describe the Geometry type of different classes. --- include/openmc/cell.h | 12 +++--------- include/openmc/surface.h | 13 +++++++++++-- src/cell.cpp | 16 ++++++++++++---- src/dagmc.cpp | 2 +- src/surface.cpp | 31 +++++++++++++++++++------------ 5 files changed, 46 insertions(+), 28 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index d8de483867..21ba3ddcd4 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -31,11 +31,6 @@ enum class Fill { LATTICE }; -enum class UniverseType { - CSG, - DAG -}; - // TODO: Convert to enum constexpr int32_t OP_LEFT_PAREN {std::numeric_limits::max()}; constexpr int32_t OP_RIGHT_PAREN {std::numeric_limits::max() - 1}; @@ -78,7 +73,7 @@ public: BoundingBox bounding_box() const; - UniverseType type_ = UniverseType::CSG; + GeometryType type_ = GeometryType::CSG; unique_ptr partitioner_; }; @@ -178,8 +173,6 @@ public: //! \param[in] name Cell name void set_name(const std::string& name) { name_ = name; }; - - //! Get all cell instances contained by this cell //! \return Map with cell indexes as keys and instances as values std::unordered_map> get_contained_cells() const; @@ -195,10 +188,11 @@ public: int32_t id_; //!< Unique ID std::string name_; //!< User-defined name - Fill type_; //!< Material, universe, or lattice + Fill type_; //!< Material, universe, or lattice int32_t universe_; //!< Universe # this cell is in int32_t fill_; //!< Universe # filling this cell int32_t n_instances_{0}; //!< Number of instances of this cell + GeometryType geom_type_; //!< Geometric representation type (CSG, DAGMC) //! \brief Index corresponding to this cell in distribcell arrays int distribcell_index_{C_NONE}; diff --git a/include/openmc/surface.h b/include/openmc/surface.h index 8b4e416052..28590b4493 100644 --- a/include/openmc/surface.h +++ b/include/openmc/surface.h @@ -30,7 +30,16 @@ namespace model { } // namespace model //============================================================================== -//! Coordinates for an axis-aligned cuboid bounding a geometric object. +// Constants +//============================================================================== + +enum class GeometryType { + CSG, + DAG +}; + +//============================================================================== +//! Coordinates for an axis-aligned cube that bounds a geometric object. //============================================================================== struct BoundingBox @@ -166,7 +175,7 @@ public: Direction normal(Position r) const; Direction reflect(Position r, Direction u, Particle* p) const; - void to_hdf5_inner(hid_t group_id) const override; + inline void to_hdf5_inner(hid_t group_id) const override {}; std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance int32_t dag_index_; //!< DagMC index of surface diff --git a/src/cell.cpp b/src/cell.cpp index 10c1669cba..c5d53dda4a 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -195,10 +195,10 @@ Universe::to_hdf5(hid_t universes_group) const auto group = create_group(universes_group, fmt::format("universe {}", id_)); switch(type_) { - case UniverseType::CSG : + case GeometryType::CSG : write_string(group, "geom_type", "csg", false); break; - case UniverseType::DAG : + case GeometryType::DAG : write_string(group, "geom_type", "dagmc", false); break; } @@ -355,10 +355,15 @@ Cell::to_hdf5(hid_t cell_group) const { // CSGCell implementation //============================================================================== -CSGCell::CSGCell() {} // empty constructor +// default constructor +CSGCell::CSGCell() { + geom_type_ = GeometryType::CSG; +} CSGCell::CSGCell(pugi::xml_node cell_node) { + geom_type_ = GeometryType::CSG; + if (check_for_node(cell_node, "id")) { id_ = std::stoi(get_node_value(cell_node, "id")); } else { @@ -800,7 +805,10 @@ CSGCell::contains_complex(Position r, Direction u, int32_t on_surface) const // DAGMC Cell implementation //============================================================================== #ifdef DAGMC -DAGCell::DAGCell() : Cell{} { simple_ = true; }; +DAGCell::DAGCell() : Cell{} { + geom_type_ = GeometryType::DAG; + simple_ = true; +}; std::pair DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) const diff --git a/src/dagmc.cpp b/src/dagmc.cpp index e0bc322eea..97398374c0 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -241,7 +241,7 @@ DAGUniverse::DAGUniverse(const std::string& filename, bool auto_ids) } void DAGUniverse::initialize() { - type_ = UniverseType::DAG; + type_ = GeometryType::DAG; // determine the next cell id int32_t next_cell_id = 0; diff --git a/src/surface.cpp b/src/surface.cpp index c2c20d0bfa..92e50a76bb 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -203,12 +203,17 @@ Surface::to_hdf5(hid_t group_id) const { hid_t surf_group = create_group(group_id, fmt::format("surface {}", id_)); - write_string(surf_group, "geom_type", "csg", false); + if (geom_type_ == GeometryType::DAG) { + write_string(surf_group, "geom_type", "dagmc", false); + } + else if (geom_type_ == GeometryType::CSG) { + write_string(surf_group, "geom_type", "csg", false); - if (bc_) { - write_string(surf_group, "boundary_type", bc_->type(), false); - } else { - write_string(surf_group, "boundary_type", "transmission", false); + if (bc_) { + write_string(surf_group, "boundary_type", bc_->type(), false); + } else { + write_string(surf_group, "boundary_type", "transmission", false); + } } if (!name_.empty()) { @@ -220,14 +225,20 @@ Surface::to_hdf5(hid_t group_id) const close_group(surf_group); } -CSGSurface::CSGSurface() : Surface{} {}; -CSGSurface::CSGSurface(pugi::xml_node surf_node) : Surface{surf_node} {}; +CSGSurface::CSGSurface() : Surface{} { + geom_type_ = GeometryType::CSG; +}; +CSGSurface::CSGSurface(pugi::xml_node surf_node) : Surface{surf_node} { + geom_type_ = GeometryType::CSG; +}; //============================================================================== // DAGSurface implementation //============================================================================== #ifdef DAGMC -DAGSurface::DAGSurface() : Surface{} {} // empty constructor +DAGSurface::DAGSurface() : Surface{} { + geom_type_ = GeometryType::DAG; +} // empty constructor double DAGSurface::evaluate(Position r) const { @@ -274,10 +285,6 @@ Direction DAGSurface::reflect(Position r, Direction u, Particle* p) const return p->last_dir(); } -void DAGSurface::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "geom_type", "dagmc", false); -} - #endif //============================================================================== From 67aca58079d4c68cfd6f1d6e9e781232f74131f2 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 12 Nov 2020 10:12:01 -0600 Subject: [PATCH 19/93] Adding ifdefs to fix builds without DAGMC. --- src/particle.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/particle.cpp b/src/particle.cpp index 73cdb3dd6a..5c6d0d466a 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -286,7 +286,9 @@ Particle::event_collide() // Score flux derivative accumulators for differential tallies. if (!model::active_tallies.empty()) score_collision_derivative(*this); + #ifdef DAGMC history_.reset(); + #endif } void @@ -502,6 +504,10 @@ Particle::cross_reflective_bc(const Surface& surf, Direction new_u) coord(0).cell = cell_last(n_coord_last() - 1); surface() = -surface(); + #ifdef DAGMC + if (surf->geom_type_ != GeometryType::DAGMC) history_.reset(); + #endif + // If a reflective surface is coincident with a lattice or universe // boundary, it is necessary to redetermine the particle's coordinates in // the lower universes. From 3e93b814a94d4a2b6a6613c75b7f2d0f3c8d969c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 12 Nov 2020 10:26:44 -0600 Subject: [PATCH 20/93] Updating python module to enable summary file reads from DAGMC simulations. Updating legacy DAGMC test as well. --- openmc/summary.py | 3 ++- openmc/surface.py | 4 +++- openmc/universe.py | 3 +++ tests/regression_tests/dagmc/legacy/inputs_true.dat | 5 ++++- tests/regression_tests/dagmc/legacy/test.py | 4 ++++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/openmc/summary.py b/openmc/summary.py index 63ed665169..a1ee2dcd66 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -123,7 +123,8 @@ class Summary: def _read_surfaces(self): for group in self._f['geometry/surfaces'].values(): surface = openmc.Surface.from_hdf5(group) - self._fast_surfaces[surface.id] = surface + if surface: + self._fast_surfaces[surface.id] = surface def _read_cells(self): diff --git a/openmc/surface.py b/openmc/surface.py index d71e73788e..3c2c550101 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -455,7 +455,9 @@ class Surface(IDManagerMixin, ABC): surface_id = int(group.name.split('/')[-1].lstrip('surface ')) name = group['name'][()].decode() if 'name' in group else '' - surf_type = group['type'][()].decode() + surf_type = group['geom_type'][()].decode() + if surf_type == 'dagmc': + return bc = group['boundary_type'][()].decode() coeffs = group['coefficients'][...] kwargs = {'boundary_type': bc, 'name': name, 'surface_id': surface_id} diff --git a/openmc/universe.py b/openmc/universe.py index f7ae0390ac..c3f4e36ced 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -694,6 +694,9 @@ class DAGMCUniverse(UniverseBase): def get_all_cells(self, memo=None): return OrderedDict() + def get_all_materials(self, memo=None): + return OrderedDict() + def create_xml_subelement(self, xml_element, memo=None): if memo and self in memo: diff --git a/tests/regression_tests/dagmc/legacy/inputs_true.dat b/tests/regression_tests/dagmc/legacy/inputs_true.dat index 769a3384c3..ecc5d7373a 100644 --- a/tests/regression_tests/dagmc/legacy/inputs_true.dat +++ b/tests/regression_tests/dagmc/legacy/inputs_true.dat @@ -1,4 +1,8 @@ + + + + @@ -22,7 +26,6 @@ -4 -4 -4 4 4 4 - true diff --git a/tests/regression_tests/dagmc/legacy/test.py b/tests/regression_tests/dagmc/legacy/test.py index 5af18e5c8c..76b76fbda0 100644 --- a/tests/regression_tests/dagmc/legacy/test.py +++ b/tests/regression_tests/dagmc/legacy/test.py @@ -26,6 +26,10 @@ def model(): model.settings.dagmc = True + # geometry + dag_univ = openmc.DAGMCUniverse("dagmc.h5m") + model.geometry = openmc.Geometry(root=dag_univ) + # tally tally = openmc.Tally() tally.scores = ['total'] From 0bd2f9263b132b7091bd0f85821bf3fb6a9d66e5 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 6 Dec 2020 00:20:28 -0600 Subject: [PATCH 21/93] Always checking DAGMC models for additional material definitions. --- include/openmc/dagmc.h | 1 + src/dagmc.cpp | 44 +++++++++++++++++++ src/material.cpp | 4 ++ .../dagmc/uwuw/inputs_true.dat | 8 +++- tests/regression_tests/dagmc/uwuw/test.py | 6 ++- 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 91755ed146..f0c6d47186 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -27,6 +27,7 @@ void load_dagmc_geometry(); int32_t create_dagmc_universe(const std::string& filename); void read_geometry_dagmc(); void read_dagmc_universes(pugi::xml_node node); +void read_dagmc_uwuw_materials(); bool read_uwuw_materials(pugi::xml_document& doc); bool get_uwuw_materials_xml(std::string& s); diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 97398374c0..c162096c23 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -128,6 +128,50 @@ bool read_uwuw_materials(pugi::xml_document& doc) { return found_uwuw_mats; } +void read_dagmc_uwuw_materials() { + std::string filename = settings::path_input + "geometry.xml"; + if (!file_exists(filename)) { + fatal_error(fmt::format("Geometry XML file '{}' does not exist!", filename)); + } + + pugi::xml_document doc; + auto result = doc.load_file(filename.c_str()); + if (!result) { + fatal_error("Error processing geometry.xml file."); + } + pugi::xml_node root = doc.document_element(); + // Loop over DAGMC elements + for (pugi::xml_node dagmc_node : root.children("dagmc")) { + if (!check_for_node(dagmc_node, "filename")) { + fatal_error("No filename specified on a DAGMC universe element"); + } + std::string dagmc_filename = get_node_value(dagmc_node, "filename"); + // Load any existing UWUW materials + UWUW uwuw(dagmc_filename.c_str()); + const auto& mat_lib = uwuw.material_library; + if (mat_lib.size() == 0) continue; + + std::stringstream ss; + ss << "\n"; + ss << "\n"; + for (auto mat : mat_lib) { ss << mat.second.openmc("atom"); } + ss << ""; + std::string mat_xml_string = ss.str(); + + // create a pugi XML document from this string + pugi::xml_document doc; + auto result = doc.load_string(mat_xml_string.c_str()); + if (!result) { + fatal_error("Error processing XML created using DAGMC UWUW materials."); + } + pugi::xml_node root = doc.document_element(); + for (pugi::xml_node material_node : root.children("material")) { + model::materials.push_back(std::make_unique(material_node)); + } + } +} + + bool write_uwuw_materials_xml() { std::string s; bool found_uwuw_mats = get_uwuw_materials_xml(s); diff --git a/src/material.cpp b/src/material.cpp index a1aa6ea5f8..9010e8b01c 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -1237,6 +1237,10 @@ void read_materials_xml() for (pugi::xml_node material_node : root.children("material")) { model::materials.push_back(make_unique(material_node)); } + + // Search for materials defined on DAGMC models + read_dagmc_uwuw_materials(); + model::materials.shrink_to_fit(); } diff --git a/tests/regression_tests/dagmc/uwuw/inputs_true.dat b/tests/regression_tests/dagmc/uwuw/inputs_true.dat index 87ceb944d8..901547fa29 100644 --- a/tests/regression_tests/dagmc/uwuw/inputs_true.dat +++ b/tests/regression_tests/dagmc/uwuw/inputs_true.dat @@ -1,4 +1,11 @@ + + + + + + + eigenvalue 100 @@ -9,7 +16,6 @@ -4 -4 -4 4 4 4 - true diff --git a/tests/regression_tests/dagmc/uwuw/test.py b/tests/regression_tests/dagmc/uwuw/test.py index b4391d8e77..5c9777d481 100644 --- a/tests/regression_tests/dagmc/uwuw/test.py +++ b/tests/regression_tests/dagmc/uwuw/test.py @@ -27,13 +27,17 @@ class UWUWTest(PyAPITestHarness): model.settings.export_to_xml() + # geometry + dag_univ = openmc.DAGMCUniverse("dagmc.h5m") + model.geometry = openmc.Geometry(root=dag_univ) + # tally tally = openmc.Tally() tally.scores = ['total'] tally.filters = [openmc.CellFilter(1)] model.tallies = [tally] - model.tallies.export_to_xml() + model.export_to_xml() def test_uwuw(): harness = UWUWTest('statepoint.5.h5') From 9c2f9b523bbe8c08740dced743bcdbce6eaffdf7 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 6 Dec 2020 11:36:23 -0600 Subject: [PATCH 22/93] Updating history reset to account for reflective boundaries. Adding mark as lost warning when no intersection is found. --- src/cell.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index c5d53dda4a..ae121d2ba1 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -816,10 +816,8 @@ DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) cons Expects(p); // if we've changed direction or we're not on a surface, // reset the history and update last direction - if (u != p->last_dir() || on_surface == 0) { - p->history().reset(); - p->last_dir() = u; - } + if (u != p->last_dir()) { p->last_dir() = u; p->history().reset(); } + if (on_surface == 0) { p->history().reset(); } const auto& univ = model::universes[p->coord_[p->n_coord_ - 1].universe]; @@ -841,6 +839,7 @@ DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) cons // indicate that particle is lost surf_idx = -1; dist = INFINITY; + p->mark_as_lost(fmt::format("No intersection found with DAGMC cell {}", id_)); } return {dist, surf_idx}; From bac09e62959b8294fdaea75a1f6bb16ddcb19b79 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 6 Dec 2020 13:43:11 -0600 Subject: [PATCH 23/93] Adding geometry output to the reflecting boundary DAGMC test. --- tests/regression_tests/dagmc/refl/test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/regression_tests/dagmc/refl/test.py b/tests/regression_tests/dagmc/refl/test.py index 305e18ed5c..1920a572d9 100644 --- a/tests/regression_tests/dagmc/refl/test.py +++ b/tests/regression_tests/dagmc/refl/test.py @@ -27,6 +27,10 @@ class UWUWTest(PyAPITestHarness): model.settings.export_to_xml() + # geometry + dag_univ = openmc.DAGMCUniverse("dagmc.h5m") + model.geometry = openmc.Geometry(root=dag_univ) + # tally tally = openmc.Tally() tally.scores = ['total'] @@ -34,6 +38,7 @@ class UWUWTest(PyAPITestHarness): model.tallies = [tally] model.tallies.export_to_xml() + model.export_to_xml() def test_refl(): harness = UWUWTest('statepoint.5.h5') From d12eed03a23dd853dec87abb732eafe7deaa0c52 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sun, 6 Dec 2020 21:28:38 -0600 Subject: [PATCH 24/93] Updates to the reflection test inputs to ensure the correct cell is tallied. --- tests/regression_tests/dagmc/refl/inputs_true.dat | 8 +++++++- tests/regression_tests/dagmc/refl/test.py | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/regression_tests/dagmc/refl/inputs_true.dat b/tests/regression_tests/dagmc/refl/inputs_true.dat index 2732730010..fdd68002d6 100644 --- a/tests/regression_tests/dagmc/refl/inputs_true.dat +++ b/tests/regression_tests/dagmc/refl/inputs_true.dat @@ -1,4 +1,11 @@ + + + + + + + eigenvalue 100 @@ -9,7 +16,6 @@ -4 -4 -4 4 4 4 - true diff --git a/tests/regression_tests/dagmc/refl/test.py b/tests/regression_tests/dagmc/refl/test.py index 1920a572d9..2b43caf89e 100644 --- a/tests/regression_tests/dagmc/refl/test.py +++ b/tests/regression_tests/dagmc/refl/test.py @@ -29,6 +29,7 @@ class UWUWTest(PyAPITestHarness): # geometry dag_univ = openmc.DAGMCUniverse("dagmc.h5m") + dag_univ.auto_ids = True model.geometry = openmc.Geometry(root=dag_univ) # tally From 49e22c9091acfe51939cb17c7b87690f54a89f76 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 7 Dec 2020 10:09:42 -0600 Subject: [PATCH 25/93] Correcting extraction of surface type from hdf5 formats. --- openmc/surface.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openmc/surface.py b/openmc/surface.py index 3c2c550101..70fd008318 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -453,15 +453,19 @@ class Surface(IDManagerMixin, ABC): """ + # If this is a DAGMC surface, do nothing for now + geom_type = group['geom_type'][()].decode() + if geom_type == 'dagmc': + return + surface_id = int(group.name.split('/')[-1].lstrip('surface ')) name = group['name'][()].decode() if 'name' in group else '' - surf_type = group['geom_type'][()].decode() - if surf_type == 'dagmc': - return + bc = group['boundary_type'][()].decode() coeffs = group['coefficients'][...] kwargs = {'boundary_type': bc, 'name': name, 'surface_id': surface_id} + surf_type = group['type'][()].decode() cls = _SURFACE_CLASSES[surf_type] return cls(*coeffs, **kwargs) From 41c462a0b17364fdd0b6c7feb6f7d43b32542011 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 7 Dec 2020 10:10:14 -0600 Subject: [PATCH 26/93] Using a Boolean type instead of the object pointer to dectect the surface type. --- src/particle.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/particle.cpp b/src/particle.cpp index 5c6d0d466a..817f7f60ba 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -389,8 +389,8 @@ Particle::cross_surface() // ========================================================================== // SEARCH NEIGHBOR LISTS FOR NEXT CELL - #ifdef DAGMC + // in DAGMC, we know what the next cell should be auto surfp = dynamic_cast(model::surfaces[std::abs(surface_) - 1].get()); if (surfp) { auto cellp = dynamic_cast(model::cells[cell_last_[n_coord_ - 1]].get()); @@ -512,13 +512,11 @@ Particle::cross_reflective_bc(const Surface& surf, Direction new_u) // 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) - if (!settings::dagmc) { - n_coord() = 1; - if (!neighbor_list_find_cell(*this)) { - mark_as_lost("Couldn't find particle after reflecting from surface " + - std::to_string(surf.id_) + "."); - return; - } + n_coord() = 1; + if (surf->geom_type_ != GeometryType::DAGMC && !neighbor_list_find_cell(*this, true)) { + this->mark_as_lost("Couldn't find particle after reflecting from surface " + + std::to_string(surf.id_) + "."); + return; } // Set previous coordinate going slightly past surface crossing From a09c468faf773bb1fc5c496c4ced226ebcc4072b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 7 Dec 2020 15:49:40 -0600 Subject: [PATCH 27/93] Updates to the dagmc test and settings test from the Python API. --- tests/unit_tests/dagmc/test.py | 4 +++- tests/unit_tests/test_settings.py | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/dagmc/test.py b/tests/unit_tests/dagmc/test.py index e5d7725551..b3e2c390f4 100644 --- a/tests/unit_tests/dagmc/test.py +++ b/tests/unit_tests/dagmc/test.py @@ -29,7 +29,9 @@ def dagmc_model(request): source = openmc.Source(space=source_box) model.settings.source = source - model.settings.dagmc = True + # geometry + dagmc_universe = openmc.DAGMCUniverse('dagmc.h5m') + model.geometry = openmc.Geometry(dagmc_universe) # tally tally = openmc.Tally() diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py index 7a3357d439..fdaf5c2db8 100644 --- a/tests/unit_tests/test_settings.py +++ b/tests/unit_tests/test_settings.py @@ -54,7 +54,6 @@ def test_export_to_xml(run_in_tmpdir): s.log_grid_bins = 2000 s.photon_transport = False s.electron_treatment = 'led' - s.dagmc = False # Make sure exporting XML works s.export_to_xml() @@ -111,4 +110,3 @@ def test_export_to_xml(run_in_tmpdir): assert s.log_grid_bins == 2000 assert not s.photon_transport assert s.electron_treatment == 'led' - assert not s.dagmc From c732e2ae88bb1ac58c3247c46677c24a7e468172 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 7 Dec 2020 16:05:52 -0600 Subject: [PATCH 28/93] Adding empty definition for dagmc materials function. --- include/openmc/dagmc.h | 8 ++++++-- src/dagmc.cpp | 2 +- src/material.cpp | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index f0c6d47186..d18b705761 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -27,12 +27,16 @@ void load_dagmc_geometry(); int32_t create_dagmc_universe(const std::string& filename); void read_geometry_dagmc(); void read_dagmc_universes(pugi::xml_node node); -void read_dagmc_uwuw_materials(); +void read_dagmc_materials(); bool read_uwuw_materials(pugi::xml_document& doc); bool get_uwuw_materials_xml(std::string& s); } // namespace openmc -#endif // DAGMC +#else + +inline void read_dagmc_materials() {}; + +#endif #endif // OPENMC_DAGMC_H diff --git a/src/dagmc.cpp b/src/dagmc.cpp index c162096c23..f459580d64 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -128,7 +128,7 @@ bool read_uwuw_materials(pugi::xml_document& doc) { return found_uwuw_mats; } -void read_dagmc_uwuw_materials() { +void read_dagmc_materials() { std::string filename = settings::path_input + "geometry.xml"; if (!file_exists(filename)) { fatal_error(fmt::format("Geometry XML file '{}' does not exist!", filename)); diff --git a/src/material.cpp b/src/material.cpp index 9010e8b01c..80999abae9 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -1239,7 +1239,7 @@ void read_materials_xml() } // Search for materials defined on DAGMC models - read_dagmc_uwuw_materials(); + read_dagmc_materials(); model::materials.shrink_to_fit(); } From 70cb36b474e8a31a71cc2d453658818403a89aa6 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 17 Feb 2021 23:08:51 -0600 Subject: [PATCH 29/93] Corrections after rebasing. --- include/openmc/surface.h | 8 +++++--- src/dagmc.cpp | 13 ++++++------- src/particle.cpp | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/openmc/surface.h b/include/openmc/surface.h index 28590b4493..3d386e8768 100644 --- a/include/openmc/surface.h +++ b/include/openmc/surface.h @@ -97,6 +97,7 @@ public: int id_; //!< Unique ID std::string name_; //!< User-defined name std::shared_ptr bc_ {nullptr}; //!< Boundary condition + GeometryType geom_type_; //!< Geometry type indicator (CSG or DAGMC) bool surf_source_ {false}; //!< Activate source banking for the surface? explicit Surface(pugi::xml_node surf_node); @@ -143,13 +144,13 @@ public: //! Write all information needed to reconstruct the surface to an HDF5 group. //! \param group_id An HDF5 group id. - virtual void to_hdf5(hid_t group_id) const = 0; + void to_hdf5(hid_t group_id) const; //! Get the BoundingBox for this surface. virtual BoundingBox bounding_box(bool /*pos_side*/) const { return {}; } protected: - virtual void to_hdf5_inner(hid_t group_id) const = 0; + virtual void to_hdf5_inner(hid_t group_id) const = 0; }; class CSGSurface : public Surface @@ -158,7 +159,8 @@ public: explicit CSGSurface(pugi::xml_node surf_node); CSGSurface(); - void to_hdf5(hid_t group_id) const; +protected: + virtual void to_hdf5_inner(hid_t group_id) const = 0; }; //============================================================================== diff --git a/src/dagmc.cpp b/src/dagmc.cpp index f459580d64..91e2ffb012 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -154,7 +154,7 @@ void read_dagmc_materials() { std::stringstream ss; ss << "\n"; ss << "\n"; - for (auto mat : mat_lib) { ss << mat.second.openmc("atom"); } + for (auto mat : mat_lib) { ss << mat.second->openmc("atom"); } ss << ""; std::string mat_xml_string = ss.str(); @@ -389,7 +389,7 @@ void DAGUniverse::initialize() { std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle]; if (uwuw.material_library.count(uwuw_mat) != 0) { // Note: material numbers are set by UWUW - int mat_number = uwuw.material_library[uwuw_mat].metadata["mat_number"].asInt(); + int mat_number = uwuw.material_library.get_material(uwuw_mat).metadata["mat_number"].asInt(); c->material_.push_back(mat_number); } else { fatal_error(fmt::format("Material with value {} not found in the " @@ -448,12 +448,11 @@ void DAGUniverse::initialize() { std::string bc_value = DMD.get_surface_property("boundary", surf_handle); to_lower(bc_value); if (bc_value.empty() || bc_value == "transmit" || bc_value == "transmission") { - // set to transmission by default - s->bc_ = Surface::BoundaryType::TRANSMIT; + // set to transmission by default (nullptr) } else if (bc_value == "vacuum") { - s->bc_ = Surface::BoundaryType::VACUUM; + s->bc_ = std::make_shared(); } else if (bc_value == "reflective" || bc_value == "reflect" || bc_value == "reflecting") { - s->bc_ = Surface::BoundaryType::REFLECT; + s->bc_ = std::make_shared(); } else if (bc_value == "periodic") { fatal_error("Periodic boundary condition not supported in DAGMC."); } else { @@ -469,7 +468,7 @@ void DAGUniverse::initialize() { // if this surface belongs to the graveyard if (graveyard && parent_vols.find(graveyard) != parent_vols.end()) { // set graveyard surface BC's to vacuum - s->bc_ = Surface::BoundaryType::VACUUM; + s->bc_ = std::make_shared(); } // add to global array and map diff --git a/src/particle.cpp b/src/particle.cpp index 817f7f60ba..5b2105a36e 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -505,7 +505,7 @@ Particle::cross_reflective_bc(const Surface& surf, Direction new_u) surface() = -surface(); #ifdef DAGMC - if (surf->geom_type_ != GeometryType::DAGMC) history_.reset(); + if (surf.geom_type_ != GeometryType::DAG) history_.reset(); #endif // If a reflective surface is coincident with a lattice or universe From 2eac03cee1edb56cf1a53b2409d662f8527473a1 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 17 Feb 2021 23:11:24 -0600 Subject: [PATCH 30/93] Adding basic test for dagmc universes. --- .../dagmc/universes/__init__.py | 0 .../dagmc/universes/dagmc.h5m | Bin 0 -> 1233488 bytes .../dagmc/universes/geometry.xml | 27 ++++++++++++++++++ .../dagmc/universes/materials.xml | 26 +++++++++++++++++ .../dagmc/universes/settings.xml | 10 +++++++ .../regression_tests/dagmc/universes/test.py | 4 +++ 6 files changed, 67 insertions(+) create mode 100644 tests/regression_tests/dagmc/universes/__init__.py create mode 100644 tests/regression_tests/dagmc/universes/dagmc.h5m create mode 100644 tests/regression_tests/dagmc/universes/geometry.xml create mode 100644 tests/regression_tests/dagmc/universes/materials.xml create mode 100644 tests/regression_tests/dagmc/universes/settings.xml create mode 100644 tests/regression_tests/dagmc/universes/test.py diff --git a/tests/regression_tests/dagmc/universes/__init__.py b/tests/regression_tests/dagmc/universes/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regression_tests/dagmc/universes/dagmc.h5m b/tests/regression_tests/dagmc/universes/dagmc.h5m new file mode 100644 index 0000000000000000000000000000000000000000..d5f884db27448dec82e80c18b1bea02833926b92 GIT binary patch literal 1233488 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%0A=3heyKvQlV3y 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�Q{Wx_^Ac`TNrS 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 v-eGRd`wr{^-jkn4Wz{4*z$4f&IS#v3cVT literal 0 HcmV?d00001 diff --git a/tests/regression_tests/dagmc/universes/geometry.xml b/tests/regression_tests/dagmc/universes/geometry.xml new file mode 100644 index 0000000000..556637f65d --- /dev/null +++ b/tests/regression_tests/dagmc/universes/geometry.xml @@ -0,0 +1,27 @@ + + + + + + 48.0 48.0 48.0 + 3 3 3 + -24.0 -24.0 -24.0 + + 1 1 1 + 1 1 1 + 1 1 1 + 1 1 1 + 1 1 1 + 1 1 1 + 1 1 1 + 1 1 1 + 1 1 1 + + + + + + + + + diff --git a/tests/regression_tests/dagmc/universes/materials.xml b/tests/regression_tests/dagmc/universes/materials.xml new file mode 100644 index 0000000000..47e740ba0e --- /dev/null +++ b/tests/regression_tests/dagmc/universes/materials.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/regression_tests/dagmc/universes/settings.xml b/tests/regression_tests/dagmc/universes/settings.xml new file mode 100644 index 0000000000..770ec7c355 --- /dev/null +++ b/tests/regression_tests/dagmc/universes/settings.xml @@ -0,0 +1,10 @@ + + + eigenvalue + 100 + 10 + 5 + +

false + + diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py new file mode 100644 index 0000000000..0ed2025462 --- /dev/null +++ b/tests/regression_tests/dagmc/universes/test.py @@ -0,0 +1,4 @@ +import openmc + +def test_dagmc_universes(): + openmc.run() \ No newline at end of file From b3ad45f9a8a0098828da1b81396a057826093d59 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 3 Mar 2021 11:55:18 -0600 Subject: [PATCH 31/93] Formatting update to surface header. --- include/openmc/surface.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/openmc/surface.h b/include/openmc/surface.h index 3d386e8768..5c729f8202 100644 --- a/include/openmc/surface.h +++ b/include/openmc/surface.h @@ -149,8 +149,8 @@ public: //! Get the BoundingBox for this surface. virtual BoundingBox bounding_box(bool /*pos_side*/) const { return {}; } - protected: - virtual void to_hdf5_inner(hid_t group_id) const = 0; +protected: + virtual void to_hdf5_inner(hid_t group_id) const = 0; }; class CSGSurface : public Surface From 41e3179167c06244ca3af1d332bccaaa07217d3b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 3 Mar 2021 20:01:45 -0600 Subject: [PATCH 32/93] Updating the DAGMC universes test. --- .../dagmc/universes/inputs_true.dat | 47 +++++++++++++ .../dagmc/universes/results_true.dat | 2 + .../regression_tests/dagmc/universes/test.py | 69 ++++++++++++++++++- 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 tests/regression_tests/dagmc/universes/inputs_true.dat create mode 100644 tests/regression_tests/dagmc/universes/results_true.dat diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat new file mode 100644 index 0000000000..f8acb45ccc --- /dev/null +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 2 + + false + + diff --git a/tests/regression_tests/dagmc/universes/results_true.dat b/tests/regression_tests/dagmc/universes/results_true.dat new file mode 100644 index 0000000000..203d35efeb --- /dev/null +++ b/tests/regression_tests/dagmc/universes/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +7.531408E-01 1.260163E-02 diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index 0ed2025462..0144a0c3a8 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -1,4 +1,71 @@ import openmc +import openmc.lib + +import pytest +from tests.testing_harness import PyAPITestHarness + +pytestmark = pytest.mark.skipif( + not openmc.lib._dagmc_enabled(), + reason="DAGMC CAD geometry is not enabled.") + + +class DAGMCUniverseTest(PyAPITestHarness): + + def _build_inputs(self): + model = openmc.model.Model() + + ### MATERIALS ### + fuel = openmc.Material(name='no-void fuel') + fuel.set_density('g/cc', 10.29769) + fuel.add_nuclide('U234', 0.93120485) + fuel.add_nuclide('U235', 0.00055815) + fuel.add_nuclide('U238', 0.022408) + fuel.add_nuclide('O16', 0.045829) + + cladding = openmc.Material(name='clad') + cladding.set_density('g/cc', 6.55) + cladding.add_nuclide('Zr90', 0.021827) + cladding.add_nuclide('Zr91', 0.00476) + cladding.add_nuclide('Zr92', 0.0072758) + cladding.add_nuclide('Zr94', 0.0073734) + cladding.add_nuclide('Zr96', 0.0011879) + + water = openmc.Material(name='water') + water.set_density('g/cc', 0.740582) + water.add_nuclide('H1', 0.049457) + water.add_nuclide('O16', 0.024672) + water.add_nuclide('B10', 8.0042e-06) + water.add_nuclide('B11', 3.2218e-05) + water.add_s_alpha_beta('c_H_in_H2O') + + model.materials = openmc.Materials([fuel, cladding, water]) + + ### GEOMETRY ### + # create the DAGMC universe + pincell_univ = openmc.DAGMCUniverse(filename='dagmc.h5m', auto_ids=True) + + left = openmc.XPlane(x0=-24.0, name='left', boundary_type='reflective') + right = openmc.XPlane(x0=24.0, name='right', boundary_type='reflective') + front = openmc.YPlane(y0=-24.0, name='front', boundary_type='reflective') + back = openmc.YPlane(y0=24.0, name='back', boundary_type='reflective') + bottom = openmc.ZPlane(z0=-20.0, name='bottom', boundary_type='vacuum') + top = openmc.ZPlane(z0=20.0, name='top', boundary_type='vacuum') + + box = +left & -right & +front & -back & +bottom & -top + + bounding_cell = openmc.Cell(fill=pincell_univ, region=box) + + model.geometry = openmc.Geometry(root=[bounding_cell]) + + # settings + model.settings.particles = 100 + model.settings.batches = 10 + model.settings.inactive = 2 + model.settings.output = {'summary' : False} + + model.export_to_xml() + def test_dagmc_universes(): - openmc.run() \ No newline at end of file + harness = DAGMCUniverseTest('statepoint.10.h5') + harness.main() \ No newline at end of file From 30e42489cd0cd62a56a6b20c54dac00e65db402d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 3 Mar 2021 20:02:09 -0600 Subject: [PATCH 33/93] Removing XML files. --- .../dagmc/universes/geometry.xml | 27 ------------------- .../dagmc/universes/materials.xml | 26 ------------------ .../dagmc/universes/settings.xml | 10 ------- 3 files changed, 63 deletions(-) delete mode 100644 tests/regression_tests/dagmc/universes/geometry.xml delete mode 100644 tests/regression_tests/dagmc/universes/materials.xml delete mode 100644 tests/regression_tests/dagmc/universes/settings.xml diff --git a/tests/regression_tests/dagmc/universes/geometry.xml b/tests/regression_tests/dagmc/universes/geometry.xml deleted file mode 100644 index 556637f65d..0000000000 --- a/tests/regression_tests/dagmc/universes/geometry.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - 48.0 48.0 48.0 - 3 3 3 - -24.0 -24.0 -24.0 - - 1 1 1 - 1 1 1 - 1 1 1 - 1 1 1 - 1 1 1 - 1 1 1 - 1 1 1 - 1 1 1 - 1 1 1 - - - - - - - - - diff --git a/tests/regression_tests/dagmc/universes/materials.xml b/tests/regression_tests/dagmc/universes/materials.xml deleted file mode 100644 index 47e740ba0e..0000000000 --- a/tests/regression_tests/dagmc/universes/materials.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/dagmc/universes/settings.xml b/tests/regression_tests/dagmc/universes/settings.xml deleted file mode 100644 index 770ec7c355..0000000000 --- a/tests/regression_tests/dagmc/universes/settings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - eigenvalue - 100 - 10 - 5 - - false - - From a06b906da6a3d4f6d7c150e5350e34527c552217 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 4 Mar 2021 15:29:19 -0600 Subject: [PATCH 34/93] Updating example notebooks. --- examples/jupyter/cad-based-geometry.ipynb | 159 ++++++++++-------- .../jupyter/unstructured-mesh-part-ii.ipynb | 43 ++--- 2 files changed, 114 insertions(+), 88 deletions(-) diff --git a/examples/jupyter/cad-based-geometry.ipynb b/examples/jupyter/cad-based-geometry.ipynb index 9fa56f6fbd..4c950b744b 100644 --- a/examples/jupyter/cad-based-geometry.ipynb +++ b/examples/jupyter/cad-based-geometry.ipynb @@ -141,7 +141,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "OpenMC expects that the model has the name \"dagmc.h5m\" so we'll name the file that and indicate to OpenMC that a DAGMC geometry is being used by setting the `settings.dagmc` attribute to `True`." + "To create a geometry where DAGMC represents the entire model, we'll make a DAGMC universe and use it as the root universe of the model." ] }, { @@ -149,9 +149,19 @@ "execution_count": 6, "metadata": {}, "outputs": [], + "source": [ + "dagmc_univ = openmc.DAGMCUniverse(filename=\"dagmc.h5m\")\n", + "geometry = openmc.Geometry(root=dagmc_univ)\n", + "geometry.export_to_xml()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], "source": [ "settings = openmc.Settings()\n", - "settings.dagmc = True\n", "settings.batches = 10\n", "settings.inactive = 2\n", "settings.particles = 5000\n", @@ -169,12 +179,12 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "" ] @@ -201,7 +211,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -219,7 +229,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -246,7 +256,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "metadata": { "scrolled": true }, @@ -280,28 +290,35 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 2c0b16e73d5d81a2f849f4e2bfae5eb5319f2417\n", - " Date/Time | 2019-06-18 08:54:17\n", - " OpenMP Threads | 2\n", + " Copyright | 2011-2020 MIT and OpenMC contributors\n", + " License | https://docs.openmc.org/en/latest/license.html\n", + " Version | 0.12.1-dev\n", + " Git SHA1 | 9fb298b039bcd447c1a745cd9fea47f0d04eebdf\n", + " Date/Time | 2021-03-04 13:23:02\n", + " MPI Processes | 1\n", + " OpenMP Threads | 4\n", "\n", " Reading settings XML file...\n", " Reading cross sections XML file...\n", " Reading materials XML file...\n", - " Reading DAGMC geometry...\n", + " Reading geometry XML file...\n", + "Set overlap thickness = 0\n", + "Set numerical precision = 0.001\n", "Loading file dagmc.h5m\n", "Initializing the GeomQueryTool...\n", "Using faceting tolerance: 0.0001\n", - "Building OBB Tree...\n", + "Building acceleration data structures...\n", + "Implicit Complement assumed to be Vacuum\n", " Reading U235 from /home/shriwise/opt/openmc/xs/nndc_hdf5/U235.h5\n", " Reading H1 from /home/shriwise/opt/openmc/xs/nndc_hdf5/H1.h5\n", " Reading O16 from /home/shriwise/opt/openmc/xs/nndc_hdf5/O16.h5\n", " Reading c_H_in_H2O from /home/shriwise/opt/openmc/xs/nndc_hdf5/c_H_in_H2O.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for U235\n", + " Minimum neutron data temperature: 294.0 K\n", + " Maximum neutron data temperature: 294.0 K\n", " Reading tallies XML file...\n", + " Preparing distributed cell instances...\n", " Writing summary.h5 file...\n", + " Maximum neutron transport energy: 20000000.0 eV for U235\n", " Initializing source particles...\n", "\n", " ====================> K EIGENVALUE SIMULATION <====================\n", @@ -322,20 +339,21 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 2.4575e-01 seconds\n", - " Reading cross sections = 1.3129e-01 seconds\n", - " Total time in simulation = 1.6897e+00 seconds\n", - " Time in transport only = 1.6829e+00 seconds\n", - " Time in inactive batches = 3.1605e-01 seconds\n", - " Time in active batches = 1.3737e+00 seconds\n", - " Time synchronizing fission bank = 2.8739e-03 seconds\n", - " Sampling source sites = 2.5550e-03 seconds\n", - " SEND/RECV source sites = 2.8512e-04 seconds\n", - " Time accumulating tallies = 7.8450e-06 seconds\n", - " Total time for finalization = 1.7404e-04 seconds\n", - " Total time elapsed = 1.9588e+00 seconds\n", - " Calculation Rate (inactive) = 31640.8 particles/second\n", - " Calculation Rate (active) = 29119.1 particles/second\n", + " Total time for initialization = 1.1835e+00 seconds\n", + " Reading cross sections = 1.3664e-01 seconds\n", + " Total time in simulation = 1.0779e+01 seconds\n", + " Time in transport only = 1.0771e+01 seconds\n", + " Time in inactive batches = 1.6833e+00 seconds\n", + " Time in active batches = 9.0961e+00 seconds\n", + " Time synchronizing fission bank = 4.0641e-03 seconds\n", + " Sampling source sites = 3.6309e-03 seconds\n", + " SEND/RECV source sites = 3.4735e-04 seconds\n", + " Time accumulating tallies = 4.9789e-05 seconds\n", + " Time writing statepoints = 2.9456e-03 seconds\n", + " Total time for finalization = 6.8913e-05 seconds\n", + " Total time elapsed = 1.2048e+01 seconds\n", + " Calculation Rate (inactive) = 5940.54 particles/second\n", + " Calculation Rate (active) = 4397.49 particles/second\n", "\n", " ============================> RESULTS <============================\n", "\n", @@ -368,7 +386,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -377,7 +395,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -387,7 +405,7 @@ "" ] }, - "execution_count": 12, + "execution_count": 13, "metadata": { "image/jpeg": { "width": 600 @@ -409,7 +427,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -432,12 +450,12 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "" ] @@ -466,12 +484,12 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 16, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "" ] @@ -498,7 +516,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -537,12 +555,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "...and setup a couple mesh tallies. One for the kettle, and one for the water inside." + "...and setup a couple of mesh tallies. One for the kettle, and one for the water inside." ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ @@ -570,7 +588,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -602,21 +620,25 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 2c0b16e73d5d81a2f849f4e2bfae5eb5319f2417\n", - " Date/Time | 2019-06-18 08:54:35\n", - " OpenMP Threads | 2\n", + " Copyright | 2011-2020 MIT and OpenMC contributors\n", + " License | https://docs.openmc.org/en/latest/license.html\n", + " Version | 0.12.1-dev\n", + " Git SHA1 | 9fb298b039bcd447c1a745cd9fea47f0d04eebdf\n", + " Date/Time | 2021-03-04 13:25:29\n", + " MPI Processes | 1\n", + " OpenMP Threads | 4\n", "\n", " Reading settings XML file...\n", " Reading cross sections XML file...\n", " Reading materials XML file...\n", - " Reading DAGMC geometry...\n", + " Reading geometry XML file...\n", + "Set overlap thickness = 0\n", + "Set numerical precision = 0.001\n", "Loading file dagmc.h5m\n", "Initializing the GeomQueryTool...\n", "Using faceting tolerance: 0.001\n", - "Building OBB Tree...\n", + "Building acceleration data structures...\n", + "Implicit Complement assumed to be Vacuum\n", " Reading Fe54 from /home/shriwise/opt/openmc/xs/nndc_hdf5/Fe54.h5\n", " Reading Fe56 from /home/shriwise/opt/openmc/xs/nndc_hdf5/Fe56.h5\n", " Reading Fe57 from /home/shriwise/opt/openmc/xs/nndc_hdf5/Fe57.h5\n", @@ -624,10 +646,12 @@ " Reading H1 from /home/shriwise/opt/openmc/xs/nndc_hdf5/H1.h5\n", " Reading O16 from /home/shriwise/opt/openmc/xs/nndc_hdf5/O16.h5\n", " Reading c_H_in_H2O from /home/shriwise/opt/openmc/xs/nndc_hdf5/c_H_in_H2O.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for Fe58\n", + " Minimum neutron data temperature: 294.0 K\n", + " Maximum neutron data temperature: 294.0 K\n", " Reading tallies XML file...\n", + " Preparing distributed cell instances...\n", " Writing summary.h5 file...\n", - " Initializing source particles...\n", + " Maximum neutron transport energy: 20000000.0 eV for Fe58\n", "\n", " ===============> FIXED SOURCE TRANSPORT SIMULATION <===============\n", "\n", @@ -645,15 +669,16 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 4.9659e+00 seconds\n", - " Reading cross sections = 6.3783e-01 seconds\n", - " Total time in simulation = 1.5112e+01 seconds\n", - " Time in transport only = 1.4102e+01 seconds\n", - " Time in active batches = 1.5112e+01 seconds\n", - " Time accumulating tallies = 2.8790e-04 seconds\n", - " Total time for finalization = 3.2375e-02 seconds\n", - " Total time elapsed = 2.0224e+01 seconds\n", - " Calculation Rate (active) = 3308.59 particles/second\n", + " Total time for initialization = 5.6350e+01 seconds\n", + " Reading cross sections = 6.7418e-01 seconds\n", + " Total time in simulation = 1.0014e+02 seconds\n", + " Time in transport only = 1.0013e+02 seconds\n", + " Time in active batches = 1.0014e+02 seconds\n", + " Time accumulating tallies = 4.0980e-04 seconds\n", + " Time writing statepoints = 5.3643e-03 seconds\n", + " Total time for finalization = 1.9142e-02 seconds\n", + " Total time elapsed = 1.5651e+02 seconds\n", + " Calculation Rate (active) = 499.320 particles/second\n", "\n", " ============================> RESULTS <============================\n", "\n", @@ -675,7 +700,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ @@ -696,22 +721,22 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 20, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABA4AAADHCAYAAACZdhEvAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAgAElEQVR4nO3debSkV1nv8d9TVWfqOZ1OmkwkZAAMcBPmoEyXgERE411XASeCgnGpLMErSoB1Fa94RRQRBbyGKUG8zC7hKqKICXNCEghDJjKPnU6n08PpPn2mquf+UdWn3uepfqtOnalOd38/a2Wldr3Tfne9p87uffbzbHN3AQAAAAAAHEpl0BUAAAAAAACrFwMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHwBHMzJ5vZvctw3nvMrMXLvV5AQAA5svMrjSz1wy6HsDRgIEDYIDyP8DN7BVmtsvMnjePYzt+WZqZm9mZS1S3y8xs2sz2Ff57+VKcGwAADJ6ZvcnM/jW9d2vJe6+Yx/neamYfXeI6vtXMZlJ/5PeX8hoAemPgAFglzOwiSe+V9JPu/uVB16flHe6+rvDfJwZdIQAAsGS+IulHzawqSWZ2gqQhSU9O753Z2ndZmVmtZNMnUn/kHctdFwARAwfAKmBmvy7pnZJe7O7fKLx/npl9w8x2m9l3zez5rff/RNJzJL2nNfL+HjM7+Av9u2WzA8zsRDP7jJntMLM7zey3l6Dul5nZ2wrlufAIMzvDzB4xs6cUrr/j4H0AAICBukbNgYJzW+XnSLpC0i3pvdvd/QFJMrN3m9m9ZrbXzK4zs+e03r9A0pslvbzVD/lu6/2NZvZBM9tmZveb2dsKgxKvMrOvm9m7zGynpLcu9EbybAczO601E7NmZpvN7D4z+6nWtnVmdpuZvXKh1wOONgwcAIP3G5L+l6Tz3f3ag2+a2UmS/kXS2yRtlvQGSZ8xs+Pc/S2Svirpta2R99e6+3Nbh55zqNkBZlaR9P8kfVfSSZLOl/R6M3vxct2Yu98u6Y2SPmpmayR9WNLl7n7lcl0TAADMj7tPS7pa0sE+xHPV7F98Lb1XnG1wjZqDCpsl/V9JnzKzUXf/gqT/rfbsgHNa+18maVbNWQtPlvTjkoqhls+UdIekrZL+ZCnv7yB3f0TSr0p6v5kdL+ldkq53948sx/WAIxEDB8DgvUjSVZK+n97/JUmfd/fPu3vD3b8o6VpJL1ngdZ4u6Th3/1/uPu3ud0h6v6RuMYtvaM122G1mDy/kou7+fkm3qdkxOUHSWxZyHgAAsCy+rPYgwXPUHDj4anpvLoTS3T/q7jvdfdbd3ylpRNLjDnViM9uqZr/l9e6+390fUvMf7cW+xwPu/jet8x0oqePLCv2R3WZ2Yr836e7/LulTkr7UqtOv93sO4GjGwAEweL8h6bGSPmBmVnj/VEk/V/xFKenZav7jeyFOlXRiOt+b1RzhL/MX7r6p9d+WBV5Xag5QPFHS37j71CLOAwAAltZXJD3bzDar+QeGWyV9Q83cB5vV/P09N+PAzN5gZjeZ2Z5WX2KjpLI+wqlqhkJsK/Q9/k7S8YV97p1HHT9Z6I9sOhg2sQCXqnk/l7n7zgWeAzgqMXAADN52NcMGniPpfYX375X09+kX5Vp3f3tru/d5nXsl3ZnOt97dFzqD4aD9ktYUyo8qbjSzdZL+StIHJb211QkBAACrwzfV/Mf/r0n6uiS5+15JD7Tee8Dd75SkVj6D35f0MknHuPsmSXskHfzDR+6b3CtpStKWQt9jg7s/obBPv/2ZMr36I1U1Bw4+Iuk3l2oVKuBowcABsAq0Rs7Pl3SBmb2r9fZHJf2Umb3YzKpmNtpKPHhya/t2SaenUx3qvYO+JWnczN5oZmOtcz7RzJ6+yOpfL+klrcRDj5L0+rT93ZKudffXqJmz4f8s8noAAGCJtMIDrpX0P9QMUTjoa633ivkN1quZr2CHpJqZ/YGkDYXt2yWd1sqrJHffJunfJb3TzDaYWaWVOLnnstMLcL2k55rZo81so6Q3pe1vVnOQ4lcl/bmkjxxM0gigNwYOgFXC3e+R9AJJP2tmf+ru90q6UM1fdDvUHLX/PbV/bt/d2neXmf116723Srq8NR3wZen8dUkvVTOh0Z2SHpb0ATX/yrAYf69mwsW71OwczCVlNLMLJV2gZjiG1OyAPMXMfnGR1wQAAEvny2qGD3yt8N5XW+8VBw7+TdIXJP1Q0t2SJhVDDT7V+v9OM/t26/UrJQ1LulHSLkmf1sLDLku1ckF9QtL3JF0n6Z8PbjOzp6rZB3llqz/0Z2oOIlyy1PUAjlTmvlSzgwAAAAAAwJGGGQcAAAAAAKAUAwcAAAAAAKAUAwcAAAAAAKDUogYOzOwCM7vFzG4zM5KLAACAFUd/BACA5bXg5Iit5Ut+KOlFku6TdI2kn3f3G5euegAAAOXojwAAsPxqizj2GZJuc/c7JMnMPq7m0nGlv6iHbcRHtXYRlwQA4Mgzqf2a9ikbdD0OU/RHAABYAt36I4sZODhJcd3W+yQ9s9sBo1qrZ9r5i7gkAABHnqv9S4OuwuGM/ggAAEugW39kMQMH82JmF0u6WJJGtWa5LwcAANCB/ggAAAu3mIGD+yWdUiif3HovcPdLJV0qSRts88ISKgAlKmvanT9bMxa22chIKDd274nl/fuXr2I4LFRGR2P5uC1xh5QDxvftm3tdT88TgIGhPwIAwDJbzKoK10g6y8weY2bDkl4h6XNLUy0AAIB5oT8CAMAyW/CMA3efNbPXSvo3SVVJH3L3G5asZgAAAD3QHwEAYPktKseBu39e0ueXqC4AAAB9oz8CAMDyWvbkiMCiVKqhWP2RM0O5cdtd7V3XpaW1Uny6nbg1br/1jkVXD4e3xrmPDWXbuS/usHs8FL3emHtdOffsuO2m22N5amoJaggAAAAM3mJyHAAAAAAAgCMcAwcAAAAAAKAUoQpY1aqPPyOU/fa7Y7kwHXz2rnu6nsue+oR47h85K5TrN926kCriMFJ9XAx12b8lLsc4etX35n2uys0x1KVy2imhXL/ltj5rdwQyi2UvXwEvL41pw8OhXB+PYSPdzgUAAIClxYwDAAAAAABQioEDAAAAAABQioEDAAAAAABQihwHWFVqp58Wyj49E8qNyckFn9uvuyGU6ws+Ew5XOe/A6C0LP1d+Fmt741KOlfXr4/45Rv9oVFxetRF/AhvpZ115OUtL49zOTzAAAMBKYcYBAAAAAAAoxcABAAAAAAAoxcABAAAAAAAoRY6Dw1kxXliSvNF+neOBk+oxG+OhOb44bJsOZctrsyeWYrs1O9t+feymsKmxcU0oT6+La7dXvnJ912sBq8Xs9h2h3PjRJ4Vy5WtHwbPc47sh5zWY9zaJnAYAAAADxIwDAAAAAABQioEDAAAAAABQioEDAAAAAABQihwHq4iNjIRyZVPMQ6ADcd14d4/7r1vb3rY5Hmt798dzVWIsckfegkphTGlmNmzy0ZiHwPL2VE/btGHu9cSZW8K2A8fGPA3r70lrt6d7BFatFKM/fP+uUPYNG0K5vnfvsldpudnQcNftPjPddXv3k6fvJL4LAAAABoYZBwAAAAAAoBQDBwAAAAAAoBQDBwAAAAAAoBQ5DlZYNcU5a2x07qWtGQubfM1oKHfkKRgfj/uvLRw/FWOLG8esC+XK+IG4fX28dn1tO9+CV2Os8dAjE7Ee0zPxXCcfF6+1r523YHZNHKuqpKXZq1fdEMpENeNwNXv3faFcffwZcYcbD/8cBzmHQc7T0iHnLQgn8+5lAAAADAwzDgAAAAAAQCkGDgAAAAAAQCkGDgAAAAAAQClyHCyzymjMU6CTHxXLhfwAjXUxz4BNxdwBsydtjsc2jgnF2kN72oWZ2bjveMyP4I0YP2wTMedBrbh9Np2rFh+bHIlcuWcy1bOdyGD9V/eETfUzTojnWsy678Bq0ogJPGw85gax/HOUf85Wo0o1FK0Scxb41JS6KuYt6JbvAAAAAKsKMw4AAAAAAEApBg4AAAAAAEApQhWWWGX9+lDOSyzann2h3DhuU/vYB3fGbXvjcos2Hafx56nNh8FEZ1XOPTuUqzfeFcppdUbgiNHYHcN07OwzQ9m/d/NKVmfeKmvXtl9viN9v9Ud2xZ37CbdguUUAAIDDBjMOAAAAAABAKQYOAAAAAABAqZ4DB2b2ITN7yMx+UHhvs5l90cxubf3/mG7nAAAAWAz6IwAADM58chxcJuk9kj5SeO8SSV9y97eb2SWt8huXvnqHH095COzErXF7NY7V2LaH517Pbn9o+So2SIUl3LwW77+xd+9K1wYYiMZ4zFni60ZCuVJYnnE1Lc1YrEv94Ufitj6XT7WR9j3n70pyHmAeLhP9EQAABqLnjAN3/4qkR9LbF0q6vPX6ckk/s8T1AgAAmEN/BACAwVlojoOt7r6t9fpBSVu77QwAALAM6I8AALACFp0c0d1dUukcUzO72MyuNbNrZzS12MsBAAB0oD8CAMDymU+Og0PZbmYnuPs2MztBUmlwvrtfKulSSdpgm4/4INbKSIxbVsppkGP8bRXFMi+X2qknz71u3HJ32HbEPxBAidrt2+Ibjztj7mX9hltWuDblrFrIUdKI31fVTRtD2adnQrkxOZW2F/IakNMAS4P+CBbGLJXT39K8ETcXvgt7n7vH3+Uq8dqW6xL2Tefqtq/U+d3aKNxHPlcj3qN3HJvKhTbxvC2xSvd6Fo/P+3acO30WuX17XavbsR3yZ1Pr459KqX07cvl0U6/Hco/nsWv75/bqF7+fUWKhMw4+J+mi1uuLJH12aaoDAAAwb/RHAABYAfNZjvFjkr4p6XFmdp+ZvVrS2yW9yMxulfTCVhkAAGBZ0B8BAGBwes6/cfefL9l0/hLXBQAA4JDojwAAMDgLzXGAErZ+XXxj7/64PcUwze7as9xVWnkp/q6+ud0mfufdeW/gqFTfHkOxZ59wytzr2g0rXZu2jrwFM+28BpWx0bgt5TTo0C0u1VM8JwCsIBsejuWcOyDlNLCh2GX2enkcea9z5Th6pTj6cHyOsa/1yLUwm2PlC+dKses+E7/DO/JupT5r8Z5zf7Zf3bISWKNHjH5He6acB8U265EfoSOnwdBQ+bXSM6D8DORcDROTKtUjx5nn7alNQvvn9ujx2XQ8uzl/wlGQfw0Ls+hVFQAAAAAAwJGLgQMAAAAAAFCKgQMAAAAAAFCKHAdLbPb+B0K5uuXYULaxsVCurF0z97oxPr58FVtB1bMfG9/YMzH3kqhm4NBq+9rrPeefofqNP1y261bWrg1lS2XtL+RpyetG5zXAU1xkXve817rfALCcbKid1yB/P9lwim3vFQuftxfi6q2Wv/tSfHrOW5DzJxSPz9+jIykfQj3lLUj5FUK+gJn0HZ3vOeWt8anpUDYrHF9N95+/33O9+4ib76hXLznGv6g2Es9dyZ9rKufPoliXnOOgh45rFdrfc56L1H6Wt6fPzovnzjkh8nVzzo2U68Is3XOxLo1V1HPvkq8DK4MZBwAAAAAAoBQDBwAAAAAAoBQDBwAAAAAAoBQ5DpZYZc2a+MZxm0Mxx/ja5FS7cITkOLjvxTGvwwl/dfWAagIcPuzbN829fuTlTwvbNt64dNfJOQ101qmh6HfdH7eH9bDj91dj3/5Q7shpkNeSXk2xkgCOOsXY+fx91fvglDtgJMXhF78r874pXt17xcqPtHMxNMbidRrDsd71se7nqk62v3er+6bixumU8yDHvuc8BoUcCD4d8x/Iusec2+hofGOmcHyv/Dc5n0SuV5fP0sbSdVP8f8dnkfJTNEbb2+trhsM2r8bPtTITcw1Uh1IejUJ722Rqv5TDoCOHkMXPLly53iPfUM5xkKXf1VZoE58a4O/tbvXukbcBy4MZBwAAAAAAoBQDBwAAAAAAoBShCkusMRmnEtXSVCQfi8vC+Antaf2ViYmwrbE/TgNerarHxnAMS6vCMD0Z6K04tXB6Q5yCl5d1rT+8c97nrZ51eijvOfe4UN7ww73d67Wv/HsoT7+trI3Lzebpp/W93a8FAEupY9nD4jT1vNxdng6flgTsmO49EqetdyyBFw+O5RzWNZrCEQpLLjZSKMLUMXHfyY1pOnyasT2yp90HG6nFetR2T8Z65CUqU5+22AYdSw2me/TJeO6O9i5eK0ca5M8thzJ0LI1Z/tl0hCLkUIXc9ik0ZHZtuzxxfNzmqQlGd8f+7lBq78qB9o1W63kJxXRPsyl8IO4dwxHSs9sxwT+HIuTQjtRGVmjvRjq2n2U1+1bpHj5U7HN0hEISurAimHEAAAAAAABKMXAAAAAAAABKMXAAAAAAAABKkeNgqaV4ft+bllgcjTFxM5vbyzcO6ZS47/duXtKqLZe9//WsUH7UVfsGVBPgyLDp1pgb5YVX3hnKn3jHi0N572kpNrIQ2rfhjhhHuemHaQnFO+Pyi/Wc06BLjpKO+OGh+P3WIKcBgAHK31HF5Rg74ujzsUN5ucWUlyCVQ+x8jrfOyzEOx2sXcxpIMa/B1KZYj/ET074/viuUDxyI38Prr0jLhBfYdFo+8MBM3KEjj0GjfFteyjG1r+eY/i5L7XXkLKh2zxHR8dkUP+eUqyLLn0Uxp4Ek7T213Z47nxdzPlRq8Z43XRmXftxwd9xeKSxtmHMvVPJyjLl90z1acbnGWsrbkPNJzKZyzg+QFdrXRlJutn5zHBTzYuQcGt1ykOhQSzq329PSI9CxL5YFMw4AAAAAAEApBg4AAAAAAEApBg4AAAAAAEApchwss8aeGONbHYvrnA8XYn8mTt0Ytq3ZFtdbr+/YscS1Wxq7fyHmNFj3sltCmZVUgf4M/cd1ofyeK18Uyn5ejOU74ctxDPiYax5s75u+g+qPxHjY+iLWOu6IH14XY2l9lX5nAThCpdh4Wxu/k2y4EP+f46urKb465zDIcfe5XIxZb6R4/h719ByjXtjeqOV946n++AmfDeVRi3kK3vj1X2tfNoeMj8R7rMzGeltuEy/Evuf7zzHmFnMFmGK93MtzHHToyBmR/u6Zcx4UzabcYyPd/+lTH47nnlnbvvb7fuwfuh77pm+8OpTzZ1ds78pkatuR1F5TKd9ER16H8t/dlnMF5Gc9t2fuBxT2z89ANeVmKOYdkNSRz6OrdKznPBnp58iLVSGlwUAw4wAAAAAAAJRi4AAAAAAAAJRi4AAAAAAAAJQix8Eyy+ud+v6JUC6uKVydirE8s2eeGMrViXhsY39ab32FVLccG8pPP/GeUH6g3zVeAXR11muv7mv/lfoJtI0bVuhKANCb1VKceDGngSQV+lw+krZ1xHnHmPIcg96Rx6BYzPsmjdHY/W4Mx2vVR9p/16vMxnqN7Irlt/zdq0K5Oh2vNbKnvb/1ymmTY8pTXL3VC9vzueqpPTpyHqT8E8VCjt/vkU/CR9NnlxXq5ikmP99TbntLtzW2s31fl7z71fPeV5KsnnYoNl/Ka2EHUrx/yi1guX2LuQRynoGcf0jJTMqf0C0HQv6cq/39zdknp9qnzbkXUv4Jm4kPr9fTtYrPVH5mchs4SRCWAzMOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAKXIcrLD67t2hXJlqx/6MpJi4R54ScwlUT3lSKG+84vZ47hVaM338OWeG8s3XxO1nqb94bACHiRRnOvPYk0K5dt0tK1kbAAgqY6PxjdGRUCzGuzfWp31zHH1aj97ymvOVFGMdKpKOTbHunuP98/r1hf29GvcdGY+x29XpFDeeqjWyp72/5bQDsyluPucWSNcO8e459r0jFj5VJOc8KG5Pse8d50psJmXy6ZYDIf+JNN2T53QKqU1GdrVfD+2P2xpD8eDagbi9Oh3LlZlCG+T8Bzl3QCU/jznnQeFcub06Psd87pQjIrd/4ficI6JDPneuS/H4/LnlPCH5mammnBHFy+TnydO5sCyYcQAAAAAAAEr1HDgws1PM7Aozu9HMbjCz17Xe32xmXzSzW1v/P2b5qwsAAI5G9EcAABic+YQqzEr6XXf/tpmtl3SdmX1R0qskfcnd325ml0i6RNIbl6+qR4g0hcen20uPVHbtDds2fzseuu+xsS904KmnhfLYnRvnXtdvuW0Rlexuz0Wxnqe9Z82yXQvA6lHdtCmUPU3dbaQlY4ElRn8EXdna2B/pWIpvrD1FuzEaw0OnN6alHNNU8o5p59N5Ocb2/pU03T0v+Zenx+ewiErh2sO74/TuPD2+MpX6lbV88vbL6mRa/i5Pl0+6hTLkts1L7XWEJuQp7MX9K3nBwI4FBKO0jF9xmc3Oc3f/G2lug9qBeO5GcTnMyXhsx+eW2stmyp8R69U+Wdq/2P6WY1B6hS7kZRFz+xc/27RvYzgtJTqW/imZIzAmCkssTkyFbR3hP6lstfL78Bz20Kv9sCR6zjhw923u/u3W63FJN0k6SdKFki5v7Xa5pJ9ZrkoCAICjG/0RAAAGp68cB2Z2mqQnS7pa0lZ339ba9KCkrUtaMwAAgEOgPwIAwMqa98CBma2T9BlJr3f3MFfd3V0dk1PmjrvYzK41s2tnNHWoXQAAAOaF/ggAACtvXssxmtmQmr+k/8Hd/7H19nYzO8Hdt5nZCZIeOtSx7n6ppEslaYNtJgAl8dl2jM7sQw+HbbWhGLM1tn0slPc9OsbyTZ+zpb3viRviub5xQ7zu1MI7Tb985rdC+UtXxtwLfMjAEaSw5Ni+554VNq39z5tCmcWQsNzojyDIsdsjcZk5T3kMZte3l2ecPC4u1bh/a/e/pa15OH7DDe9NyyJOtPtzDXWPIc9LLOaOU1iOcbj70o6WV0VMceKVmULuhRxz35FaINVzKOZmCFtzjHmWcwt0+xdHPdUrx6vX0jJ9OadB1ke8e14K05VzSLQ/Z6+lz3UoL5kYy9WOHAflvyU72noqtW9eqrBwro58EzkHRL5WXkIxf+6FPAaechrMbIg/Y/sf1f2zWH9P+1pDKQeE52VIZ+M9eyPldZgufBY5RwRWxHxWVTBJH5R0k7v/ZWHT5yRd1Hp9kaTPLn31AAAA6I8AADBI85lx8GOSflnS983s+tZ7b5b0dkmfNLNXS7pb0suWp4oAAAD0RwAAGJSeAwfu/jWVr4ty/tJWBwAAoBP9EQAABmdeOQ6wQlIsz+z920K5OhnzEqyfOT6Ux09fN/d695kxdk9nPiUUj//6zlCu3/jDeVfz6WN3hvJ/zK6f97EADi8P/eYz514fc3P8DmqMj690dQBgjuW47x7r1xdj1CeOi9G6f/yGD4fypspEKL/2L18bT51DrAu5BTpi25Oca8DzcFghB0LOh9CopTj6qe55C6xQr3wdyzunGHSb6RJH3tG2KUZ/eqb82B7nyp+jp9wVPWP4i/kVUl4B65GaIeeQaBSeGUu5GCo5Rj/ll8ifndfa/+yq5lwVua1zHoKcU6J47ZxPIn82PXIadFyrsL0+Ej/Xia0xp8FL33hlKI/XR0P5629r9yEsPV+1R9I997gPFfMaNMhxMAh9LccIAAAAAACOLgwcAAAAAACAUgwcAAAAAACAUuQ4WM1S/E59x45Qrqb1TsfWP2bu9exozHEwuSXGCd3z01tC2S+M5dM+fHv7XA9uD9suffB5qaK7BODIMHv+U0N5Yms7jvL4912fdweAwelY2z6vC59yCVTafaFKCsF/3bdeEcojI3GH4ZxKIF+rGHJ+IPbPGiOxu51zDTRGcq6Gwrlmcox+jptP5Uoqe/H4+PdCy7kYOmLy0/6T5XkLeuUdyJ+NivXMuSmGYntZiu/3tL0jFj5cJ95DzjuglGtAuT1rffyNNadqyNcq5pvI5835EnLOg3yPxXLK49B5rtR+KR+FcrlwvvycKxU/+I3nxmtNx3qePNs+oDKZ8jTketfjPfuBybj7ZCxj5THjAAAAAAAAlGLgAAAAAAAAlGLgAAAAAAAAlCLHwWGsvivmFhj6VnuN9XWVHwnbRsZj/NLuM+JHP7M+nvvGt55aKJ0atv3hsf8Uyh/TifOpLoBVwIbieth3/c+Y02Bqa4xBfPzrvjP3usG6yQBWs7wefd5ciLFe+1Dct/ovcf15WSxbPcZjV2ZSHHmOBS9KMec5vr2R4uqL+RIaVr5N6syX0FHOcfbFc002SrdJnTkiQl6CFDffU46jL+ZEGB4Km3Kehtz2HTkRchsVYuc9H5qupVStjvYttF/+nCopP0J9KJ6seiD+zuz2jHTkk5hO7ZvvuVDOOQw68iHknAepPT3lpygeXZmK516zPea5ePS/xHvOz8zow+28BJX9MUeBTU6HcmP/RCxPxDIGjxkHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFDkOjiDFWKDaFd8O24b/y+NDeWbNxlDefmqMf3rWk26de3386HjYdlxtb7oyOQ6A1WrqJU8P5Xe+972h/IpPxRwHj/ut74RyY7bPOFYAWCk5ZnwqxkxbivUudnor0zGuuzYR8780Um6AxlCKQc9h9jON0m35WvUcz57PNdt+ozES9805DBpD8Y2cH0CFPAb5r4UduQRSe3XG3ZfnROi4biXFvufPqhh3n2L0reNcqR45Rj9XppDjQJX4uXqPPBj1kVjvYo6D+mjcNpPavnYg1qsxHK9VKdxzIyVXqE7EZ9erOXdAl3wJqX3C/UudOQ/y9lwufByVyXjs8NT+UB5KeR0s51PYd6DwOuUwGN8Xy/vjubH6MOMAAAAAAACUYuAAAAAAAACUIlThSJWmCjW+e1MoH3Pf5lAe2XNGKF9lj517fe45d4RtZ295OJStFh8jZ2ozsKyqx8af3x0//bhQfu8f/PXc63tn4s/vm1/+6lA+/VvfDOUuC4oBwKriszOpnKZz5yXsittmUqjC3qlQzlPaG2Opy5yW4qtOtc/XsSRins6djq3MxKnis4Up8Y2ReLJ6mv4+tT5ur8YZ76oWjh/ZHe+54x7TlPZKbr9CvTuWSOw1HT7/dukWMpCm6fecWp9DG4YKn1W6TH4mGik0YXYslddUCttS++TursWLDe0tD+3omNKfl77sOKB8Wc2e+/ZavjIv51gMfeiyVO1lzuIAABEcSURBVKOkzmU502fT2L1n7nU9L6/Y5ecTqxMzDgAAAAAAQCkGDgAAAAAAQCkGDgAAAAAAQClyHByl6jsfCeWRz+8K5cc+cPbc61tfeFbY9jsv/e+hPP7fTgvldZ+6eglqCOCgvKTilR94fyiff+O6UH7Lqy6ee135clxeUfr+ktYNAAYmxUj75GQo2/BQLO9vLw2nsZG4bTYte5iWIsxLKnbEZxfj//Of5fJyjGvjEoGaSfkSCjHoeVm+qS0xynzfKd3j7kd3tF8P7UvLLaYlJ3vF2Vsxfj3Fsncst5jzEHSLZ88x+T3i5lVLORDycoTF86VtHctG5ltOp5pe335j/LTueQbW35U+x8n0DBWW2bQDKT9HzjswGXNudCi253Q8V2cOiB7LNWbF/espL0bKY1Z/ZHc6d/o5wRGFGQcAAAAAAKAUAwcAAAAAAKAUAwcAAAAAAKAUOQ7QlOMEv3PD3OsTU4j0nu/HeOsHXxzjss78dI/1YwF0l2Idz/iDm0L5J5/+klCu3X9POkEuA8CRr7E/rhPfkeOgPlR4HeO8fd1Y3PdAirPPcfXpeFULf4vL4f3D3fMl1Efiub24ew7/XxvfuPnX3qduznnHb7avMxqPrU6m8kTKWzCd2qDYn7Me+RJynoKs2F6zKS4+xdV3xOhnHTH7hfZMeRsqM7E8Mxr/KdSoxfuY3Nwuf/FX3xG2HVeNeTLO+9PXhbI9GGtVvLbNxHu0qelY7pUzIrdZF55zIGR95CWo79qz4GNx+GPGAQAAAAAAKMXAAQAAAAAAKMXAAQAAAAAAKEWOA/Rt+AvXhPIpFnMe7HzNeaF87Pu/uex1Ao4k913yrFDe/b4Y67jpfn6mAKBDirdu7N0XypV1a9uFlH/J9qYY8pzTYCoWfahLF7ra/e9yHfHttbi/Fapi9VjP4fFYPuujv5EqFoub9rbfqO2P91g7kOqR8jbka6sQd285xj7ns8rtl3MeFMspX0K/cj6AYky/pc/JZ2O9KjlXheL20Z3tc7/go7+XLhyLx+xNbZDbpFDuaNtebZDzPHi7/frOYZDzJ+ScEsVdp9KDT06DoxozDgAAAAAAQKmeAwdmNmpm3zKz75rZDWb2R633H2NmV5vZbWb2CTMbXv7qAgCAoxH9EQAABmc+Mw6mJL3A3c+RdK6kC8zsPEl/Juld7n6mpF2SXr181QQAAEc5+iMAAAxIzxwH7u6SDgaJDbX+c0kvkPQLrfcvl/RWSX+79FXEajfyrzHnwczLYo4De/qT5l77Nd9fkToBh5vG854893rtAymnwUfIaQDQH0G/fGY6lg+0/16WI8o9xX13RJynGHRTitkvxMp7ynGQcwf46FAoV1LOAy/kPLAUJ79mR6zH0ER5fgRJqk2036hNxutUplOOg1QPpdj5cB+NnBugh5z3oXiunAsg8dnY1pbj/eupnoX8Cp4/t3SP1X3xGRlJt1WZbtdtZDxe11M1hsbjuYf2xXpXDhTKKeeD5RwQuX1zHodim+S8AzlngeX8COl5TO3rheM95zjAUW1eOQ7MrGpm10t6SNIXJd0uabf7XGaO+ySdtDxVBAAAoD8CAMCgzGvgwN3r7n6upJMlPUPS4+d7ATO72MyuNbNrZ3JKWgAAgHmiPwIAwGD0taqCu++WdIWkZ0naZGYHQx1OlnR/yTGXuvvT3P1pQxpZVGUBAADojwAAsLJ65jgws+Mkzbj7bjMbk/QiNRMRXSHpZyV9XNJFkj67nBXF4WPdp64O5R0Xt3MeHFs7J2yzb353ReoErDbVs04P5QOb2jGvx1xOTgMgoz+CxWpMTs69zrkDKiNxMMlz3HgtdpnNUxe6UOyIVy/E3DdPnmL6LV67Otk+vlGLf+OrpZj9ofEUn16J26tT7fuoTOacBd69nO9jMTkOOuLu2/X06Wl1le45729DMWdE11Ple0p/Qq3tnYybpwofbGrbnD+hMp3zFqQcErNd2i+XU36JrnkgUv6DjnwInj/HlFMjtUnODQIc1HPgQNIJki43s6qaP16fdPd/NrMbJX3czN4m6TuSPriM9QQAAEc3+iMAAAzIfFZV+J6kJx/i/TvUjC8EAABYVvRHAAAYnPnMOAD6k6ZTbbn0qrnX+37umWFbdWvs643907eWr17AADWefW4oT22MUyvHPsuzDwArJS8z18jLMXoMH8hT3L2awg8Kyw1aCmvI/aIcJpGXKrTClHcbjufKSzd2nDtvL0yn79iWlonsmMY/W77Mn+dt3iN0IV0r3HOeap/ljGy99i9cy+pp2n0KN7CptGTnyHAoV2fL78tr5Z/boeoZ2jeHbqT27GjfFDrjOZQh7JvqnJ6RHOqRl2MEyvSVHBEAAAAAABxdGDgAAAAAAAClGDgAAAAAAAClyHGA5VeIrVr3yavCpsq5Z4fyrl88L5Q3fuyaeK68PBKwWlRivOvUTzwllNfcuSfu/rUfLnuVAADzk5eg8xSDXhkbDeUYKa8Q4++W/i6XcwmkZfxs34G4fzEOfybmw7FKj7/5pXpbMc4+51boVc7L9hXj7lNcfI6Tt5S3wXMb1AvLMebrphh9G0r/XMn5JnJ+hUL753oo56ZIOnJZjLVzXVjO05CW2ezIEZHvq0tego6cBjnvQM6JUGyj/Dn1yGnQdWlHoAtmHAAAAAAAgFIMHAAAAAAAgFIMHAAAAAAAgFLkOMBANa6/MZQ333dsKN/9xmeG8il/Hte6Z+1ZrBrPeEIorrn27lCub39oJWsDAFiMlFOpMTERypWRkVAuxs6HvAJpmyR5pSNDQlSIWbd6zK2gHLOf5Vj5Qix8jqPviP9PfOJA1+3hXClvg3eJ55ckty5t0BGjn86Vj52K+xfvyxspp8FMOlet+z+FrNgEOX9EPrZXvYu5GHK+hJSnwXvkS+jYHrZNl24DFoMZBwAAAAAAoBQDBwAAAAAAoBQDBwAAAAAAoBQ5DrCq1B/eGcqn/Md4KPvTzg7lyvdum3ud4w+BpVaMZ6w+amvY5rfdH8r5WQYAHMZyjHnOsVSMWa+mPAMpx4GmYwy6DZV3x31yMr5h6W9+KTa+Q46lLx460/1YT/dczJfQ0R45/j/nPMjn6ibniOiRE8JyDolQl5RnIO1rqd6ZT02VHqv82fTgXT6LDqleuf3CPfZ6BoAlwowDAAAAAABQioEDAAAAAABQioEDAAAAAABQihwHWNX8mu+HcuWJj4/bzz597vXEKWvDtv2PiuNijVqMkRvbGWPCDmxp7z+2I24bfSTGMk4cP5TOHeu9blt7f0/Dc6PbUy6GStyhsidut7372udaH+9Ru1MOiBRvl2MMi3GCjf1xfebKunjujjWrx+Ja0rY21aV4rR6xjI1jNsTymtiexXqOn7ombKpNxc/Gypcyblal8NnkZ2BoPMYQTm+MH+TQ/rh9zW272ue694GwjRwbAHD06MhxUNyWwuqVfxfnPAUH8mYr3zfrFf9fuHZfeQakjlwDVm3XJcfr5xwHfV0px+jne67nzSl/Qrc8BflcM/Fz89x+Ob9CN30eW6xnz3vo97MCVgAzDgAAAAAAQCkGDgAAAAAAQCkGDgAAAAAAQClyHOCw0vjBzaXb1lybyn2ee9P69XOvc7x/NrZhXSj7SJc1mEdi/H59LMXz59jHRswlUC3E4/nIcDz0uGNieefudK4Un7iu3SqW4hMt3VMlxd9ZbpPZFM84NqIyNhnXrK5MpFwMjRTfWIjt23hDOnZ8f+l1JMkLOSEkyQvrZTf2dz92uOvWjjBLAAB6y/Hq3v23SQ75X9Sll+5UnbkblssKts+gHAn3gKMPMw4AAAAAAEApBg4AAAAAAEApQhWAlsb4+CFfH9K2hV+n12hdnlbYY7XB/uwo39Tznnc+spQ1WTBm9wEAAAArixkHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACglLnnVeOX8WJmOyTdLWmLpIdX7MKHP9qrP7RXf2iv/tBe/aG95udUdz9u0JU4WtAfWTDaqz+0V39or/7QXv2hveantD+yogMHcxc1u9bdn7biFz5M0V79ob36Q3v1h/bqD+2F1Yznsz+0V39or/7QXv2hvfpDey0eoQoAAAAAAKAUAwcAAAAAAKDUoAYOLh3QdQ9XtFd/aK/+0F79ob36Q3thNeP57A/t1R/aqz+0V39or/7QXos0kBwHAAAAAADg8ECoAgAAAAAAKLWiAwdmdoGZ3WJmt5nZJSt57cOBmZ1iZleY2Y1mdoOZva71/mYz+6KZ3dr6/zGDrutqYmZVM/uOmf1zq/wYM7u69Zx9wsyGB13H1cLMNpnZp83sZjO7ycyexfNVzsx+p/Wz+AMz+5iZjfJ8RWb2ITN7yMx+UHjvkM+UNf11q+2+Z2ZPGVzNcTSjP9Id/ZGFoT8yf/RH+kN/pDf6I8tvxQYOzKwq6b2SfkLS2ZJ+3szOXqnrHyZmJf2uu58t6TxJv9Vqo0skfcndz5L0pVYZba+TdFOh/GeS3uXuZ0raJenVA6nV6vRuSV9w98dLOkfNduP5OgQzO0nSb0t6mrs/UVJV0ivE85VdJumC9F7ZM/UTks5q/XexpL9doToCc+iPzAv9kYWhPzJ/9Efmif7IvF0m+iPLaiVnHDxD0m3ufoe7T0v6uKQLV/D6q567b3P3b7dej6v5JXqSmu10eWu3yyX9zGBquPqY2cmSflLSB1plk/QCSZ9u7UJ7tZjZRknPlfRBSXL3aXffLZ6vbmqSxsysJmmNpG3i+Qrc/SuSHklvlz1TF0r6iDddJWmTmZ2wMjUF5tAf6YH+SP/oj8wf/ZEFoT/SA/2R5beSAwcnSbq3UL6v9R4OwcxOk/RkSVdL2uru21qbHpS0dUDVWo3+StLvS2q0ysdK2u3us60yz1nbYyTtkPTh1lTKD5jZWvF8HZK73y/pLyTdo+Yv6D2SrhPP13yUPVP8HsBqwHPYB/oj80Z/ZP7oj/SB/sii0B9ZQiRHXIXMbJ2kz0h6vbvvLW7z5jIYLIUhycxeKukhd79u0HU5TNQkPUXS37r7kyXtV5oGyPPV1oqDu1DNDs6JktaqcwoceuCZAg5f9Efmh/5I3+iP9IH+yNLgmVq8lRw4uF/SKYXyya33UGBmQ2r+kv4Hd//H1tvbD06faf3/oUHVb5X5MUk/bWZ3qTnV9AVqxsxtak3lknjOiu6TdJ+7X90qf1rNX9w8X4f2Qkl3uvsOd5+R9I9qPnM8X72VPVP8HsBqwHM4D/RH+kJ/pD/0R/pDf2Th6I8soZUcOLhG0lmtDKDDaib1+NwKXn/Va8XDfVDSTe7+l4VNn5N0Uev1RZI+u9J1W43c/U3ufrK7n6bm8/Sf7v6Lkq6Q9LOt3WivFnd/UNK9Zva41lvnS7pRPF9l7pF0npmtaf1sHmwvnq/eyp6pz0l6ZSub8XmS9hSmEAIrhf5ID/RH+kN/pD/0R/pGf2Th6I8sIWvO2lihi5m9RM0YsKqkD7n7n6zYxQ8DZvZsSV+V9H21Y+TerGZc4SclPVrS3ZJe5u45+cdRzcyeL+kN7v5SMztdzRH/zZK+I+mX3H1qkPVbLczsXDUTNw1LukPSr6g5gMjzdQhm9keSXq5mhvHvSHqNmjFwPF8tZvYxSc+XtEXSdkl/KOmfdIhnqtXheY+aUywnJP2Ku187iHrj6EZ/pDv6IwtHf2R+6I/0h/5Ib/RHlt+KDhwAAAAAAIDDC8kRAQAAAABAKQYOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAqf8PQX3FyrAi+8wAAAAASUVORK5CYII=\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -750,7 +775,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.3" + "version": "3.7.3" } }, "nbformat": 4, diff --git a/examples/jupyter/unstructured-mesh-part-ii.ipynb b/examples/jupyter/unstructured-mesh-part-ii.ipynb index 478417970e..3dcc9d418a 100644 --- a/examples/jupyter/unstructured-mesh-part-ii.ipynb +++ b/examples/jupyter/unstructured-mesh-part-ii.ipynb @@ -181,14 +181,15 @@ "\n", "settings.run_mode = \"fixed source\"\n", "settings.batches = 10\n", - "settings.particles = 100" + "settings.particles = 100\n", + "settings.export_to_xml()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "And we'll indicate that we're using a CAD-based geometry." + "Next we'll apply the DAGMC model as the root universe of the geometry." ] }, { @@ -197,9 +198,9 @@ "metadata": {}, "outputs": [], "source": [ - "settings.dagmc = True\n", - "\n", - "settings.export_to_xml()" + "dagmc_univ = openmc.DAGMCUniverse(filename='dagmc.h5m')\n", + "geometry = openmc.Geometry(root=dagmc_univ)\n", + "geometry.export_to_xml()" ] }, { @@ -246,15 +247,15 @@ " Copyright | 2011-2020 MIT and OpenMC contributors\n", " License | https://docs.openmc.org/en/latest/license.html\n", " Version | 0.12.1-dev\n", - " Git SHA1 | 8ae407c90e927af62bfdc8f150e96bfd5d7b2ec2\n", - " Date/Time | 2021-01-06 09:17:05\n", + " Git SHA1 | 9fb298b039bcd447c1a745cd9fea47f0d04eebdf\n", + " Date/Time | 2021-03-04 13:34:25\n", " MPI Processes | 1\n", - " OpenMP Threads | 2\n", + " OpenMP Threads | 4\n", "\n", " Reading settings XML file...\n", " Reading cross sections XML file...\n", " Reading materials XML file...\n", - " Reading DAGMC geometry...\n", + " Reading geometry XML file...\n", "Set overlap thickness = 0\n", "Set numerical precision = 0.001\n", "Loading file dagmc.h5m\n", @@ -317,16 +318,16 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 2.4196e+01 seconds\n", - " Reading cross sections = 2.1428e+00 seconds\n", - " Total time in simulation = 1.9512e-01 seconds\n", - " Time in transport only = 1.9269e-01 seconds\n", - " Time in active batches = 1.9512e-01 seconds\n", - " Time accumulating tallies = 2.0220e-06 seconds\n", - " Time writing statepoints = 2.2461e-03 seconds\n", - " Total time for finalization = 1.8940e-06 seconds\n", - " Total time elapsed = 2.4401e+01 seconds\n", - " Calculation Rate (active) = 5125.02 particles/second\n", + " Total time for initialization = 1.7970e+02 seconds\n", + " Reading cross sections = 1.8083e+00 seconds\n", + " Total time in simulation = 7.2061e-01 seconds\n", + " Time in transport only = 7.1887e-01 seconds\n", + " Time in active batches = 7.2061e-01 seconds\n", + " Time accumulating tallies = 2.7050e-06 seconds\n", + " Time writing statepoints = 1.5381e-03 seconds\n", + " Total time for finalization = 1.1780e-06 seconds\n", + " Total time elapsed = 1.8043e+02 seconds\n", + " Calculation Rate (active) = 1387.71 particles/second\n", "\n", " ============================> RESULTS <============================\n", "\n", @@ -352,7 +353,7 @@ "metadata": {}, "outputs": [], "source": [ - "unstructured_mesh = openmc.UnstructuredMesh(\"manifold.h5m\", library='moab')\n", + "unstructured_mesh = openmc.UnstructuredMesh(\"manifold.h5m\")\n", "\n", "mesh_filter = openmc.MeshFilter(unstructured_mesh)\n", "\n", @@ -496,7 +497,7 @@ "text": [ "\r\n", "\r\n", - " \r\n", + " \r\n", " manifold.h5m\r\n", " \r\n", " \r\n", From 58222a7ded7bf4c8cf2c7cd8d2bae54e8fbb8500 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 4 Mar 2021 15:30:00 -0600 Subject: [PATCH 35/93] Correcting docstrings on the DAGMC Universe class. --- openmc/universe.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index c3f4e36ced..59a41a44f1 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -641,8 +641,9 @@ class DAGMCUniverse(UniverseBase): automatically be assigned name : str, optional Name of the universe. If not specified, the name is the empty string. - cells : Iterable of openmc.Cell, optional - Cells to add to the universe. By default no cells are added. + auto_ids : bool + Set IDs automatically on initialization (True) or report overlaps + in ID space between CSG and DAGMC (False) Attributes ---------- From b35158d44ad2363bc15f529fcb514fdcb076a40a Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 12 Mar 2021 11:20:13 -0600 Subject: [PATCH 36/93] Updating documentation on DAGMC geometry. --- docs/source/usersguide/geometry.rst | 73 +++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index c8e5fd99f3..a271490717 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -433,30 +433,65 @@ will handle creating the unverse:: Using CAD-based Geometry -------------------------- -OpenMC relies on the Direct Accelerated Geometry Monte Carlo toolkit (`DAGMC -`_) to represent CAD-based geometry in a -surface mesh format. A DAGMC run can be enabled in OpenMC by setting the -``dagmc`` property to ``True`` in the model Settings either via the Python -:class:`openmc.settings` Python class:: +Defining Geometry +----------------- - settings = openmc.Settings() - settings.dagmc = True +OpenMC relies on the `Direct Accelerated Geometry Monte Carlo`_ (DAGMC) +to represent CAD-based geometry in a surface mesh format. DAGMC geometries are +applied as universes in the OpenMC geometry file. A geometry represented +entirely by a DAGMC geometry will contain only the DAGMC universe. Using a +:class:`openmc.DAGMCUniverse` looks like the following:: -or in the :ref:`settings.xml ` file:: + dag_univ = openmc.DAGMCUniverse(filename='dagmc.h5m') + geometry = openmc.Geometry(root=dag_univ) + geometry.export_to_xml() - true +The resulting ``geometry.xml`` file will be: -With ``dagmc`` set to true, OpenMC will load the DAGMC model (from a local file -named ``dagmc.h5m``) when initializing a simulation. If a `geometry.xml -<../io_formats/geometry.html>`_ is present as well, it will be ignored. +.. code-block:: xml - **Note:** DAGMC geometries used in OpenMC are currently required to be clean, - meaning that all surfaces have been `imprinted and merged - `_ - successfully and that the model is `watertight - `_. Future - implementations of DAGMC geometry will support small volume overlaps and - un-merged surfaces. + + + + + +DAGMC universes can also be used to fill CSG cells or lattice cells in a geometry:: + + cell.fill = dagmc_univ + +It is important in these cases to understand the DAGMC model's position +with respect to the CSG geometry. DAGMC geometries can be plotted with +OpenMC to verify that the model matches one's expectations. + +**Note:** DAGMC geometries used in OpenMC are currently required to be clean, +meaning that all surfaces have been `imprinted and merged +`_ +successfully and that the model is `watertight +`_. Future +implementations of DAGMC geometry will support small volume overlaps and +un-merged surfaces. + + +Cell and Material IDs +--------------------- + +By default, DAGMC applies cell IDs defined by the CAD engine that the model +originated in. If these IDs overlap with ID's in the CSG cell ID space, this +will result in an error. However, the ``auto_ids`` property of a DAGMC universe +can be set to set DAGMC cell IDs by appending to the existing CSG cell ID space +in the OpenMC model. + +Similar options exist for the material IDs of DAGMC models. If DAGMC material +assignments are based on natively defined OpenMC materials, no further work is +required. If DAGMC materials are assigned using the `University of Wisconsin +Unified Workflow`_ (UWUW), however, material IDs in the UWUW material library +may overlap with those used in the CSG geometry. In this case, overlaps in the +UWUW and OpenMC material ID space will cause an error. To automatically resolved +these ID overlaps, ``auto_ids`` can be set to ``True`` to append the UWUW +material IDs to the OpenMC material ID space. + +.. _Direct Accelerated Geometry Monte Carlo: https://svalinn.github.io/DAGMC/ +.. _University of Wisconsin Unified Workflow: https://svalinn.github.io/DAGMC/usersguide/uw2.html ------------------------- Calculating Atoms Content From 6af978efb9357640ac0b85d50d73297c1025b6f9 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 12 Mar 2021 23:05:42 -0600 Subject: [PATCH 37/93] Moving UWUW material read into the DAGUniverse class. --- include/openmc/cell.h | 3 ++ include/openmc/dagmc.h | 1 - src/dagmc.cpp | 80 ++++++++++++++++++------------------------ src/material.cpp | 4 --- 4 files changed, 37 insertions(+), 51 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 21ba3ddcd4..d1e3dc50ec 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -87,12 +87,15 @@ public: void initialize(); //!< Sets up the DAGMC instance and OpenMC internals + std::map read_uwuw_materials(); //!< Reads UWUW materials and returns an ID map + // Data Members std::string filename_; std::shared_ptr dagmc_instance_; //! DAGMC Instance for this universe int32_t cell_idx_offset_; int32_t surf_idx_offset_; bool adjust_ids_; + }; #endif diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index d18b705761..0c76d6b1df 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -27,7 +27,6 @@ void load_dagmc_geometry(); int32_t create_dagmc_universe(const std::string& filename); void read_geometry_dagmc(); void read_dagmc_universes(pugi::xml_node node); -void read_dagmc_materials(); bool read_uwuw_materials(pugi::xml_document& doc); bool get_uwuw_materials_xml(std::string& s); diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 91e2ffb012..02bd2338e3 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -55,7 +55,8 @@ std::string dagmc_file() { } std::string dagmc_ids_for_dim(std::shared_ptr& dagmc_instance, - int dim) { + int dim) +{ // generate a vector of ids std::vector id_vec; int n_cells = dagmc_instance->num_entities(dim); @@ -128,50 +129,9 @@ bool read_uwuw_materials(pugi::xml_document& doc) { return found_uwuw_mats; } -void read_dagmc_materials() { - std::string filename = settings::path_input + "geometry.xml"; - if (!file_exists(filename)) { - fatal_error(fmt::format("Geometry XML file '{}' does not exist!", filename)); - } - - pugi::xml_document doc; - auto result = doc.load_file(filename.c_str()); - if (!result) { - fatal_error("Error processing geometry.xml file."); - } - pugi::xml_node root = doc.document_element(); - // Loop over DAGMC elements - for (pugi::xml_node dagmc_node : root.children("dagmc")) { - if (!check_for_node(dagmc_node, "filename")) { - fatal_error("No filename specified on a DAGMC universe element"); - } - std::string dagmc_filename = get_node_value(dagmc_node, "filename"); - // Load any existing UWUW materials - UWUW uwuw(dagmc_filename.c_str()); - const auto& mat_lib = uwuw.material_library; - if (mat_lib.size() == 0) continue; - - std::stringstream ss; - ss << "\n"; - ss << "\n"; - for (auto mat : mat_lib) { ss << mat.second->openmc("atom"); } - ss << ""; - std::string mat_xml_string = ss.str(); - - // create a pugi XML document from this string - pugi::xml_document doc; - auto result = doc.load_string(mat_xml_string.c_str()); - if (!result) { - fatal_error("Error processing XML created using DAGMC UWUW materials."); - } - pugi::xml_node root = doc.document_element(); - for (pugi::xml_node material_node : root.children("material")) { - model::materials.push_back(std::make_unique(material_node)); - } - } +void read_single_file_dagmc_materials(std::string dagmc_filename) { } - bool write_uwuw_materials_xml() { std::string s; bool found_uwuw_mats = get_uwuw_materials_xml(s); @@ -308,6 +268,9 @@ void DAGUniverse::initialize() { // --- Materials --- + // read any UWUW materials from the file + auto uwuw_id_map = read_uwuw_materials(); + // create uwuw instance UWUW uwuw(filename_.c_str()); @@ -317,6 +280,8 @@ void DAGUniverse::initialize() { // notify user if UWUW materials are going to be used if (using_uwuw) { write_message("Found UWUW Materials in the DAGMC geometry file.", 6); + + } // load the DAGMC geometry @@ -353,7 +318,6 @@ void DAGUniverse::initialize() { c->universe_ = id_; // set to zero for now c->fill_ = C_NONE; // no fill, single universe - auto in_map = model::cell_map.find(c->id_); if (in_map == model::cell_map.end()) { model::cell_map[c->id_] = model::cells.size(); @@ -418,7 +382,6 @@ void DAGUniverse::initialize() { } else { c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * settings::temperature_default)); } - } // allocate the cell overlap count if necessary @@ -484,9 +447,34 @@ void DAGUniverse::initialize() { model::surfaces.emplace_back(s); } // end surface loop - } +std::map +DAGUniverse::read_uwuw_materials() { + + UWUW uwuw(filename_.c_str()); + const auto& mat_lib = uwuw.material_library; + if (mat_lib.size() == 0) return {}; + + std::stringstream ss; + ss << "\n"; + ss << "\n"; + for (auto mat : mat_lib) { ss << mat.second->openmc("atom"); } + ss << ""; + std::string mat_xml_string = ss.str(); + + // create a pugi XML document from this string + pugi::xml_document doc; + auto result = doc.load_string(mat_xml_string.c_str()); + if (!result) { + fatal_error("Error processing XML created using DAGMC UWUW materials."); + } + pugi::xml_node root = doc.document_element(); + for (pugi::xml_node material_node : root.children("material")) { + model::materials.push_back(std::make_unique(material_node)); + } + return {}; +} int32_t create_dagmc_universe(const std::string& filename) { if (!model::DAG) { diff --git a/src/material.cpp b/src/material.cpp index 80999abae9..3ef8c70c26 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -14,7 +14,6 @@ #include "openmc/capi.h" #include "openmc/cross_sections.h" #include "openmc/container_util.h" -#include "openmc/dagmc.h" #include "openmc/error.h" #include "openmc/file_utils.h" #include "openmc/hdf5_interface.h" @@ -1238,9 +1237,6 @@ void read_materials_xml() model::materials.push_back(make_unique(material_node)); } - // Search for materials defined on DAGMC models - read_dagmc_materials(); - model::materials.shrink_to_fit(); } From 9fca1f690dd13752f73214627faf63778bba6df5 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 12 Mar 2021 23:42:09 -0600 Subject: [PATCH 38/93] Moving the DAGUniverse into the DAGMC header file. --- docs/source/usersguide/geometry.rst | 15 +++++++-------- include/openmc/cell.h | 25 +------------------------ include/openmc/constants.h | 9 +++++++++ include/openmc/dagmc.h | 22 +++++++++++++++++++--- include/openmc/surface.h | 9 --------- src/cell.cpp | 1 - src/particle.cpp | 1 + 7 files changed, 37 insertions(+), 45 deletions(-) diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index a271490717..4df3681a53 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -471,15 +471,14 @@ successfully and that the model is `watertight implementations of DAGMC geometry will support small volume overlaps and un-merged surfaces. +Cell, Surface, and Material IDs +------------------------------- -Cell and Material IDs ---------------------- - -By default, DAGMC applies cell IDs defined by the CAD engine that the model -originated in. If these IDs overlap with ID's in the CSG cell ID space, this -will result in an error. However, the ``auto_ids`` property of a DAGMC universe -can be set to set DAGMC cell IDs by appending to the existing CSG cell ID space -in the OpenMC model. +By default, DAGMC applies cell and surface IDs defined by the CAD engine that +the model originated in. If these IDs overlap with ID's in the CSG ID space, +this will result in an error. However, the ``auto_ids`` property of a DAGMC +universe can be set to set DAGMC cell and surface IDs by appending to the +existing CSG cell ID space in the OpenMC model. Similar options exist for the material IDs of DAGMC models. If DAGMC material assignments are based on natively defined OpenMC materials, no further work is diff --git a/include/openmc/cell.h b/include/openmc/cell.h index d1e3dc50ec..b7f18a116f 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -10,7 +10,6 @@ #include #include "hdf5.h" #include "pugixml.hpp" -#include "dagmc.h" #include "openmc/constants.h" #include "openmc/memory.h" // for unique_ptr @@ -77,29 +76,6 @@ public: unique_ptr partitioner_; }; -#ifdef DAGMC - -class DAGUniverse : public Universe { - -public: - explicit DAGUniverse(pugi::xml_node node); - explicit DAGUniverse(const std::string& filename, bool auto_ids = false); - - void initialize(); //!< Sets up the DAGMC instance and OpenMC internals - - std::map read_uwuw_materials(); //!< Reads UWUW materials and returns an ID map - - // Data Members - std::string filename_; - std::shared_ptr dagmc_instance_; //! DAGMC Instance for this universe - int32_t cell_idx_offset_; - int32_t surf_idx_offset_; - bool adjust_ids_; - -}; - -#endif - //============================================================================== //============================================================================== @@ -372,6 +348,7 @@ void read_cells(pugi::xml_node node); #ifdef DAGMC +class DAGUniverse; int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed); #endif diff --git a/include/openmc/constants.h b/include/openmc/constants.h index aac3a52a83..89afadeb43 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -379,6 +379,15 @@ enum class RunMode { // For non-accelerated regions on coarse mesh overlay constexpr int CMFD_NOACCEL {-1}; +//============================================================================== +// Geometry Constants + +enum class GeometryType { + CSG, + DAG +}; + + } // namespace openmc #endif // OPENMC_CONSTANTS_H diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 0c76d6b1df..69b3f1610e 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -10,6 +10,7 @@ extern "C" const bool DAGMC_ENABLED; #include "DagMC.hpp" +#include "openmc/cell.h" #include "openmc/position.h" #include "openmc/xml_interface.h" @@ -19,9 +20,24 @@ namespace model { extern std::shared_ptr DAG; } -//============================================================================== -// Non-member functions -//============================================================================== +class DAGUniverse : public Universe { + +public: + explicit DAGUniverse(pugi::xml_node node); + explicit DAGUniverse(const std::string& filename, bool auto_ids = false); + + void initialize(); //!< Sets up the DAGMC instance and OpenMC internals + + std::map read_uwuw_materials(); //!< Reads UWUW materials and returns an ID map + + // Data Members + std::string filename_; + std::shared_ptr dagmc_instance_; //! DAGMC Instance for this universe + int32_t cell_idx_offset_; + int32_t surf_idx_offset_; + bool adjust_ids_; + +}; void load_dagmc_geometry(); int32_t create_dagmc_universe(const std::string& filename); diff --git a/include/openmc/surface.h b/include/openmc/surface.h index 5c729f8202..2bebdc8ce6 100644 --- a/include/openmc/surface.h +++ b/include/openmc/surface.h @@ -29,15 +29,6 @@ namespace model { extern vector> surfaces; } // namespace model -//============================================================================== -// Constants -//============================================================================== - -enum class GeometryType { - CSG, - DAG -}; - //============================================================================== //! Coordinates for an axis-aligned cube that bounds a geometric object. //============================================================================== diff --git a/src/cell.cpp b/src/cell.cpp index ae121d2ba1..63edf644be 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -22,7 +22,6 @@ #include "openmc/material.h" #include "openmc/nuclide.h" #include "openmc/settings.h" -#include "openmc/surface.h" #include "openmc/xml_interface.h" namespace openmc { diff --git a/src/particle.cpp b/src/particle.cpp index 5b2105a36e..b623b29178 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -9,6 +9,7 @@ #include "openmc/capi.h" #include "openmc/cell.h" #include "openmc/constants.h" +#include "openmc/dagmc.h" #include "openmc/error.h" #include "openmc/geometry.h" #include "openmc/hdf5_interface.h" From fdcc1ddb7ba2a0a86a1e7089069a6c41fd4eccfe Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 13 Mar 2021 00:05:41 -0600 Subject: [PATCH 39/93] Creating a new data member for auto-assigning material IDs. --- include/openmc/dagmc.h | 6 +++--- src/dagmc.cpp | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 69b3f1610e..cf399c9364 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -24,7 +24,7 @@ class DAGUniverse : public Universe { public: explicit DAGUniverse(pugi::xml_node node); - explicit DAGUniverse(const std::string& filename, bool auto_ids = false); + explicit DAGUniverse(const std::string& filename, bool auto_geom_ids = false); void initialize(); //!< Sets up the DAGMC instance and OpenMC internals @@ -35,8 +35,8 @@ public: std::shared_ptr dagmc_instance_; //! DAGMC Instance for this universe int32_t cell_idx_offset_; int32_t surf_idx_offset_; - bool adjust_ids_; - + bool adjust_geometry_ids_; + bool adjust_material_ids_; }; void load_dagmc_geometry(); diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 02bd2338e3..e6d0d56a2c 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -222,15 +222,15 @@ DAGUniverse::DAGUniverse(pugi::xml_node node) { fatal_error("Must specify a file for the DAGMC universe"); } - adjust_ids_ = false; + adjust_geometry_ids_ = false; if (check_for_node(node, "auto_ids")) { - adjust_ids_ = get_node_value_bool(node, "auto_ids"); + adjust_geometry_ids_ = get_node_value_bool(node, "auto_ids"); } initialize(); } -DAGUniverse::DAGUniverse(const std::string& filename, bool auto_ids) -: filename_(filename), adjust_ids_(auto_ids) { +DAGUniverse::DAGUniverse(const std::string& filename, bool auto_geom_ids) +: filename_(filename), adjust_geometry_ids_(auto_geom_ids) { // determine the next universe id int32_t next_univ_id = 0; for (const auto& u : model::universes) { @@ -313,7 +313,7 @@ void DAGUniverse::initialize() { // set cell ids using global IDs DAGCell* c = new DAGCell(); c->dag_index_ = i + 1; - c->id_ = adjust_ids_ ? next_cell_id++ : dagmc_instance_->id_by_index(3, c->dag_index_); + c->id_ = adjust_geometry_ids_ ? next_cell_id++ : dagmc_instance_->id_by_index(3, c->dag_index_); c->dagmc_ptr_ = dagmc_instance_; c->universe_ = id_; // set to zero for now c->fill_ = C_NONE; // no fill, single universe @@ -404,7 +404,7 @@ void DAGUniverse::initialize() { // set cell ids using global IDs DAGSurface* s = new DAGSurface(); s->dag_index_ = i+1; - s->id_ = adjust_ids_ ? next_surf_id++ : dagmc_instance_->id_by_index(2, i+1); + s->id_ = adjust_geometry_ids_ ? next_surf_id++ : dagmc_instance_->id_by_index(2, i+1); s->dagmc_ptr_ = dagmc_instance_; // set BCs From cdcc9181f9396a446d50d59de421bfa68c56135e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 13 Mar 2021 15:43:58 -0600 Subject: [PATCH 40/93] Differentiating between geometry and material ID updates in the Python API. --- openmc/universe.py | 42 ++++++++++++++----- src/dagmc.cpp | 12 ++++-- .../dagmc/refl/inputs_true.dat | 2 +- tests/regression_tests/dagmc/refl/test.py | 3 +- .../dagmc/universes/inputs_true.dat | 2 +- .../regression_tests/dagmc/universes/test.py | 2 +- 6 files changed, 43 insertions(+), 20 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 59a41a44f1..c246e33bb0 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -653,16 +653,25 @@ class DAGMCUniverse(UniverseBase): Name of the universe filename : str Path to the DAGMC file used to represent this universe. - auto_ids : bool + auto_geom_ids : bool Set IDs automatically on initialization (True) or report overlaps in ID space between CSG and DAGMC (False) + auto_mat_ids : bool + Set IDs automatically on initialization (True) or report overlaps + in ID space between OpenMC and UWUW materials (False) """ - def __init__(self, filename, universe_id=None, name='', auto_ids=False): + def __init__(self, + filename, + universe_id=None, + name='', + auto_geom_ids=False, + auto_mat_ids=False): super().__init__(universe_id, name) # Initialize class attributes self.filename = filename - self.auto_ids = auto_ids + self.auto_geom_ids = auto_geom_ids + self.auto_mat_ids = auto_mat_ids def __repr__(self): fmt_str = '{: <16}=\t{}\n' @@ -681,13 +690,22 @@ class DAGMCUniverse(UniverseBase): self._filename = val @property - def auto_ids(self): - return self._auto_ids + def auto_geom_ids(self): + return self._auto_geom_ids - @auto_ids.setter - def auto_ids(self, val): - cv.check_type('DAGMC auto ids', val, bool) - self._auto_ids = val + @auto_geom_ids.setter + def auto_geom_ids(self, val): + cv.check_type('DAGMC automatic geometry ids', val, bool) + self._auto_geom_ids = val + + @property + def auto_mat_ids(self): + return self._auto_mat_ids + + @auto_geom_ids.setter + def auto_mat_ids(self, val): + cv.check_type('DAGMC automatic material ids', val, bool) + self._auto_mat_ids = val def clone(self, clone_materials=True, clone_regions=True, memo=None): pass @@ -710,7 +728,9 @@ class DAGMCUniverse(UniverseBase): dagmc_element = ET.Element('dagmc') dagmc_element.set('id', str(self.id)) dagmc_element.set('name', self.name) - if self.auto_ids: - dagmc_element.set('auto_ids', 'true') + if self.auto_geom_ids: + dagmc_element.set('auto_geom_ids', 'true') + if self.auto_mat_ids: + dagmc_element.set('auto_mat_ids', 'true') dagmc_element.set('filename', self.filename) xml_element.append(dagmc_element) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index e6d0d56a2c..8a54b1546f 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -223,9 +223,15 @@ DAGUniverse::DAGUniverse(pugi::xml_node node) { } adjust_geometry_ids_ = false; - if (check_for_node(node, "auto_ids")) { - adjust_geometry_ids_ = get_node_value_bool(node, "auto_ids"); + if (check_for_node(node, "auto_geom_ids")) { + adjust_geometry_ids_ = get_node_value_bool(node, "auto_geom_ids"); } + + adjust_material_ids_ = false; + if (check_for_node(node, "auto_mat_ids")) { + adjust_geometry_ids_ = get_node_value_bool(node, "auto_mat_ids"); + } + initialize(); } @@ -280,8 +286,6 @@ void DAGUniverse::initialize() { // notify user if UWUW materials are going to be used if (using_uwuw) { write_message("Found UWUW Materials in the DAGMC geometry file.", 6); - - } // load the DAGMC geometry diff --git a/tests/regression_tests/dagmc/refl/inputs_true.dat b/tests/regression_tests/dagmc/refl/inputs_true.dat index fdd68002d6..ca3cba5f04 100644 --- a/tests/regression_tests/dagmc/refl/inputs_true.dat +++ b/tests/regression_tests/dagmc/refl/inputs_true.dat @@ -1,6 +1,6 @@ - + diff --git a/tests/regression_tests/dagmc/refl/test.py b/tests/regression_tests/dagmc/refl/test.py index 2b43caf89e..2f4162b16a 100644 --- a/tests/regression_tests/dagmc/refl/test.py +++ b/tests/regression_tests/dagmc/refl/test.py @@ -28,8 +28,7 @@ class UWUWTest(PyAPITestHarness): model.settings.export_to_xml() # geometry - dag_univ = openmc.DAGMCUniverse("dagmc.h5m") - dag_univ.auto_ids = True + dag_univ = openmc.DAGMCUniverse("dagmc.h5m", auto_geom_ids=True) model.geometry = openmc.Geometry(root=dag_univ) # tally diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat index f8acb45ccc..3113159393 100644 --- a/tests/regression_tests/dagmc/universes/inputs_true.dat +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -1,7 +1,7 @@ - + diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index 0144a0c3a8..2ae2b0e9f2 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -42,7 +42,7 @@ class DAGMCUniverseTest(PyAPITestHarness): ### GEOMETRY ### # create the DAGMC universe - pincell_univ = openmc.DAGMCUniverse(filename='dagmc.h5m', auto_ids=True) + pincell_univ = openmc.DAGMCUniverse(filename='dagmc.h5m', auto_geom_ids=True) left = openmc.XPlane(x0=-24.0, name='left', boundary_type='reflective') right = openmc.XPlane(x0=24.0, name='right', boundary_type='reflective') From 4d58990957f5536e7aff16bbe76c3fe3a23112bc Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 13 Mar 2021 17:03:14 -0600 Subject: [PATCH 41/93] Adjusting UWUW material IDs if needed. --- include/openmc/dagmc.h | 6 +++++- src/dagmc.cpp | 34 ++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index cf399c9364..a908f9f6c6 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -14,12 +14,15 @@ extern "C" const bool DAGMC_ENABLED; #include "openmc/position.h" #include "openmc/xml_interface.h" +class UWUW; + namespace openmc { namespace model { extern std::shared_ptr DAG; } + class DAGUniverse : public Universe { public: @@ -28,7 +31,8 @@ public: void initialize(); //!< Sets up the DAGMC instance and OpenMC internals - std::map read_uwuw_materials(); //!< Reads UWUW materials and returns an ID map + std::shared_ptr + read_uwuw_materials(); //!< Reads UWUW materials and returns an ID map // Data Members std::string filename_; diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 8a54b1546f..9f29912684 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -275,13 +275,10 @@ void DAGUniverse::initialize() { // --- Materials --- // read any UWUW materials from the file - auto uwuw_id_map = read_uwuw_materials(); - - // create uwuw instance - UWUW uwuw(filename_.c_str()); + std::shared_ptr uwuw = read_uwuw_materials(); // check for uwuw material definitions - bool using_uwuw = !uwuw.material_library.empty(); + bool using_uwuw = !uwuw->material_library.empty(); // notify user if UWUW materials are going to be used if (using_uwuw) { @@ -355,9 +352,9 @@ void DAGUniverse::initialize() { if (using_uwuw) { // lookup material in uwuw if present std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle]; - if (uwuw.material_library.count(uwuw_mat) != 0) { + if (uwuw->material_library.count(uwuw_mat) != 0) { // Note: material numbers are set by UWUW - int mat_number = uwuw.material_library.get_material(uwuw_mat).metadata["mat_number"].asInt(); + int mat_number = uwuw->material_library.get_material(uwuw_mat).metadata["mat_number"].asInt(); c->material_.push_back(mat_number); } else { fatal_error(fmt::format("Material with value {} not found in the " @@ -453,12 +450,25 @@ void DAGUniverse::initialize() { } // end surface loop } -std::map +std::shared_ptr DAGUniverse::read_uwuw_materials() { - UWUW uwuw(filename_.c_str()); - const auto& mat_lib = uwuw.material_library; - if (mat_lib.size() == 0) return {}; + int32_t next_material_id = 0; + for (const auto& m : model::materials) { + next_material_id = std::max(m->id_, next_material_id); + } + next_material_id++; + + auto uwuw = std::make_shared(filename_.c_str()); + const auto& mat_lib = uwuw->material_library; + if (mat_lib.size() == 0) return uwuw; + + // if we're using automatic IDs, update the UWUW material metadata + if (adjust_material_ids_) { + for (auto& mat : uwuw->material_library) { + mat.second->metadata["mat_number"] = std::to_string(next_material_id++); + } + } std::stringstream ss; ss << "\n"; @@ -477,7 +487,7 @@ DAGUniverse::read_uwuw_materials() { for (pugi::xml_node material_node : root.children("material")) { model::materials.push_back(std::make_unique(material_node)); } - return {}; + return uwuw; } int32_t create_dagmc_universe(const std::string& filename) { From 4819e02f227394b7f687aa0e456d934245bbb2e4 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 13 Mar 2021 22:24:27 -0600 Subject: [PATCH 42/93] Removing some unused DAGMC functions. --- include/openmc/dagmc.h | 10 -- src/dagmc.cpp | 211 ----------------------------------------- 2 files changed, 221 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index a908f9f6c6..650829fa47 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -18,11 +18,6 @@ class UWUW; namespace openmc { -namespace model { - extern std::shared_ptr DAG; -} - - class DAGUniverse : public Universe { public: @@ -43,12 +38,7 @@ public: bool adjust_material_ids_; }; -void load_dagmc_geometry(); -int32_t create_dagmc_universe(const std::string& filename); -void read_geometry_dagmc(); void read_dagmc_universes(pugi::xml_node node); -bool read_uwuw_materials(pugi::xml_document& doc); -bool get_uwuw_materials_xml(std::string& s); } // namespace openmc diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 9f29912684..d04ec4fc00 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -39,13 +39,6 @@ namespace openmc { const std::string DAGMC_FILENAME = "dagmc.h5m"; -namespace model { - -std::shared_ptr DAG; - -} // namespace model - - std::string dagmc_file() { std::string filename = settings::path_input + DAGMC_FILENAME; if (!file_exists(filename)) { @@ -129,9 +122,6 @@ bool read_uwuw_materials(pugi::xml_document& doc) { return found_uwuw_mats; } -void read_single_file_dagmc_materials(std::string dagmc_filename) { -} - bool write_uwuw_materials_xml() { std::string s; bool found_uwuw_mats = get_uwuw_materials_xml(s); @@ -193,21 +183,12 @@ void legacy_assign_material(std::string mat_string, DAGCell* c) } } -void load_dagmc_geometry() -{ - model::universes.push_back(std::make_unique(dagmc_file())); - model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; -} - -#ifdef DAGMC void read_dagmc_universes(pugi::xml_node node) { for (pugi::xml_node dag_node : node.children("dagmc")) { model::universes.push_back(std::make_unique(dag_node)); model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; } } -#endif - DAGUniverse::DAGUniverse(pugi::xml_node node) { if (check_for_node(node, "id")) { @@ -490,197 +471,5 @@ DAGUniverse::read_uwuw_materials() { return uwuw; } -int32_t create_dagmc_universe(const std::string& filename) { - if (!model::DAG) { - model::DAG = std::make_shared(); - } - - // --- Materials --- - - // create uwuw instance - UWUW uwuw(filename.c_str()); - - // check for uwuw material definitions - bool using_uwuw = !uwuw.material_library.empty(); - - // notify user if UWUW materials are going to be used - if (using_uwuw) { - write_message("Found UWUW Materials in the DAGMC geometry file.", 6); - } - - int32_t dagmc_univ_id = 0; // universe is always 0 for DAGMC runs - - // load the DAGMC geometry - moab::ErrorCode rval = model::DAG->load_file(filename.c_str()); - MB_CHK_ERR_CONT(rval); - - // initialize acceleration data structures - rval = model::DAG->init_OBBTree(); - MB_CHK_ERR_CONT(rval); - - // parse model metadata - dagmcMetaData DMD(model::DAG.get(), false, false); - DMD.load_property_data(); - - vector keywords {"temp"}; - std::map dum; - std::string delimiters = ":/"; - rval = model::DAG->parse_properties(keywords, dum, delimiters.c_str()); - MB_CHK_ERR_CONT(rval); - - // --- Cells (Volumes) --- - - // initialize cell objects - int n_cells = model::DAG->num_entities(3); - moab::EntityHandle graveyard = 0; - for (int i = 0; i < n_cells; i++) { - moab::EntityHandle vol_handle = model::DAG->entity_by_index(3, i+1); - // set cell ids using global IDs - DAGCell* c = new DAGCell(); - c->dag_index_ = i+1; - c->id_ = model::DAG->id_by_index(3, c->dag_index_); - c->dagmc_ptr_ = model::DAG; - c->universe_ = dagmc_univ_id; // set to zero for now - c->fill_ = C_NONE; // no fill, single universe - - model::cells.emplace_back(c); - model::cell_map[c->id_] = i; - - // Populate the Universe vector and dict - auto it = model::universe_map.find(dagmc_univ_id); - if (it == model::universe_map.end()) { - model::universes.push_back(make_unique()); - model::universes.back()->id_ = dagmc_univ_id; - model::universes.back()->cells_.push_back(i); - model::universe_map[dagmc_univ_id] = model::universes.size() - 1; - } else { - model::universes[it->second]->cells_.push_back(i); - } - - // MATERIALS - - // determine volume material assignment - std::string mat_str = DMD.get_volume_property("material", vol_handle); - - if (mat_str.empty()) { - fatal_error(fmt::format("Volume {} has no material assignment.", c->id_)); - } - - to_lower(mat_str); - - if (mat_str == "graveyard") { - graveyard = vol_handle; - } - - // material void checks - if (mat_str == "void" || mat_str == "vacuum" || mat_str == "graveyard") { - c->material_.push_back(MATERIAL_VOID); - } else { - if (using_uwuw) { - // lookup material in uwuw if present - std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle]; - if (uwuw.material_library.count(uwuw_mat) != 0) { - // Note: material numbers are set by UWUW - int mat_number = uwuw.material_library.get_material(uwuw_mat).metadata["mat_number"].asInt(); - c->material_.push_back(mat_number); - } else { - fatal_error(fmt::format("Material with value {} not found in the " - "UWUW material library", mat_str)); - } - } else { - legacy_assign_material(mat_str, c); - } - } - - // check for temperature assignment - std::string temp_value; - - // no temperature if void - if (c->material_[0] == MATERIAL_VOID) continue; - - // assign cell temperature - const auto& mat = model::materials[model::material_map.at(c->material_[0])]; - if (model::DAG->has_prop(vol_handle, "temp")) { - rval = model::DAG->prop_value(vol_handle, "temp", temp_value); - MB_CHK_ERR_CONT(rval); - double temp = std::stod(temp_value); - c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * temp)); - } else { - c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * mat->temperature())); - } - - } - - // allocate the cell overlap count if necessary - if (settings::check_overlaps) { - model::overlap_check_count.resize(model::cells.size(), 0); - } - - if (!graveyard) { - warning("No graveyard volume found in the DagMC model." - "This may result in lost particles and rapid simulation failure."); - } - - // --- Surfaces --- - - // initialize surface objects - int n_surfaces = model::DAG->num_entities(2); - - for (int i = 0; i < n_surfaces; i++) { - moab::EntityHandle surf_handle = model::DAG->entity_by_index(2, i+1); - - // set cell ids using global IDs - DAGSurface* s = new DAGSurface(); - s->dag_index_ = i+1; - s->id_ = model::DAG->id_by_index(2, s->dag_index_); - s->dagmc_ptr_ = model::DAG; - - if (contains(settings::source_write_surf_id, s->id_)) { - s->surf_source_ = true; - } - - // set BCs - std::string bc_value = DMD.get_surface_property("boundary", surf_handle); - to_lower(bc_value); - if (bc_value.empty() || bc_value == "transmit" || bc_value == "transmission") { - // Leave the bc_ a nullptr - } else if (bc_value == "vacuum") { - s->bc_ = std::make_shared(); - } else if (bc_value == "reflective" || bc_value == "reflect" || bc_value == "reflecting") { - s->bc_ = std::make_shared(); - } else if (bc_value == "white") { - fatal_error("White boundary condition not supported in DAGMC."); - } else if (bc_value == "periodic") { - fatal_error("Periodic boundary condition not supported in DAGMC."); - } else { - fatal_error(fmt::format("Unknown boundary condition \"{}\" specified " - "on surface {}", bc_value, s->id_)); - } - - // graveyard check - moab::Range parent_vols; - rval = model::DAG->moab_instance()->get_parent_meshsets(surf_handle, parent_vols); - MB_CHK_ERR_CONT(rval); - - // if this surface belongs to the graveyard - if (graveyard && parent_vols.find(graveyard) != parent_vols.end()) { - // set graveyard surface BC's to vacuum - s->bc_ = std::make_shared(); - } - - // add to global array and map - model::surfaces.emplace_back(s); - model::surface_map[s->id_] = i; - } - - return model::universes.size() - 1; -} - -void read_geometry_dagmc() -{ - write_message("Reading DAGMC geometry...", 5); - model::root_universe = find_root_universe(); -} - } #endif From da6a369d1fa04b13fa40618059cae52f9d467fe6 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 15 Mar 2021 14:28:44 -0500 Subject: [PATCH 43/93] Refactoring all of the openmc namespace functions into the DAGUniverse class. --- include/openmc/dagmc.h | 15 ++++- src/dagmc.cpp | 128 ++++++++++++++++++++--------------------- 2 files changed, 76 insertions(+), 67 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 650829fa47..8eb7f272bd 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -26,12 +26,23 @@ public: void initialize(); //!< Sets up the DAGMC instance and OpenMC internals - std::shared_ptr - read_uwuw_materials(); //!< Reads UWUW materials and returns an ID map + void read_uwuw_materials(); //!< Reads UWUW materials and returns an ID map + + bool uses_uwuw() const; + + std::string get_uwuw_materials_xml() const; + + void write_uwuw_materials_xml(const std::string& outfile = "uwuw_materials.xml") const; + + void legacy_assign_material(std::string mat_string, + std::unique_ptr& c) const; + + std::string dagmc_ids_for_dim(int dim) const; // Data Members std::string filename_; std::shared_ptr dagmc_instance_; //! DAGMC Instance for this universe + std::shared_ptr uwuw_; int32_t cell_idx_offset_; int32_t surf_idx_offset_; bool adjust_geometry_ids_; diff --git a/src/dagmc.cpp b/src/dagmc.cpp index d04ec4fc00..947f48a647 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -47,14 +47,14 @@ std::string dagmc_file() { return filename; } -std::string dagmc_ids_for_dim(std::shared_ptr& dagmc_instance, - int dim) +std::string +DAGUniverse::dagmc_ids_for_dim(int dim) const { // generate a vector of ids std::vector id_vec; - int n_cells = dagmc_instance->num_entities(dim); + int n_cells = dagmc_instance_->num_entities(dim); for (int i = 1; i <= n_cells; i++) { - id_vec.push_back(dagmc_instance->id_by_index(dim, i)); + id_vec.push_back(dagmc_instance_->id_by_index(dim, i)); } // sort the vector of ids @@ -88,55 +88,50 @@ std::string dagmc_ids_for_dim(std::shared_ptr& dagmc_instance, return out.str(); } -bool get_uwuw_materials_xml(std::string& s) { - std::string filename = dagmc_file(); - UWUW uwuw(filename.c_str()); +bool +DAGUniverse::uses_uwuw() const +{ + return uwuw_ && !uwuw_->material_library.empty(); +} + +std::string +DAGUniverse::get_uwuw_materials_xml() const +{ + + if (!uses_uwuw()) { + throw std::runtime_error("This DAGMC Universe does not use UWUW materials"); + } std::stringstream ss; - bool uwuw_mats_present = false; - if (uwuw.material_library.size() != 0) { - uwuw_mats_present = true; - // write header - ss << "\n"; - ss << "\n"; - const auto& mat_lib = uwuw.material_library; - // write materials - for (auto mat : mat_lib) { ss << mat.second->openmc("atom"); } - // write footer - ss << ""; - s = ss.str(); - } + // write header + ss << "\n"; + ss << "\n"; + const auto& mat_lib = uwuw_->material_library; + // write materials + for (auto mat : mat_lib) { ss << mat.second->openmc("atom"); } + // write footer + ss << ""; - return uwuw_mats_present; + return ss.str(); } -bool read_uwuw_materials(pugi::xml_document& doc) { - std::string s; - bool found_uwuw_mats = get_uwuw_materials_xml(s); - if (found_uwuw_mats) { - pugi::xml_parse_result result = doc.load_string(s.c_str()); - if (!result) { - throw std::runtime_error{"Error reading UWUW materials"}; - } - } - return found_uwuw_mats; -} - -bool write_uwuw_materials_xml() { - std::string s; - bool found_uwuw_mats = get_uwuw_materials_xml(s); - // if there is a material library in the file - if (found_uwuw_mats) { - // write a material.xml file - std::ofstream mats_xml("materials.xml"); - mats_xml << s; - mats_xml.close(); +void +DAGUniverse::write_uwuw_materials_xml(const std::string& outfile) const +{ + if (!uses_uwuw()) { + throw std::runtime_error("This DAGMC universe does not use UWUW materials."); } - return found_uwuw_mats; + std::string xml_str = get_uwuw_materials_xml(); + // if there is a material library in the file + std::ofstream mats_xml(outfile); + mats_xml << xml_str; + mats_xml.close(); } -void legacy_assign_material(std::string mat_string, DAGCell* c) +void +DAGUniverse::legacy_assign_material(std::string mat_string, + std::unique_ptr& c) const { bool mat_found_by_name = false; // attempt to find a material with a matching name @@ -152,7 +147,7 @@ void legacy_assign_material(std::string mat_string, DAGCell* c) // report error if more than one material is found } else { fatal_error(fmt::format( - "More than one material found with name {}. Please ensure materials " + "More than one material found with name '{}'. Please ensure materials " "have unique names if using this property to assign materials.", mat_string)); } @@ -166,7 +161,7 @@ void legacy_assign_material(std::string mat_string, DAGCell* c) c->material_.emplace_back(id); } catch (const std::invalid_argument&) { fatal_error(fmt::format( - "No material {} found for volume (cell) {}", mat_string, c->id_)); + "No material '{}' found for volume (cell) {}", mat_string, c->id_)); } } @@ -256,10 +251,10 @@ void DAGUniverse::initialize() { // --- Materials --- // read any UWUW materials from the file - std::shared_ptr uwuw = read_uwuw_materials(); + read_uwuw_materials(); // check for uwuw material definitions - bool using_uwuw = !uwuw->material_library.empty(); + bool using_uwuw = uses_uwuw(); // notify user if UWUW materials are going to be used if (using_uwuw) { @@ -293,7 +288,7 @@ void DAGUniverse::initialize() { moab::EntityHandle vol_handle = dagmc_instance_->entity_by_index(3, i + 1); // set cell ids using global IDs - DAGCell* c = new DAGCell(); + auto c = std::make_unique(); c->dag_index_ = i + 1; c->id_ = adjust_geometry_ids_ ? next_cell_id++ : dagmc_instance_->id_by_index(3, c->dag_index_); c->dagmc_ptr_ = dagmc_instance_; @@ -304,13 +299,11 @@ void DAGUniverse::initialize() { if (in_map == model::cell_map.end()) { model::cell_map[c->id_] = model::cells.size(); } else { - warning(fmt::format("DAGMC Cell IDs: {}", dagmc_ids_for_dim(dagmc_instance_, 3))); + warning(fmt::format("DAGMC Cell IDs: {}", dagmc_ids_for_dim(3))); fatal_error(fmt::format("Cell ID {} exists in both DAGMC Universe {} " "and the CSG geometry.", c->id_, this->id_)); } - model::cells.emplace_back(c); - // MATERIALS // determine volume material assignment @@ -333,12 +326,12 @@ void DAGUniverse::initialize() { if (using_uwuw) { // lookup material in uwuw if present std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle]; - if (uwuw->material_library.count(uwuw_mat) != 0) { + if (uwuw_->material_library.count(uwuw_mat) != 0) { // Note: material numbers are set by UWUW - int mat_number = uwuw->material_library.get_material(uwuw_mat).metadata["mat_number"].asInt(); + int mat_number = uwuw_->material_library.get_material(uwuw_mat).metadata["mat_number"].asInt(); c->material_.push_back(mat_number); } else { - fatal_error(fmt::format("Material with value {} not found in the " + fatal_error(fmt::format("Material with value '{}' not found in the " "UWUW material library", mat_str)); } } else { @@ -350,7 +343,10 @@ void DAGUniverse::initialize() { std::string temp_value; // no temperature if void - if (c->material_[0] == MATERIAL_VOID) continue; + if (c->material_[0] == MATERIAL_VOID) { + model::cells.emplace_back(std::move(c)); + continue; + } // assign cell temperature const auto& mat = model::materials[model::material_map.at(c->material_[0])]; @@ -364,6 +360,8 @@ void DAGUniverse::initialize() { } else { c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * settings::temperature_default)); } + + model::cells.emplace_back(std::move(c)); } // allocate the cell overlap count if necessary @@ -384,7 +382,7 @@ void DAGUniverse::initialize() { moab::EntityHandle surf_handle = dagmc_instance_->entity_by_index(2, i+1); // set cell ids using global IDs - DAGSurface* s = new DAGSurface(); + auto s = std::make_unique(); s->dag_index_ = i+1; s->id_ = adjust_geometry_ids_ ? next_surf_id++ : dagmc_instance_->id_by_index(2, i+1); s->dagmc_ptr_ = dagmc_instance_; @@ -422,16 +420,17 @@ void DAGUniverse::initialize() { if (in_map == model::surface_map.end()) { model::surface_map[s->id_] = model::surfaces.size(); } else { - warning(fmt::format("DAGMC Surface IDs: {}", dagmc_ids_for_dim(dagmc_instance_, 2))); + warning(fmt::format("DAGMC Surface IDs: {}", dagmc_ids_for_dim(2))); fatal_error(fmt::format("Surface ID {} exists in both Universe {} " "and the CSG geometry.", s->id_, this->id_)); } - model::surfaces.emplace_back(s); + + model::surfaces.emplace_back(std::move(s)); } // end surface loop } -std::shared_ptr +void DAGUniverse::read_uwuw_materials() { int32_t next_material_id = 0; @@ -440,13 +439,13 @@ DAGUniverse::read_uwuw_materials() { } next_material_id++; - auto uwuw = std::make_shared(filename_.c_str()); - const auto& mat_lib = uwuw->material_library; - if (mat_lib.size() == 0) return uwuw; + uwuw_ = std::make_shared(filename_.c_str()); + const auto& mat_lib = uwuw_->material_library; + if (mat_lib.size() == 0) return; // if we're using automatic IDs, update the UWUW material metadata if (adjust_material_ids_) { - for (auto& mat : uwuw->material_library) { + for (auto& mat : uwuw_->material_library) { mat.second->metadata["mat_number"] = std::to_string(next_material_id++); } } @@ -468,7 +467,6 @@ DAGUniverse::read_uwuw_materials() { for (pugi::xml_node material_node : root.children("material")) { model::materials.push_back(std::make_unique(material_node)); } - return uwuw; } } From 8658dbaed7f03de103f090d62b060fcc2440bd7d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 15 Mar 2021 14:32:17 -0500 Subject: [PATCH 44/93] Removing another now unused function. --- include/openmc/dagmc.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 8eb7f272bd..8da6898d36 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -1,4 +1,3 @@ - #ifndef OPENMC_DAGMC_H #define OPENMC_DAGMC_H @@ -53,10 +52,6 @@ void read_dagmc_universes(pugi::xml_node node); } // namespace openmc -#else - -inline void read_dagmc_materials() {}; - -#endif +#endif // DAGMC #endif // OPENMC_DAGMC_H From 8f9788742a23d5a6901a2d86add0037a28429dc6 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 26 Mar 2021 20:10:10 -0500 Subject: [PATCH 45/93] A couple of cosmetic fixes. --- src/dagmc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 947f48a647..880a42ebc1 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -292,7 +292,7 @@ void DAGUniverse::initialize() { c->dag_index_ = i + 1; c->id_ = adjust_geometry_ids_ ? next_cell_id++ : dagmc_instance_->id_by_index(3, c->dag_index_); c->dagmc_ptr_ = dagmc_instance_; - c->universe_ = id_; // set to zero for now + c->universe_ = id_; c->fill_ = C_NONE; // no fill, single universe auto in_map = model::cell_map.find(c->id_); @@ -370,7 +370,7 @@ void DAGUniverse::initialize() { } if (!graveyard) { - warning("No graveyard volume found in the DagMC model." + warning("No graveyard volume found in the DagMC model. " "This may result in lost particles and rapid simulation failure."); } From 329394824893e63170139b6785affa3d5f68a79e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 29 Mar 2021 14:58:18 -0500 Subject: [PATCH 46/93] 65;6003;1cAdding a find_cell method to universes. --- include/openmc/cell.h | 2 ++ src/cell.cpp | 25 +++++++++++++++++++++++++ src/geometry.cpp | 27 +++------------------------ 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index b7f18a116f..54e06f782e 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -70,6 +70,8 @@ public: //! \param group_id An HDF5 group id. void to_hdf5(hid_t group_id) const; + virtual bool find_cell(Particle &p) const; + BoundingBox bounding_box() const; GeometryType type_ = GeometryType::CSG; diff --git a/src/cell.cpp b/src/cell.cpp index 63edf644be..4dee4730f0 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -212,6 +212,31 @@ Universe::to_hdf5(hid_t universes_group) const close_group(group); } +bool +Universe::find_cell(Particle& p) const { + const auto& cells { + !partitioner_ + ? cells_ + : partitioner_->get_cells(p.r_local(), p.u_local()) + }; + + for (auto it = cells.begin(); it != cells.end(); it++) { + int32_t i_cell = *it; + int32_t i_univ = p.coord_[p.n_coord_-1].universe; + if (model::cells[i_cell]->universe_ != i_univ) continue; + + // Check if this cell contains the particle; + Position r {p.r_local()}; + Direction u {p.u_local()}; + auto surf = p.surface_; + if (model::cells[i_cell]->contains(r, u, surf)) { + p.coord_[p.n_coord_-1].cell = i_cell; + return true; + } + } + return false; +} + BoundingBox Universe::bounding_box() const { BoundingBox bbox = {INFTY, -INFTY, INFTY, -INFTY, INFTY, -INFTY}; if (cells_.size() == 0) { diff --git a/src/geometry.cpp b/src/geometry.cpp index 59607f637a..7e7b3b1729 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -112,34 +112,13 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list) // that. if (i_cell == C_NONE) { int i_universe = p.coord(p.n_coord() - 1).universe; - const auto& univ {*model::universes[i_universe]}; - const auto& cells { - !univ.partitioner_ - ? model::universes[i_universe]->cells_ - : univ.partitioner_->get_cells(p.r_local(), p.u_local()) - }; - - for (auto it = cells.cbegin(); it != cells.cend(); it++) { - i_cell = *it; - - // Make sure the search cell is in the same universe. - int i_universe = p.coord(p.n_coord() - 1).universe; - if (model::cells[i_cell]->universe_ != i_universe) continue; - - // Check if this cell contains the particle. - Position r {p.r_local()}; - Direction u {p.u_local()}; - auto surf = p.surface(); - if (model::cells[i_cell]->contains(r, u, surf)) { - p.coord(p.n_coord() - 1).cell = i_cell; - found = true; - break; - } - } + const auto& univ {model::universes[i_universe]}; + found = univ->find_cell(p); } if (!found) { return found; } + i_cell = p.coord_[p.n_coord_ - 1].cell; // Announce the cell that the particle is entering. if (found && (settings::verbosity >= 10 || p.trace())) { From 7190f6685f224f52f80a2a99cd204fd992774f19 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 29 Mar 2021 18:19:02 -0500 Subject: [PATCH 47/93] Fix after rebase. --- src/particle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/particle.cpp b/src/particle.cpp index b623b29178..6fc27ebfa8 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -514,7 +514,7 @@ Particle::cross_reflective_bc(const Surface& surf, Direction new_u) // the lower universes. // (unless we're using a dagmc model, which has exactly one universe) n_coord() = 1; - if (surf->geom_type_ != GeometryType::DAGMC && !neighbor_list_find_cell(*this, true)) { + if (surf.geom_type_ != GeometryType::DAG && !neighbor_list_find_cell(*this)) { this->mark_as_lost("Couldn't find particle after reflecting from surface " + std::to_string(surf.id_) + "."); return; From 97691874f62c0872c9b0b03db9eef7ddd9544c2f Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 30 Mar 2021 01:31:15 -0500 Subject: [PATCH 48/93] Improved handling of lower level DAGMC universes. --- include/openmc/dagmc.h | 4 ++++ src/cell.cpp | 4 +++- src/dagmc.cpp | 20 ++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 8da6898d36..76bd0a4ec3 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -29,6 +29,8 @@ public: bool uses_uwuw() const; + int32_t implicit_complement_idx() const; + std::string get_uwuw_materials_xml() const; void write_uwuw_materials_xml(const std::string& outfile = "uwuw_materials.xml") const; @@ -38,6 +40,8 @@ public: std::string dagmc_ids_for_dim(int dim) const; + virtual bool find_cell(Particle &p) const override; + // Data Members std::string filename_; std::shared_ptr dagmc_instance_; //! DAGMC Instance for this universe diff --git a/src/cell.cpp b/src/cell.cpp index 4dee4730f0..ad711573b2 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -863,7 +863,9 @@ DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) cons // indicate that particle is lost surf_idx = -1; dist = INFINITY; - p->mark_as_lost(fmt::format("No intersection found with DAGMC cell {}", id_)); + if (!dagmc_ptr_->is_implicit_complement(vol) || model::universe_map[dag_univ->id_] == model::root_universe) { + p->mark_as_lost(fmt::format("No intersection found with DAGMC cell {}", id_)); + } } return {dist, surf_idx}; diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 880a42ebc1..635f05bd88 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -88,6 +88,26 @@ DAGUniverse::dagmc_ids_for_dim(int dim) const return out.str(); } +int32_t +DAGUniverse::implicit_complement_idx() const { + moab::EntityHandle ic; + moab::ErrorCode rval = dagmc_instance_->geom_tool()->get_implicit_complement(ic); + MB_CHK_SET_ERR_CONT(rval, "Failed to get implicit complement"); + return cell_idx_offset_ + dagmc_instance_->index_by_handle(ic) - 1; +} + +bool +DAGUniverse::find_cell(Particle &p) const { + // if the particle isn't in any of the other DagMC + // cells, place it in the implicit complement + bool found = Universe::find_cell(p); + if (!found && model::universe_map[this->id_] != model::root_universe) { + p.coord_[p.n_coord_ - 1].cell = implicit_complement_idx(); + found = true; + } + return found; +} + bool DAGUniverse::uses_uwuw() const { From 5978d78e1caceb5b0bd30f5fb126353935e34ae0 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 31 Mar 2021 18:07:08 -0500 Subject: [PATCH 49/93] Creating a more complicated test --- tests/regression_tests/rotation/test.py | 44 +++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/rotation/test.py b/tests/regression_tests/rotation/test.py index 31c3d8d655..4a4526342e 100644 --- a/tests/regression_tests/rotation/test.py +++ b/tests/regression_tests/rotation/test.py @@ -1,6 +1,46 @@ from tests.testing_harness import TestHarness -def test_rotation(): - harness = TestHarness('statepoint.10.h5') +@pytest.fixture +def model(): + model = openmc.model.Model() + + fuel = openmc.Material() + fuel.set_density('g/cc', 10.0) + fuel.add_nuclide('U235', 1.0) + + h1 = openmc.Material() + h1.set_density('g/cc', 0.1) + h1.add_nuclide('H1', 0.1) + + inner_sphere = openmc.Sphere(x0=1.0, r=5.0) + + fuel_cell = openmc.Cell(fill=fuel, region=-inner_sphere) + hydrogen_cell = openmc.Cell(fill=h1, region=+inner_sphere) + univ = openmc.Universe(cells=[fuel_cell, hydrogen_cell]) + + + box = openmc.rectangular_prism(15., 15., 'z', boundary_type='vacuum') + lower_z = openmc.ZPlane(-7.5, boundary_type='vacuum') + upper_z = openmc.ZPlane(22.5, boundary_type='vacuum') + middle_z = openmc.ZPlane(7.5) + + lower_cell = openmc.Cell(fill=univ, region=box & +lower_z & -middle_z) + lower_cell.rotation = (10, 20, 30) + upper_cell = openmc.Cell(fill=univ, region=box & +middle_z & -upper_z) + upper_cell.translation = (0, 0, 15) + + model.geometry = openmc.Geometry(root=[lower_cell, upper_cell]) + + model.settings.particles = 10000 + model.settings.inactive = 5 + model.settings.batches = 10 + source_box = openmc.stats.Box((-4., -4., -4.), (4., 4., 4.)) + model.settings.source = openmc.Source(space=source_box) + + return model + + +def test_rotation(model): + harness = PyAPITestHarness('statepoint.10.h5', model) harness.main() From 67ae0806297d127f5237f31ce39859c8b84615c1 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 31 Mar 2021 18:26:34 -0500 Subject: [PATCH 50/93] Updating test results for new problem. --- tests/regression_tests/rotation/geometry.xml | 11 ------ .../regression_tests/rotation/inputs_true.dat | 38 +++++++++++++++++++ tests/regression_tests/rotation/materials.xml | 14 ------- .../rotation/results_true.dat | 4 ++ tests/regression_tests/rotation/settings.xml | 15 -------- tests/regression_tests/rotation/test.py | 5 ++- 6 files changed, 46 insertions(+), 41 deletions(-) delete mode 100644 tests/regression_tests/rotation/geometry.xml create mode 100644 tests/regression_tests/rotation/inputs_true.dat delete mode 100644 tests/regression_tests/rotation/materials.xml delete mode 100644 tests/regression_tests/rotation/settings.xml diff --git a/tests/regression_tests/rotation/geometry.xml b/tests/regression_tests/rotation/geometry.xml deleted file mode 100644 index f324617065..0000000000 --- a/tests/regression_tests/rotation/geometry.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/regression_tests/rotation/inputs_true.dat b/tests/regression_tests/rotation/inputs_true.dat new file mode 100644 index 0000000000..24b00199be --- /dev/null +++ b/tests/regression_tests/rotation/inputs_true.dat @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 10000 + 10 + 5 + + + -4.0 -4.0 -4.0 4.0 4.0 4.0 + + + diff --git a/tests/regression_tests/rotation/materials.xml b/tests/regression_tests/rotation/materials.xml deleted file mode 100644 index 160c9c6789..0000000000 --- a/tests/regression_tests/rotation/materials.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/tests/regression_tests/rotation/results_true.dat b/tests/regression_tests/rotation/results_true.dat index f4a3cfcccb..f0e7868a01 100644 --- a/tests/regression_tests/rotation/results_true.dat +++ b/tests/regression_tests/rotation/results_true.dat @@ -1,2 +1,6 @@ k-combined: +<<<<<<< HEAD 4.132181E-01 1.130226E-02 +======= +4.453328E-01 5.918369E-03 +>>>>>>> Updating test results for new problem. diff --git a/tests/regression_tests/rotation/settings.xml b/tests/regression_tests/rotation/settings.xml deleted file mode 100644 index 70b4e802f8..0000000000 --- a/tests/regression_tests/rotation/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/rotation/test.py b/tests/regression_tests/rotation/test.py index 4a4526342e..7a59ce2000 100644 --- a/tests/regression_tests/rotation/test.py +++ b/tests/regression_tests/rotation/test.py @@ -1,4 +1,7 @@ -from tests.testing_harness import TestHarness +import pytest +import openmc + +from tests.testing_harness import PyAPITestHarness @pytest.fixture From e455c3d58e83f3ecff41c22b314ecfa034901a22 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 31 Mar 2021 18:27:37 -0500 Subject: [PATCH 51/93] Adding a quick comment. --- tests/regression_tests/rotation/test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/regression_tests/rotation/test.py b/tests/regression_tests/rotation/test.py index 7a59ce2000..25aada5aad 100644 --- a/tests/regression_tests/rotation/test.py +++ b/tests/regression_tests/rotation/test.py @@ -22,7 +22,8 @@ def model(): hydrogen_cell = openmc.Cell(fill=h1, region=+inner_sphere) univ = openmc.Universe(cells=[fuel_cell, hydrogen_cell]) - + # Create one cell on top of the other. Only one + # has a rotation box = openmc.rectangular_prism(15., 15., 'z', boundary_type='vacuum') lower_z = openmc.ZPlane(-7.5, boundary_type='vacuum') upper_z = openmc.ZPlane(22.5, boundary_type='vacuum') From e0aed3d2b3a1c938b0346cefa9f97bd83ab6cdf0 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 31 Mar 2021 22:56:03 -0500 Subject: [PATCH 52/93] Restoring old test (but using PyAPITestHarnes). Moving the new test into its own directory. --- .../regression_tests/rotation/inputs_true.dat | 19 +++++---------- .../rotation/results_true.dat | 4 ---- tests/regression_tests/rotation/test.py | 24 ++++++------------- 3 files changed, 13 insertions(+), 34 deletions(-) diff --git a/tests/regression_tests/rotation/inputs_true.dat b/tests/regression_tests/rotation/inputs_true.dat index 24b00199be..d90d498bf6 100644 --- a/tests/regression_tests/rotation/inputs_true.dat +++ b/tests/regression_tests/rotation/inputs_true.dat @@ -1,17 +1,10 @@ - - - - - - - - - - - - + + + + + @@ -27,7 +20,7 @@ eigenvalue - 10000 + 1000 10 5 diff --git a/tests/regression_tests/rotation/results_true.dat b/tests/regression_tests/rotation/results_true.dat index f0e7868a01..a58aa1c8ec 100644 --- a/tests/regression_tests/rotation/results_true.dat +++ b/tests/regression_tests/rotation/results_true.dat @@ -1,6 +1,2 @@ k-combined: -<<<<<<< HEAD -4.132181E-01 1.130226E-02 -======= 4.453328E-01 5.918369E-03 ->>>>>>> Updating test results for new problem. diff --git a/tests/regression_tests/rotation/test.py b/tests/regression_tests/rotation/test.py index 25aada5aad..6b68367b40 100644 --- a/tests/regression_tests/rotation/test.py +++ b/tests/regression_tests/rotation/test.py @@ -1,8 +1,7 @@ -import pytest import openmc +import pytest -from tests.testing_harness import PyAPITestHarness - +from tests.testing_harness import TestHarness, PyAPITestHarness @pytest.fixture def model(): @@ -16,27 +15,18 @@ def model(): h1.set_density('g/cc', 0.1) h1.add_nuclide('H1', 0.1) + outer_sphere = openmc.Sphere(r=10.0, boundary_type='vacuum') inner_sphere = openmc.Sphere(x0=1.0, r=5.0) fuel_cell = openmc.Cell(fill=fuel, region=-inner_sphere) hydrogen_cell = openmc.Cell(fill=h1, region=+inner_sphere) univ = openmc.Universe(cells=[fuel_cell, hydrogen_cell]) + outer_cell = openmc.Cell(fill=univ, region=-outer_sphere) + outer_cell.rotation = (10, 20, 30) - # Create one cell on top of the other. Only one - # has a rotation - box = openmc.rectangular_prism(15., 15., 'z', boundary_type='vacuum') - lower_z = openmc.ZPlane(-7.5, boundary_type='vacuum') - upper_z = openmc.ZPlane(22.5, boundary_type='vacuum') - middle_z = openmc.ZPlane(7.5) + model.geometry = openmc.Geometry(root=[outer_cell]) - lower_cell = openmc.Cell(fill=univ, region=box & +lower_z & -middle_z) - lower_cell.rotation = (10, 20, 30) - upper_cell = openmc.Cell(fill=univ, region=box & +middle_z & -upper_z) - upper_cell.translation = (0, 0, 15) - - model.geometry = openmc.Geometry(root=[lower_cell, upper_cell]) - - model.settings.particles = 10000 + model.settings.particles = 1000 model.settings.inactive = 5 model.settings.batches = 10 source_box = openmc.stats.Box((-4., -4., -4.), (4., 4., 4.)) From 230e054ec39134369fd908a1c516293eb449b8e4 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 1 Apr 2021 23:24:06 -0500 Subject: [PATCH 53/93] Move DAGCell implementation into the dagmc files. --- include/openmc/cell.h | 23 ----------- include/openmc/dagmc.h | 22 ++++++++++- src/cell.cpp | 90 ------------------------------------------ src/dagmc.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 114 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 54e06f782e..ad17b6f78b 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -260,28 +260,6 @@ protected: vector::iterator start, const vector& rpn); }; -//============================================================================== - -#ifdef DAGMC -class DAGCell : public Cell -{ -public: - DAGCell(); - - bool contains(Position r, Direction u, int32_t on_surface) const; - - std::pair - distance(Position r, Direction u, int32_t on_surface, Particle* p) const; - - BoundingBox bounding_box() const; - - void to_hdf5_inner(hid_t group_id) const; - - std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance - int32_t dag_index_; //!< DagMC index of cell -}; -#endif - //============================================================================== //! Speeds up geometry searches by grouping cells in a search tree. // @@ -351,7 +329,6 @@ void read_cells(pugi::xml_node node); #ifdef DAGMC class DAGUniverse; -int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed); #endif } // namespace openmc diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 76bd0a4ec3..1dc1c2bc37 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -10,13 +10,32 @@ extern "C" const bool DAGMC_ENABLED; #include "DagMC.hpp" #include "openmc/cell.h" +#include "openmc/particle.h" #include "openmc/position.h" +#include "openmc/surface.h" #include "openmc/xml_interface.h" class UWUW; namespace openmc { +class DAGCell : public Cell { +public: + DAGCell(); + + bool contains(Position r, Direction u, int32_t on_surface) const; + + std::pair + distance(Position r, Direction u, int32_t on_surface, Particle* p) const; + + BoundingBox bounding_box() const; + + void to_hdf5_inner(hid_t group_id) const; + + std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance + int32_t dag_index_; //!< DagMC index of cell +}; + class DAGUniverse : public Universe { public: @@ -26,7 +45,6 @@ public: void initialize(); //!< Sets up the DAGMC instance and OpenMC internals void read_uwuw_materials(); //!< Reads UWUW materials and returns an ID map - bool uses_uwuw() const; int32_t implicit_complement_idx() const; @@ -52,7 +70,9 @@ public: bool adjust_material_ids_; }; +// DAGMC Functions void read_dagmc_universes(pugi::xml_node node); +int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed); } // namespace openmc diff --git a/src/cell.cpp b/src/cell.cpp index ad711573b2..23786727f1 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -825,81 +825,6 @@ CSGCell::contains_complex(Position r, Direction u, int32_t on_surface) const } } -//============================================================================== -// DAGMC Cell implementation -//============================================================================== -#ifdef DAGMC -DAGCell::DAGCell() : Cell{} { - geom_type_ = GeometryType::DAG; - simple_ = true; -}; - -std::pair -DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) const -{ - Expects(p); - // if we've changed direction or we're not on a surface, - // reset the history and update last direction - if (u != p->last_dir()) { p->last_dir() = u; p->history().reset(); } - if (on_surface == 0) { p->history().reset(); } - - const auto& univ = model::universes[p->coord_[p->n_coord_ - 1].universe]; - - DAGUniverse* dag_univ = static_cast(univ.get()); - if (!dag_univ) fatal_error("DAGMC call made for particle in a non-DAGMC universe"); - - moab::ErrorCode rval; - moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); - moab::EntityHandle hit_surf; - double dist; - double pnt[3] = {r.x, r.y, r.z}; - double dir[3] = {u.x, u.y, u.z}; - rval = dagmc_ptr_->ray_fire(vol, pnt, dir, hit_surf, dist, &p->history()); - MB_CHK_ERR_CONT(rval); - int surf_idx; - if (hit_surf != 0) { - surf_idx = dag_univ->surf_idx_offset_ + dagmc_ptr_->index_by_handle(hit_surf); - } else { - // indicate that particle is lost - surf_idx = -1; - dist = INFINITY; - if (!dagmc_ptr_->is_implicit_complement(vol) || model::universe_map[dag_univ->id_] == model::root_universe) { - p->mark_as_lost(fmt::format("No intersection found with DAGMC cell {}", id_)); - } - } - - return {dist, surf_idx}; -} - -bool DAGCell::contains(Position r, Direction u, int32_t on_surface) const -{ - moab::ErrorCode rval; - moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); - - int result = 0; - double pnt[3] = {r.x, r.y, r.z}; - double dir[3] = {u.x, u.y, u.z}; - rval = dagmc_ptr_->point_in_volume(vol, pnt, result, dir); - MB_CHK_ERR_CONT(rval); - return result; -} - -void DAGCell::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "geom_type", "dagmc", false); -} - -BoundingBox DAGCell::bounding_box() const -{ - moab::ErrorCode rval; - moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); - double min[3], max[3]; - rval = dagmc_ptr_->getobb(vol, min, max); - MB_CHK_ERR_CONT(rval); - return {min[0], max[0], min[1], max[1], min[2], max[2]}; -} - -#endif - //============================================================================== // UniversePartitioner implementation //============================================================================== @@ -1356,21 +1281,6 @@ openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end) return 0; } -#ifdef DAGMC -int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed) -{ - moab::EntityHandle surf = - surf_xed->dagmc_ptr_->entity_by_index(2, surf_xed->dag_index_); - moab::EntityHandle vol = - cur_cell->dagmc_ptr_->entity_by_index(3, cur_cell->dag_index_); - - moab::EntityHandle new_vol; - cur_cell->dagmc_ptr_->next_vol(surf, vol, new_vol); - - return cur_cell->dagmc_ptr_->index_by_handle(new_vol) + dag_univ->cell_idx_offset_; -} -#endif - extern "C" int cells_size() { return model::cells.size(); } } // namespace openmc diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 635f05bd88..10d620d7d0 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -7,6 +7,7 @@ #include "openmc/file_utils.h" #include "openmc/geometry.h" #include "openmc/geometry_aux.h" +#include "openmc/hdf5_interface.h" #include "openmc/material.h" #include "openmc/string_utils.h" #include "openmc/settings.h" @@ -489,5 +490,94 @@ DAGUniverse::read_uwuw_materials() { } } + +//============================================================================== +// DAGMC Cell implementation +//============================================================================== + +DAGCell::DAGCell() : Cell{} { + geom_type_ = GeometryType::DAG; + simple_ = true; +}; + +std::pair +DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) const +{ + Expects(p); + // if we've changed direction or we're not on a surface, + // reset the history and update last direction + if (u != p->last_dir_) { p->last_dir_ = u; p->history_.reset(); } + if (on_surface == 0) { p->history_.reset(); } + + const auto& univ = model::universes[p->coord_[p->n_coord_ - 1].universe]; + + DAGUniverse* dag_univ = static_cast(univ.get()); + if (!dag_univ) fatal_error("DAGMC call made for particle in a non-DAGMC universe"); + + moab::ErrorCode rval; + moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); + moab::EntityHandle hit_surf; + double dist; + double pnt[3] = {r.x, r.y, r.z}; + double dir[3] = {u.x, u.y, u.z}; + rval = dagmc_ptr_->ray_fire(vol, pnt, dir, hit_surf, dist, &p->history_); + MB_CHK_ERR_CONT(rval); + int surf_idx; + if (hit_surf != 0) { + surf_idx = dag_univ->surf_idx_offset_ + dagmc_ptr_->index_by_handle(hit_surf); + } else { + // indicate that particle is lost + surf_idx = -1; + dist = INFINITY; + if (!dagmc_ptr_->is_implicit_complement(vol) || model::universe_map[dag_univ->id_] == model::root_universe) { + p->mark_as_lost(fmt::format("No intersection found with DAGMC cell {}", id_)); + } + } + + return {dist, surf_idx}; +} + +bool DAGCell::contains(Position r, Direction u, int32_t on_surface) const +{ + moab::ErrorCode rval; + moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); + + int result = 0; + double pnt[3] = {r.x, r.y, r.z}; + double dir[3] = {u.x, u.y, u.z}; + rval = dagmc_ptr_->point_in_volume(vol, pnt, result, dir); + MB_CHK_ERR_CONT(rval); + return result; +} + +void DAGCell::to_hdf5_inner(hid_t group_id) const { + write_string(group_id, "geom_type", "dagmc", false); +} + +BoundingBox DAGCell::bounding_box() const +{ + moab::ErrorCode rval; + moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); + double min[3], max[3]; + rval = dagmc_ptr_->getobb(vol, min, max); + MB_CHK_ERR_CONT(rval); + return {min[0], max[0], min[1], max[1], min[2], max[2]}; +} + +// DAGMC Functions +int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed) +{ + moab::EntityHandle surf = + surf_xed->dagmc_ptr_->entity_by_index(2, surf_xed->dag_index_); + moab::EntityHandle vol = + cur_cell->dagmc_ptr_->entity_by_index(3, cur_cell->dag_index_); + + moab::EntityHandle new_vol; + cur_cell->dagmc_ptr_->next_vol(surf, vol, new_vol); + + return cur_cell->dagmc_ptr_->index_by_handle(new_vol) + dag_univ->cell_idx_offset_; +} + + } #endif From 9874004e946527969fc5b683f64fd5839804ae98 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 1 Apr 2021 23:27:56 -0500 Subject: [PATCH 54/93] Moving the DAGMC surface implementation into the DAGMC files as well. --- include/openmc/dagmc.h | 16 ++++++++++++ include/openmc/surface.h | 21 --------------- src/dagmc.cpp | 51 +++++++++++++++++++++++++++++++++++++ src/surface.cpp | 55 ---------------------------------------- 4 files changed, 67 insertions(+), 76 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 1dc1c2bc37..c062467c4a 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -19,6 +19,22 @@ class UWUW; namespace openmc { +class DAGSurface : public Surface +{ +public: + DAGSurface(); + + double evaluate(Position r) const; + double distance(Position r, Direction u, bool coincident) const; + Direction normal(Position r) const; + Direction reflect(Position r, Direction u, Particle* p) const; + + inline void to_hdf5_inner(hid_t group_id) const override {}; + + std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance + int32_t dag_index_; //!< DagMC index of surface +}; + class DAGCell : public Cell { public: DAGCell(); diff --git a/include/openmc/surface.h b/include/openmc/surface.h index 2bebdc8ce6..d29bbee086 100644 --- a/include/openmc/surface.h +++ b/include/openmc/surface.h @@ -154,27 +154,6 @@ protected: virtual void to_hdf5_inner(hid_t group_id) const = 0; }; -//============================================================================== -//! A `Surface` representing a DAGMC-based surface in DAGMC. -//============================================================================== -#ifdef DAGMC -class DAGSurface : public Surface -{ -public: - DAGSurface(); - - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - Direction reflect(Position r, Direction u, Particle* p) const; - - inline void to_hdf5_inner(hid_t group_id) const override {}; - - std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance - int32_t dag_index_; //!< DagMC index of surface -}; -#endif - //============================================================================== //! A plane perpendicular to the x-axis. // diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 10d620d7d0..6a81ebd5f7 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -578,6 +578,57 @@ int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed return cur_cell->dagmc_ptr_->index_by_handle(new_vol) + dag_univ->cell_idx_offset_; } +//============================================================================== +// DAGSurface implementation +//============================================================================== +DAGSurface::DAGSurface() : Surface{} { + geom_type_ = GeometryType::DAG; +} // empty constructor + +double DAGSurface::evaluate(Position r) const +{ + return 0.0; +} + +double +DAGSurface::distance(Position r, Direction u, bool coincident) const +{ + moab::ErrorCode rval; + moab::EntityHandle surf = dagmc_ptr_->entity_by_index(2, dag_index_); + moab::EntityHandle hit_surf; + double dist; + double pnt[3] = {r.x, r.y, r.z}; + double dir[3] = {u.x, u.y, u.z}; + rval = dagmc_ptr_->ray_fire(surf, pnt, dir, hit_surf, dist, NULL, 0, 0); + MB_CHK_ERR_CONT(rval); + if (dist < 0.0) dist = INFTY; + return dist; +} + +Direction DAGSurface::normal(Position r) const +{ + moab::ErrorCode rval; + moab::EntityHandle surf = dagmc_ptr_->entity_by_index(2, dag_index_); + double pnt[3] = {r.x, r.y, r.z}; + double dir[3]; + rval = dagmc_ptr_->get_angle(surf, pnt, dir); + MB_CHK_ERR_CONT(rval); + return dir; +} + +Direction DAGSurface::reflect(Position r, Direction u, Particle* p) const +{ + Expects(p); + p->history_.reset_to_last_intersection(); + moab::ErrorCode rval; + moab::EntityHandle surf = dagmc_ptr_->entity_by_index(2, dag_index_); + double pnt[3] = {r.x, r.y, r.z}; + double dir[3]; + rval = dagmc_ptr_->get_angle(surf, pnt, dir, &p->history_); + MB_CHK_ERR_CONT(rval); + p->last_dir_ = u.reflect(dir); + return p->last_dir_; +} } #endif diff --git a/src/surface.cpp b/src/surface.cpp index 92e50a76bb..e0b88d24a5 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -232,61 +232,6 @@ CSGSurface::CSGSurface(pugi::xml_node surf_node) : Surface{surf_node} { geom_type_ = GeometryType::CSG; }; -//============================================================================== -// DAGSurface implementation -//============================================================================== -#ifdef DAGMC -DAGSurface::DAGSurface() : Surface{} { - geom_type_ = GeometryType::DAG; -} // empty constructor - -double DAGSurface::evaluate(Position r) const -{ - return 0.0; -} - -double -DAGSurface::distance(Position r, Direction u, bool coincident) const -{ - moab::ErrorCode rval; - moab::EntityHandle surf = dagmc_ptr_->entity_by_index(2, dag_index_); - moab::EntityHandle hit_surf; - double dist; - double pnt[3] = {r.x, r.y, r.z}; - double dir[3] = {u.x, u.y, u.z}; - rval = dagmc_ptr_->ray_fire(surf, pnt, dir, hit_surf, dist, NULL, 0, 0); - MB_CHK_ERR_CONT(rval); - if (dist < 0.0) dist = INFTY; - return dist; -} - -Direction DAGSurface::normal(Position r) const -{ - moab::ErrorCode rval; - moab::EntityHandle surf = dagmc_ptr_->entity_by_index(2, dag_index_); - double pnt[3] = {r.x, r.y, r.z}; - double dir[3]; - rval = dagmc_ptr_->get_angle(surf, pnt, dir); - MB_CHK_ERR_CONT(rval); - return dir; -} - -Direction DAGSurface::reflect(Position r, Direction u, Particle* p) const -{ - Expects(p); - p->history().reset_to_last_intersection(); - moab::ErrorCode rval; - moab::EntityHandle surf = dagmc_ptr_->entity_by_index(2, dag_index_); - double pnt[3] = {r.x, r.y, r.z}; - double dir[3]; - rval = dagmc_ptr_->get_angle(surf, pnt, dir, &p->history()); - MB_CHK_ERR_CONT(rval); - p->last_dir() = u.reflect(dir); - return p->last_dir(); -} - -#endif - //============================================================================== // Generic functions for x-, y-, and z-, planes. //============================================================================== From 3d8c6a9f4b7200ada54d30b7575624a154fb1a15 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 23 Apr 2021 11:08:48 -0500 Subject: [PATCH 55/93] Some updates from self-review. --- openmc/summary.py | 1 + openmc/universe.py | 2 +- src/cell.cpp | 4 ++-- src/geometry.cpp | 5 ++--- src/material.cpp | 1 - src/particle.cpp | 10 ++++------ tests/regression_tests/dagmc/universes/test.py | 2 +- 7 files changed, 11 insertions(+), 14 deletions(-) diff --git a/openmc/summary.py b/openmc/summary.py index a1ee2dcd66..0af45b7701 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -123,6 +123,7 @@ class Summary: def _read_surfaces(self): for group in self._f['geometry/surfaces'].values(): surface = openmc.Surface.from_hdf5(group) + # surface may be None for DAGMC surfaces if surface: self._fast_surfaces[surface.id] = surface diff --git a/openmc/universe.py b/openmc/universe.py index c246e33bb0..40b7ca70f4 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -638,7 +638,7 @@ class DAGMCUniverse(UniverseBase): Path to the DAGMC file used to represent this universe. universe_id : int, optional Unique identifier of the universe. If not specified, an identifier will - automatically be assigned + automatically be assigned. name : str, optional Name of the universe. If not specified, the name is the empty string. auto_ids : bool diff --git a/src/cell.cpp b/src/cell.cpp index 23786727f1..501fef4957 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -193,6 +193,7 @@ Universe::to_hdf5(hid_t universes_group) const // Create a group for this universe. auto group = create_group(universes_group, fmt::format("universe {}", id_)); + // Write the geometry representation type. switch(type_) { case GeometryType::CSG : write_string(group, "geom_type", "csg", false); @@ -318,7 +319,7 @@ Cell::set_temperature(double T, int32_t instance, bool set_contained) void Cell::to_hdf5(hid_t cell_group) const { - // Create a group for this cell. + // Create a group for this cell. auto group = create_group(cell_group, fmt::format("cell {}", id_)); if (!name_.empty()) { @@ -984,7 +985,6 @@ void read_cells(pugi::xml_node node) model::cells.push_back(make_unique(cell_node)); } - // Fill the cell map. for (int i = 0; i < model::cells.size(); i++) { int32_t id = model::cells[i]->id_; diff --git a/src/geometry.cpp b/src/geometry.cpp index 7e7b3b1729..efa993b061 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -115,9 +115,8 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list) const auto& univ {model::universes[i_universe]}; found = univ->find_cell(p); } - if (!found) { - return found; - } + + if (!found) { return found; } i_cell = p.coord_[p.n_coord_ - 1].cell; // Announce the cell that the particle is entering. diff --git a/src/material.cpp b/src/material.cpp index 3ef8c70c26..4e6dfbdf1b 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -1236,7 +1236,6 @@ void read_materials_xml() for (pugi::xml_node material_node : root.children("material")) { model::materials.push_back(make_unique(material_node)); } - model::materials.shrink_to_fit(); } diff --git a/src/particle.cpp b/src/particle.cpp index 6fc27ebfa8..136963d578 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -392,12 +392,11 @@ Particle::cross_surface() #ifdef DAGMC // in DAGMC, we know what the next cell should be - auto surfp = dynamic_cast(model::surfaces[std::abs(surface_) - 1].get()); - if (surfp) { + if (surf->geom_type_ == GeometryType::DAG) { + auto surfp = dynamic_cast(surf); auto cellp = dynamic_cast(model::cells[cell_last_[n_coord_ - 1]].get()); - // TODO: off-by-one auto univp = static_cast(model::universes[coord_[n_coord_ - 1].universe].get()); - + // determine the next cell for this crossing int32_t i_cell = next_cell(univp, cellp, surfp) - 1; // save material and temp material_last_ = material_; @@ -505,9 +504,8 @@ Particle::cross_reflective_bc(const Surface& surf, Direction new_u) coord(0).cell = cell_last(n_coord_last() - 1); surface() = -surface(); - #ifdef DAGMC + // if we're crossing a CSG surface, make sure the DAG history is reset if (surf.geom_type_ != GeometryType::DAG) history_.reset(); - #endif // If a reflective surface is coincident with a lattice or universe // boundary, it is necessary to redetermine the particle's coordinates in diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index 2ae2b0e9f2..d94f6fe011 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -66,6 +66,6 @@ class DAGMCUniverseTest(PyAPITestHarness): model.export_to_xml() -def test_dagmc_universes(): +def test_univ(): harness = DAGMCUniverseTest('statepoint.10.h5') harness.main() \ No newline at end of file From c38b30221d030e8cdb633c88a94e96450f9b639e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 23 Apr 2021 11:18:47 -0500 Subject: [PATCH 56/93] Re-adding ifdef cause I'm a dummy. --- src/particle.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/particle.cpp b/src/particle.cpp index 136963d578..2f0f52e63d 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -505,7 +505,9 @@ Particle::cross_reflective_bc(const Surface& surf, Direction new_u) surface() = -surface(); // if we're crossing a CSG surface, make sure the DAG history is reset + #ifdef DAGMC if (surf.geom_type_ != GeometryType::DAG) history_.reset(); + #endif // If a reflective surface is coincident with a lattice or universe // boundary, it is necessary to redetermine the particle's coordinates in From 400f3e9334780ea527a7a9320a6830e41d1f5e64 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 23 Apr 2021 12:20:42 -0500 Subject: [PATCH 57/93] More updates from self review. Moving check for BCs into geometry_aux. --- src/geometry_aux.cpp | 15 +++++++++++++++ src/surface.cpp | 17 ----------------- tests/regression_tests/dagmc/universes/test.py | 2 +- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index d45cdcb23a..80741b3e78 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -66,6 +66,21 @@ void read_geometry_xml() read_cells(root); read_lattices(root); + // Check to make sure a boundary condition was applied to at least one + // surface + bool boundary_exists = false; + for (const auto& surf : model::surfaces) { + if (surf->bc_) { + boundary_exists = true; + break; + } + } + + if (settings::run_mode != RunMode::PLOTTING && !boundary_exists) { + fatal_error("No boundary conditions were applied to any surfaces!"); + } + + // Allocate universes, universe cell arrays, and assign base universe model::root_universe = find_root_universe(); } diff --git a/src/surface.cpp b/src/surface.cpp index e0b88d24a5..8c1ed51d19 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -1133,23 +1133,6 @@ void read_surfaces(pugi::xml_node node) surf2.bc_ = surf1.bc_; } } - - // Check to make sure a boundary condition was applied to at least one - // surface - bool boundary_exists = false; - for (const auto& surf : model::surfaces) { - if (surf->bc_) { - boundary_exists = true; - break; - } - } - // if (settings::run_mode != RunMode::PLOTTING && !boundary_exists) { - // fatal_error("No boundary conditions were applied to any surfaces!"); - // } - - // if (model::surfaces.size() == 0) { - // fatal_error("No surfaces found in geometry.xml!"); - // } } void free_memory_surfaces() diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index d94f6fe011..cc407aa5ec 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -68,4 +68,4 @@ class DAGMCUniverseTest(PyAPITestHarness): def test_univ(): harness = DAGMCUniverseTest('statepoint.10.h5') - harness.main() \ No newline at end of file + harness.main() From ec7595261fc592742c6af127e58d90b24c97903d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 23 Apr 2021 12:42:13 -0500 Subject: [PATCH 58/93] Adding doc strings to the dagmc header. --- include/openmc/dagmc.h | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index c062467c4a..5f58fb902a 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -58,35 +58,52 @@ public: explicit DAGUniverse(pugi::xml_node node); explicit DAGUniverse(const std::string& filename, bool auto_geom_ids = false); - void initialize(); //!< Sets up the DAGMC instance and OpenMC internals + //! Initialize the DAGMC accel. data structures, indices, material assignments, etc. + void initialize(); - void read_uwuw_materials(); //!< Reads UWUW materials and returns an ID map + //! Reads UWUW materials and returns an ID map + void read_uwuw_materials(); + //! Indicates whether or not UWUW materials are present + //! \return True if UWUW materials are present, False if not bool uses_uwuw() const; + //! Returns the index to the implicit complement's index in OpenMC for this DAGMC universe int32_t implicit_complement_idx() const; + //! Transform UWUW materials into an OpenMC-readable XML format + //! \return A string representing a materials.xml file of the UWUW materials in this universe std::string get_uwuw_materials_xml() const; + //! Writes the UWUW material file to XML (for debugging purposes) void write_uwuw_materials_xml(const std::string& outfile = "uwuw_materials.xml") const; + //! Assign a material to a cell based + //! \param[in] mat_string The DAGMC material assignment string + //! \param[in] c The OpenMC cell to which the material is assigned void legacy_assign_material(std::string mat_string, std::unique_ptr& c) const; + //! Generate a string representing the ranges of IDs present in the DAGMC model + //! \param[in] dim Dimension of the entities + //! \return A string of the ID ranges for entities of dimension \p dim std::string dagmc_ids_for_dim(int dim) const; virtual bool find_cell(Particle &p) const override; // Data Members - std::string filename_; - std::shared_ptr dagmc_instance_; //! DAGMC Instance for this universe - std::shared_ptr uwuw_; - int32_t cell_idx_offset_; - int32_t surf_idx_offset_; - bool adjust_geometry_ids_; - bool adjust_material_ids_; + std::string filename_; //!< Name of the DAGMC file used to create this universe + std::shared_ptr dagmc_instance_; //!< DAGMC Instance for this universe + std::shared_ptr uwuw_; //!< Pointer to the UWUW instance for this universe + int32_t cell_idx_offset_; //!< An offset to the start of the cells in this universe in OpenMC's cell vector + int32_t surf_idx_offset_; //!< An offset to the start of the surfaces in this universe in OpenMC's surface vector + bool adjust_geometry_ids_; //!< Indicates whether or not to automatically generate new cell and surface IDs for the universe + bool adjust_material_ids_; //!< Indicates whether or not to automatically generate new material IDs for the universe }; -// DAGMC Functions +//============================================================================== +// Non-member functions +//============================================================================== + void read_dagmc_universes(pugi::xml_node node); int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed); From d0f32b80e0711f9cd24ad633a50027cf305a4502 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 23 Apr 2021 14:48:48 -0500 Subject: [PATCH 59/93] Updating formatting and a small refactor for the dagmc_filename function. --- include/openmc/dagmc.h | 10 +- src/dagmc.cpp | 398 +++++++++++++++++++++-------------------- 2 files changed, 212 insertions(+), 196 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 5f58fb902a..6d44f9e1b5 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -55,8 +55,16 @@ public: class DAGUniverse : public Universe { public: + explicit DAGUniverse(pugi::xml_node node); - explicit DAGUniverse(const std::string& filename, bool auto_geom_ids = false); + + //! Create a new DAGMC universe + //! \param[in] filename Name of the DAGMC file + //! \param[in] auto_geom_ids Whether or not to automatically assign cell and surface IDs + //! \param[in] auto_mat_ids Whether or not to automatically assign material IDs + explicit DAGUniverse(const std::string& filename, + bool auto_geom_ids = false, + bool auto_mat_ids = false); //! Initialize the DAGMC accel. data structures, indices, material assignments, etc. void initialize(); diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 6a81ebd5f7..ce750a4e6d 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -1,6 +1,5 @@ #include "openmc/dagmc.h" -#include "openmc/cell.h" #include "openmc/constants.h" #include "openmc/container_util.h" #include "openmc/error.h" @@ -11,7 +10,6 @@ #include "openmc/material.h" #include "openmc/string_utils.h" #include "openmc/settings.h" -#include "openmc/surface.h" #ifdef DAGMC #include "uwuw.hpp" @@ -38,173 +36,9 @@ const bool DAGMC_ENABLED = false; namespace openmc { -const std::string DAGMC_FILENAME = "dagmc.h5m"; - -std::string dagmc_file() { - std::string filename = settings::path_input + DAGMC_FILENAME; - if (!file_exists(filename)) { - fatal_error("Geometry DAGMC file '" + filename + "' does not exist!"); - } - return filename; -} - -std::string -DAGUniverse::dagmc_ids_for_dim(int dim) const -{ - // generate a vector of ids - std::vector id_vec; - int n_cells = dagmc_instance_->num_entities(dim); - for (int i = 1; i <= n_cells; i++) { - id_vec.push_back(dagmc_instance_->id_by_index(dim, i)); - } - - // sort the vector of ids - std::sort(id_vec.begin(), id_vec.end()); - - // generate a string representation of the range - std::stringstream out; - - int i = 0; - int start_id = id_vec[0]; - int stop_id; - while (i < n_cells) { - stop_id = id_vec[i]; - - if (id_vec[i + 1] > stop_id + 1) { - if (start_id != stop_id) { - // there are several IDs in a row, print condensed version - out << start_id << "-" << stop_id; - } else { - // only one ID in this contiguous block - out << start_id; - } - if (i < n_cells - 1) { out << ", "; } - start_id = id_vec[++i]; - stop_id = start_id; - } - - i++; - } - - return out.str(); -} - -int32_t -DAGUniverse::implicit_complement_idx() const { - moab::EntityHandle ic; - moab::ErrorCode rval = dagmc_instance_->geom_tool()->get_implicit_complement(ic); - MB_CHK_SET_ERR_CONT(rval, "Failed to get implicit complement"); - return cell_idx_offset_ + dagmc_instance_->index_by_handle(ic) - 1; -} - -bool -DAGUniverse::find_cell(Particle &p) const { - // if the particle isn't in any of the other DagMC - // cells, place it in the implicit complement - bool found = Universe::find_cell(p); - if (!found && model::universe_map[this->id_] != model::root_universe) { - p.coord_[p.n_coord_ - 1].cell = implicit_complement_idx(); - found = true; - } - return found; -} - -bool -DAGUniverse::uses_uwuw() const -{ - return uwuw_ && !uwuw_->material_library.empty(); -} - -std::string -DAGUniverse::get_uwuw_materials_xml() const -{ - - if (!uses_uwuw()) { - throw std::runtime_error("This DAGMC Universe does not use UWUW materials"); - } - - std::stringstream ss; - // write header - ss << "\n"; - ss << "\n"; - const auto& mat_lib = uwuw_->material_library; - // write materials - for (auto mat : mat_lib) { ss << mat.second->openmc("atom"); } - // write footer - ss << ""; - - return ss.str(); -} - -void -DAGUniverse::write_uwuw_materials_xml(const std::string& outfile) const -{ - if (!uses_uwuw()) { - throw std::runtime_error("This DAGMC universe does not use UWUW materials."); - } - - std::string xml_str = get_uwuw_materials_xml(); - // if there is a material library in the file - std::ofstream mats_xml(outfile); - mats_xml << xml_str; - mats_xml.close(); -} - -void -DAGUniverse::legacy_assign_material(std::string mat_string, - std::unique_ptr& c) const -{ - bool mat_found_by_name = false; - // attempt to find a material with a matching name - to_lower(mat_string); - for (const auto& m : model::materials) { - std::string m_name = m->name(); - to_lower(m_name); - if (mat_string == m_name) { - // assign the material with that name - if (!mat_found_by_name) { - mat_found_by_name = true; - c->material_.push_back(m->id_); - // report error if more than one material is found - } else { - fatal_error(fmt::format( - "More than one material found with name '{}'. Please ensure materials " - "have unique names if using this property to assign materials.", - mat_string)); - } - } - } - - // if no material was set using a name, assign by id - if (!mat_found_by_name) { - try { - auto id = std::stoi(mat_string); - c->material_.emplace_back(id); - } catch (const std::invalid_argument&) { - fatal_error(fmt::format( - "No material '{}' found for volume (cell) {}", mat_string, c->id_)); - } - } - - if (settings::verbosity >= 10) { - const auto& m = model::materials[model::material_map.at(c->material_[0])]; - std::stringstream msg; - msg << "DAGMC material " << mat_string << " was assigned"; - if (mat_found_by_name) { - msg << " using material name: " << m->name_; - } else { - msg << " using material id: " << m->id_; - } - write_message(msg.str(), 10); - } -} - -void read_dagmc_universes(pugi::xml_node node) { - for (pugi::xml_node dag_node : node.children("dagmc")) { - model::universes.push_back(std::make_unique(dag_node)); - model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; - } -} +//============================================================================== +// DAGMC Universe implementation +//============================================================================== DAGUniverse::DAGUniverse(pugi::xml_node node) { if (check_for_node(node, "id")) { @@ -232,8 +66,10 @@ DAGUniverse::DAGUniverse(pugi::xml_node node) { initialize(); } -DAGUniverse::DAGUniverse(const std::string& filename, bool auto_geom_ids) -: filename_(filename), adjust_geometry_ids_(auto_geom_ids) { +DAGUniverse::DAGUniverse(const std::string& filename, + bool auto_geom_ids, + bool auto_mat_ids) +: filename_(filename), adjust_geometry_ids_(auto_geom_ids), adjust_material_ids_(auto_mat_ids) { // determine the next universe id int32_t next_univ_id = 0; for (const auto& u : model::universes) { @@ -247,7 +83,8 @@ DAGUniverse::DAGUniverse(const std::string& filename, bool auto_geom_ids) initialize(); } -void DAGUniverse::initialize() { +void +DAGUniverse::initialize() { type_ = GeometryType::DAG; // determine the next cell id @@ -283,6 +120,10 @@ void DAGUniverse::initialize() { } // load the DAGMC geometry + filename_ = settings::path_input + filename_; + if (!file_exists(filename_)) { + fatal_error("Geometry DAGMC file '" + filename_ + "' does not exist!"); + } moab::ErrorCode rval = dagmc_instance_->load_file(filename_.c_str()); MB_CHK_ERR_CONT(rval); @@ -325,7 +166,7 @@ void DAGUniverse::initialize() { "and the CSG geometry.", c->id_, this->id_)); } - // MATERIALS + // --- Materials --- // determine volume material assignment std::string mat_str = DMD.get_volume_property("material", vol_handle); @@ -447,10 +288,160 @@ void DAGUniverse::initialize() { } model::surfaces.emplace_back(std::move(s)); - } // end surface loop } +std::string +DAGUniverse::dagmc_ids_for_dim(int dim) const +{ + // generate a vector of ids + std::vector id_vec; + int n_cells = dagmc_instance_->num_entities(dim); + for (int i = 1; i <= n_cells; i++) { + id_vec.push_back(dagmc_instance_->id_by_index(dim, i)); + } + + // sort the vector of ids + std::sort(id_vec.begin(), id_vec.end()); + + // generate a string representation of the ID range(s) + std::stringstream out; + + int i = 0; + int start_id = id_vec[0]; + int stop_id; + while (i < n_cells) { + stop_id = id_vec[i]; + + if (id_vec[i + 1] > stop_id + 1) { + if (start_id != stop_id) { + // there are several IDs in a row, print condensed version + out << start_id << "-" << stop_id; + } else { + // only one ID in this contiguous block + out << start_id; + } + if (i < n_cells - 1) { out << ", "; } + start_id = id_vec[++i]; + stop_id = start_id; + } + + i++; + } + + return out.str(); +} + +int32_t +DAGUniverse::implicit_complement_idx() const { + moab::EntityHandle ic; + moab::ErrorCode rval = dagmc_instance_->geom_tool()->get_implicit_complement(ic); + MB_CHK_SET_ERR_CONT(rval, "Failed to get implicit complement"); + // off-by-one: DAGMC indices start at one + return cell_idx_offset_ + dagmc_instance_->index_by_handle(ic) - 1; +} + +bool +DAGUniverse::find_cell(Particle &p) const { + // if the particle isn't in any of the other DagMC + // cells, place it in the implicit complement + bool found = Universe::find_cell(p); + if (!found && model::universe_map[this->id_] != model::root_universe) { + p.coord_[p.n_coord_ - 1].cell = implicit_complement_idx(); + found = true; + } + return found; +} + +bool +DAGUniverse::uses_uwuw() const +{ + return !uwuw_->material_library.empty(); +} + +std::string +DAGUniverse::get_uwuw_materials_xml() const +{ + if (!uses_uwuw()) { + throw std::runtime_error("This DAGMC Universe does not use UWUW materials"); + } + + std::stringstream ss; + // write header + ss << "\n"; + ss << "\n"; + const auto& mat_lib = uwuw_->material_library; + // write materials + for (auto mat : mat_lib) { ss << mat.second->openmc("atom"); } + // write footer + ss << ""; + + return ss.str(); +} + +void +DAGUniverse::write_uwuw_materials_xml(const std::string& outfile) const +{ + if (!uses_uwuw()) { + throw std::runtime_error("This DAGMC universe does not use UWUW materials."); + } + + std::string xml_str = get_uwuw_materials_xml(); + // if there is a material library in the file + std::ofstream mats_xml(outfile); + mats_xml << xml_str; + mats_xml.close(); +} + +void +DAGUniverse::legacy_assign_material(std::string mat_string, + std::unique_ptr& c) const +{ + bool mat_found_by_name = false; + // attempt to find a material with a matching name + to_lower(mat_string); + for (const auto& m : model::materials) { + std::string m_name = m->name(); + to_lower(m_name); + if (mat_string == m_name) { + // assign the material with that name + if (!mat_found_by_name) { + mat_found_by_name = true; + c->material_.push_back(m->id_); + // report error if more than one material is found + } else { + fatal_error(fmt::format( + "More than one material found with name '{}'. Please ensure materials " + "have unique names if using this property to assign materials.", + mat_string)); + } + } + } + + // if no material was set using a name, assign by id + if (!mat_found_by_name) { + try { + auto id = std::stoi(mat_string); + c->material_.emplace_back(id); + } catch (const std::invalid_argument&) { + fatal_error(fmt::format( + "No material '{}' found for volume (cell) {}", mat_string, c->id_)); + } + } + + if (settings::verbosity >= 10) { + const auto& m = model::materials[model::material_map.at(c->material_[0])]; + std::stringstream msg; + msg << "DAGMC material " << mat_string << " was assigned"; + if (mat_found_by_name) { + msg << " using material name: " << m->name_; + } else { + msg << " using material id: " << m->id_; + } + write_message(msg.str(), 10); + } +} + void DAGUniverse::read_uwuw_materials() { @@ -490,7 +481,6 @@ DAGUniverse::read_uwuw_materials() { } } - //============================================================================== // DAGMC Cell implementation //============================================================================== @@ -537,7 +527,8 @@ DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) cons return {dist, surf_idx}; } -bool DAGCell::contains(Position r, Direction u, int32_t on_surface) const +bool +DAGCell::contains(Position r, Direction u, int32_t on_surface) const { moab::ErrorCode rval; moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); @@ -550,11 +541,13 @@ bool DAGCell::contains(Position r, Direction u, int32_t on_surface) const return result; } -void DAGCell::to_hdf5_inner(hid_t group_id) const { +void +DAGCell::to_hdf5_inner(hid_t group_id) const { write_string(group_id, "geom_type", "dagmc", false); } -BoundingBox DAGCell::bounding_box() const +BoundingBox +DAGCell::bounding_box() const { moab::ErrorCode rval; moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); @@ -564,28 +557,16 @@ BoundingBox DAGCell::bounding_box() const return {min[0], max[0], min[1], max[1], min[2], max[2]}; } -// DAGMC Functions -int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed) -{ - moab::EntityHandle surf = - surf_xed->dagmc_ptr_->entity_by_index(2, surf_xed->dag_index_); - moab::EntityHandle vol = - cur_cell->dagmc_ptr_->entity_by_index(3, cur_cell->dag_index_); - - moab::EntityHandle new_vol; - cur_cell->dagmc_ptr_->next_vol(surf, vol, new_vol); - - return cur_cell->dagmc_ptr_->index_by_handle(new_vol) + dag_univ->cell_idx_offset_; -} - //============================================================================== // DAGSurface implementation //============================================================================== + DAGSurface::DAGSurface() : Surface{} { geom_type_ = GeometryType::DAG; } // empty constructor -double DAGSurface::evaluate(Position r) const +double +DAGSurface::evaluate(Position r) const { return 0.0; } @@ -605,7 +586,8 @@ DAGSurface::distance(Position r, Direction u, bool coincident) const return dist; } -Direction DAGSurface::normal(Position r) const +Direction +DAGSurface::normal(Position r) const { moab::ErrorCode rval; moab::EntityHandle surf = dagmc_ptr_->entity_by_index(2, dag_index_); @@ -616,7 +598,8 @@ Direction DAGSurface::normal(Position r) const return dir; } -Direction DAGSurface::reflect(Position r, Direction u, Particle* p) const +Direction +DAGSurface::reflect(Position r, Direction u, Particle* p) const { Expects(p); p->history_.reset_to_last_intersection(); @@ -630,5 +613,30 @@ Direction DAGSurface::reflect(Position r, Direction u, Particle* p) const return p->last_dir_; } +//============================================================================== +// Non-member functions +//============================================================================== + +void read_dagmc_universes(pugi::xml_node node) { + for (pugi::xml_node dag_node : node.children("dagmc")) { + model::universes.push_back(std::make_unique(dag_node)); + model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; + } +} + +int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed) +{ + moab::EntityHandle surf = + surf_xed->dagmc_ptr_->entity_by_index(2, surf_xed->dag_index_); + moab::EntityHandle vol = + cur_cell->dagmc_ptr_->entity_by_index(3, cur_cell->dag_index_); + + moab::EntityHandle new_vol; + cur_cell->dagmc_ptr_->next_vol(surf, vol, new_vol); + + return cur_cell->dagmc_ptr_->index_by_handle(new_vol) + dag_univ->cell_idx_offset_; +} + + } #endif From b466941b78cd39969747db87779278dfd78137fe Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 27 Apr 2021 15:57:01 -0500 Subject: [PATCH 60/93] Correction to attribute setting in constructor. --- src/dagmc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index ce750a4e6d..ac3edb7da9 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -60,7 +60,7 @@ DAGUniverse::DAGUniverse(pugi::xml_node node) { adjust_material_ids_ = false; if (check_for_node(node, "auto_mat_ids")) { - adjust_geometry_ids_ = get_node_value_bool(node, "auto_mat_ids"); + adjust_material_ids_ = get_node_value_bool(node, "auto_mat_ids"); } initialize(); From bf1a2435ea4f83b93b1a9098f9577c79ad956824 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 28 Apr 2021 12:36:42 -0500 Subject: [PATCH 61/93] Assign material IDs as int instead of string. --- src/dagmc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index ac3edb7da9..34917a562a 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -458,7 +458,7 @@ DAGUniverse::read_uwuw_materials() { // if we're using automatic IDs, update the UWUW material metadata if (adjust_material_ids_) { for (auto& mat : uwuw_->material_library) { - mat.second->metadata["mat_number"] = std::to_string(next_material_id++); + mat.second->metadata["mat_number"] = next_material_id++; } } From 3b9f9fa1bd4ea544b63f2ac00e22d52db9fdcf20 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 28 Apr 2021 12:36:58 -0500 Subject: [PATCH 62/93] Correction to doc strings and auto_mat_ids setter. --- openmc/universe.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index 40b7ca70f4..333441a8e5 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -641,9 +641,12 @@ class DAGMCUniverse(UniverseBase): automatically be assigned. name : str, optional Name of the universe. If not specified, the name is the empty string. - auto_ids : bool + auto_geom_ids : bool Set IDs automatically on initialization (True) or report overlaps in ID space between CSG and DAGMC (False) + auto_mat_ids : bool + Set IDs automatically on initialization (True) or report overlaps + in ID space between OpenMC and UWUW materials (False) Attributes ---------- @@ -702,7 +705,7 @@ class DAGMCUniverse(UniverseBase): def auto_mat_ids(self): return self._auto_mat_ids - @auto_geom_ids.setter + @auto_mat_ids.setter def auto_mat_ids(self, val): cv.check_type('DAGMC automatic material ids', val, bool) self._auto_mat_ids = val From d1a24339dad1852339c579b123faa437b9647569 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 28 Apr 2021 12:37:49 -0500 Subject: [PATCH 63/93] Updating expected inputs for the DAGMC reflecting BC and universe tests. --- tests/regression_tests/dagmc/refl/inputs_true.dat | 2 +- tests/regression_tests/dagmc/universes/inputs_true.dat | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/dagmc/refl/inputs_true.dat b/tests/regression_tests/dagmc/refl/inputs_true.dat index ca3cba5f04..4ac926e5ec 100644 --- a/tests/regression_tests/dagmc/refl/inputs_true.dat +++ b/tests/regression_tests/dagmc/refl/inputs_true.dat @@ -1,6 +1,6 @@ - + diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat index 3113159393..6c0fa8ccd9 100644 --- a/tests/regression_tests/dagmc/universes/inputs_true.dat +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -1,7 +1,7 @@ - + From 9ffbf02f4028027567567683a8e0b61696292c13 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 5 May 2021 23:15:49 -0500 Subject: [PATCH 64/93] Addressing comments from @makeclean. --- include/openmc/dagmc.h | 4 +++- include/openmc/surface.h | 2 +- openmc/universe.py | 1 - src/cell.cpp | 1 - src/dagmc.cpp | 24 ++++++++++++++++-------- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 6d44f9e1b5..6e292488a0 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -91,7 +91,9 @@ public: void legacy_assign_material(std::string mat_string, std::unique_ptr& c) const; - //! Generate a string representing the ranges of IDs present in the DAGMC model + //! Generate a string representing the ranges of IDs present in the DAGMC model. + //! Contiguous chunks of IDs are represented as a range (i.e. 1-10). If there is + //! a single ID a chunk, it will be represented as a single number (i.e. 2, 4, 6, 8). //! \param[in] dim Dimension of the entities //! \return A string of the ID ranges for entities of dimension \p dim std::string dagmc_ids_for_dim(int dim) const; diff --git a/include/openmc/surface.h b/include/openmc/surface.h index d29bbee086..5d747b4894 100644 --- a/include/openmc/surface.h +++ b/include/openmc/surface.h @@ -30,7 +30,7 @@ namespace model { } // namespace model //============================================================================== -//! Coordinates for an axis-aligned cube that bounds a geometric object. +//! Coordinates for an axis-aligned cuboid that bounds a geometric object. //============================================================================== struct BoundingBox diff --git a/openmc/universe.py b/openmc/universe.py index 333441a8e5..8a12d1160f 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -720,7 +720,6 @@ class DAGMCUniverse(UniverseBase): return OrderedDict() def create_xml_subelement(self, xml_element, memo=None): - if memo and self in memo: return diff --git a/src/cell.cpp b/src/cell.cpp index 501fef4957..b85e4fd569 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -328,7 +328,6 @@ Cell::to_hdf5(hid_t cell_group) const { write_dataset(group, "universe", model::universes[universe_]->id_); - to_hdf5_inner(group); // Write fill information. diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 34917a562a..5254035794 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -296,8 +296,8 @@ DAGUniverse::dagmc_ids_for_dim(int dim) const { // generate a vector of ids std::vector id_vec; - int n_cells = dagmc_instance_->num_entities(dim); - for (int i = 1; i <= n_cells; i++) { + int n_ents = dagmc_instance_->num_entities(dim); + for (int i = 1; i <= n_ents; i++) { id_vec.push_back(dagmc_instance_->id_by_index(dim, i)); } @@ -308,22 +308,30 @@ DAGUniverse::dagmc_ids_for_dim(int dim) const std::stringstream out; int i = 0; - int start_id = id_vec[0]; + int start_id = id_vec[0]; // initialize with first ID int stop_id; - while (i < n_cells) { + // loop over all cells in the universe + while (i < n_ents) { + stop_id = id_vec[i]; + // if the next ID is not in this contiguous set of IDS, + // figure out how to write the string representing this set if (id_vec[i + 1] > stop_id + 1) { + if (start_id != stop_id) { - // there are several IDs in a row, print condensed version + // there are several IDs in a row, print condensed version (i.e. 1-10, 12-20) out << start_id << "-" << stop_id; } else { - // only one ID in this contiguous block + // only one ID in this contiguous block (i.e. 3, 5, 7, 9) out << start_id; } - if (i < n_cells - 1) { out << ", "; } + // insert a comma as long as we aren't in the last ID set + if (i < n_ents - 1) { out << ", "; } + + // if we are at the end of a set, set the start ID to the first value + // in the next set. start_id = id_vec[++i]; - stop_id = start_id; } i++; From a4fa21eea54ca66879978a6a3cdfe5cb325772b6 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 5 May 2021 23:17:28 -0500 Subject: [PATCH 65/93] Fixing rotation test. --- tests/regression_tests/rotation/geometry.xml | 11 +++++ tests/regression_tests/rotation/materials.xml | 14 +++++++ tests/regression_tests/rotation/settings.xml | 15 +++++++ tests/regression_tests/rotation/test.py | 40 ++----------------- 4 files changed, 43 insertions(+), 37 deletions(-) create mode 100644 tests/regression_tests/rotation/geometry.xml create mode 100644 tests/regression_tests/rotation/materials.xml create mode 100644 tests/regression_tests/rotation/settings.xml diff --git a/tests/regression_tests/rotation/geometry.xml b/tests/regression_tests/rotation/geometry.xml new file mode 100644 index 0000000000..f324617065 --- /dev/null +++ b/tests/regression_tests/rotation/geometry.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tests/regression_tests/rotation/materials.xml b/tests/regression_tests/rotation/materials.xml new file mode 100644 index 0000000000..160c9c6789 --- /dev/null +++ b/tests/regression_tests/rotation/materials.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tests/regression_tests/rotation/settings.xml b/tests/regression_tests/rotation/settings.xml new file mode 100644 index 0000000000..70b4e802f8 --- /dev/null +++ b/tests/regression_tests/rotation/settings.xml @@ -0,0 +1,15 @@ + + + + eigenvalue + 10 + 5 + 1000 + + + + -4 -4 -4 4 4 4 + + + + diff --git a/tests/regression_tests/rotation/test.py b/tests/regression_tests/rotation/test.py index 6b68367b40..31c3d8d655 100644 --- a/tests/regression_tests/rotation/test.py +++ b/tests/regression_tests/rotation/test.py @@ -1,40 +1,6 @@ -import openmc -import pytest - -from tests.testing_harness import TestHarness, PyAPITestHarness - -@pytest.fixture -def model(): - model = openmc.model.Model() - - fuel = openmc.Material() - fuel.set_density('g/cc', 10.0) - fuel.add_nuclide('U235', 1.0) - - h1 = openmc.Material() - h1.set_density('g/cc', 0.1) - h1.add_nuclide('H1', 0.1) - - outer_sphere = openmc.Sphere(r=10.0, boundary_type='vacuum') - inner_sphere = openmc.Sphere(x0=1.0, r=5.0) - - fuel_cell = openmc.Cell(fill=fuel, region=-inner_sphere) - hydrogen_cell = openmc.Cell(fill=h1, region=+inner_sphere) - univ = openmc.Universe(cells=[fuel_cell, hydrogen_cell]) - outer_cell = openmc.Cell(fill=univ, region=-outer_sphere) - outer_cell.rotation = (10, 20, 30) - - model.geometry = openmc.Geometry(root=[outer_cell]) - - model.settings.particles = 1000 - model.settings.inactive = 5 - model.settings.batches = 10 - source_box = openmc.stats.Box((-4., -4., -4.), (4., 4., 4.)) - model.settings.source = openmc.Source(space=source_box) - - return model +from tests.testing_harness import TestHarness -def test_rotation(model): - harness = PyAPITestHarness('statepoint.10.h5', model) +def test_rotation(): + harness = TestHarness('statepoint.10.h5') harness.main() From a754f34e606db9ba4eb4b79dfdc2dd8510fa2e9c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 6 May 2021 11:48:08 -0500 Subject: [PATCH 66/93] Updating the CAD notebook to remove . --- examples/jupyter/cad-based-geometry.ipynb | 139 +++++++++++----------- 1 file changed, 69 insertions(+), 70 deletions(-) diff --git a/examples/jupyter/cad-based-geometry.ipynb b/examples/jupyter/cad-based-geometry.ipynb index 4c950b744b..bfd03c7745 100644 --- a/examples/jupyter/cad-based-geometry.ipynb +++ b/examples/jupyter/cad-based-geometry.ipynb @@ -184,7 +184,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQAgMAAAD90d5fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACVBMVEX///8AAP///wCN6GYzAAAAAWJLR0QAiAUdSAAAAAd0SU1FB+UFBgYlBxXMycsAAAWvSURBVHja7Z3NddswEISjA0pgPyqBB9MHlsB+UgIPUpV5tmPiRwSwfxg6CPacvC87M4D0InL3169Ro0aNGjVq1KhRP7Buy2fdGyKm5ai3Rgi3RDU3bqNZM8tJIRjWlOkcYqpYhmFKcUu2ZivGbSnU3QiyFMuGMZUhJrbclkpZCFZjWAjm6pAZ0Ii+FUIj6laqrlt4P9EgqhgTG9G1QnJE6wqVoQkYuRFNK3SGvBVGI/JWJg5EmGJyfr/q3l4tqV48hsx6ZiOyVli2S63nMiR6ZdR6fpaVXmdqvT+P+m2h19kh2Z5BPU7+wF2v1jMpvV5TlXFCYer1qtb2CnlVjKeXIzBOKDy9UrXW52ntKr3y2Y0rTbJGrS0HSQXj6JWotT6zlQjG0aua3myO6YwkwFsJkgh2F1ry/ixW7D3dlIneSNoK3RROI2krMku2GiRuhWqKYzWStEI1ZWI1krRCNYV8Rk7PisCSlQKJjj3NFMdtJG6FZkpoCcH21HqaKUzbX6xnW0JjxHpRTAktIdmeWk8xZeKrFetFMYVve2o9zxKyWrFedVOcRK1Yr7opk0itSK+6KZNIrUivOkSmVqwXx3cOIzqPNeedUK1Ir5rzk1CtSK+aKZNUrVCvGkQY4I8KQkz2nWlJZErZ+cB3piWRKTMVwmWEppQh3ne2JaEpZecVlkSmECFsSyJTiOHiM0JTSvHyvgssCU0pOe99F1gSmvJGgggsCU0pQXSWhKZQICJLQlMo4RJZEpqSj5ezg8wEyCaDPAgQHy4ZI3A+Hy+t7yTntZaEpjQLFyVeHrJJIY8qxIdLygicn2sQse+B8znIZAl5q0FWOWSvQfS+h843C1c9Xh4iZwTxOodYhKsaLwjEIlzVeB2QTQN5/ACISbiCeF0GOY6JKlxBvO4lyKqD7CWIs4bMJcimgzxKEJsEVzJ8QHQMH6/LIEYJDjJ8EcTqmBQPChayaSGPPMTqLBZP4wHRMnyGL4KYncXSafyGqI+JPygXQcyOSXBQ+oXYHfjCkcdC9Ax/UC6BGN4q+XvlG2JwFv1pvARieKvk75VvyGoB2buHGF5d+cvL8FYJ7pXuIRYMf680vB9zN2R/EJOry19eF0BMb/rcXd8fZLWB7AOih5h+MOY+GqGQzQbyGJAB6RGytIEspxAbRuaL14AMyIAMyIAMyIAMyIBgvtxNbSC9fuEekP8cstpA9usgrg1kHhA9pJ//F24K6edXh/5+CWoKgfwE2OEvphDIagHZMxDTj8bzD8YeIU0fKTG9689vejCk6QNL/Tzf1c8zd/08B4mBGN4ruVsFDGn6ULLhvZK7VdCQTcsoPPIOeXi/n3cd+nn/pKN3gg7IpmMUX6GyOo3Fl8EOyKqD7CUI5AU9yKuG/byZ2dHbsgdk1UD2MuQ4KP/8u9iQV9chL+FDxglgBiMckJYjHiziVQkXaOwGZIAIZBQKZKgLZjzNkeGWg3Z8vDYZgzIyyGlN2QkQyBgnyEAqzGgtH69NwqANCZt0puwkiNOZ4i2ZCxDICDrIMD3MWEDvfMMBh975hqMaAwjbFPLQScj4TMggUMxI0wDCNIUxnDVwnmlKYMlcgUAG5kJG/2KGGAeQduOYnUwv3mBpyIhsyLBvzNhyJ9ErVKtuCWiUPGQoPma8v+PrFf4NiiWglQuQ5RGYNRiRKa0WekBWk0CWrGDWxThOK3EjVEtAK3wgy4gwa5Vc8u/LCqZZEAVZdYVZ2pXq1WT9GGSRGmQlHGa5HWRNH2ThIGZ1ImQJJGadpeNCBGphVoxilqVC1r5CFthiVvFClgpj1iNDFj1jVlZDlm9D1ohjFqJDVrtjltRTWlE3QmlFz6h7fzeA1GKsiy9RMBtGWTATsT6qkLDZilGwxciQIsWUkTPflnFOsWacKGas1VclGZtbMOJmmrTxt27GJ3DUqFGjRo0aNWqUZf0BnVivRTb4g0AAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjEtMDUtMDZUMTE6Mzc6MDctMDU6MDBpKI5GAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIxLTA1LTA2VDExOjM3OjA3LTA1OjAwGHU2+gAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] @@ -290,13 +290,13 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2020 MIT and OpenMC contributors\n", + " Copyright | 2011-2021 MIT and OpenMC contributors\n", " License | https://docs.openmc.org/en/latest/license.html\n", - " Version | 0.12.1-dev\n", - " Git SHA1 | 9fb298b039bcd447c1a745cd9fea47f0d04eebdf\n", - " Date/Time | 2021-03-04 13:23:02\n", + " Version | 0.13.0-dev\n", + " Git SHA1 | c3d81b5ac372c1412d112070c0f9120b7e3c9162\n", + " Date/Time | 2021-05-06 11:37:07\n", " MPI Processes | 1\n", - " OpenMP Threads | 4\n", + " OpenMP Threads | 2\n", "\n", " Reading settings XML file...\n", " Reading cross sections XML file...\n", @@ -309,59 +309,59 @@ "Using faceting tolerance: 0.0001\n", "Building acceleration data structures...\n", "Implicit Complement assumed to be Vacuum\n", - " Reading U235 from /home/shriwise/opt/openmc/xs/nndc_hdf5/U235.h5\n", - " Reading H1 from /home/shriwise/opt/openmc/xs/nndc_hdf5/H1.h5\n", - " Reading O16 from /home/shriwise/opt/openmc/xs/nndc_hdf5/O16.h5\n", - " Reading c_H_in_H2O from /home/shriwise/opt/openmc/xs/nndc_hdf5/c_H_in_H2O.h5\n", + " Reading U235 from /home/shriwise/opt/openmc/xs/endfb80_hdf5/U235.h5\n", + " Reading H1 from /home/shriwise/opt/openmc/xs/endfb80_hdf5/H1.h5\n", + " Reading O16 from /home/shriwise/opt/openmc/xs/endfb80_hdf5/O16.h5\n", + " Reading c_H_in_H2O from /home/shriwise/opt/openmc/xs/endfb80_hdf5/c_H_in_H2O.h5\n", " Minimum neutron data temperature: 294.0 K\n", " Maximum neutron data temperature: 294.0 K\n", " Reading tallies XML file...\n", " Preparing distributed cell instances...\n", " Writing summary.h5 file...\n", - " Maximum neutron transport energy: 20000000.0 eV for U235\n", + " Maximum neutron transport energy: 20000000.0 eV for H1\n", " Initializing source particles...\n", "\n", " ====================> K EIGENVALUE SIMULATION <====================\n", "\n", " Bat./Gen. k Average k\n", " ========= ======== ====================\n", - " 1/1 1.15789\n", - " 2/1 1.05169\n", - " 3/1 1.00736\n", - " 4/1 0.97863 0.99300 +/- 0.01436\n", - " 5/1 0.95316 0.97972 +/- 0.01566\n", - " 6/1 0.95079 0.97248 +/- 0.01322\n", - " 7/1 0.96879 0.97175 +/- 0.01027\n", - " 8/1 0.94253 0.96688 +/- 0.00970\n", - " 9/1 0.97406 0.96790 +/- 0.00826\n", - " 10/1 0.97362 0.96862 +/- 0.00719\n", + " 1/1 1.16335\n", + " 2/1 1.03688\n", + " 3/1 0.99328\n", + " 4/1 0.97507 0.98417 +/- 0.00911\n", + " 5/1 0.98174 0.98336 +/- 0.00532\n", + " 6/1 0.97979 0.98247 +/- 0.00387\n", + " 7/1 0.97215 0.98040 +/- 0.00364\n", + " 8/1 0.96031 0.97705 +/- 0.00448\n", + " 9/1 0.95999 0.97462 +/- 0.00450\n", + " 10/1 0.95588 0.97227 +/- 0.00455\n", " Creating state point statepoint.10.h5...\n", "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 1.1835e+00 seconds\n", - " Reading cross sections = 1.3664e-01 seconds\n", - " Total time in simulation = 1.0779e+01 seconds\n", - " Time in transport only = 1.0771e+01 seconds\n", - " Time in inactive batches = 1.6833e+00 seconds\n", - " Time in active batches = 9.0961e+00 seconds\n", - " Time synchronizing fission bank = 4.0641e-03 seconds\n", - " Sampling source sites = 3.6309e-03 seconds\n", - " SEND/RECV source sites = 3.4735e-04 seconds\n", - " Time accumulating tallies = 4.9789e-05 seconds\n", - " Time writing statepoints = 2.9456e-03 seconds\n", - " Total time for finalization = 6.8913e-05 seconds\n", - " Total time elapsed = 1.2048e+01 seconds\n", - " Calculation Rate (inactive) = 5940.54 particles/second\n", - " Calculation Rate (active) = 4397.49 particles/second\n", + " Total time for initialization = 5.5283e+00 seconds\n", + " Reading cross sections = 5.4196e+00 seconds\n", + " Total time in simulation = 2.5960e+00 seconds\n", + " Time in transport only = 2.5805e+00 seconds\n", + " Time in inactive batches = 4.9064e-01 seconds\n", + " Time in active batches = 2.1054e+00 seconds\n", + " Time synchronizing fission bank = 9.9395e-03 seconds\n", + " Sampling source sites = 5.0143e-03 seconds\n", + " SEND/RECV source sites = 7.6818e-04 seconds\n", + " Time accumulating tallies = 4.0849e-05 seconds\n", + " Time writing statepoints = 2.5422e-03 seconds\n", + " Total time for finalization = 9.8980e-05 seconds\n", + " Total time elapsed = 8.1568e+00 seconds\n", + " Calculation Rate (inactive) = 20381.7 particles/second\n", + " Calculation Rate (active) = 18998.8 particles/second\n", "\n", " ============================> RESULTS <============================\n", "\n", - " k-effective (Collision) = 0.97020 +/- 0.00750\n", - " k-effective (Track-length) = 0.96862 +/- 0.00719\n", - " k-effective (Absorption) = 0.95742 +/- 0.00791\n", - " Combined k-effective = 0.96203 +/- 0.00898\n", - " Leakage Fraction = 0.57677 +/- 0.00317\n", + " k-effective (Collision) = 0.97074 +/- 0.00589\n", + " k-effective (Track-length) = 0.97227 +/- 0.00455\n", + " k-effective (Absorption) = 0.96869 +/- 0.00491\n", + " Combined k-effective = 0.97175 +/- 0.00373\n", + " Leakage Fraction = 0.57322 +/- 0.00242\n", "\n" ] } @@ -455,7 +455,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAcIAAAEsAgMAAAAtOFskAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACVBMVEX///+AgIAAAP8RXFShAAAAAWJLR0QAiAUdSAAAAAd0SU1FB+UDBAcYHabNLxMAAAa1SURBVHja7Zy7ltsgEEBNQZ+G/1GTnkKk2E/w/7hJr0L5ynglIfEWMA/n5DDFeu2z4jIPBjEa7+MxZMiQIUOGDBkyZMiQIUOGDBkyZMiQdhHmkJkbyIZUF9FMPCrOiV8pRToUYViI2nnDQ5ycN+o/JWrnDYtVhUtkiVUxp38nFMeSnoXpRE2pXynFUYwlcFznMbnR0YzJjZ8gnvHCFDiOakyBcwUMW+CcurG58fQfmxvPDYtlqzqIenthC5xzw+ILnIPlbZSDOIiDuMmewhkT+QdyznFsVJpNReO/Mqhod2TDpKQ6z+KK51Su3FM5B1IZ99zBgFQ+Q5Ejo4LKG6kJeTJRwfmu7lDxRLpkpKhqV3ttLKc5PnMbNesxk51Nt6gbNQR2ka7CbKJkgx4NK9wk8LSsTiwKyZcNmQwH2ZStFcYqkU3xgKFk07RRtq+mdCIwVgi3jt/JpuEoLH9CF6VoTJjwpK6mtu1v20BBBYl5G6V+BPU9O8h5ZLtW/mwgKjvPTtmqKKJFxw0GqLpsl7YTZeaCiplsMZM8tGXG3P82Uz2reeS0HxOdcHdAP5Jjlo6y8t6/h3bO8pjKFxxZP3OUrTj8HXNtSJXHn6aJFUbtrmYmx645xOdi7laSQVkz/+51lZxqTfLDJdak5+5slVoeNW7sr9ckibrvukpJzLUmcAC3LAliJnCcdgbQ7YPKf/Qji8Mm2lC9DBfxQMT4Ult1OokyBgJur+MFaQP/DCBlcIk6/MTqZueS0hByFxgvLDuHw97CYBOja61upmBT0AkiIlrd5rxNsYmH8rqgIuj8oDIf7O5MexGZOLvGlRTE8GJL3H5mgKDzdZgCbPCaklFhRB0QtQPOGRV0DAxTgCVqNuJh5V31TEoFPnoP5muJ20smPIHPwdLELYSvwPERQB2DuFPOi7gMmZpVr6jk2w0iM3FCQnQWx3x3SasEE54j4u0kUYh7NKrMxgQsIgahHhETlwALpT7RbsQnMTE69CGxf/3B302t0kYFPwjPEw0H0Wvoyey9wOUYxPrHiKZEBPdQeQO4KSdLBAKTzcNFovkDlEVHo61F4i8ocdXRaMdH/wpRfEGJf+ZotIWfOBWIEk50GxWeFcQnmPj6JFF5n6SJCgy0GjmL+yCmdytc4q8KIjjluElHHERTIoITgJsC7FKb2Yg2DEtEhATgpAAVE2daovGVlskjAAbRJh0bOGXiE4H4CqbvEg0pUR3EpUS0voYRjxRgjsFsSkj2MiGknJMgjP+enmiNWiYiJIDrJuNprXyulkQKQCTKM0UzELdFZ6xRfWKwIFFSzp505GnU6zZEkRG/EeYy1+wSDQ1Rvwc/VbyIMg5WlLT6Jr7FiYgi8dlNceX1Hvh65+zQiQoZGtEZKCDOFMTFBboHkZiIkuQi/uQRDStRRaETEVcCohc6CHersbwuooyIKGk1Ij584sxJjFvUSIiuTlFR/ouFqDmJKnAkCdGrfYSFay6is1woiF4NSwSORErkAdHLasEDCBLiyyMq35E0RG+vCBxJQjQJ4ulIks3K34GF70gG4sN/+khB9JbjGTqakLgERP8BHQlx8onCMyvFZvUKiA/vuS4JMQAejpzpiHFxwzUrAXGNi1SuWSmIOiTargAq4hIT1WVWQUCMQtV7SE9xCxCFqmdWCmLqSbU6Y4eAGIeqZ1YCYiJwrv6OiYKYCJzLkTMFMd3OIK2S+MQ1TbRm1fi3q0umncE26lyVNCx56UfRrPjEXLOfoCKu2T4YRURcdI4oiYiFDkoa4lpoLlIkxNzacGIHmVhsS92JuDvyWuzYkgTEV7l/Cp+43vT6KnTijYp77GAS19sm8U1JTBVvO/0ELnGp6INXqMSa/unvBfLEs+l0T3wgEpe69mmJl+buw8YqiUWsbfSXeMQ6oPcEDyRrlRe3BYJF1LVEgbQgw4pKyaxPFOKrnojS8pA+puai9QuF2NCujVMJqA/VB27PQ2XoYBCXFiJqtwxf6DT1+fMTMYK1KVSRuxC5QqcpcLB7dHkc2ehG7A52Fkc2uhHBkc3f84E6stmNYEc2u9Fp5es0aqsb344EmXXt+LoW7IZuaXcj8IYuV20smxXiyK7vwEHM2mVUkFm7jApaH53f1+5fHz1rYzdrtxv7jArYP5r3jdOsvY7s/n5o7/7RsW9Y6SX2uvETxM7mh4bT+D9AfEaj/a5o9OxeHF4zeIPU1sZSIjoqnwvsvyc017DXVM9/myebHrn4rUwQNXcp+fR1/hVIwcuZ1YL173RlJQ8Jd4oqsCZs2JAhQ4YMGXLJX9ZWayALnJC6AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIxLTAzLTA0VDEzOjI0OjI5LTA2OjAwOR6icAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMS0wMy0wNFQxMzoyNDoyOS0wNjowMEhDGswAAAAASUVORK5CYII=\n", + "image/png": "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\n", "text/plain": [ "" ] @@ -489,7 +489,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "" ] @@ -521,7 +521,6 @@ "outputs": [], "source": [ "settings = openmc.Settings()\n", - "settings.dagmc = True\n", "settings.batches = 10\n", "settings.particles = 5000\n", "settings.run_mode = \"fixed source\"\n", @@ -620,13 +619,13 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2020 MIT and OpenMC contributors\n", + " Copyright | 2011-2021 MIT and OpenMC contributors\n", " License | https://docs.openmc.org/en/latest/license.html\n", - " Version | 0.12.1-dev\n", - " Git SHA1 | 9fb298b039bcd447c1a745cd9fea47f0d04eebdf\n", - " Date/Time | 2021-03-04 13:25:29\n", + " Version | 0.13.0-dev\n", + " Git SHA1 | c3d81b5ac372c1412d112070c0f9120b7e3c9162\n", + " Date/Time | 2021-05-06 11:37:35\n", " MPI Processes | 1\n", - " OpenMP Threads | 4\n", + " OpenMP Threads | 2\n", "\n", " Reading settings XML file...\n", " Reading cross sections XML file...\n", @@ -639,19 +638,19 @@ "Using faceting tolerance: 0.001\n", "Building acceleration data structures...\n", "Implicit Complement assumed to be Vacuum\n", - " Reading Fe54 from /home/shriwise/opt/openmc/xs/nndc_hdf5/Fe54.h5\n", - " Reading Fe56 from /home/shriwise/opt/openmc/xs/nndc_hdf5/Fe56.h5\n", - " Reading Fe57 from /home/shriwise/opt/openmc/xs/nndc_hdf5/Fe57.h5\n", - " Reading Fe58 from /home/shriwise/opt/openmc/xs/nndc_hdf5/Fe58.h5\n", - " Reading H1 from /home/shriwise/opt/openmc/xs/nndc_hdf5/H1.h5\n", - " Reading O16 from /home/shriwise/opt/openmc/xs/nndc_hdf5/O16.h5\n", - " Reading c_H_in_H2O from /home/shriwise/opt/openmc/xs/nndc_hdf5/c_H_in_H2O.h5\n", + " Reading Fe54 from /home/shriwise/opt/openmc/xs/endfb80_hdf5/Fe54.h5\n", + " Reading Fe56 from /home/shriwise/opt/openmc/xs/endfb80_hdf5/Fe56.h5\n", + " Reading Fe57 from /home/shriwise/opt/openmc/xs/endfb80_hdf5/Fe57.h5\n", + " Reading Fe58 from /home/shriwise/opt/openmc/xs/endfb80_hdf5/Fe58.h5\n", + " Reading H1 from /home/shriwise/opt/openmc/xs/endfb80_hdf5/H1.h5\n", + " Reading O16 from /home/shriwise/opt/openmc/xs/endfb80_hdf5/O16.h5\n", + " Reading c_H_in_H2O from /home/shriwise/opt/openmc/xs/endfb80_hdf5/c_H_in_H2O.h5\n", " Minimum neutron data temperature: 294.0 K\n", " Maximum neutron data temperature: 294.0 K\n", " Reading tallies XML file...\n", " Preparing distributed cell instances...\n", " Writing summary.h5 file...\n", - " Maximum neutron transport energy: 20000000.0 eV for Fe58\n", + " Maximum neutron transport energy: 20000000.0 eV for H1\n", "\n", " ===============> FIXED SOURCE TRANSPORT SIMULATION <===============\n", "\n", @@ -669,20 +668,20 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 5.6350e+01 seconds\n", - " Reading cross sections = 6.7418e-01 seconds\n", - " Total time in simulation = 1.0014e+02 seconds\n", - " Time in transport only = 1.0013e+02 seconds\n", - " Time in active batches = 1.0014e+02 seconds\n", - " Time accumulating tallies = 4.0980e-04 seconds\n", - " Time writing statepoints = 5.3643e-03 seconds\n", - " Total time for finalization = 1.9142e-02 seconds\n", - " Total time elapsed = 1.5651e+02 seconds\n", - " Calculation Rate (active) = 499.320 particles/second\n", + " Total time for initialization = 7.8856e+00 seconds\n", + " Reading cross sections = 3.6158e+00 seconds\n", + " Total time in simulation = 3.9350e+01 seconds\n", + " Time in transport only = 3.9334e+01 seconds\n", + " Time in active batches = 3.9350e+01 seconds\n", + " Time accumulating tallies = 1.1706e-02 seconds\n", + " Time writing statepoints = 3.4045e-03 seconds\n", + " Total time for finalization = 1.0902e-01 seconds\n", + " Total time elapsed = 4.7351e+01 seconds\n", + " Calculation Rate (active) = 1270.66 particles/second\n", "\n", " ============================> RESULTS <============================\n", "\n", - " Leakage Fraction = 0.62594 +/- 0.00117\n", + " Leakage Fraction = 0.62666 +/- 0.00245\n", "\n" ] } @@ -727,7 +726,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 21, @@ -736,7 +735,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] From ff69f5a07a1437afb763f77b4c125263e39f570e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 19 May 2021 20:33:34 -0500 Subject: [PATCH 67/93] Fixing dagmc header includes after rebase. --- include/openmc/surface.h | 1 - src/surface.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/include/openmc/surface.h b/include/openmc/surface.h index 5d747b4894..b3f2bdfad6 100644 --- a/include/openmc/surface.h +++ b/include/openmc/surface.h @@ -8,7 +8,6 @@ #include "hdf5.h" #include "pugixml.hpp" -#include "dagmc.h" #include "openmc/boundary_condition.h" #include "openmc/constants.h" #include "openmc/memory.h" // for unique_ptr diff --git a/src/surface.cpp b/src/surface.cpp index 8c1ed51d19..20aadc6e83 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -9,7 +9,6 @@ #include "openmc/array.h" #include "openmc/container_util.h" -#include "openmc/dagmc.h" #include "openmc/error.h" #include "openmc/hdf5_interface.h" #include "openmc/math_functions.h" From 618efbe9a777f2835a78d7a0c36e0e32d3981af0 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 19 May 2021 20:33:59 -0500 Subject: [PATCH 68/93] Using ParticleData accessors where needed. --- src/cell.cpp | 6 +++--- src/dagmc.cpp | 18 +++++++++--------- src/geometry.cpp | 2 +- src/particle.cpp | 22 +++++++++++----------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/cell.cpp b/src/cell.cpp index b85e4fd569..c58fb17679 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -223,15 +223,15 @@ Universe::find_cell(Particle& p) const { for (auto it = cells.begin(); it != cells.end(); it++) { int32_t i_cell = *it; - int32_t i_univ = p.coord_[p.n_coord_-1].universe; + int32_t i_univ = p.coord(p.n_coord()-1).universe; if (model::cells[i_cell]->universe_ != i_univ) continue; // Check if this cell contains the particle; Position r {p.r_local()}; Direction u {p.u_local()}; - auto surf = p.surface_; + auto surf = p.surface(); if (model::cells[i_cell]->contains(r, u, surf)) { - p.coord_[p.n_coord_-1].cell = i_cell; + p.coord(p.n_coord()-1).cell = i_cell; return true; } } diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 5254035794..5932e04a12 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -355,7 +355,7 @@ DAGUniverse::find_cell(Particle &p) const { // cells, place it in the implicit complement bool found = Universe::find_cell(p); if (!found && model::universe_map[this->id_] != model::root_universe) { - p.coord_[p.n_coord_ - 1].cell = implicit_complement_idx(); + p.coord(p.n_coord() - 1).cell = implicit_complement_idx(); found = true; } return found; @@ -504,10 +504,10 @@ DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) cons Expects(p); // if we've changed direction or we're not on a surface, // reset the history and update last direction - if (u != p->last_dir_) { p->last_dir_ = u; p->history_.reset(); } - if (on_surface == 0) { p->history_.reset(); } + if (u != p->last_dir()) { p->last_dir() = u; p->history().reset(); } + if (on_surface == 0) { p->history().reset(); } - const auto& univ = model::universes[p->coord_[p->n_coord_ - 1].universe]; + const auto& univ = model::universes[p->coord(p->n_coord() - 1).universe]; DAGUniverse* dag_univ = static_cast(univ.get()); if (!dag_univ) fatal_error("DAGMC call made for particle in a non-DAGMC universe"); @@ -518,7 +518,7 @@ DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) cons double dist; double pnt[3] = {r.x, r.y, r.z}; double dir[3] = {u.x, u.y, u.z}; - rval = dagmc_ptr_->ray_fire(vol, pnt, dir, hit_surf, dist, &p->history_); + rval = dagmc_ptr_->ray_fire(vol, pnt, dir, hit_surf, dist, &p->history()); MB_CHK_ERR_CONT(rval); int surf_idx; if (hit_surf != 0) { @@ -610,15 +610,15 @@ Direction DAGSurface::reflect(Position r, Direction u, Particle* p) const { Expects(p); - p->history_.reset_to_last_intersection(); + p->history().reset_to_last_intersection(); moab::ErrorCode rval; moab::EntityHandle surf = dagmc_ptr_->entity_by_index(2, dag_index_); double pnt[3] = {r.x, r.y, r.z}; double dir[3]; - rval = dagmc_ptr_->get_angle(surf, pnt, dir, &p->history_); + rval = dagmc_ptr_->get_angle(surf, pnt, dir, &p->history()); MB_CHK_ERR_CONT(rval); - p->last_dir_ = u.reflect(dir); - return p->last_dir_; + p->last_dir() = u.reflect(dir); + return p->last_dir(); } //============================================================================== diff --git a/src/geometry.cpp b/src/geometry.cpp index efa993b061..c93e1940b6 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -117,7 +117,7 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list) } if (!found) { return found; } - i_cell = p.coord_[p.n_coord_ - 1].cell; + i_cell = p.coord(p.n_coord() - 1).cell; // Announce the cell that the particle is entering. if (found && (settings::verbosity >= 10 || p.trace())) { diff --git a/src/particle.cpp b/src/particle.cpp index 2f0f52e63d..de1b2431fe 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -288,7 +288,7 @@ Particle::event_collide() if (!model::active_tallies.empty()) score_collision_derivative(*this); #ifdef DAGMC - history_.reset(); + history().reset(); #endif } @@ -323,7 +323,7 @@ void Particle::event_death() { #ifdef DAGMC - history_.reset(); + history().reset(); #endif // Finish particle track output. @@ -394,18 +394,18 @@ Particle::cross_surface() // in DAGMC, we know what the next cell should be if (surf->geom_type_ == GeometryType::DAG) { auto surfp = dynamic_cast(surf); - auto cellp = dynamic_cast(model::cells[cell_last_[n_coord_ - 1]].get()); - auto univp = static_cast(model::universes[coord_[n_coord_ - 1].universe].get()); + auto cellp = dynamic_cast(model::cells[cell_last(n_coord() - 1)].get()); + auto univp = static_cast(model::universes[coord(n_coord() - 1).universe].get()); // determine the next cell for this crossing int32_t i_cell = next_cell(univp, cellp, surfp) - 1; // save material and temp - material_last_ = material_; - sqrtkT_last_ = sqrtkT_; + material_last() = material(); + sqrtkT_last() = sqrtkT(); // set new cell value - coord_[n_coord_ - 1].cell = i_cell; - cell_instance_ = 0; - material_ = model::cells[i_cell]->material_[0]; - sqrtkT_ = model::cells[i_cell]->sqrtkT_[0]; + coord(n_coord() - 1).cell = i_cell; + cell_instance() = 0; + material() = model::cells[i_cell]->material_[0]; + sqrtkT() = model::cells[i_cell]->sqrtkT_[0]; return; } #endif @@ -506,7 +506,7 @@ Particle::cross_reflective_bc(const Surface& surf, Direction new_u) // if we're crossing a CSG surface, make sure the DAG history is reset #ifdef DAGMC - if (surf.geom_type_ != GeometryType::DAG) history_.reset(); + if (surf.geom_type_ != GeometryType::DAG) history().reset(); #endif // If a reflective surface is coincident with a lattice or universe From e244b8f0cf64635204ca0bd5945752a7c699dd2c Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 19 May 2021 20:34:43 -0500 Subject: [PATCH 69/93] Resetting rotation test results to match upstream after PRN update. --- tests/regression_tests/rotation/results_true.dat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/rotation/results_true.dat b/tests/regression_tests/rotation/results_true.dat index a58aa1c8ec..f4a3cfcccb 100644 --- a/tests/regression_tests/rotation/results_true.dat +++ b/tests/regression_tests/rotation/results_true.dat @@ -1,2 +1,2 @@ k-combined: -4.453328E-01 5.918369E-03 +4.132181E-01 1.130226E-02 From 9779906d0188265412a3ed74c6287c4a95cbb041 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 19 May 2021 20:35:40 -0500 Subject: [PATCH 70/93] Updating the DAGMC universes test result for the PRN update. --- tests/regression_tests/dagmc/universes/results_true.dat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/dagmc/universes/results_true.dat b/tests/regression_tests/dagmc/universes/results_true.dat index 203d35efeb..c9e1bc8fa5 100644 --- a/tests/regression_tests/dagmc/universes/results_true.dat +++ b/tests/regression_tests/dagmc/universes/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.531408E-01 1.260163E-02 +7.687742E-01 3.415061E-02 From 0d6bc863311c0092fc0a07d2ed50177909bc35ab Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 25 May 2021 09:21:00 -0500 Subject: [PATCH 71/93] Moving history reset on CSG surface crossing to correct location after rebase. --- src/particle.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/particle.cpp b/src/particle.cpp index de1b2431fe..8abe2d9c68 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -381,6 +381,12 @@ Particle::cross_surface() int64_t idx = simulation::surf_source_bank.thread_safe_append(site); } + // if we're crossing a CSG surface, make sure the DAG history is reset + #ifdef DAGMC + if (surf->geom_type_ != GeometryType::DAG) history().reset(); + #endif + + // Handle any applicable boundary conditions. if (surf->bc_ && settings::run_mode != RunMode::PLOTTING) { surf->bc_->handle_particle(*this, *surf); @@ -504,11 +510,6 @@ Particle::cross_reflective_bc(const Surface& surf, Direction new_u) coord(0).cell = cell_last(n_coord_last() - 1); surface() = -surface(); - // if we're crossing a CSG surface, make sure the DAG history is reset - #ifdef DAGMC - if (surf.geom_type_ != GeometryType::DAG) history().reset(); - #endif - // If a reflective surface is coincident with a lattice or universe // boundary, it is necessary to redetermine the particle's coordinates in // the lower universes. From a7dab4e68c022b039b0f4f8ca2b3e58c4b74aa59 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 25 Jun 2021 06:39:49 -0500 Subject: [PATCH 72/93] Adding comment on DAGMC indices. --- src/dagmc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 5932e04a12..1132681a5b 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -245,7 +245,7 @@ DAGUniverse::initialize() { // set cell ids using global IDs auto s = std::make_unique(); - s->dag_index_ = i+1; + s->dag_index_ = i+1; // DAGMC indices start at 1 s->id_ = adjust_geometry_ids_ ? next_surf_id++ : dagmc_instance_->id_by_index(2, i+1); s->dagmc_ptr_ = dagmc_instance_; From fbcaf5acd8db43707ea6b6f430d1f2ba240ca6d4 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 25 Jun 2021 07:45:02 -0500 Subject: [PATCH 73/93] Apply PR suggestions from @paulromano Co-authored-by: Paul Romano --- docs/source/usersguide/geometry.rst | 6 +++--- include/openmc/cell.h | 2 +- include/openmc/dagmc.h | 21 +++++++++---------- openmc/universe.py | 5 ++--- src/particle.cpp | 1 - src/surface.cpp | 3 +-- tests/regression_tests/dagmc/legacy/test.py | 2 +- tests/regression_tests/dagmc/refl/test.py | 2 +- .../regression_tests/dagmc/universes/test.py | 2 +- 9 files changed, 20 insertions(+), 24 deletions(-) diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index 4df3681a53..2b6a6fef2f 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -443,7 +443,7 @@ entirely by a DAGMC geometry will contain only the DAGMC universe. Using a :class:`openmc.DAGMCUniverse` looks like the following:: dag_univ = openmc.DAGMCUniverse(filename='dagmc.h5m') - geometry = openmc.Geometry(root=dag_univ) + geometry = openmc.Geometry(dag_univ) geometry.export_to_xml() The resulting ``geometry.xml`` file will be: @@ -475,7 +475,7 @@ Cell, Surface, and Material IDs ------------------------------- By default, DAGMC applies cell and surface IDs defined by the CAD engine that -the model originated in. If these IDs overlap with ID's in the CSG ID space, +the model originated in. If these IDs overlap with IDs in the CSG ID space, this will result in an error. However, the ``auto_ids`` property of a DAGMC universe can be set to set DAGMC cell and surface IDs by appending to the existing CSG cell ID space in the OpenMC model. @@ -485,7 +485,7 @@ assignments are based on natively defined OpenMC materials, no further work is required. If DAGMC materials are assigned using the `University of Wisconsin Unified Workflow`_ (UWUW), however, material IDs in the UWUW material library may overlap with those used in the CSG geometry. In this case, overlaps in the -UWUW and OpenMC material ID space will cause an error. To automatically resolved +UWUW and OpenMC material ID space will cause an error. To automatically resolve these ID overlaps, ``auto_ids`` can be set to ``True`` to append the UWUW material IDs to the OpenMC material ID space. diff --git a/include/openmc/cell.h b/include/openmc/cell.h index ad17b6f78b..f04f9f6b76 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -231,7 +231,7 @@ public: std::pair distance(Position r, Direction u, int32_t on_surface, Particle* p) const; - void to_hdf5_inner(hid_t group_id) const; + void to_hdf5_inner(hid_t group_id) const override; BoundingBox bounding_box() const; diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 6e292488a0..1369424e73 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -19,15 +19,14 @@ class UWUW; namespace openmc { -class DAGSurface : public Surface -{ +class DAGSurface : public Surface { public: DAGSurface(); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - Direction reflect(Position r, Direction u, Particle* p) const; + double evaluate(Position r) const override; + double distance(Position r, Direction u, bool coincident) const override; + Direction normal(Position r) const override; + Direction reflect(Position r, Direction u, Particle* p) const override; inline void to_hdf5_inner(hid_t group_id) const override {}; @@ -39,14 +38,14 @@ class DAGCell : public Cell { public: DAGCell(); - bool contains(Position r, Direction u, int32_t on_surface) const; + bool contains(Position r, Direction u, int32_t on_surface) const override; std::pair - distance(Position r, Direction u, int32_t on_surface, Particle* p) const; + distance(Position r, Direction u, int32_t on_surface, Particle* p) const override; - BoundingBox bounding_box() const; + BoundingBox bounding_box() const override; - void to_hdf5_inner(hid_t group_id) const; + void to_hdf5_inner(hid_t group_id) const override; std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance int32_t dag_index_; //!< DagMC index of cell @@ -98,7 +97,7 @@ public: //! \return A string of the ID ranges for entities of dimension \p dim std::string dagmc_ids_for_dim(int dim) const; - virtual bool find_cell(Particle &p) const override; + bool find_cell(Particle &p) const override; // Data Members std::string filename_; //!< Name of the DAGMC file used to create this universe diff --git a/openmc/universe.py b/openmc/universe.py index 8a12d1160f..d5d015eba5 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -677,10 +677,9 @@ class DAGMCUniverse(UniverseBase): self.auto_mat_ids = auto_mat_ids def __repr__(self): - fmt_str = '{: <16}=\t{}\n' string = super().__repr__() - string += fmt_str.format('\tGeom', 'DAGMC') - string += fmt_str.format('\tFile', self.filename) + string += '{: <16}=\t{}\n'.format('\tGeom', 'DAGMC') + string += '{: <16}=\t{}\n'.format('\tFile', self.filename) return string @property diff --git a/src/particle.cpp b/src/particle.cpp index 8abe2d9c68..6acd989faa 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -386,7 +386,6 @@ Particle::cross_surface() if (surf->geom_type_ != GeometryType::DAG) history().reset(); #endif - // Handle any applicable boundary conditions. if (surf->bc_ && settings::run_mode != RunMode::PLOTTING) { surf->bc_->handle_particle(*this, *surf); diff --git a/src/surface.cpp b/src/surface.cpp index 20aadc6e83..1de606198a 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -204,8 +204,7 @@ Surface::to_hdf5(hid_t group_id) const if (geom_type_ == GeometryType::DAG) { write_string(surf_group, "geom_type", "dagmc", false); - } - else if (geom_type_ == GeometryType::CSG) { + } else if (geom_type_ == GeometryType::CSG) { write_string(surf_group, "geom_type", "csg", false); if (bc_) { diff --git a/tests/regression_tests/dagmc/legacy/test.py b/tests/regression_tests/dagmc/legacy/test.py index 76b76fbda0..e0fccb9344 100644 --- a/tests/regression_tests/dagmc/legacy/test.py +++ b/tests/regression_tests/dagmc/legacy/test.py @@ -28,7 +28,7 @@ def model(): # geometry dag_univ = openmc.DAGMCUniverse("dagmc.h5m") - model.geometry = openmc.Geometry(root=dag_univ) + model.geometry = openmc.Geometry(dag_univ) # tally tally = openmc.Tally() diff --git a/tests/regression_tests/dagmc/refl/test.py b/tests/regression_tests/dagmc/refl/test.py index 2f4162b16a..3fe41345cf 100644 --- a/tests/regression_tests/dagmc/refl/test.py +++ b/tests/regression_tests/dagmc/refl/test.py @@ -29,7 +29,7 @@ class UWUWTest(PyAPITestHarness): # geometry dag_univ = openmc.DAGMCUniverse("dagmc.h5m", auto_geom_ids=True) - model.geometry = openmc.Geometry(root=dag_univ) + model.geometry = openmc.Geometry(dag_univ) # tally tally = openmc.Tally() diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index cc407aa5ec..1458462c48 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -55,7 +55,7 @@ class DAGMCUniverseTest(PyAPITestHarness): bounding_cell = openmc.Cell(fill=pincell_univ, region=box) - model.geometry = openmc.Geometry(root=[bounding_cell]) + model.geometry = openmc.Geometry([bounding_cell]) # settings model.settings.particles = 100 From 5e4aef6cb05eb87845cb30c68a19134d3fd7d732 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 25 Jun 2021 07:21:33 -0500 Subject: [PATCH 74/93] Removing virtual on Cell::to_hdf5. --- include/openmc/cell.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index f04f9f6b76..8bcc1ea067 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -121,7 +121,7 @@ public: //! Write all information needed to reconstruct the cell to an HDF5 group. //! \param group_id An HDF5 group id. - virtual void to_hdf5(hid_t group_id) const; + void to_hdf5(hid_t group_id) const; virtual void to_hdf5_inner(hid_t group_id) const = 0; From 1a839061d4d7a758656af5b489a60e715cf13928 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 25 Jun 2021 07:22:20 -0500 Subject: [PATCH 75/93] Making DAGMC geom class attrs private where possible and adding accessors. --- include/openmc/dagmc.h | 24 ++++++++++++++++++------ src/dagmc.cpp | 27 +++++++++++++-------------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 1369424e73..591ea64748 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -21,7 +21,7 @@ namespace openmc { class DAGSurface : public Surface { public: - DAGSurface(); + DAGSurface(std::shared_ptr dag_ptr, int32_t dag_idx); double evaluate(Position r) const override; double distance(Position r, Direction u, bool coincident) const override; @@ -30,13 +30,18 @@ public: inline void to_hdf5_inner(hid_t group_id) const override {}; + // Accessor methods + const std::shared_ptr& dagmc_ptr() const { return dagmc_ptr_; } + int32_t dag_index() const { return dag_index_; } + +private: std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance - int32_t dag_index_; //!< DagMC index of surface + int32_t dag_index_; //!< DagMC index of surface }; class DAGCell : public Cell { public: - DAGCell(); + DAGCell(std::shared_ptr dag_ptr, int32_t dag_idx); bool contains(Position r, Direction u, int32_t on_surface) const override; @@ -47,8 +52,13 @@ public: void to_hdf5_inner(hid_t group_id) const override; + // Accessor methods + const std::shared_ptr& dagmc_ptr() const { return dagmc_ptr_; } + int32_t dag_index() const { return dag_index_; } + +private: std::shared_ptr dagmc_ptr_; //!< Pointer to DagMC instance - int32_t dag_index_; //!< DagMC index of cell + int32_t dag_index_; //!< DagMC index of cell }; class DAGUniverse : public Universe { @@ -100,11 +110,13 @@ public: bool find_cell(Particle &p) const override; // Data Members - std::string filename_; //!< Name of the DAGMC file used to create this universe std::shared_ptr dagmc_instance_; //!< DAGMC Instance for this universe - std::shared_ptr uwuw_; //!< Pointer to the UWUW instance for this universe int32_t cell_idx_offset_; //!< An offset to the start of the cells in this universe in OpenMC's cell vector int32_t surf_idx_offset_; //!< An offset to the start of the surfaces in this universe in OpenMC's surface vector + +private: + std::string filename_; //!< Name of the DAGMC file used to create this universe + std::shared_ptr uwuw_; //!< Pointer to the UWUW instance for this universe bool adjust_geometry_ids_; //!< Indicates whether or not to automatically generate new cell and surface IDs for the universe bool adjust_material_ids_; //!< Indicates whether or not to automatically generate new material IDs for the universe }; diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 1132681a5b..9f8d233d21 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -150,11 +150,9 @@ DAGUniverse::initialize() { moab::EntityHandle vol_handle = dagmc_instance_->entity_by_index(3, i + 1); // set cell ids using global IDs - auto c = std::make_unique(); - c->dag_index_ = i + 1; - c->id_ = adjust_geometry_ids_ ? next_cell_id++ : dagmc_instance_->id_by_index(3, c->dag_index_); - c->dagmc_ptr_ = dagmc_instance_; - c->universe_ = id_; + auto c = std::make_unique(dagmc_instance_, i + 1); + c->id_ = adjust_geometry_ids_ ? next_cell_id++ : dagmc_instance_->id_by_index(3, c->dag_index()); + c->universe_ = this->id_; c->fill_ = C_NONE; // no fill, single universe auto in_map = model::cell_map.find(c->id_); @@ -244,10 +242,8 @@ DAGUniverse::initialize() { moab::EntityHandle surf_handle = dagmc_instance_->entity_by_index(2, i+1); // set cell ids using global IDs - auto s = std::make_unique(); - s->dag_index_ = i+1; // DAGMC indices start at 1 + auto s = std::make_unique(dagmc_instance_, i+1); s->id_ = adjust_geometry_ids_ ? next_surf_id++ : dagmc_instance_->id_by_index(2, i+1); - s->dagmc_ptr_ = dagmc_instance_; // set BCs std::string bc_value = DMD.get_surface_property("boundary", surf_handle); @@ -493,7 +489,8 @@ DAGUniverse::read_uwuw_materials() { // DAGMC Cell implementation //============================================================================== -DAGCell::DAGCell() : Cell{} { +DAGCell::DAGCell(std::shared_ptr dag_ptr, int32_t dag_idx) + : Cell{}, dagmc_ptr_(dag_ptr), dag_index_(dag_idx) { geom_type_ = GeometryType::DAG; simple_ = true; }; @@ -569,7 +566,9 @@ DAGCell::bounding_box() const // DAGSurface implementation //============================================================================== -DAGSurface::DAGSurface() : Surface{} { +DAGSurface::DAGSurface(std::shared_ptr dag_ptr, int32_t dag_idx) +: Surface{}, dagmc_ptr_(dag_ptr), dag_index_(dag_idx) +{ geom_type_ = GeometryType::DAG; } // empty constructor @@ -635,14 +634,14 @@ void read_dagmc_universes(pugi::xml_node node) { int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed) { moab::EntityHandle surf = - surf_xed->dagmc_ptr_->entity_by_index(2, surf_xed->dag_index_); + surf_xed->dagmc_ptr()->entity_by_index(2, surf_xed->dag_index()); moab::EntityHandle vol = - cur_cell->dagmc_ptr_->entity_by_index(3, cur_cell->dag_index_); + cur_cell->dagmc_ptr()->entity_by_index(3, cur_cell->dag_index()); moab::EntityHandle new_vol; - cur_cell->dagmc_ptr_->next_vol(surf, vol, new_vol); + cur_cell->dagmc_ptr()->next_vol(surf, vol, new_vol); - return cur_cell->dagmc_ptr_->index_by_handle(new_vol) + dag_univ->cell_idx_offset_; + return cur_cell->dagmc_ptr()->index_by_handle(new_vol) + dag_univ->cell_idx_offset_; } From 8942659fe0682cca23b2bb2571f22871e22f21f7 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 25 Jun 2021 07:38:37 -0500 Subject: [PATCH 76/93] Adding support for cloning DAGMC universes in the Python API. --- openmc/universe.py | 50 ++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index d5d015eba5..fe08e27c98 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -35,6 +35,10 @@ class UniverseBase(ABC, IDManagerMixin): self._volume = None self._atoms = {} + # Keys - Cell IDs + # Values - Cells + self._cells = OrderedDict() + def __repr__(self): string = 'Universe\n' string += '{: <16}=\t{}\n'.format('\tID', self._id) @@ -101,7 +105,6 @@ class UniverseBase(ABC, IDManagerMixin): """ - @abstractmethod def clone(self, clone_materials=True, clone_regions=True, memo=None): """Create a copy of this universe with a new unique ID, and clones all cells within this universe. @@ -124,6 +127,24 @@ class UniverseBase(ABC, IDManagerMixin): The clone of this universe """ + if memo is None: + memo = {} + + # If no memoize'd clone exists, instantiate one + if self not in memo: + clone = deepcopy(self) + clone.id = None + + # Clone all cells for the universe clone + clone._cells = OrderedDict() + for cell in self._cells.values(): + clone.add_cell(cell.clone(clone_materials, clone_regions, + memo)) + + # Memoize the clone + memo[self] = clone + + return memo[self] class Universe(UniverseBase): @@ -161,10 +182,6 @@ class Universe(UniverseBase): def __init__(self, universe_id=None, name='', cells=None): super().__init__(universe_id, name) - # Keys - Cell IDs - # Values - Cells - self._cells = OrderedDict() - if cells is not None: self.add_cells(cells) @@ -546,26 +563,6 @@ class Universe(UniverseBase): return universes - def clone(self, clone_materials=True, clone_regions=True, memo=None): - if memo is None: - memo = {} - - # If no nemoize'd clone exists, instantiate one - if self not in memo: - clone = deepcopy(self) - clone.id = None - - # Clone all cells for the universe clone - clone._cells = OrderedDict() - for cell in self._cells.values(): - clone.add_cell(cell.clone(clone_materials, clone_regions, - memo)) - - # Memoize the clone - memo[self] = clone - - return memo[self] - def create_xml_subelement(self, xml_element, memo=None): # Iterate over all Cells for cell in self._cells.values(): @@ -709,9 +706,6 @@ class DAGMCUniverse(UniverseBase): cv.check_type('DAGMC automatic material ids', val, bool) self._auto_mat_ids = val - def clone(self, clone_materials=True, clone_regions=True, memo=None): - pass - def get_all_cells(self, memo=None): return OrderedDict() From ff39f76a3dfb193a979a3f1e649bac2213e9d0ac Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 25 Jun 2021 07:40:29 -0500 Subject: [PATCH 77/93] Changing name of XML element from 'dagmc' to 'dagmc_universe' --- openmc/universe.py | 2 +- src/dagmc.cpp | 2 +- tests/regression_tests/dagmc/legacy/inputs_true.dat | 2 +- tests/regression_tests/dagmc/refl/inputs_true.dat | 2 +- tests/regression_tests/dagmc/universes/inputs_true.dat | 2 +- tests/regression_tests/dagmc/uwuw/inputs_true.dat | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index fe08e27c98..402609e2cb 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -720,7 +720,7 @@ class DAGMCUniverse(UniverseBase): memo.add(self) # Set xml element values - dagmc_element = ET.Element('dagmc') + dagmc_element = ET.Element('dagmc_universe') dagmc_element.set('id', str(self.id)) dagmc_element.set('name', self.name) if self.auto_geom_ids: diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 9f8d233d21..775c130f75 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -625,7 +625,7 @@ DAGSurface::reflect(Position r, Direction u, Particle* p) const //============================================================================== void read_dagmc_universes(pugi::xml_node node) { - for (pugi::xml_node dag_node : node.children("dagmc")) { + for (pugi::xml_node dag_node : node.children("dagmc_universe")) { model::universes.push_back(std::make_unique(dag_node)); model::universe_map[model::universes.back()->id_] = model::universes.size() - 1; } diff --git a/tests/regression_tests/dagmc/legacy/inputs_true.dat b/tests/regression_tests/dagmc/legacy/inputs_true.dat index ecc5d7373a..45c10a7aaa 100644 --- a/tests/regression_tests/dagmc/legacy/inputs_true.dat +++ b/tests/regression_tests/dagmc/legacy/inputs_true.dat @@ -1,6 +1,6 @@ - + diff --git a/tests/regression_tests/dagmc/refl/inputs_true.dat b/tests/regression_tests/dagmc/refl/inputs_true.dat index 4ac926e5ec..13bc9ecf52 100644 --- a/tests/regression_tests/dagmc/refl/inputs_true.dat +++ b/tests/regression_tests/dagmc/refl/inputs_true.dat @@ -1,6 +1,6 @@ - + diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat index 6c0fa8ccd9..fdc8b07bc9 100644 --- a/tests/regression_tests/dagmc/universes/inputs_true.dat +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -1,7 +1,7 @@ - + diff --git a/tests/regression_tests/dagmc/uwuw/inputs_true.dat b/tests/regression_tests/dagmc/uwuw/inputs_true.dat index 901547fa29..54b7a9cb83 100644 --- a/tests/regression_tests/dagmc/uwuw/inputs_true.dat +++ b/tests/regression_tests/dagmc/uwuw/inputs_true.dat @@ -1,6 +1,6 @@ - + From d1df19a21f127f3208c745a5a00245f3e9054f53 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 25 Jun 2021 07:44:40 -0500 Subject: [PATCH 78/93] Removing errant inputs true file from rotation test. --- .../regression_tests/rotation/inputs_true.dat | 31 ------------------- 1 file changed, 31 deletions(-) delete mode 100644 tests/regression_tests/rotation/inputs_true.dat diff --git a/tests/regression_tests/rotation/inputs_true.dat b/tests/regression_tests/rotation/inputs_true.dat deleted file mode 100644 index d90d498bf6..0000000000 --- a/tests/regression_tests/rotation/inputs_true.dat +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - -4.0 -4.0 -4.0 4.0 4.0 4.0 - - - From e6ce90dd782b4b11162f0ee0b073f8e561883729 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 28 Jun 2021 14:38:16 -0500 Subject: [PATCH 79/93] Removing unecessary DAGMC include from cross_sections.cpp --- src/cross_sections.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cross_sections.cpp b/src/cross_sections.cpp index 942b088d90..8124bd7947 100644 --- a/src/cross_sections.cpp +++ b/src/cross_sections.cpp @@ -3,9 +3,6 @@ #include "openmc/capi.h" #include "openmc/constants.h" #include "openmc/container_util.h" -#ifdef DAGMC -#include "openmc/dagmc.h" -#endif #include "openmc/error.h" #include "openmc/geometry_aux.h" #include "openmc/file_utils.h" From 019316e18d5453c047e6047646e9af4177ea0aab Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 28 Jun 2021 14:38:51 -0500 Subject: [PATCH 80/93] Updating DAGMC history reset conditional for clarity. --- src/particle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/particle.cpp b/src/particle.cpp index 6acd989faa..ef5c3199ad 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -383,7 +383,7 @@ Particle::cross_surface() // if we're crossing a CSG surface, make sure the DAG history is reset #ifdef DAGMC - if (surf->geom_type_ != GeometryType::DAG) history().reset(); + if (surf->geom_type_ == GeometryType::CSG) history().reset(); #endif // Handle any applicable boundary conditions. From 648054fbc7829b6342729cd9e1b67310d53cca2e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 28 Jun 2021 14:39:35 -0500 Subject: [PATCH 81/93] Adding a fucntion for printing a warning if a root DAGMC universe does not contain a graveyard volume. --- include/openmc/cell.h | 7 ++++++- include/openmc/dagmc.h | 20 ++++++++++++++++++-- src/cell.cpp | 4 +--- src/dagmc.cpp | 34 +++++++++++++++++++++++++++------- src/geometry_aux.cpp | 4 +++- 5 files changed, 55 insertions(+), 14 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 8bcc1ea067..1728392953 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -74,8 +74,13 @@ public: BoundingBox bounding_box() const; - GeometryType type_ = GeometryType::CSG; + const GeometryType& geom_type() const { return geom_type_; } + GeometryType& geom_type() { return geom_type_; } + unique_ptr partitioner_; + +private: + GeometryType geom_type_ = GeometryType::CSG; }; //============================================================================== diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index 591ea64748..f2cc1ee2a3 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -5,6 +5,20 @@ namespace openmc { extern "C" const bool DAGMC_ENABLED; } +// always include the XML interface header +#include "openmc/xml_interface.h" + +//============================================================================== +// Functions that are always defined +//============================================================================== + +namespace openmc { + +void read_dagmc_universes(pugi::xml_node node); +void check_dagmc_root_univ(); + +} + #ifdef DAGMC #include "DagMC.hpp" @@ -13,7 +27,6 @@ extern "C" const bool DAGMC_ENABLED; #include "openmc/particle.h" #include "openmc/position.h" #include "openmc/surface.h" -#include "openmc/xml_interface.h" class UWUW; @@ -114,18 +127,21 @@ public: int32_t cell_idx_offset_; //!< An offset to the start of the cells in this universe in OpenMC's cell vector int32_t surf_idx_offset_; //!< An offset to the start of the surfaces in this universe in OpenMC's surface vector + // Accessors + bool has_graveyard() const { return has_graveyard_; } + private: std::string filename_; //!< Name of the DAGMC file used to create this universe std::shared_ptr uwuw_; //!< Pointer to the UWUW instance for this universe bool adjust_geometry_ids_; //!< Indicates whether or not to automatically generate new cell and surface IDs for the universe bool adjust_material_ids_; //!< Indicates whether or not to automatically generate new material IDs for the universe + bool has_graveyard_; //!< Indicates if the DAGMC geometry has a "graveyard" volume }; //============================================================================== // Non-member functions //============================================================================== -void read_dagmc_universes(pugi::xml_node node); int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed); } // namespace openmc diff --git a/src/cell.cpp b/src/cell.cpp index c58fb17679..4de98aaddb 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -194,7 +194,7 @@ Universe::to_hdf5(hid_t universes_group) const auto group = create_group(universes_group, fmt::format("universe {}", id_)); // Write the geometry representation type. - switch(type_) { + switch(geom_type_) { case GeometryType::CSG : write_string(group, "geom_type", "csg", false); break; @@ -995,9 +995,7 @@ void read_cells(pugi::xml_node node) } } - #ifdef DAGMC read_dagmc_universes(node); - #endif // Populate the Universe vector and map. for (int i = 0; i < model::cells.size(); i++) { diff --git a/src/dagmc.cpp b/src/dagmc.cpp index 775c130f75..bde33157f5 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -85,7 +85,7 @@ DAGUniverse::DAGUniverse(const std::string& filename, void DAGUniverse::initialize() { - type_ = GeometryType::DAG; + geom_type() = GeometryType::DAG; // determine the next cell id int32_t next_cell_id = 0; @@ -229,10 +229,7 @@ DAGUniverse::initialize() { model::overlap_check_count.resize(model::cells.size(), 0); } - if (!graveyard) { - warning("No graveyard volume found in the DagMC model. " - "This may result in lost particles and rapid simulation failure."); - } + has_graveyard_ = graveyard; // --- Surfaces --- @@ -631,6 +628,19 @@ void read_dagmc_universes(pugi::xml_node node) { } } +void check_dagmc_root_univ() { + const auto& ru = model::universes[model::root_universe]; + if (ru->geom_type() == GeometryType::DAG) { + // if the root universe contains DAGMC geometry, warn the user + // if it does not contain a graveyard volume + auto dag_univ = dynamic_cast(ru.get()); + if (dag_univ && !dag_univ->has_graveyard()) { + warning("No graveyard volume found in the DagMC model. " + "This may result in lost particles and rapid simulation failure."); + } + } +} + int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed) { moab::EntityHandle surf = @@ -645,5 +655,15 @@ int32_t next_cell(DAGUniverse* dag_univ, DAGCell* cur_cell, DAGSurface* surf_xed } -} -#endif +} // namespace openmc + +#else + +namespace openmc { + +void read_dagmc_universes(pugi::xml_node node) {}; +void check_dagmc_root_univ() {}; + +} // namespace openmc + +#endif // DAGMC diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index 80741b3e78..af6ebac9f8 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -80,9 +80,11 @@ void read_geometry_xml() fatal_error("No boundary conditions were applied to any surfaces!"); } - // Allocate universes, universe cell arrays, and assign base universe model::root_universe = find_root_universe(); + + // if the root universe is DAGMC geometry, make sure the model is well-formed + check_dagmc_root_univ(); } //============================================================================== From 263addffc1ea2c63f5666934bd9c9d7b26f98c0e Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Mon, 28 Jun 2021 15:31:22 -0500 Subject: [PATCH 82/93] Updating test and test results for the DAGMC geometry in a lattice. --- .../dagmc/universes/inputs_true.dat | 14 ++++++++--- .../dagmc/universes/results_true.dat | 2 +- .../regression_tests/dagmc/universes/test.py | 25 +++++++++++++------ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat index fdc8b07bc9..e235c06a8a 100644 --- a/tests/regression_tests/dagmc/universes/inputs_true.dat +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -1,13 +1,21 @@ - + + + 24.0 24.0 + 2 2 + -24.0 -24.0 + +9 9 +9 9 + - - + + diff --git a/tests/regression_tests/dagmc/universes/results_true.dat b/tests/regression_tests/dagmc/universes/results_true.dat index c9e1bc8fa5..0dc1789d45 100644 --- a/tests/regression_tests/dagmc/universes/results_true.dat +++ b/tests/regression_tests/dagmc/universes/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.687742E-01 3.415061E-02 +9.436168E-01 2.905559E-02 diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index 1458462c48..01963986c5 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -1,3 +1,5 @@ +import numpy as np + import openmc import openmc.lib @@ -44,16 +46,23 @@ class DAGMCUniverseTest(PyAPITestHarness): # create the DAGMC universe pincell_univ = openmc.DAGMCUniverse(filename='dagmc.h5m', auto_geom_ids=True) - left = openmc.XPlane(x0=-24.0, name='left', boundary_type='reflective') - right = openmc.XPlane(x0=24.0, name='right', boundary_type='reflective') - front = openmc.YPlane(y0=-24.0, name='front', boundary_type='reflective') - back = openmc.YPlane(y0=24.0, name='back', boundary_type='reflective') - bottom = openmc.ZPlane(z0=-20.0, name='bottom', boundary_type='vacuum') - top = openmc.ZPlane(z0=20.0, name='top', boundary_type='vacuum') + # create a 2 x 2 lattice using the DAGMC pincell + pitch = np.asarray((24.0, 24.0)) + lattice = openmc.RectLattice() + lattice.pitch = pitch + lattice.universes = [[pincell_univ] * 2] * 2 + lattice.lower_left = -pitch - box = +left & -right & +front & -back & +bottom & -top + left = openmc.XPlane(x0=-pitch[0], name='left', boundary_type='reflective') + right = openmc.XPlane(x0=pitch[0], name='right', boundary_type='reflective') + front = openmc.YPlane(y0=-pitch[1], name='front', boundary_type='reflective') + back = openmc.YPlane(y0=pitch[1], name='back', boundary_type='reflective') + # clip the DAGMC geometry at +/- 10 cm w/ CSG planes + bottom = openmc.ZPlane(z0=-10.0, name='bottom', boundary_type='reflective') + top = openmc.ZPlane(z0=10.0, name='top', boundary_type='reflective') - bounding_cell = openmc.Cell(fill=pincell_univ, region=box) + bounding_region = +left & -right & +front & -back & +bottom & -top + bounding_cell = openmc.Cell(fill=lattice, region=bounding_region) model.geometry = openmc.Geometry([bounding_cell]) From f2e0af378fd2c87c71c5384020f37c4036f0cbd4 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 29 Jun 2021 11:16:29 -0500 Subject: [PATCH 83/93] Addressing case where is not present in surface HDF5 groups. --- openmc/surface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/surface.py b/openmc/surface.py index 70fd008318..b2f3c6710c 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -454,8 +454,8 @@ class Surface(IDManagerMixin, ABC): """ # If this is a DAGMC surface, do nothing for now - geom_type = group['geom_type'][()].decode() - if geom_type == 'dagmc': + geom_type = group.get('geom_type') + if geom_type and geom_type[()].decode() == 'dagmc': return surface_id = int(group.name.split('/')[-1].lstrip('surface ')) From 9c849f405862b8c48a8c9338c2c1c6741fce0c4d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 29 Jun 2021 17:49:14 -0500 Subject: [PATCH 84/93] Updating IO format documentation. --- docs/source/io_formats/geometry.rst | 41 +++++++++++++++++++++++++++++ docs/source/io_formats/settings.rst | 8 ------ docs/source/io_formats/summary.rst | 10 +++++-- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/docs/source/io_formats/geometry.rst b/docs/source/io_formats/geometry.rst index af229bcfff..c94657f9a8 100644 --- a/docs/source/io_formats/geometry.rst +++ b/docs/source/io_formats/geometry.rst @@ -370,3 +370,44 @@ Here is an example of a properly defined 2d hexagonal lattice: 202 + + +.. _dagmc_element: + +---------------------------- +```` Element +---------------------------- + +Each ```` element can have the following attributes or sub-elements: + + :id: + A unique integer used to identify the universe. + + *Default*: "" + + :name: + An optional string name to identify the surface in summary output + files. This string is limited to 52 characters for formatting purposes. + + *Default*: "" + + :auto_geom_ids: + Boolean value indicating whether the existing geometry IDs will be used or appended + to the existing ID space of natively defined OpenMC geometry entities. + + *Default*: false + + :auto_mat_ids: + Boolean value indicating whether the existing material IDs will be used or appended + to the existing ID space of natively defined OpenMC materials. + + *Default*: false + + :filename: + A required string indicating the file to be loaded representing the DAGMC universe. + + *Default*: None + + + + diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 53376b04c7..6ea8cfc56e 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -88,14 +88,6 @@ you care. This element has the following attributes/sub-elements: *Default*: 0.0 --------------------------------- -```` Element --------------------------------- - -When the DAGMC mode is enabled, the OpenMC geometry will be read from the file -``dagmc.h5m``. If a :ref:`geometry.xml ` file is present with -``dagmc`` set to ``true``, it will be ignored. - ---------------------------- ```` ---------------------------- diff --git a/docs/source/io_formats/summary.rst b/docs/source/io_formats/summary.rst index cf0eca4aae..96c3f8ab47 100644 --- a/docs/source/io_formats/summary.rst +++ b/docs/source/io_formats/summary.rst @@ -24,8 +24,6 @@ The current version of the summary file format is 6.0. - **n_universes** (*int*) -- Number of unique universes in the problem. - **n_lattices** (*int*) -- Number of lattices in the problem. - - **dagmc** (*int*) -- Indicates that a DAGMC geometry was used - if present. **/geometry/cells/cell /** @@ -49,6 +47,8 @@ The current version of the summary file format is 6.0. - **lattice** (*int*) -- Unique ID of the lattice which fills the cell. Only present if fill_type is set to 'lattice'. - **region** (*char[]*) -- Region specification for the cell. + - **geom_type** (*char[]*) -- Type of geometry used to create the cell. + Either 'csg' or 'dagmc'. **/geometry/surfaces/surface /** @@ -62,12 +62,18 @@ The current version of the summary file format is 6.0. - **boundary_condition** (*char[]*) -- Boundary condition applied to the surface. Can be 'transmission', 'vacuum', 'reflective', or 'periodic'. + - **geom_type** (*char[]*) -- Type of geometry used to create the cell. + Either 'csg' or 'dagmc'. + **/geometry/universes/universe /** :Datasets: - **cells** (*int[]*) -- Array of unique IDs of cells that appear in the universe. + - **geom_type** (*char[]*) -- Type of geometry used to create the cell. + Either 'csg' or 'dagmc'. + **/geometry/lattices/lattice /** From e2826fa57b2754f844b574bd56628a2d373bbdda Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 29 Jun 2021 17:54:57 -0500 Subject: [PATCH 85/93] Adding a from_xml method to the DAGUniverse class. Ensuring DAGMC universes are read into geometries from XML files. --- openmc/geometry.py | 5 +++++ openmc/universe.py | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/openmc/geometry.py b/openmc/geometry.py index 36cff94e30..13113338a5 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -198,6 +198,11 @@ class Geometry: if c.fill_type in ('universe', 'lattice'): child_of[c.fill].append(c) + # Add any DAGMC universes + for elem in root.findall('dagmc_universe'): + dag_univ = openmc.DAGMCUniverse.from_xml(elem) + universes[dag_univ.id] = dag_univ + # Determine which universe is the root by finding one which is not a # child of any other object for u in universes.values(): diff --git a/openmc/universe.py b/openmc/universe.py index 402609e2cb..6f27148ea9 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -10,6 +10,7 @@ import numpy as np import openmc import openmc.checkvalue as cv +from ._xml import get_text from .mixin import IDManagerMixin from .plots import _SVG_COLORS @@ -729,3 +730,19 @@ class DAGMCUniverse(UniverseBase): dagmc_element.set('auto_mat_ids', 'true') dagmc_element.set('filename', self.filename) xml_element.append(dagmc_element) + + @classmethod + def from_xml(cls, elem): + id = int(get_text(elem, 'id')) + fname = get_text(elem, 'filename') + + out = cls(fname, universe_id=id) + + name = get_text(elem, 'name') + if name is not None: + out.name = name + + out.auto_geom_ids = bool(elem.get('auto_geom_ids')) + out.auto_mat_ids = bool(elem.get('auto_mat_ids')) + + return out From ef70e121420aa00a0bc70292eb34050c783c1c18 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 29 Jun 2021 21:04:23 -0500 Subject: [PATCH 86/93] Enhancing to/from hdf5 methods so that DAGMC universes can be reproduced and exported to XML from a summary file. --- include/openmc/cell.h | 2 +- include/openmc/dagmc.h | 2 ++ openmc/geometry.py | 10 +++++----- openmc/summary.py | 6 +++++- openmc/universe.py | 39 +++++++++++++++++++++++++++++++++++++++ src/cell.cpp | 9 +-------- src/dagmc.cpp | 17 +++++++++++++++++ 7 files changed, 70 insertions(+), 15 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 1728392953..9e977bc937 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -68,7 +68,7 @@ public: //! \brief Write universe information to an HDF5 group. //! \param group_id An HDF5 group id. - void to_hdf5(hid_t group_id) const; + virtual void to_hdf5(hid_t group_id) const; virtual bool find_cell(Particle &p) const; diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h index f2cc1ee2a3..6a71e61702 100644 --- a/include/openmc/dagmc.h +++ b/include/openmc/dagmc.h @@ -122,6 +122,8 @@ public: bool find_cell(Particle &p) const override; + void to_hdf5(hid_t universes_group) const override; + // Data Members std::shared_ptr dagmc_instance_; //!< DAGMC Instance for this universe int32_t cell_idx_offset_; //!< An offset to the start of the cells in this universe in OpenMC's cell vector diff --git a/openmc/geometry.py b/openmc/geometry.py index 13113338a5..1ae0015b2a 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -159,6 +159,11 @@ class Geometry: for s1, s2 in periodic.items(): surfaces[s1].periodic_surface = surfaces[s2] + # Add any DAGMC universes + for elem in root.findall('dagmc_universe'): + dag_univ = openmc.DAGMCUniverse.from_xml(elem) + universes[dag_univ.id] = dag_univ + # Dictionary that maps each universe to a list of cells/lattices that # contain it (needed to determine which universe is the root) child_of = defaultdict(list) @@ -198,11 +203,6 @@ class Geometry: if c.fill_type in ('universe', 'lattice'): child_of[c.fill].append(c) - # Add any DAGMC universes - for elem in root.findall('dagmc_universe'): - dag_univ = openmc.DAGMCUniverse.from_xml(elem) - universes[dag_univ.id] = dag_univ - # Determine which universe is the root by finding one which is not a # child of any other object for u in universes.values(): diff --git a/openmc/summary.py b/openmc/summary.py index 0af45b7701..6e64120618 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -178,7 +178,11 @@ class Summary: def _read_universes(self): for group in self._f['geometry/universes'].values(): - universe = openmc.Universe.from_hdf5(group, self._fast_cells) + geom_type = group.get('geom_type') + if geom_type and geom_type[()].decode() == 'dagmc': + universe = openmc.DAGMCUniverse.from_hdf5(group) + else: + universe = openmc.Universe.from_hdf5(group, self._fast_cells) self._fast_universes[universe.id] = universe def _read_lattices(self): diff --git a/openmc/universe.py b/openmc/universe.py index 6f27148ea9..bf7481cabd 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -731,8 +731,47 @@ class DAGMCUniverse(UniverseBase): dagmc_element.set('filename', self.filename) xml_element.append(dagmc_element) + @classmethod + def from_hdf5(cls, group): + """Create DAGMC universe from HDF5 group + + Parameters + ---------- + group : h5py.Group + Group in HDF5 file + + Returns + ------- + openmc.DAGMCUniverse + DAGMCUniverse instance + + """ + id = int(group.name.split('/')[-1].lstrip('universe ')) + fname = group['filename'][()].decode() + name = group['name'][()].decode() if 'name' in group else None + + out = cls(fname, universe_id=id, name=name) + + out.auto_geom_ids = bool(group.attrs['auto_geom_ids']) + out.auto_mat_ids = bool(group.attrs['auto_mat_ids']) + + return out + @classmethod def from_xml(cls, elem): + """Generate DAGMC universe from XML element + + Parameters + ---------- + elem : xml.etree.ElementTree.Element + `` element + + Returns + ------- + openmc.DAGMCUniverse + DAGMCUniverse instance + + """ id = int(get_text(elem, 'id')) fname = get_text(elem, 'filename') diff --git a/src/cell.cpp b/src/cell.cpp index 4de98aaddb..4ae5177fa0 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -194,14 +194,7 @@ Universe::to_hdf5(hid_t universes_group) const auto group = create_group(universes_group, fmt::format("universe {}", id_)); // Write the geometry representation type. - switch(geom_type_) { - case GeometryType::CSG : - write_string(group, "geom_type", "csg", false); - break; - case GeometryType::DAG : - write_string(group, "geom_type", "dagmc", false); - break; - } + write_string(group, "geom_type", "csg", false); // Write the contained cells. if (cells_.size() > 0) { diff --git a/src/dagmc.cpp b/src/dagmc.cpp index bde33157f5..630f665fae 100644 --- a/src/dagmc.cpp +++ b/src/dagmc.cpp @@ -354,6 +354,22 @@ DAGUniverse::find_cell(Particle &p) const { return found; } +void +DAGUniverse::to_hdf5(hid_t universes_group) const { + // Create a group for this universe. + auto group = create_group(universes_group, fmt::format("universe {}", id_)); + + // Write the geometry representation type. + write_string(group, "geom_type", "dagmc", false); + + // Write other properties of the DAGMC Universe + write_string(group, "filename", filename_, false); + write_attribute(group, "auto_geom_ids", static_cast(adjust_geometry_ids_)); + write_attribute(group, "auto_mat_ids", static_cast(adjust_material_ids_)); + + close_group(group); +} + bool DAGUniverse::uses_uwuw() const { @@ -546,6 +562,7 @@ DAGCell::contains(Position r, Direction u, int32_t on_surface) const void DAGCell::to_hdf5_inner(hid_t group_id) const { write_string(group_id, "geom_type", "dagmc", false); + } BoundingBox From 25cf7a3e9712f80b05e918311fbd5e65cfd6d627 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 29 Jun 2021 21:05:03 -0500 Subject: [PATCH 87/93] Ensuring that surface names are read from the HDF5 format. --- openmc/surface.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openmc/surface.py b/openmc/surface.py index b2f3c6710c..ac0cb1b0b2 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -432,6 +432,7 @@ class Surface(IDManagerMixin, ABC): kwargs = {} kwargs['surface_id'] = int(elem.get('id')) kwargs['boundary_type'] = elem.get('boundary', 'transmission') + kwargs['name'] = elem.get('name') coeffs = [float(x) for x in elem.get('coeffs').split()] kwargs.update(dict(zip(cls._coeff_keys, coeffs))) From 4f5654a152e6868d52fca7677b1e798d95f7cd1b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 29 Jun 2021 21:15:33 -0500 Subject: [PATCH 88/93] Adding documentation for new entries in the summary.h5 file. --- docs/source/io_formats/summary.rst | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/source/io_formats/summary.rst b/docs/source/io_formats/summary.rst index 96c3f8ab47..9b92b30187 100644 --- a/docs/source/io_formats/summary.rst +++ b/docs/source/io_formats/summary.rst @@ -73,6 +73,15 @@ The current version of the summary file format is 6.0. the universe. - **geom_type** (*char[]*) -- Type of geometry used to create the cell. Either 'csg' or 'dagmc'. + - **filename** (*char[]*) -- Name of the DAGMC file representing this universe. + Only present for DAGMC Universes. +:Attributes: + - **auto_geom_ids** (*int*) -- ``1`` if geometry IDs of the DAGMC + model will be appended to the ID space of the natively defined + CSG geometry, ``0`` if the existing DAGMC IDs will be used. + - **auto_mat_ids** (*int*) -- ``1`` if UWUW material IDs of the DAGMC + model will be appended to the ID space of the natively defined + OpenMC materials, ``0`` if the existing UWUW IDs will be used. **/geometry/lattices/lattice /** @@ -125,8 +134,8 @@ The current version of the summary file format is 6.0. :Attributes: - **volume** (*double[]*) -- Volume of this material [cm^3]. Only present if ``volume`` supplied - **temperature** (*double[]*) -- Temperature of this material [K]. - Only present in ``temperature`` supplied - - **depletable** (*int[]*) -- ``1`` if the material can be depleted, + Only present if ``temperature`` is supplied + - **depletable** (*int*) -- ``1`` if the material can be depleted, ``0`` otherwise. Always present **/nuclides/** From 8500ed57ffa91706046cf46efbcf75d06c960518 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 30 Jun 2021 08:44:47 -0500 Subject: [PATCH 89/93] Apply @paulromano's suggestions from code review Co-authored-by: Paul Romano --- docs/source/io_formats/geometry.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/source/io_formats/geometry.rst b/docs/source/io_formats/geometry.rst index c94657f9a8..6494d14877 100644 --- a/docs/source/io_formats/geometry.rst +++ b/docs/source/io_formats/geometry.rst @@ -383,13 +383,13 @@ Each ```` element can have the following attributes or sub-eleme :id: A unique integer used to identify the universe. - *Default*: "" + *Default*: None :name: An optional string name to identify the surface in summary output files. This string is limited to 52 characters for formatting purposes. - *Default*: "" + *Default*: None :auto_geom_ids: Boolean value indicating whether the existing geometry IDs will be used or appended @@ -407,7 +407,3 @@ Each ```` element can have the following attributes or sub-eleme A required string indicating the file to be loaded representing the DAGMC universe. *Default*: None - - - - From 00446222405c9adae9418197923d6177f20502fc Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 30 Jun 2021 08:39:03 -0500 Subject: [PATCH 90/93] Removing indications that material/cell/surface/universe/tally names are limited to 52 characters. --- docs/source/io_formats/geometry.rst | 9 ++++----- docs/source/io_formats/materials.rst | 2 +- docs/source/io_formats/tallies.rst | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/source/io_formats/geometry.rst b/docs/source/io_formats/geometry.rst index 6494d14877..1d04bb8fbf 100644 --- a/docs/source/io_formats/geometry.rst +++ b/docs/source/io_formats/geometry.rst @@ -19,7 +19,7 @@ Each ```` element can have the following attributes or sub-elements: :name: An optional string name to identify the surface in summary output - files. This string is limited to 52 characters for formatting purposes. + files. *Default*: "" @@ -122,7 +122,6 @@ Each ```` element can have the following attributes or sub-elements: :name: An optional string name to identify the cell in summary output files. - This string is limmited to 52 characters for formatting purposes. *Default*: "" @@ -235,7 +234,7 @@ the following attributes or sub-elements: :name: An optional string name to identify the lattice in summary output - files. This string is limited to 52 characters for formatting purposes. + files. *Default*: "" @@ -301,7 +300,7 @@ the following attributes or sub-elements: :name: An optional string name to identify the hex_lattice in summary output - files. This string is limited to 52 characters for formatting purposes. + files. *Default*: "" @@ -387,7 +386,7 @@ Each ```` element can have the following attributes or sub-eleme :name: An optional string name to identify the surface in summary output - files. This string is limited to 52 characters for formatting purposes. + files. *Default*: None diff --git a/docs/source/io_formats/materials.rst b/docs/source/io_formats/materials.rst index ac2cfe271e..92b0165a43 100644 --- a/docs/source/io_formats/materials.rst +++ b/docs/source/io_formats/materials.rst @@ -31,7 +31,7 @@ Each ``material`` element can have the following attributes or sub-elements: :name: An optional string name to identify the material in summary output - files. This string is limited to 52 characters for formatting purposes. + files. *Default*: "" diff --git a/docs/source/io_formats/tallies.rst b/docs/source/io_formats/tallies.rst index 8c1ad91b58..ad72273690 100644 --- a/docs/source/io_formats/tallies.rst +++ b/docs/source/io_formats/tallies.rst @@ -31,7 +31,7 @@ The ```` element accepts the following sub-elements: :name: An optional string name to identify the tally in summary output - files. This string is limited to 52 characters for formatting purposes. + files. *Default*: "" From 4fd6f0e8dfc158c5a81016d7eaae4968b26c56e9 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 30 Jun 2021 08:43:29 -0500 Subject: [PATCH 91/93] Removing export of the DAGUniverse name attribute to match behavior with standard Universes. --- openmc/universe.py | 4 ++-- tests/regression_tests/dagmc/legacy/inputs_true.dat | 2 +- tests/regression_tests/dagmc/refl/inputs_true.dat | 2 +- tests/regression_tests/dagmc/universes/inputs_true.dat | 2 +- tests/regression_tests/dagmc/uwuw/inputs_true.dat | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc/universe.py b/openmc/universe.py index bf7481cabd..5cfb985793 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -723,7 +723,7 @@ class DAGMCUniverse(UniverseBase): # Set xml element values dagmc_element = ET.Element('dagmc_universe') dagmc_element.set('id', str(self.id)) - dagmc_element.set('name', self.name) + if self.auto_geom_ids: dagmc_element.set('auto_geom_ids', 'true') if self.auto_mat_ids: @@ -758,7 +758,7 @@ class DAGMCUniverse(UniverseBase): return out @classmethod - def from_xml(cls, elem): + def from_xml_element(cls, elem): """Generate DAGMC universe from XML element Parameters diff --git a/tests/regression_tests/dagmc/legacy/inputs_true.dat b/tests/regression_tests/dagmc/legacy/inputs_true.dat index 45c10a7aaa..2f56410466 100644 --- a/tests/regression_tests/dagmc/legacy/inputs_true.dat +++ b/tests/regression_tests/dagmc/legacy/inputs_true.dat @@ -1,6 +1,6 @@ - + diff --git a/tests/regression_tests/dagmc/refl/inputs_true.dat b/tests/regression_tests/dagmc/refl/inputs_true.dat index 13bc9ecf52..938916ece1 100644 --- a/tests/regression_tests/dagmc/refl/inputs_true.dat +++ b/tests/regression_tests/dagmc/refl/inputs_true.dat @@ -1,6 +1,6 @@ - + diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat index e235c06a8a..4443f9a35d 100644 --- a/tests/regression_tests/dagmc/universes/inputs_true.dat +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -1,7 +1,7 @@ - + 24.0 24.0 2 2 diff --git a/tests/regression_tests/dagmc/uwuw/inputs_true.dat b/tests/regression_tests/dagmc/uwuw/inputs_true.dat index 54b7a9cb83..7d533c5db2 100644 --- a/tests/regression_tests/dagmc/uwuw/inputs_true.dat +++ b/tests/regression_tests/dagmc/uwuw/inputs_true.dat @@ -1,6 +1,6 @@ - + From 0aafa81907ac79b9bdb4a86aede0b63fee3a9a9b Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 30 Jun 2021 08:44:27 -0500 Subject: [PATCH 92/93] Adding Python pickle extension to the git ignore. Nearly added another one of these by accident. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 6838e75689..c8d4d7140a 100644 --- a/.gitignore +++ b/.gitignore @@ -116,3 +116,6 @@ CMakeSettings.json # Visual Studio Code configuration files .vscode/ + +# Python pickle files +*.pkl \ No newline at end of file From a407c12aae112c15e0e218256357f107f64b0d8d Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 30 Jun 2021 12:45:08 -0500 Subject: [PATCH 93/93] Update openmc/geometry.py Co-authored-by: Paul Romano --- openmc/geometry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/geometry.py b/openmc/geometry.py index 1ae0015b2a..8f7bf05f85 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -161,7 +161,7 @@ class Geometry: # Add any DAGMC universes for elem in root.findall('dagmc_universe'): - dag_univ = openmc.DAGMCUniverse.from_xml(elem) + dag_univ = openmc.DAGMCUniverse.from_xml_element(elem) universes[dag_univ.id] = dag_univ # Dictionary that maps each universe to a list of cells/lattices that

E`hr*FP_v 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