Skip to content

Commit ddc9526

Browse files
Storing surface source points using a cell ID (#2888)
Co-authored-by: Paul Romano <[email protected]>
1 parent 84f561c commit ddc9526

File tree

120 files changed

+3963
-86
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+3963
-86
lines changed

docs/source/io_formats/settings.rst

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,12 @@ attributes/sub-elements:
902902

903903
The ``<surf_source_write>`` element triggers OpenMC to bank particles crossing
904904
certain surfaces and write out the source bank in a separate file called
905-
``surface_source.h5``. This element has the following attributes/sub-elements:
905+
``surface_source.h5``. One or multiple surface IDs and one cell ID can be used
906+
to select the surfaces of interest. If no surface IDs are declared, every surface
907+
of the model is eligible to bank particles. In that case, a cell ID (using
908+
either the ``cell``, ``cellfrom`` or ``cellto`` attributes) can be used to select
909+
every surface of a specific cell. This element has the following
910+
attributes/sub-elements:
906911

907912
:surface_ids:
908913
A list of integers separated by spaces indicating the unique IDs of surfaces
@@ -928,6 +933,34 @@ certain surfaces and write out the source bank in a separate file called
928933

929934
.. _MCPL: https://mctools.github.io/mcpl/mcpl.pdf
930935

936+
:cell:
937+
An integer representing the cell ID used to determine if particles crossing
938+
identified surfaces are to be banked. Particles coming from or going to this
939+
declared cell will be banked if they cross the identified surfaces.
940+
941+
*Default*: None
942+
943+
:cellfrom:
944+
An integer representing the cell ID used to determine if particles crossing
945+
identified surfaces are to be banked. Particles coming from this declared
946+
cell will be banked if they cross the identified surfaces.
947+
948+
*Default*: None
949+
950+
:cellto:
951+
An integer representing the cell ID used to determine if particles crossing
952+
identified surfaces are to be banked. Particles going to this declared cell
953+
will be banked if they cross the identified surfaces.
954+
955+
*Default*: None
956+
957+
.. note:: The ``cell``, ``cellfrom`` and ``cellto`` attributes cannot be
958+
used simultaneously.
959+
960+
.. note:: Surfaces with boundary conditions that are not "transmission" or "vacuum"
961+
are not eligible to store any particles when using ``cell``, ``cellfrom``
962+
or ``cellto`` attributes. It is recommended to use surface IDs instead.
963+
931964
------------------------------
932965
``<survival_biasing>`` Element
933966
------------------------------

docs/source/usersguide/settings.rst

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ source file can be manually generated with the :func:`openmc.write_source_file`
277277
function. This is particularly useful for coupling OpenMC with another program
278278
that generates a source to be used in OpenMC.
279279

280+
Surface Sources
281+
+++++++++++++++
282+
280283
A source file based on particles that cross one or more surfaces can be
281284
generated during a simulation using the :attr:`Settings.surf_source_write`
282285
attribute::
@@ -287,7 +290,51 @@ attribute::
287290
}
288291

289292
In this example, at most 10,000 source particles are stored when particles cross
290-
surfaces with IDs of 1, 2, or 3.
293+
surfaces with IDs of 1, 2, or 3. If no surface IDs are declared, particles
294+
crossing any surface of the model will be banked::
295+
296+
settings.surf_source_write = {'max_particles': 10000}
297+
298+
A cell ID can also be used to bank particles that are crossing any surface of
299+
a cell that particles are either coming from or going to::
300+
301+
settings.surf_source_write = {'cell': 1, 'max_particles': 10000}
302+
303+
In this example, particles that are crossing any surface that bounds cell 1 will
304+
be banked excluding any surface that does not use a 'transmission' or 'vacuum'
305+
boundary condition.
306+
307+
.. note:: Surfaces with boundary conditions that are not "transmission" or "vacuum"
308+
are not eligible to store any particles when using ``cell``, ``cellfrom``
309+
or ``cellto`` attributes. It is recommended to use surface IDs instead.
310+
311+
Surface IDs can be used in combination with a cell ID::
312+
313+
settings.surf_source_write = {
314+
'cell': 1,
315+
'surfaces_ids': [1, 2, 3],
316+
'max_particles': 10000
317+
}
318+
319+
In that case, only particles that are crossing the declared surfaces coming from
320+
cell 1 or going to cell 1 will be banked. To account specifically for particles
321+
leaving or entering a given cell, ``cellfrom`` and ``cellto`` are also available
322+
to respectively account for particles coming from a cell::
323+
324+
settings.surf_source_write = {
325+
'cellfrom': 1,
326+
'max_particles': 10000
327+
}
328+
329+
or particles going to a cell::
330+
331+
settings.surf_source_write = {
332+
'cellto': 1,
333+
'max_particles': 10000
334+
}
335+
336+
.. note:: The ``cell``, ``cellfrom`` and ``cellto`` attributes cannot be
337+
used simultaneously.
291338

292339
.. _compiled_source:
293340

include/openmc/particle.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class Particle : public ParticleData {
7474
void pht_secondary_particles();
7575

7676
//! Cross a surface and handle boundary conditions
77-
void cross_surface();
77+
void cross_surface(const Surface& surf);
7878

7979
//! Cross a vacuum boundary condition.
8080
//
@@ -127,6 +127,8 @@ std::string particle_type_to_str(ParticleType type);
127127

128128
ParticleType str_to_particle_type(std::string str);
129129

130+
void add_surf_source_to_bank(Particle& p, const Surface& surf);
131+
130132
} // namespace openmc
131133

132134
#endif // OPENMC_PARTICLE_H

include/openmc/particle_data.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,15 @@ class GeometryState {
211211
// resets all coordinate levels for the particle
212212
void clear()
213213
{
214-
for (auto& level : coord_)
214+
for (auto& level : coord_) {
215215
level.reset();
216+
}
216217
n_coord_ = 1;
218+
219+
for (auto& cell : cell_last_) {
220+
cell = C_NONE;
221+
}
222+
n_coord_last_ = 1;
217223
}
218224

219225
// Initialize all internal state from position and direction

include/openmc/settings.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@
1616

1717
namespace openmc {
1818

19+
// Type of surface source write
20+
enum class SSWCellType {
21+
None,
22+
Both,
23+
From,
24+
To,
25+
};
26+
1927
//==============================================================================
2028
// Global variable declarations
2129
//==============================================================================
@@ -125,6 +133,10 @@ extern int
125133
max_history_splits; //!< maximum number of particle splits for weight windows
126134
extern int64_t max_surface_particles; //!< maximum number of particles to be
127135
//!< banked on surfaces per process
136+
extern int64_t ssw_cell_id; //!< Cell id for the surface source
137+
//!< write setting
138+
extern SSWCellType ssw_cell_type; //!< Type of option for the cell
139+
//!< argument of surface source write
128140
extern TemperatureMethod
129141
temperature_method; //!< method for choosing temperatures
130142
extern double

openmc/settings.py

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,15 @@ class Settings:
201201
:max_particles: Maximum number of particles to be banked on surfaces per
202202
process (int)
203203
:mcpl: Output in the form of an MCPL-file (bool)
204+
:cell: Cell ID used to determine if particles crossing identified
205+
surfaces are to be banked. Particles coming from or going to this
206+
declared cell will be banked (int)
207+
:cellfrom: Cell ID used to determine if particles crossing identified
208+
surfaces are to be banked. Particles coming from this
209+
declared cell will be banked (int)
210+
:cellto: Cell ID used to determine if particles crossing identified
211+
surfaces are to be banked. Particles going to this declared
212+
cell will be banked (int)
204213
survival_biasing : bool
205214
Indicate whether survival biasing is to be used
206215
tabular_legendre : dict
@@ -693,23 +702,30 @@ def surf_source_write(self) -> dict:
693702

694703
@surf_source_write.setter
695704
def surf_source_write(self, surf_source_write: dict):
696-
cv.check_type('surface source writing options', surf_source_write, Mapping)
705+
cv.check_type("surface source writing options", surf_source_write, Mapping)
697706
for key, value in surf_source_write.items():
698-
cv.check_value('surface source writing key', key,
699-
('surface_ids', 'max_particles', 'mcpl'))
700-
if key == 'surface_ids':
701-
cv.check_type('surface ids for source banking', value,
702-
Iterable, Integral)
707+
cv.check_value(
708+
"surface source writing key",
709+
key,
710+
("surface_ids", "max_particles", "mcpl", "cell", "cellfrom", "cellto"),
711+
)
712+
if key == "surface_ids":
713+
cv.check_type(
714+
"surface ids for source banking", value, Iterable, Integral
715+
)
703716
for surf_id in value:
704-
cv.check_greater_than('surface id for source banking',
705-
surf_id, 0)
706-
elif key == 'max_particles':
707-
cv.check_type('maximum particle banks on surfaces per process',
708-
value, Integral)
709-
cv.check_greater_than('maximum particle banks on surfaces per process',
710-
value, 0)
711-
elif key == 'mcpl':
712-
cv.check_type('write to an MCPL-format file', value, bool)
717+
cv.check_greater_than("surface id for source banking", surf_id, 0)
718+
elif key == "mcpl":
719+
cv.check_type("write to an MCPL-format file", value, bool)
720+
elif key in ("max_particles", "cell", "cellfrom", "cellto"):
721+
name = {
722+
"max_particles": "maximum particle banks on surfaces per process",
723+
"cell": "Cell ID for source banking (from or to)",
724+
"cellfrom": "Cell ID for source banking (from only)",
725+
"cellto": "Cell ID for source banking (to only)",
726+
}[key]
727+
cv.check_type(name, value, Integral)
728+
cv.check_greater_than(name, value, 0)
713729

714730
self._surf_source_write = surf_source_write
715731

@@ -1207,16 +1223,18 @@ def _create_surf_source_read_subelement(self, root):
12071223
def _create_surf_source_write_subelement(self, root):
12081224
if self._surf_source_write:
12091225
element = ET.SubElement(root, "surf_source_write")
1210-
if 'surface_ids' in self._surf_source_write:
1226+
if "surface_ids" in self._surf_source_write:
12111227
subelement = ET.SubElement(element, "surface_ids")
1212-
subelement.text = ' '.join(
1213-
str(x) for x in self._surf_source_write['surface_ids'])
1214-
if 'max_particles' in self._surf_source_write:
1215-
subelement = ET.SubElement(element, "max_particles")
1216-
subelement.text = str(self._surf_source_write['max_particles'])
1217-
if 'mcpl' in self._surf_source_write:
1228+
subelement.text = " ".join(
1229+
str(x) for x in self._surf_source_write["surface_ids"]
1230+
)
1231+
if "mcpl" in self._surf_source_write:
12181232
subelement = ET.SubElement(element, "mcpl")
1219-
subelement.text = str(self._surf_source_write['mcpl']).lower()
1233+
subelement.text = str(self._surf_source_write["mcpl"]).lower()
1234+
for key in ("max_particles", "cell", "cellfrom", "cellto"):
1235+
if key in self._surf_source_write:
1236+
subelement = ET.SubElement(element, key)
1237+
subelement.text = str(self._surf_source_write[key])
12201238

12211239
def _create_confidence_intervals(self, root):
12221240
if self._confidence_intervals is not None:
@@ -1381,9 +1399,9 @@ def _create_create_fission_neutrons_subelement(self, root):
13811399
elem.text = str(self._create_fission_neutrons).lower()
13821400

13831401
def _create_create_delayed_neutrons_subelement(self, root):
1384-
if self._create_delayed_neutrons is not None:
1385-
elem = ET.SubElement(root, "create_delayed_neutrons")
1386-
elem.text = str(self._create_delayed_neutrons).lower()
1402+
if self._create_delayed_neutrons is not None:
1403+
elem = ET.SubElement(root, "create_delayed_neutrons")
1404+
elem.text = str(self._create_delayed_neutrons).lower()
13871405

13881406
def _create_delayed_photon_scaling_subelement(self, root):
13891407
if self._delayed_photon_scaling is not None:
@@ -1610,17 +1628,18 @@ def _surf_source_read_from_xml_element(self, root):
16101628

16111629
def _surf_source_write_from_xml_element(self, root):
16121630
elem = root.find('surf_source_write')
1613-
if elem is not None:
1614-
for key in ('surface_ids', 'max_particles','mcpl'):
1615-
value = get_text(elem, key)
1616-
if value is not None:
1617-
if key == 'surface_ids':
1618-
value = [int(x) for x in value.split()]
1619-
elif key in ('max_particles'):
1620-
value = int(value)
1621-
elif key == 'mcpl':
1622-
value = value in ('true', '1')
1623-
self.surf_source_write[key] = value
1631+
if elem is None:
1632+
return
1633+
for key in ('surface_ids', 'max_particles', 'mcpl', 'cell', 'cellto', 'cellfrom'):
1634+
value = get_text(elem, key)
1635+
if value is not None:
1636+
if key == 'surface_ids':
1637+
value = [int(x) for x in value.split()]
1638+
elif key == 'mcpl':
1639+
value = value in ('true', '1')
1640+
elif key in ('max_particles', 'cell', 'cellfrom', 'cellto'):
1641+
value = int(value)
1642+
self.surf_source_write[key] = value
16241643

16251644
def _confidence_intervals_from_xml_element(self, root):
16261645
text = get_text(root, 'confidence_intervals')

src/dagmc.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,10 @@ void DAGUniverse::init_geometry()
271271
: dagmc_instance_->id_by_index(2, i + 1);
272272

273273
// set surface source attribute if needed
274-
if (contains(settings::source_write_surf_id, s->id_))
274+
if (contains(settings::source_write_surf_id, s->id_) ||
275+
settings::source_write_surf_id.empty()) {
275276
s->surf_source_ = true;
277+
}
276278

277279
// set BCs
278280
std::string bc_value =

0 commit comments

Comments
 (0)