diff --git a/include/base/OpenMCCellAverageProblem.h b/include/base/OpenMCCellAverageProblem.h index 3ff51e059..00848eed1 100644 --- a/include/base/OpenMCCellAverageProblem.h +++ b/include/base/OpenMCCellAverageProblem.h @@ -21,6 +21,7 @@ #include "OpenMCProblemBase.h" #include "SymmetryPointGenerator.h" #include "OpenMCVolumeCalculation.h" +#include "MooseMesh.h" /// Tally/filter includes. #include "TallyBase.h" @@ -870,6 +871,9 @@ class OpenMCCellAverageProblem : public OpenMCProblemBase */ const bool _needs_global_tally; + /// Whether OpenMCCellAverageProblem should use the displaced mesh + const bool & _use_displaced; + /** * A map of the filter objects created by the [Problem/Filters] block. The key for each filter is * it's corresponding MOOSE name to allow tallies to look up filters. @@ -1030,6 +1034,9 @@ class OpenMCCellAverageProblem : public OpenMCProblemBase /// Number of particles simulated in the first iteration unsigned int _n_particles_1; + // Get a modifyable reference to the Moose mesh + virtual const MooseMesh & getMooseMesh() const; + /// Mapping from temperature variable name to the subdomains on which to read it from std::map> _temp_vars_to_blocks; diff --git a/include/userobjects/OpenMCVolumeCalculation.h b/include/userobjects/OpenMCVolumeCalculation.h index c0db52f03..c73184808 100644 --- a/include/userobjects/OpenMCVolumeCalculation.h +++ b/include/userobjects/OpenMCVolumeCalculation.h @@ -79,6 +79,9 @@ class OpenMCVolumeCalculation : public GeneralUserObject /// Upper right of the box within which to compute OpenMC volumes Point _upper_right; + /// Get a modifyable reference to the Moose mesh + MooseMesh & getMooseMesh(); + /// Volume calculation object std::unique_ptr _volume_calc; diff --git a/src/base/OpenMCCellAverageProblem.C b/src/base/OpenMCCellAverageProblem.C index b047818ee..38d5945e0 100644 --- a/src/base/OpenMCCellAverageProblem.C +++ b/src/base/OpenMCCellAverageProblem.C @@ -20,6 +20,7 @@ #include "OpenMCCellAverageProblem.h" #include "DelimitedFileReader.h" +#include "DisplacedProblem.h" #include "TallyBase.h" #include "CellTally.h" #include "AddTallyAction.h" @@ -164,7 +165,9 @@ OpenMCCellAverageProblem::validParams() params.addParam("first_iteration_particles", "Number of particles to use for first iteration " "when using Dufek-Gudowski relaxation"); - + params.addParam("use_displaced_mesh", + false, + "Whether OpenMCCellAverageProblem should use the displaced mesh "); params.addParam( "symmetry_mapper", "User object (of type SymmetryPointGenerator) " @@ -207,6 +210,7 @@ OpenMCCellAverageProblem::OpenMCCellAverageProblem(const InputParameters & param _specified_temperature_feedback(params.isParamSetByUser("temperature_blocks")), _needs_to_map_cells(_specified_density_feedback || _specified_temperature_feedback), _needs_global_tally(_check_tally_sum || _normalize_by_global), + _use_displaced(getParam("use_displaced_mesh")), _volume_calc(nullptr), _symmetry(nullptr) { @@ -368,6 +372,16 @@ OpenMCCellAverageProblem::OpenMCCellAverageProblem(const InputParameters & param } } +const MooseMesh & +OpenMCCellAverageProblem::getMooseMesh() const +{ + if (_use_displaced && !_displaced_problem && !_first_transfer) + mooseWarning("Displaced mesh was requested but the displaced problem does not exist. " + "Regular mesh will be returned"); + return ((_use_displaced && _displaced_problem && !_first_transfer) ? _displaced_problem->mesh() + : mesh()); +} + void OpenMCCellAverageProblem::readBlockVariables( const std::string & param, @@ -545,9 +559,9 @@ OpenMCCellAverageProblem::setupProblem() { // establish the local -> global element mapping for convenience _local_to_global_elem.clear(); - for (unsigned int e = 0; e < _mesh.nElem(); ++e) + for (unsigned int e = 0; e < getMooseMesh().nElem(); ++e) { - const auto * elem = _mesh.queryElemPtr(e); + const auto * elem = getMooseMesh().queryElemPtr(e); if (!isLocalElem(elem)) continue; @@ -633,7 +647,7 @@ OpenMCCellAverageProblem::readBlockParameters(const std::string name, auto names = getParam>(name); checkEmptyVector(names, "'" + name + "'"); - auto b_ids = _mesh.getSubdomainIDs(names); + auto b_ids = getMooseMesh().getSubdomainIDs(names); std::copy(b_ids.begin(), b_ids.end(), std::inserter(blocks, blocks.end())); checkBlocksInMesh(name, b_ids, names); } @@ -644,7 +658,7 @@ OpenMCCellAverageProblem::checkBlocksInMesh(const std::string name, const std::vector & ids, const std::vector & names) const { - const auto & subdomains = _mesh.meshSubdomains(); + const auto & subdomains = getMooseMesh().meshSubdomains(); for (std::size_t b = 0; b < names.size(); ++b) if (subdomains.find(ids[b]) == subdomains.end()) mooseError("Block '" + names[b] + "' specified in '" + name + "' " + "not found in mesh!"); @@ -672,7 +686,7 @@ OpenMCCellAverageProblem::read2DBlockParameters(const std::string name, for (const auto & i : slice) flattened_names.push_back(i); - flattened_ids = _mesh.getSubdomainIDs(flattened_names); + flattened_ids = getMooseMesh().getSubdomainIDs(flattened_names); checkBlocksInMesh(name, flattened_ids, flattened_names); // should not be any duplicate blocks @@ -743,7 +757,7 @@ OpenMCCellAverageProblem::storeElementPhase() _n_moose_density_elems += numElemsInSubdomain(s); _n_moose_none_elems = - _mesh.nElem() - _n_moose_temp_density_elems - _n_moose_temp_elems - _n_moose_density_elems; + getMooseMesh().nElem() - _n_moose_temp_density_elems - _n_moose_temp_elems - _n_moose_density_elems; } void @@ -757,7 +771,7 @@ OpenMCCellAverageProblem::computeCellMappedVolumes() for (const auto & e : c.second) { // we are looping over local elements, so no need to check for nullptr - const auto * elem = _mesh.queryElemPtr(globalElemID(e)); + const auto * elem = getMooseMesh().queryElemPtr(globalElemID(e)); vol += elem->volume(); } @@ -837,7 +851,7 @@ OpenMCCellAverageProblem::getCellMappedPhase() // we are looping over local elements, so no need to check for nullptr for (const auto & e : c.second) - f[elemFeedback(_mesh.queryElemPtr(globalElemID(e)))]++; + f[elemFeedback(getMooseMesh().queryElemPtr(globalElemID(e)))]++; cells_n_temp.push_back(f[coupling::temperature]); cells_n_temp_rho.push_back(f[coupling::density_and_temperature]); @@ -998,7 +1012,7 @@ OpenMCCellAverageProblem::printAuxVariableIO() VariadicTable aux( {"Subdomain", "Temperature", "Density"}); - for (const auto & s : _mesh.meshSubdomains()) + for (const auto & s : getMooseMesh().meshSubdomains()) { std::string temp = _subdomain_to_temp_vars.count(s) ? _subdomain_to_temp_vars[s].second : ""; std::string rho = @@ -1058,7 +1072,7 @@ OpenMCCellAverageProblem::getCellMappedSubdomains() for (const auto & e : c.second) { // we are looping over local elements, so no need to check for nullptr - const auto * elem = _mesh.queryElemPtr(globalElemID(e)); + const auto * elem = getMooseMesh().queryElemPtr(globalElemID(e)); elem_ids.push_back(elem->subdomain_id()); } } @@ -1325,7 +1339,7 @@ OpenMCCellAverageProblem::initializeElementToCellMapping() mooseError("Did not find any overlap between MOOSE elements and OpenMC cells for " "the specified blocks!"); - _console << "\nMapping between " + Moose::stringify(_mesh.nElem()) + " MOOSE elements and " + + _console << "\nMapping between " + Moose::stringify(getMooseMesh().nElem()) + " MOOSE elements and " + Moose::stringify(_n_openmc_cells) + " OpenMC cells (on " + Moose::stringify(openmc::model::n_coord_levels) + " coordinate levels):" << std::endl; @@ -1633,13 +1647,14 @@ OpenMCCellAverageProblem::mapElemsToCells() // reset data structures _elem_to_cell.clear(); _cell_to_elem.clear(); + _subdomain_to_material.clear(); _flattened_ids.clear(); _flattened_instances.clear(); int local_elem = -1; - for (unsigned int e = 0; e < _mesh.nElem(); ++e) + for (unsigned int e = 0; e < getMooseMesh().nElem(); ++e) { - const auto * elem = _mesh.queryElemPtr(e); + const auto * elem = getMooseMesh().queryElemPtr(e); if (!isLocalElem(elem)) continue; @@ -1764,8 +1779,8 @@ OpenMCCellAverageProblem::mapElemsToCells() gatherCellVector(elems, n_elems, _cell_to_elem); // fill out the elem_to_cell structure - _elem_to_cell.resize(_mesh.nElem()); - for (unsigned int e = 0; e < _mesh.nElem(); ++e) + _elem_to_cell.resize(getMooseMesh().nElem()); + for (unsigned int e = 0; e < getMooseMesh().nElem(); ++e) _elem_to_cell[e] = {UNMAPPED, UNMAPPED}; for (const auto & c : _cell_to_elem) @@ -1784,7 +1799,7 @@ OpenMCCellAverageProblem::getPointInCell() for (const auto & c : _local_cell_to_elem) { // we are only dealing with local elements here, no need to check for nullptr - const Elem * elem = _mesh.queryElemPtr(globalElemID(c.second[0])); + const Elem * elem = getMooseMesh().queryElemPtr(globalElemID(c.second[0])); const Point & p = elem->vertex_average(); x.push_back(p(0)); @@ -1974,7 +1989,7 @@ OpenMCCellAverageProblem::addExternalVariables() { auto number = addExternalVariable(v.first, &v.second); - auto ids = _mesh.getSubdomainIDs(v.second); + auto ids = getMooseMesh().getSubdomainIDs(v.second); for (const auto & s : ids) _subdomain_to_density_vars[s] = {number, v.first}; } @@ -1984,7 +1999,7 @@ OpenMCCellAverageProblem::addExternalVariables() { auto number = addExternalVariable(v.first, &v.second); - auto ids = _mesh.getSubdomainIDs(v.second); + auto ids = getMooseMesh().getSubdomainIDs(v.second); for (const auto & s : ids) _subdomain_to_temp_vars[s] = {number, v.first}; } @@ -2049,7 +2064,7 @@ OpenMCCellAverageProblem::computeVolumeWeightedCellInput( for (const auto & e : c.second) { // we are only accessing local elements here, so no need to check for nullptr - const auto * elem = _mesh.queryElemPtr(globalElemID(e)); + const auto * elem = getMooseMesh().queryElemPtr(globalElemID(e)); auto v = var_num.at(elem->subdomain_id()).first; auto dof_idx = elem->dof_number(sys_number, v, 0); product += (*_serialized_solution)(dof_idx) * elem->volume(); @@ -2322,6 +2337,10 @@ OpenMCCellAverageProblem::syncSolutions(ExternalProblem::Direction direction) if (_volume_calc) _volume_calc->resetVolumeCalculation(); + if (_use_displaced) + { + _displaced_problem->updateMesh(); + } resetTallies(); setupProblem(); } diff --git a/src/userobjects/OpenMCVolumeCalculation.C b/src/userobjects/OpenMCVolumeCalculation.C index 34622d2e1..6c9b4e702 100644 --- a/src/userobjects/OpenMCVolumeCalculation.C +++ b/src/userobjects/OpenMCVolumeCalculation.C @@ -21,6 +21,7 @@ #include "OpenMCVolumeCalculation.h" #include "OpenMCCellAverageProblem.h" #include "UserErrorChecking.h" +#include "DisplacedProblem.h" registerMooseObject("CardinalApp", OpenMCVolumeCalculation); @@ -73,13 +74,10 @@ OpenMCVolumeCalculation::OpenMCVolumeCalculation(const InputParameters & paramet _scaling = openmc_problem->scaling(); - BoundingBox box = MeshTools::create_bounding_box(_fe_problem.mesh()); - _lower_left = isParamValid("lower_left") ? getParam("lower_left") : box.min(); - _upper_right = isParamValid("upper_right") ? getParam("upper_right") : box.max(); - - if (_lower_left >= _upper_right) - mooseError("The 'upper_right' (", _upper_right(0), ", ", _upper_right(1), ", ", _upper_right(2), ") " - "must be greater than the 'lower_left' (", _lower_left(0), ", ", _lower_left(1), ", ", _lower_left(2), ")!"); + if (isParamValid("lower_left")) + _lower_left = getParam("lower_left"); + if (isParamValid("upper_right")) + _upper_right = getParam("upper_right"); } openmc::Position @@ -96,9 +94,41 @@ OpenMCVolumeCalculation::resetVolumeCalculation() openmc::model::volume_calcs.erase(idx); } +MooseMesh & +OpenMCVolumeCalculation::getMooseMesh() +{ + return ((_fe_problem.getDisplacedProblem()) ? _fe_problem.getDisplacedProblem()->mesh() + : _fe_problem.mesh()); +} + void OpenMCVolumeCalculation::initializeVolumeCalculation() { + BoundingBox box = MeshTools::create_bounding_box(getMooseMesh().getMesh()); + if (_fe_problem.getDisplacedProblem() != nullptr) + _fe_problem.getDisplacedProblem()->updateMesh(); + + if (!isParamValid("lower_left")) + _lower_left = box.min(); + if (!isParamValid("upper_right")) + _upper_right = box.max(); + + if ((_lower_left >= _upper_right) && (isParamValid("lower_left") || isParamValid("lower_left"))) + mooseError("The 'upper_right' (", + _upper_right(0), + ", ", + _upper_right(1), + ", ", + _upper_right(2), + ") " + "must be greater than the 'lower_left' (", + _lower_left(0), + ", ", + _lower_left(1), + ", ", + _lower_left(2), + ")!"); + auto openmc_problem = dynamic_cast(&_fe_problem); _volume_calc.reset(new openmc::VolumeCalculation());