Skip to content

Commit 8d872be

Browse files
committed
Replace material overrides with standard cell specification subelements
1 parent 597b11c commit 8d872be

4 files changed

Lines changed: 140 additions & 34 deletions

File tree

include/openmc/dagmc.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ class DAGCell : public Cell {
9494
class DAGUniverse : public Universe {
9595

9696
public:
97+
using MaterialOverrides = std::unordered_map<int32_t, vector<int32_t>>;
98+
using TemperatureOverrides = std::unordered_map<int32_t, vector<double>>;
99+
97100
explicit DAGUniverse(pugi::xml_node node);
98101

99102
//! Create a new DAGMC universe
@@ -112,6 +115,8 @@ class DAGUniverse : public Universe {
112115
//! Initialize the DAGMC accel. data structures, indices, material
113116
//! assignments, etc.
114117
void initialize();
118+
void initialize(const MaterialOverrides& material_overrides,
119+
const TemperatureOverrides& temperature_overrides);
115120

116121
//! Reads UWUW materials and returns an ID map
117122
void read_uwuw_materials();
@@ -146,7 +151,8 @@ class DAGUniverse : public Universe {
146151

147152
//! Assign a material overriding normal assignement to a cell
148153
//! \param[in] c The OpenMC cell to which the material is assigned
149-
void override_assign_material(std::unique_ptr<DAGCell>& c) const;
154+
void override_assign_material(std::unique_ptr<DAGCell>& c,
155+
const MaterialOverrides& material_overrides) const;
150156

151157
//! Return the index into the model cells vector for a given DAGMC volume
152158
//! handle in the universe
@@ -187,7 +193,8 @@ class DAGUniverse : public Universe {
187193
void set_id(); //!< Deduce the universe id from model::universes
188194
void init_dagmc(); //!< Create and initialise DAGMC pointer
189195
void init_metadata(); //!< Create and initialise dagmcMetaData pointer
190-
void init_geometry(); //!< Create cells and surfaces from DAGMC entities
196+
void init_geometry(const MaterialOverrides& material_overrides,
197+
const TemperatureOverrides& temperature_overrides);
191198

192199
std::string
193200
filename_; //!< Name of the DAGMC file used to create this universe
@@ -201,11 +208,6 @@ class DAGUniverse : public Universe {
201208
//!< generate new material IDs for the universe
202209
bool has_graveyard_; //!< Indicates if the DAGMC geometry has a "graveyard"
203210
//!< volume
204-
std::unordered_map<int32_t, vector<int32_t>>
205-
material_overrides_; //!< Map of DAGMC cell material overrides
206-
//!< keys correspond to the DAGMCCell id
207-
//!< values are a list of material ids used
208-
//!< for the override
209211
};
210212

211213
//==============================================================================

openmc/dagmc.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ def _parse_cell_overrides(self, elem, mats):
509509
if get_text(cell_elem, 'universe') is not None:
510510
raise ValueError("DAGMC cell overrides cannot specify a "
511511
"universe.")
512-
for tag in ('temperature', 'density', 'translation', 'rotation', 'volume'):
512+
for tag in ('density', 'translation', 'rotation', 'volume'):
513513
if get_text(cell_elem, tag) is not None:
514514
raise ValueError(
515515
"DAGMC cell overrides currently only support material "
@@ -526,11 +526,22 @@ def _parse_cell_overrides(self, elem, mats):
526526
else:
527527
fill = mat_objs
528528

529+
temperature = get_elem_list(cell_elem, 'temperature', float)
530+
if temperature is not None:
531+
if len(temperature) > 1:
532+
cell_temp = temperature
533+
else:
534+
cell_temp = temperature[0]
535+
else:
536+
cell_temp = None
537+
529538
if cell_id in self.cells:
530539
raise ValueError(
531540
f"Duplicate DAGMC cell override specified for cell {cell_id}.")
532-
self.add_cell(openmc.DAGMCCell(
533-
cell_id=cell_id, name=name or '', fill=fill))
541+
cell = openmc.DAGMCCell(cell_id=cell_id, name=name or '', fill=fill)
542+
if cell_temp is not None:
543+
cell.temperature = cell_temp
544+
self.add_cell(cell)
534545
self._material_overrides[cell_id] = mat_objs
535546

536547
def _partial_deepcopy(self):
@@ -675,8 +686,13 @@ def create_xml_subelement(self, xml_element, memo=None):
675686
if self.fill_type not in ('void', 'material', 'distribmat'):
676687
raise TypeError("DAGMC cell overrides currently only support "
677688
"material fills.")
689+
if self.temperature is not None and self.fill_type not in (
690+
'material', 'distribmat'
691+
):
692+
raise TypeError("DAGMC cell temperature overrides require a "
693+
"material fill.")
678694
if any(getattr(self, attr) is not None for attr in (
679-
'temperature', 'density', 'translation', 'rotation', 'volume'
695+
'density', 'translation', 'rotation', 'volume'
680696
)):
681697
raise TypeError("DAGMC cell overrides currently only support "
682698
"material fills.")

src/dagmc.cpp

Lines changed: 86 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ namespace openmc {
5050

5151
DAGUniverse::DAGUniverse(pugi::xml_node node)
5252
{
53+
MaterialOverrides material_overrides;
54+
TemperatureOverrides temperature_overrides;
55+
5356
if (check_for_node(node, "id")) {
5457
id_ = std::stoi(get_node_value(node, "id"));
5558
} else {
@@ -99,8 +102,7 @@ DAGUniverse::DAGUniverse(pugi::xml_node node)
99102
fatal_error(fmt::format(
100103
"DAGMC cell {} override cannot specify a universe.", cell_id));
101104
}
102-
if (check_for_node(cell_node, "temperature") ||
103-
check_for_node(cell_node, "density") ||
105+
if (check_for_node(cell_node, "density") ||
104106
check_for_node(cell_node, "translation") ||
105107
check_for_node(cell_node, "rotation") ||
106108
check_for_node(cell_node, "volume")) {
@@ -131,19 +133,36 @@ DAGUniverse::DAGUniverse(pugi::xml_node node)
131133
}
132134
}
133135

134-
auto inserted = material_overrides_.emplace(cell_id, override_mats);
136+
auto inserted = material_overrides.emplace(cell_id, override_mats);
135137
if (!inserted.second) {
136138
fatal_error(fmt::format(
137139
"Duplicate DAGMC cell override specified for cell {}", cell_id));
138140
}
141+
142+
if (check_for_node(cell_node, "temperature")) {
143+
auto temperatures = get_node_array<double>(cell_node, "temperature");
144+
if (temperatures.empty()) {
145+
fatal_error(fmt::format(
146+
"DAGMC cell {} override has an empty temperature specification.",
147+
cell_id));
148+
}
149+
for (auto T : temperatures) {
150+
if (T < 0.0) {
151+
fatal_error(fmt::format(
152+
"DAGMC cell {} was specified with a negative temperature",
153+
cell_id));
154+
}
155+
}
156+
temperature_overrides.emplace(cell_id, temperatures);
157+
}
139158
}
140159
} else if (check_for_node(node, "material_overrides")) {
141160
fatal_error(
142161
"DAGMCUniverse <material_overrides> is no longer supported. Use nested "
143162
"<cell> elements under <dagmc_universe> instead.");
144163
}
145164

146-
initialize();
165+
initialize(material_overrides, temperature_overrides);
147166
}
148167

149168
DAGUniverse::DAGUniverse(
@@ -160,9 +179,11 @@ DAGUniverse::DAGUniverse(std::shared_ptr<moab::DagMC> dagmc_ptr,
160179
: dagmc_instance_(dagmc_ptr), filename_(filename),
161180
adjust_geometry_ids_(auto_geom_ids), adjust_material_ids_(auto_mat_ids)
162181
{
182+
MaterialOverrides material_overrides;
183+
TemperatureOverrides temperature_overrides;
163184
set_id();
164185
init_metadata();
165-
init_geometry();
186+
init_geometry(material_overrides, temperature_overrides);
166187
}
167188

168189
void DAGUniverse::set_id()
@@ -180,6 +201,14 @@ void DAGUniverse::set_id()
180201
}
181202

182203
void DAGUniverse::initialize()
204+
{
205+
MaterialOverrides material_overrides;
206+
TemperatureOverrides temperature_overrides;
207+
initialize(material_overrides, temperature_overrides);
208+
}
209+
210+
void DAGUniverse::initialize(const MaterialOverrides& material_overrides,
211+
const TemperatureOverrides& temperature_overrides)
183212
{
184213
#ifdef OPENMC_UWUW_ENABLED
185214
// read uwuw materials from the .h5m file if present
@@ -190,7 +219,7 @@ void DAGUniverse::initialize()
190219

191220
init_metadata();
192221

193-
init_geometry();
222+
init_geometry(material_overrides, temperature_overrides);
194223
}
195224

196225
void DAGUniverse::init_dagmc()
@@ -226,7 +255,8 @@ void DAGUniverse::init_metadata()
226255
MB_CHK_ERR_CONT(rval);
227256
}
228257

229-
void DAGUniverse::init_geometry()
258+
void DAGUniverse::init_geometry(const MaterialOverrides& material_overrides,
259+
const TemperatureOverrides& temperature_overrides)
230260
{
231261
moab::ErrorCode rval;
232262

@@ -280,8 +310,8 @@ void DAGUniverse::init_geometry()
280310
if (mat_str == "graveyard") {
281311
graveyard = vol_handle;
282312
}
283-
if (material_overrides_.count(c->id_)) {
284-
override_assign_material(c);
313+
if (material_overrides.count(c->id_)) {
314+
override_assign_material(c, material_overrides);
285315
} else if (mat_str == "void" || mat_str == "vacuum" ||
286316
mat_str == "graveyard") {
287317
c->material_.push_back(MATERIAL_VOID);
@@ -291,6 +321,35 @@ void DAGUniverse::init_geometry()
291321
legacy_assign_material(mat_str, c);
292322
}
293323

324+
if (temperature_overrides.count(c->id_)) {
325+
if (c->material_.empty() || c->material_[0] == MATERIAL_VOID) {
326+
fatal_error(fmt::format("DAGMC cell {} was specified with a "
327+
"temperature but no non-void material.",
328+
c->id_));
329+
}
330+
331+
c->sqrtkT_.clear();
332+
const auto& temp_overrides = temperature_overrides.at(c->id_);
333+
c->sqrtkT_.reserve(temp_overrides.size());
334+
for (auto T : temp_overrides) {
335+
c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * T));
336+
}
337+
338+
if (settings::verbosity >= 10) {
339+
std::stringstream override_values;
340+
for (size_t i = 0; i < temp_overrides.size(); ++i) {
341+
if (i > 0) {
342+
override_values << " ";
343+
}
344+
override_values << temp_overrides[i];
345+
}
346+
auto msg = fmt::format("Overriding DAGMC cell {} property "
347+
"'temperature [K]' with value(s): {}",
348+
c->id_, override_values.str());
349+
write_message(msg, 10);
350+
}
351+
}
352+
294353
// check for temperature assignment
295354
std::string temp_value;
296355

@@ -300,18 +359,21 @@ void DAGUniverse::init_geometry()
300359
continue;
301360
}
302361

303-
// assign cell temperature
304-
const auto& mat = model::materials[model::material_map.at(c->material_[0])];
305-
if (dagmc_instance_->has_prop(vol_handle, "temp")) {
306-
rval = dagmc_instance_->prop_value(vol_handle, "temp", temp_value);
307-
MB_CHK_ERR_CONT(rval);
308-
double temp = std::stod(temp_value);
309-
c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * temp));
310-
} else if (mat->temperature() > 0.0) {
311-
c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * mat->temperature()));
312-
} else {
313-
c->sqrtkT_.push_back(
314-
std::sqrt(K_BOLTZMANN * settings::temperature_default));
362+
// assign cell temperature if not explicitly overridden
363+
if (c->sqrtkT_.empty()) {
364+
const auto& mat =
365+
model::materials[model::material_map.at(c->material_[0])];
366+
if (dagmc_instance_->has_prop(vol_handle, "temp")) {
367+
rval = dagmc_instance_->prop_value(vol_handle, "temp", temp_value);
368+
MB_CHK_ERR_CONT(rval);
369+
double temp = std::stod(temp_value);
370+
c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * temp));
371+
} else if (mat->temperature() > 0.0) {
372+
c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * mat->temperature()));
373+
} else {
374+
c->sqrtkT_.push_back(
375+
std::sqrt(K_BOLTZMANN * settings::temperature_default));
376+
}
315377
}
316378

317379
model::cells.emplace_back(std::move(c));
@@ -678,15 +740,16 @@ void DAGUniverse::uwuw_assign_material(
678740
#endif // OPENMC_UWUW_ENABLED
679741
}
680742

681-
void DAGUniverse::override_assign_material(std::unique_ptr<DAGCell>& c) const
743+
void DAGUniverse::override_assign_material(std::unique_ptr<DAGCell>& c,
744+
const MaterialOverrides& material_overrides) const
682745
{
683746
// if Cell ID matches an override key, use it to override the material
684747
// assignment else if UWUW is used, get the material assignment from the DAGMC
685748
// metadata
686749
// Notify User that an override is being applied on a DAGMCCell
687750
write_message(fmt::format("Applying override for DAGMCCell {}", c->id_), 8);
688751

689-
const auto& mat_overrides = material_overrides_.at(c->id_);
752+
const auto& mat_overrides = material_overrides.at(c->id_);
690753
if (settings::verbosity >= 10) {
691754
std::stringstream override_values;
692755
for (size_t i = 0; i < mat_overrides.size(); ++i) {

tests/unit_tests/dagmc/test_model.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,28 @@ def test_dagmc_xml_reject_legacy_material_overrides():
314314
)
315315
with pytest.raises(ValueError, match="no longer supported"):
316316
openmc.DAGMCUniverse.from_xml_element(elem, mats)
317+
318+
319+
def test_dagmc_xml_temperature_roundtrip():
320+
mat = openmc.Material(1)
321+
mats = {'1': mat, 'void': None}
322+
323+
elem = ET.fromstring(
324+
'<dagmc_universe id="10" filename="dagmc.h5m">'
325+
'<cell id="7" material="1" temperature="825.0"/>'
326+
'</dagmc_universe>'
327+
)
328+
329+
dag_univ = openmc.DAGMCUniverse.from_xml_element(elem, mats)
330+
assert dag_univ.cells[7].fill.id == 1
331+
assert dag_univ.cells[7].temperature == pytest.approx(825.0)
332+
333+
root = ET.Element('geometry')
334+
dag_univ.create_xml_subelement(root)
335+
dagmc_elem = root.find('dagmc_universe')
336+
xml_cell = dagmc_elem.find('cell')
337+
assert xml_cell.get('temperature') == '825.0'
338+
339+
dag_univ_roundtrip = openmc.DAGMCUniverse.from_xml_element(dagmc_elem, mats)
340+
assert dag_univ_roundtrip.cells[7].fill.id == 1
341+
assert dag_univ_roundtrip.cells[7].temperature == pytest.approx(825.0)

0 commit comments

Comments
 (0)