This commit is contained in:
Skywalker 2026-07-17 23:12:48 +08:00 committed by GitHub
commit 8aae97acc3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 1183 additions and 33 deletions

View file

@ -217,6 +217,30 @@ Each ``<cell>`` element can have the following attributes or sub-elements:
*Default*: None
:triso_particle:
If the cell is filled with a TRISO particle, use this element to mark it.
.. note:: Only cells with spherical area can be marked.
*Default*: false
:virtual_lattice:
If the cell is filled with a matrix containing the TRISO particle, use this
element to mark it. This can accelerate the search speed of neutrons in the
region containing a large number of TRISO particles.
*Default*: false
:shape:
If the virtual_lattice is True. This element specifies the shape of the
lattice.
.. note:: The shape of the lattice must be specified if the virtual_lattice
is True. Related methods can be referred to Liang, J., Li, R., Liu, Z.,
2024. Virtual lattice method for efficient Monte Carlo transport simulation
of dispersion nuclear fuels. Computer Physics Communications 295, 108985.
https://doi.org/10.1016/j.cpc.2023.108985
---------------------
``<lattice>`` Element

View file

@ -99,13 +99,13 @@ public:
//! Get Boolean of if the cell is simple or not
bool is_simple() const { return simple_; }
//! Get a vector of the region expression in postfix notation
vector<int32_t> generate_postfix(int32_t cell_id) const;
private:
//----------------------------------------------------------------------------
// Private Methods
//! Get a vector of the region expression in postfix notation
vector<int32_t> generate_postfix(int32_t cell_id) const;
//! Determine if a particle is inside the cell for a simple cell (only
//! intersection operators)
bool contains_simple(Position r, Direction u, int32_t on_surface) const;
@ -365,7 +365,15 @@ public:
Fill type_; //!< Material, universe, or lattice
int32_t universe_; //!< Universe # this cell is in
int32_t fill_; //!< Universe # filling this cell
bool virtual_lattice_ =
false; //!< If the cell is the base of a virtual triso lattice
bool triso_particle_ = false; //!< If the cell contains a triso particle
//! \brief Specification of the virtual lattice
vector<double> vl_lower_left_;
vector<double> vl_pitch_;
vector<int32_t> vl_shape_;
vector<vector<int32_t>> vl_triso_distribution_;
//! \brief Index corresponding to this cell in distribcell arrays
int distribcell_index_ {C_NONE};
@ -421,10 +429,10 @@ public:
vector<int32_t> surfaces() const override { return region_.surfaces(); }
std::pair<double, int32_t> distance(Position r, Direction u,
int32_t on_surface, GeometryState* p) const override
{
return region_.distance(r, u, on_surface);
}
int32_t on_surface, GeometryState* p) const override;
std::pair<double, int32_t> distance_in_virtual_lattice(
Position r, Direction u, int32_t on_surface, GeometryState* p) const;
bool contains(Position r, Direction u, int32_t on_surface) const override
{

View file

@ -98,6 +98,10 @@ bool exhaustive_find_cell(GeometryState& p, bool verbose = false);
bool neighbor_list_find_cell(
GeometryState& p, bool verbose = false); // Only usable on surface crossings
bool find_cell_in_virtual_lattice(GeometryState& p,
bool verbose =
false); // Only usable on triso surface crossings in virtual lattice
//==============================================================================
//! Move a particle into a new lattice tile.
//==============================================================================

View file

@ -393,6 +393,9 @@ public:
// Boundary information
BoundaryInfo& boundary() { return boundary_; }
// Distance to the next collision
double& collision_distance() { return collision_distance_; }
#ifdef OPENMC_DAGMC_ENABLED
// DagMC state variables
moab::DagMC::RayHistory& history() { return history_; }
@ -446,6 +449,8 @@ private:
double density_mult_ {1.0}; //!< density multiplier
double density_mult_last_ {1.0}; //!< last density multiplier
double collision_distance_ {INFTY};
#ifdef OPENMC_DAGMC_ENABLED
moab::DagMC::RayHistory history_;
Direction last_dir_;
@ -562,8 +567,6 @@ private:
bool trace_ {false};
double collision_distance_;
int n_event_ {0};
int64_t n_tracks_ {0}; //!< number of tracks in this particle history
@ -745,9 +748,6 @@ public:
// Shows debug info
bool& trace() { return trace_; }
// Distance to the next collision
double& collision_distance() { return collision_distance_; }
// Number of events particle has undergone
int& n_event() { return n_event_; }

View file

@ -40,6 +40,9 @@ public:
std::string name_; //!< User-defined name
unique_ptr<BoundaryCondition> bc_; //!< Boundary condition
bool surf_source_ {false}; //!< Activate source banking for the surface?
int triso_base_index_;
int triso_particle_index_ = -1;
bool is_triso_surface_ = false;
explicit Surface(pugi::xml_node surf_node);
Surface();
@ -79,6 +82,15 @@ public:
//! exactly on the surface.
virtual double distance(Position r, Direction u, bool coincident) const = 0;
virtual bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return {};
};
virtual void connect_to_triso_base(int triso_index, std::string key) {};
virtual vector<double> get_center() const { return {}; };
virtual double get_radius() const { return {}; };
//! Compute the local outward normal direction of the surface.
//! \param r A 3D Cartesian coordinate.
//! \return Normal direction
@ -117,6 +129,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
BoundingBox bounding_box(bool pos_side) const override;
double x0_;
@ -135,6 +149,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
BoundingBox bounding_box(bool pos_side) const override;
double y0_;
@ -153,6 +169,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
BoundingBox bounding_box(bool pos_side) const override;
double z0_;
@ -170,6 +188,8 @@ public:
double evaluate(Position r) const override;
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
void to_hdf5_inner(hid_t group_id) const override;
double A_, B_, C_, D_;
@ -189,6 +209,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
BoundingBox bounding_box(bool pos_side) const override;
double y0_, z0_, radius_;
@ -208,6 +230,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
BoundingBox bounding_box(bool pos_side) const override;
double x0_, z0_, radius_;
@ -227,6 +251,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
BoundingBox bounding_box(bool pos_side) const override;
double x0_, y0_, radius_;
@ -246,9 +272,15 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
BoundingBox bounding_box(bool pos_side) const override;
vector<double> get_center() const override;
double get_radius() const override;
void connect_to_triso_base(int triso_index, std::string key) override;
double x0_, y0_, z0_, radius_;
// int triso_base_index_ = -1;
};
//==============================================================================
@ -265,6 +297,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
double x0_, y0_, z0_, radius_sq_;
};
@ -283,6 +317,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
double x0_, y0_, z0_, radius_sq_;
};
@ -301,6 +337,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
double x0_, y0_, z0_, radius_sq_;
};
@ -319,6 +357,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
// Ax^2 + By^2 + Cz^2 + Dxy + Eyz + Fxz + Gx + Hy + Jz + K = 0
double A_, B_, C_, D_, E_, F_, G_, H_, J_, K_;
@ -337,6 +377,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
double x0_, y0_, z0_, A_, B_, C_;
};
@ -354,6 +396,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
double x0_, y0_, z0_, A_, B_, C_;
};
@ -371,6 +415,8 @@ public:
double distance(Position r, Direction u, bool coincident) const override;
Direction normal(Position r) const override;
void to_hdf5_inner(hid_t group_id) const override;
bool triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const override;
double x0_, y0_, z0_, A_, B_, C_;
};

View file

@ -27,9 +27,10 @@ extern vector<unique_ptr<Universe>> universes;
class Universe {
public:
int32_t id_; //!< Unique ID
vector<int32_t> cells_; //!< Cells within this universe
int32_t n_instances_; //!< Number of instances of this universe
int32_t id_; //!< Unique ID
vector<int32_t> cells_; //!< Cells within this universe
int filled_with_triso_base_ = -1; //!< ID of cell filled with virtual lattice
int32_t n_instances_; //!< Number of instances of this universe
//! \brief Write universe information to an HDF5 group.
//! \param group_id An HDF5 group id.
@ -37,6 +38,8 @@ public:
virtual bool find_cell(GeometryState& p) const;
virtual bool find_cell_in_virtual_lattice(GeometryState& p) const;
BoundingBox bounding_box() const;
/* By default, universes are CSG universes. The DAGMC

View file

@ -119,6 +119,11 @@ class Cell(IDManagerMixin):
self._num_instances = None
self._volume = None
self._atoms = None
self._triso_particle = False
self.virtual_lattice = False
self.lower_left = None
self.pitch = None
self.shape = None
def __contains__(self, point):
if self.region is None:
@ -625,6 +630,13 @@ class Cell(IDManagerMixin):
"""
element = ET.Element("cell")
element.set("id", str(self.id))
if self._triso_particle:
element.set("triso_particle", 'true')
if self.virtual_lattice:
element.set("virtual_lattice", str(self.virtual_lattice))
element.set("lower_left", ' '.join(map(str, self.lower_left)))
element.set("pitch", ' '.join(map(str, self.pitch)))
element.set("shape", ' '.join(map(str, self.shape)))
if len(self._name) > 0:
element.set("name", str(self.name))

View file

@ -55,6 +55,7 @@ class TRISO(openmc.Cell):
def __init__(self, outer_radius, fill, center=(0., 0., 0.)):
self._surface = openmc.Sphere(r=outer_radius)
self._triso_particle = False
super().__init__(fill=fill, region=-self._surface)
self.center = np.asarray(center)
@ -802,7 +803,7 @@ class _SphericalShell(_Container):
q[:] = (q - c)*ll[0]/r + c
def create_triso_lattice(trisos, lower_left, pitch, shape, background):
def create_triso_lattice(trisos, lower_left, pitch, shape, background, virtual=False):
"""Create a lattice containing TRISO particles for optimized tracking.
Parameters
@ -818,6 +819,11 @@ def create_triso_lattice(trisos, lower_left, pitch, shape, background):
background : openmc.Material
A background material that is used anywhere within the lattice but
outside a TRISO particle
virtual : bool
If True, create a virtual lattice where each cell is repeated
according to the pitch and shape. This is useful for creating a
lattice with a very large number of elements.
Default is False.
Returns
-------
@ -826,6 +832,12 @@ def create_triso_lattice(trisos, lower_left, pitch, shape, background):
"""
if virtual:
real_pitch = copy.deepcopy(pitch)
real_shape = copy.deepcopy(shape)
pitch = [real_pitch[i]*real_shape[i] for i in range(len(real_pitch))]
shape = [1 for i in range(len(real_shape))]
lattice = openmc.RectLattice()
lattice.lower_left = lower_left
lattice.pitch = pitch
@ -845,6 +857,8 @@ def create_triso_lattice(trisos, lower_left, pitch, shape, background):
y0=t._surface.y0,
z0=t._surface.z0)
t_copy.region = -t_copy._surface
if virtual:
t_copy._triso_particle = True
triso_locations[idx].append(t_copy)
else:
warnings.warn('TRISO particle is partially or completely '
@ -859,6 +873,12 @@ def create_triso_lattice(trisos, lower_left, pitch, shape, background):
else:
background_cell = openmc.Cell(fill=background)
if virtual:
background_cell.virtual_lattice = True
background_cell.pitch = real_pitch
background_cell.shape = real_shape
background_cell.lower_left = [-pitch[i]/2 for i in range(len(pitch))]
u = openmc.Universe()
u.add_cell(background_cell)
for t in triso_list:

View file

@ -112,6 +112,10 @@ class Summary:
if "dagmc" not in self._f['geometry'].attrs.keys():
self._read_surfaces()
cell_fills = self._read_cells()
# Read compact TRISO particle data if present
if 'geometry/triso_particles' in self._f:
triso_fills = self._read_triso_particles()
cell_fills.update(triso_fills)
self._read_universes()
self._read_lattices()
self._finalize_geometry(cell_fills)
@ -194,6 +198,69 @@ class Summary:
return cell_fills
def _read_triso_particles(self):
"""Read compact TRISO particle data from HDF5 and reconstruct objects.
Returns
-------
dict
Cell fill information for all TRISO and background cells
"""
triso_grp = self._f['geometry/triso_particles']
n_triso = int(triso_grp.attrs['n_triso'])
if n_triso == 0:
return {}
# Batch-read all arrays
positions = triso_grp['positions'][()] # (N, 4) array
surface_ids = triso_grp['surface_ids'][()] # (N,) array
cell_ids = triso_grp['cell_ids'][()] # (N,) array
fill_universes = triso_grp['fill_universes'][()] # (N,) array
group_offsets = triso_grp['group_offsets'][()] # (n_groups+1,) array
cell_fills = {}
# Create all TRISO Sphere surfaces in batch
for i in range(n_triso):
x0, y0, z0, r = positions[i]
sid = int(surface_ids[i])
surf = openmc.Sphere(x0=float(x0), y0=float(y0),
z0=float(z0), r=float(r),
surface_id=sid)
self._fast_surfaces[sid] = surf
# Create all TRISO Cell objects in batch
for i in range(n_triso):
cid = int(cell_ids[i])
sid = int(surface_ids[i])
fill_univ_id = int(fill_universes[i])
x0, y0, z0, _ = positions[i]
cell = openmc.Cell(cell_id=cid)
cell.region = -self._fast_surfaces[sid]
cell.translation = np.array([x0, y0, z0], dtype=np.float64)
cell_fills[cid] = ('universe', fill_univ_id)
self._fast_cells[cid] = cell
# Create background cells for each group
n_groups = len(group_offsets) - 1
groups_grp = triso_grp['groups']
for g in range(n_groups):
grp = groups_grp[str(g)]
bg_cell_id = int(grp['background_cell_id'][()])
bg_material_id = int(grp['background_material_id'][()])
bg_universe_id = int(grp['background_universe_id'][()])
bg_cell = openmc.Cell(cell_id=bg_cell_id)
bg_cell.virtual_lattice = True
bg_cell.lower_left = list(grp['vl_lower_left'][()])
bg_cell.pitch = list(grp['vl_pitch'][()])
bg_cell.shape = list(grp['vl_shape'][()])
cell_fills[bg_cell_id] = ('material', bg_material_id)
self._fast_cells[bg_cell_id] = bg_cell
return cell_fills
def _read_universes(self):
for group in self._f['geometry/universes'].values():
geom_type = group.get('geom_type')

View file

@ -36,6 +36,47 @@ vector<unique_ptr<Cell>> cells;
} // namespace model
vector<vector<int32_t>> generate_triso_distribution(vector<int> lattice_shape,
vector<double> lattice_pitch, vector<double> lattice_lower_left,
vector<std::int32_t> cell_rpn, int id)
{
vector<vector<int32_t>> triso_distribution(
lattice_shape[0] * lattice_shape[1] * lattice_shape[2]);
vector<double> mesh_center(3);
vector<int> mesh_ind(3);
for (int32_t token : cell_rpn) {
if (token >= OP_UNION)
continue;
vector<double> triso_center = model::surfaces[abs(token) - 1]->get_center();
for (int i = 0; i < 3; i++) {
mesh_ind[i] =
floor((triso_center[i] - lattice_lower_left[i]) / lattice_pitch[i]);
}
for (int i = mesh_ind[0] - 1; i <= mesh_ind[0] + 1; i++) {
for (int j = mesh_ind[1] - 1; j <= mesh_ind[1] + 1; j++) {
for (int k = mesh_ind[2] - 1; k <= mesh_ind[2] + 1; k++) {
if (i < 0 || i >= lattice_shape[0] || j < 0 ||
j >= lattice_shape[1] || k < 0 || k >= lattice_shape[2])
continue;
mesh_center[0] = (i + 0.5) * lattice_pitch[0] + lattice_lower_left[0];
mesh_center[1] = (j + 0.5) * lattice_pitch[1] + lattice_lower_left[1];
mesh_center[2] = (k + 0.5) * lattice_pitch[2] + lattice_lower_left[2];
if (model::surfaces[abs(token) - 1]->triso_in_mesh(
mesh_center, lattice_pitch)) {
triso_distribution[i + j * lattice_shape[0] +
k * lattice_shape[0] * lattice_shape[1]]
.push_back(token);
model::surfaces[abs(token) - 1]->connect_to_triso_base(id, "base");
}
}
}
}
}
return triso_distribution;
}
//==============================================================================
// Cell implementation
//==============================================================================
@ -419,6 +460,33 @@ CSGCell::CSGCell(pugi::xml_node cell_node)
universe_ = 0;
}
// Check if the cell is the base of a virtual triso lattice
bool virtual_lattice_present = check_for_node(cell_node, "virtual_lattice");
if (virtual_lattice_present) {
virtual_lattice_ = get_node_value_bool(cell_node, "virtual_lattice");
if (virtual_lattice_) {
if (check_for_node(cell_node, "lower_left") &&
check_for_node(cell_node, "pitch") &&
check_for_node(cell_node, "shape")) {
vl_lower_left_ = get_node_array<double>(cell_node, "lower_left");
vl_pitch_ = get_node_array<double>(cell_node, "pitch");
vl_shape_ = get_node_array<int>(cell_node, "shape");
} else {
fatal_error(fmt::format("Lower_left, pitch and shape of the virtual "
"lattice must be specified for cell {}",
id_));
}
}
} else {
virtual_lattice_ = false;
}
if (check_for_node(cell_node, "triso_particle")) {
triso_particle_ = get_node_value_bool(cell_node, "triso_particle");
} else {
triso_particle_ = false;
}
// Make sure that either material or fill was specified, but not both.
bool fill_present = check_for_node(cell_node, "fill");
bool material_present = check_for_node(cell_node, "material");
@ -508,6 +576,21 @@ CSGCell::CSGCell(pugi::xml_node cell_node)
// Morgans law
Region region(region_spec, id_);
region_ = region;
vector<int32_t> rpn = region_.generate_postfix(id_);
if (virtual_lattice_) {
vl_triso_distribution_ = generate_triso_distribution(
vl_shape_, vl_pitch_, vl_lower_left_, rpn, id_);
}
if (triso_particle_) {
if (rpn.size() != 1) {
fatal_error(
fmt::format("Wrong surface definition of triso particle cell {}", id_));
} else {
model::surfaces[abs(rpn[0]) - 1]->connect_to_triso_base(id_, "particle");
}
}
// Read the translation vector.
if (check_for_node(cell_node, "translation")) {
@ -574,6 +657,105 @@ vector<int32_t>::iterator CSGCell::find_left_parenthesis(
}
return it;
}
std::pair<double, int32_t> CSGCell::distance(
Position r, Direction u, int32_t on_surface, GeometryState* p) const
{
if (virtual_lattice_) {
return distance_in_virtual_lattice(r, u, on_surface, p);
} else {
return region_.distance(r, u, on_surface);
}
}
std::pair<double, int32_t> CSGCell::distance_in_virtual_lattice(
Position r, Direction u, int32_t on_surface, GeometryState* p) const
{
double min_dist {INFTY};
int32_t i_surf {std::numeric_limits<int32_t>::max()};
double min_dis_vl;
int32_t i_surf_vl;
double max_dis = p->collision_distance();
double tol_dis = 0;
vector<double> dis_to_bou(3), dis_to_bou_max(3);
double u_value = sqrt(pow(u.x, 2) + pow(u.y, 2) +
pow(u.z, 2)); // don't know if u has been normalized
vector<double> norm_u = {u.x / u_value, u.y / u_value, u.z / u_value};
vector<int> lat_ind(3);
vector<double> temp_pos = {r.x, r.y, r.z};
int loop_time;
for (int i = 0; i < 3; i++) {
lat_ind[i] = floor((temp_pos[i] - vl_lower_left_[i]) / vl_pitch_[i]);
if (lat_ind[i] == vl_shape_[i] && norm_u[i] < 0) {
lat_ind[i] = vl_shape_[i] - 1;
}
if (lat_ind[i] == -1 && norm_u[i] > 0) {
lat_ind[i] = 0;
}
}
dis_to_bou = {INFTY, INFTY, INFTY};
for (int i = 0; i < 3; i++) {
if (norm_u[i] > 0) {
dis_to_bou[i] = std::abs(
((lat_ind[i] + 1) * vl_pitch_[i] + vl_lower_left_[i] - temp_pos[i]) /
norm_u[i]);
dis_to_bou_max[i] = vl_pitch_[i] / norm_u[i];
} else if (norm_u[i] < 0) {
dis_to_bou[i] =
std::abs((lat_ind[i] * vl_pitch_[i] + vl_lower_left_[i] - temp_pos[i]) /
norm_u[i]);
dis_to_bou_max[i] = -vl_pitch_[i] / norm_u[i];
}
}
while (true) {
if (lat_ind[0] < 0 || lat_ind[0] >= vl_shape_[0] || lat_ind[1] < 0 ||
lat_ind[1] >= vl_shape_[1] || lat_ind[2] < 0 ||
lat_ind[2] >= vl_shape_[2])
break;
for (int token :
vl_triso_distribution_[lat_ind[0] + lat_ind[1] * vl_shape_[0] +
lat_ind[2] * vl_shape_[0] * vl_shape_[1]]) {
bool coincident {std::abs(token) == std::abs(on_surface)};
double d {model::surfaces[abs(token) - 1]->distance(r, u, coincident)};
if (d < min_dist) {
if (min_dist - d >= FP_PRECISION * min_dist) {
min_dist = d;
i_surf = -token;
}
}
}
int mes_bou_crossed = 0;
if (dis_to_bou[1] < dis_to_bou[0]) {
mes_bou_crossed = 1;
}
if (dis_to_bou[2] < dis_to_bou[mes_bou_crossed]) {
mes_bou_crossed = 2;
}
tol_dis = dis_to_bou[mes_bou_crossed];
if (min_dist < tol_dis) {
break;
}
if (norm_u[mes_bou_crossed] > 0) {
lat_ind[mes_bou_crossed] += 1;
} else {
lat_ind[mes_bou_crossed] += -1;
}
dis_to_bou[mes_bou_crossed] += dis_to_bou_max[mes_bou_crossed];
if (tol_dis > max_dis) {
break;
}
}
return {min_dist, i_surf};
}
//==============================================================================
// Region implementation
@ -1206,6 +1388,10 @@ void populate_universes()
model::universes[it->second]->cells_.push_back(index_cell);
}
if (model::cells[index_cell]->virtual_lattice_) {
model::universes[it->second]->filled_with_triso_base_ =
model::cells[index_cell]->id_;
}
}
// Add DAGUniverse implicit complement cells last

View file

@ -321,6 +321,98 @@ bool exhaustive_find_cell(GeometryState& p, bool verbose)
return find_cell_inner(p, nullptr, verbose);
}
bool find_cell_in_virtual_lattice(GeometryState& p, bool verbose)
{
int i_surface = std::abs(p.surface());
if (p.surface() > 0) {
for (int i = p.n_coord(); i < model::n_coord_levels; i++) {
p.coord(i).reset();
}
p.coord(p.n_coord() - 1).cell() =
model::cell_map[model::surfaces[i_surface - 1]->triso_base_index_];
} else if (p.surface() < 0) {
for (int i = p.n_coord(); i < model::n_coord_levels; i++) {
p.coord(i).reset();
}
if (model::surfaces[i_surface - 1]->triso_particle_index_ == -1) {
fatal_error(fmt::format("Particle cell of surface {} is not defined",
model::surfaces[i_surface - 1]->id_));
}
p.lowest_coord().cell() =
model::cell_map[model::surfaces[i_surface - 1]->triso_particle_index_];
}
// find material
bool found = true;
int i_cell = p.lowest_coord().cell();
for (;; ++p.n_coord()) {
if (i_cell == C_NONE) {
int i_universe = p.lowest_coord().universe();
const auto& univ {model::universes[i_universe]};
if (univ->filled_with_triso_base_ != -1) {
p.lowest_coord().cell() =
model::cell_map[univ->filled_with_triso_base_];
found = true;
} else {
found = univ->find_cell(p);
}
if (!found) {
return found;
}
}
i_cell = p.lowest_coord().cell();
Cell& c {*model::cells[i_cell]};
if (c.type_ == Fill::MATERIAL) {
// Found a material cell which means this is the lowest coord level.
p.cell_instance() = 0;
// Find the distribcell instance number.
if (c.distribcell_index_ >= 0) {
p.cell_instance() = cell_instance_at_level(p, p.n_coord() - 1);
}
// Set the material and temperature.
p.material_last() = p.material();
if (c.material_.size() > 1) {
p.material() = c.material_[p.cell_instance()];
} else {
p.material() = c.material_[0];
}
p.sqrtkT_last() = p.sqrtkT();
if (c.sqrtkT_.size() > 1) {
p.sqrtkT() = c.sqrtkT_[p.cell_instance()];
} else {
p.sqrtkT() = c.sqrtkT_[0];
}
return found;
} else if (c.type_ == Fill::UNIVERSE) {
//========================================================================
//! Found a lower universe, update this coord level then search the
//! next.
// Set the lower coordinate level universe.
auto& coor {p.coord(p.n_coord())};
coor.universe() = c.fill_;
// Set the position and direction.
coor.r() = p.r_local();
coor.u() = p.u_local();
// Apply translation.
coor.r() -= c.translation_;
// Apply rotation.
if (!c.rotation_.empty()) {
coor.rotate(c.rotation_);
}
i_cell = C_NONE;
}
}
}
//==============================================================================
void cross_lattice(GeometryState& p, const BoundaryInfo& boundary, bool verbose)

View file

@ -267,9 +267,6 @@ void Particle::event_calculate_xs()
void Particle::event_advance()
{
// Find the distance to the nearest boundary
boundary() = distance_to_boundary(*this);
// Sample a distance to collision
if (type() == ParticleType::electron() ||
type() == ParticleType::positron()) {
@ -280,6 +277,9 @@ void Particle::event_advance()
collision_distance() = -std::log(prn(current_seed())) / macro_xs().total;
}
// Find the distance to the nearest boundary
boundary() = distance_to_boundary(*this);
double speed = this->speed();
double time_cutoff = settings::time_cutoff[type().transport_index()];
double distance_cutoff =
@ -685,10 +685,16 @@ void Particle::cross_surface(const Surface& surf)
return;
}
#endif
int i_surface = std::abs(surface());
bool verbose = settings::verbosity >= 10 || trace();
if (neighbor_list_find_cell(*this, verbose)) {
return;
if (surf.is_triso_surface_) {
if (find_cell_in_virtual_lattice(*this, verbose)) {
return;
}
} else {
if (neighbor_list_find_cell(*this, verbose)) {
return;
}
}
// ==========================================================================

View file

@ -1,6 +1,7 @@
#include "openmc/summary.h"
#include <fmt/core.h>
#include <map>
#include "openmc/capi.h"
#include "openmc/cell.h"
@ -93,25 +94,139 @@ void write_nuclides(hid_t file)
close_group(macro_group);
}
void write_triso_particles(hid_t geom_group)
{
// Collect all TRISO surfaces and group by background cell ID
std::map<int32_t, vector<int32_t>> bg_to_surfs;
for (int i = 0; i < model::surfaces.size(); ++i) {
const auto& surf = model::surfaces[i];
if (surf->is_triso_surface_) {
bg_to_surfs[surf->triso_base_index_].push_back(i);
}
}
int n_groups = bg_to_surfs.size();
if (n_groups == 0)
return;
// Count total TRISO particles
int n_triso = 0;
for (const auto& [bg_id, surfs] : bg_to_surfs) {
n_triso += surfs.size();
}
// Build flat arrays
vector<double> positions(n_triso * 4);
vector<int32_t> surface_ids(n_triso);
vector<int32_t> cell_ids(n_triso);
vector<int32_t> fill_universes(n_triso);
vector<int32_t> group_offsets(n_groups + 1);
int idx = 0;
int g = 0;
group_offsets[0] = 0;
for (const auto& [bg_cell_id, surfs] : bg_to_surfs) {
for (const auto& i_surf : surfs) {
const auto& surf = model::surfaces[i_surf];
vector<double> center = surf->get_center();
double radius = surf->get_radius();
positions[idx * 4 + 0] = center[0];
positions[idx * 4 + 1] = center[1];
positions[idx * 4 + 2] = center[2];
positions[idx * 4 + 3] = radius;
surface_ids[idx] = surf->id_;
// Get TRISO particle cell via triso_particle_index_
int32_t i_cell = model::cell_map.at(surf->triso_particle_index_);
const auto& cell = model::cells[i_cell];
cell_ids[idx] = cell->id_;
fill_universes[idx] = model::universes[cell->fill_]->id_;
++idx;
}
group_offsets[g + 1] = idx;
++g;
}
// Write compact TRISO data to HDF5
hid_t triso_group = create_group(geom_group, "triso_particles");
write_attribute(triso_group, "n_groups", n_groups);
write_attribute(triso_group, "n_triso", n_triso);
// Write positions as 2D dataset [n_triso, 4]
hsize_t pos_dims[] = {static_cast<hsize_t>(n_triso), 4};
write_dataset_lowlevel(triso_group, 2, pos_dims, "positions",
H5TypeMap<double>::type_id, H5S_ALL, false, positions.data());
write_dataset(triso_group, "surface_ids", surface_ids);
write_dataset(triso_group, "cell_ids", cell_ids);
write_dataset(triso_group, "fill_universes", fill_universes);
write_dataset(triso_group, "group_offsets", group_offsets);
// Write per-group metadata (background cell info)
hid_t groups_group = create_group(triso_group, "groups");
g = 0;
for (const auto& [bg_cell_id, surfs] : bg_to_surfs) {
auto grp = create_group(groups_group, std::to_string(g));
int32_t i_bg_cell = model::cell_map.at(bg_cell_id);
const auto& bg_cell = model::cells[i_bg_cell];
write_dataset(grp, "background_cell_id", bg_cell->id_);
write_dataset(grp, "background_material_id",
model::materials[bg_cell->material_[0]]->id_);
write_dataset(
grp, "background_universe_id", model::universes[bg_cell->universe_]->id_);
write_dataset(grp, "vl_lower_left", bg_cell->vl_lower_left_);
write_dataset(grp, "vl_pitch", bg_cell->vl_pitch_);
write_dataset(grp, "vl_shape", bg_cell->vl_shape_);
close_group(grp);
++g;
}
close_group(groups_group);
close_group(triso_group);
}
void write_geometry(hid_t file)
{
auto geom_group = create_group(file, "geometry");
write_attribute(geom_group, "n_cells", model::cells.size());
write_attribute(geom_group, "n_surfaces", model::surfaces.size());
// Count non-TRISO cells and surfaces for accurate counts
int n_cells = 0;
int n_surfaces = 0;
for (const auto& c : model::cells) {
if (!c->triso_particle_ && !c->virtual_lattice_)
++n_cells;
}
for (const auto& surf : model::surfaces) {
if (!surf->is_triso_surface_)
++n_surfaces;
}
write_attribute(geom_group, "n_cells", n_cells);
write_attribute(geom_group, "n_surfaces", n_surfaces);
write_attribute(geom_group, "n_universes", model::universes.size());
write_attribute(geom_group, "n_lattices", model::lattices.size());
auto cells_group = create_group(geom_group, "cells");
for (const auto& c : model::cells)
for (const auto& c : model::cells) {
if (c->triso_particle_ || c->virtual_lattice_)
continue;
c->to_hdf5(cells_group);
}
close_group(cells_group);
auto surfaces_group = create_group(geom_group, "surfaces");
for (const auto& surf : model::surfaces)
for (const auto& surf : model::surfaces) {
if (surf->is_triso_surface_)
continue;
surf->to_hdf5(surfaces_group);
}
close_group(surfaces_group);
// Write compact TRISO particle data
write_triso_particles(geom_group);
auto universes_group = create_group(geom_group, "universes");
for (const auto& u : model::universes)
u->to_hdf5(universes_group);

View file

@ -258,10 +258,20 @@ BoundingBox SurfaceXPlane::bounding_box(bool pos_side) const
}
}
bool SurfaceXPlane::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
//==============================================================================
// SurfaceYPlane implementation
//==============================================================================
bool SurfaceYPlane::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceYPlane::SurfaceYPlane(pugi::xml_node surf_node) : Surface(surf_node)
{
read_coeffs(surf_node, id_, {&y0_});
@ -301,7 +311,11 @@ BoundingBox SurfaceYPlane::bounding_box(bool pos_side) const
//==============================================================================
// SurfaceZPlane implementation
//==============================================================================
bool SurfaceZPlane::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceZPlane::SurfaceZPlane(pugi::xml_node surf_node) : Surface(surf_node)
{
read_coeffs(surf_node, id_, {&z0_});
@ -341,6 +355,11 @@ BoundingBox SurfaceZPlane::bounding_box(bool pos_side) const
//==============================================================================
// SurfacePlane implementation
//==============================================================================
bool SurfacePlane::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfacePlane::SurfacePlane(pugi::xml_node surf_node) : Surface(surf_node)
{
@ -460,6 +479,12 @@ Direction axis_aligned_cylinder_normal(
// SurfaceXCylinder implementation
//==============================================================================
bool SurfaceXCylinder::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceXCylinder::SurfaceXCylinder(pugi::xml_node surf_node)
: Surface(surf_node)
{
@ -503,6 +528,12 @@ BoundingBox SurfaceXCylinder::bounding_box(bool pos_side) const
// SurfaceYCylinder implementation
//==============================================================================
bool SurfaceYCylinder::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceYCylinder::SurfaceYCylinder(pugi::xml_node surf_node)
: Surface(surf_node)
{
@ -547,6 +578,12 @@ BoundingBox SurfaceYCylinder::bounding_box(bool pos_side) const
// SurfaceZCylinder implementation
//==============================================================================
bool SurfaceZCylinder::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceZCylinder::SurfaceZCylinder(pugi::xml_node surf_node)
: Surface(surf_node)
{
@ -665,6 +702,69 @@ BoundingBox SurfaceSphere::bounding_box(bool pos_side) const
}
}
void SurfaceSphere::connect_to_triso_base(int triso_index, std::string key)
{
if (key == "base") {
triso_base_index_ = triso_index;
is_triso_surface_ = true;
} else if (key == "particle") {
triso_particle_index_ = triso_index;
}
}
vector<double> SurfaceSphere::get_center() const
{
return {x0_, y0_, z0_};
}
double SurfaceSphere::get_radius() const
{
return radius_;
}
bool SurfaceSphere::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
double dis_x;
double dis_y;
double dis_z;
double x_min = mesh_center[0] - lattice_pitch[0] / 2;
double x_max = mesh_center[0] + lattice_pitch[0] / 2;
double y_min = mesh_center[1] - lattice_pitch[1] / 2;
double y_max = mesh_center[1] + lattice_pitch[1] / 2;
double z_min = mesh_center[2] - lattice_pitch[2] / 2;
double z_max = mesh_center[2] + lattice_pitch[2] / 2;
if (x0_ >= x_min && x0_ <= x_max) {
dis_x = 0;
} else if (x0_ < x_min) {
dis_x = pow(x_min - x0_, 2);
} else {
dis_x = pow(x_max - x0_, 2);
}
if (y0_ >= y_min && y0_ <= y_max) {
dis_y = 0;
} else if (y0_ < y_min) {
dis_y = pow(y_min - y0_, 2);
} else {
dis_y = pow(y_max - y0_, 2);
}
if (z0_ >= z_min && z0_ <= z_max) {
dis_z = 0;
} else if (z0_ < z_min) {
dis_z = pow(z_min - z0_, 2);
} else {
dis_z = pow(z_max - z0_, 2);
}
if (sqrt(dis_x + dis_y + dis_z) < radius_) {
return true;
} else {
return false;
}
}
//==============================================================================
// Generic functions for x-, y-, and z-, cones
//==============================================================================
@ -756,7 +856,11 @@ Direction axis_aligned_cone_normal(
//==============================================================================
// SurfaceXCone implementation
//==============================================================================
bool SurfaceXCone::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceXCone::SurfaceXCone(pugi::xml_node surf_node) : Surface(surf_node)
{
read_coeffs(surf_node, id_, {&x0_, &y0_, &z0_, &radius_sq_});
@ -788,7 +892,11 @@ void SurfaceXCone::to_hdf5_inner(hid_t group_id) const
//==============================================================================
// SurfaceYCone implementation
//==============================================================================
bool SurfaceYCone::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceYCone::SurfaceYCone(pugi::xml_node surf_node) : Surface(surf_node)
{
read_coeffs(surf_node, id_, {&x0_, &y0_, &z0_, &radius_sq_});
@ -820,6 +928,11 @@ void SurfaceYCone::to_hdf5_inner(hid_t group_id) const
//==============================================================================
// SurfaceZCone implementation
//==============================================================================
bool SurfaceZCone::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceZCone::SurfaceZCone(pugi::xml_node surf_node) : Surface(surf_node)
{
@ -852,7 +965,11 @@ void SurfaceZCone::to_hdf5_inner(hid_t group_id) const
//==============================================================================
// SurfaceQuadric implementation
//==============================================================================
bool SurfaceQuadric::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceQuadric::SurfaceQuadric(pugi::xml_node surf_node) : Surface(surf_node)
{
read_coeffs(
@ -1012,7 +1129,11 @@ double torus_distance(double x1, double x2, double x3, double u1, double u2,
//==============================================================================
// SurfaceXTorus implementation
//==============================================================================
bool SurfaceXTorus::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceXTorus::SurfaceXTorus(pugi::xml_node surf_node) : Surface(surf_node)
{
read_coeffs(surf_node, id_, {&x0_, &y0_, &z0_, &A_, &B_, &C_});
@ -1065,7 +1186,11 @@ Direction SurfaceXTorus::normal(Position r) const
//==============================================================================
// SurfaceYTorus implementation
//==============================================================================
bool SurfaceYTorus::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceYTorus::SurfaceYTorus(pugi::xml_node surf_node) : Surface(surf_node)
{
read_coeffs(surf_node, id_, {&x0_, &y0_, &z0_, &A_, &B_, &C_});
@ -1118,6 +1243,11 @@ Direction SurfaceYTorus::normal(Position r) const
//==============================================================================
// SurfaceZTorus implementation
//==============================================================================
bool SurfaceZTorus::triso_in_mesh(
vector<double> mesh_center, vector<double> lattice_pitch) const
{
return false;
}
SurfaceZTorus::SurfaceZTorus(pugi::xml_node surf_node) : Surface(surf_node)
{

View file

@ -39,6 +39,12 @@ void Universe::to_hdf5(hid_t universes_group) const
bool Universe::find_cell(GeometryState& p) const
{
if (filled_with_triso_base_ != -1) {
bool found = find_cell_in_virtual_lattice(p);
if (found) {
return found;
}
}
const auto& cells {
!partitioner_ ? cells_ : partitioner_->get_cells(p.r_local(), p.u_local())};
@ -58,6 +64,60 @@ bool Universe::find_cell(GeometryState& p) const
}
return false;
}
bool Universe::find_cell_in_virtual_lattice(GeometryState& p) const
{
Cell& c {*model::cells[model::cell_map[filled_with_triso_base_]]};
vector<int> lat_ind(3);
Position r {p.r_local()};
lat_ind[0] = std::max<int>(
std::min<int>(
floor((r.x - c.vl_lower_left_[0]) / c.vl_pitch_[0]), c.vl_shape_[0] - 1),
0);
lat_ind[1] = std::max<int>(
std::min<int>(
floor((r.y - c.vl_lower_left_[1]) / c.vl_pitch_[1]), c.vl_shape_[1] - 1),
0);
lat_ind[2] = std::max<int>(
std::min<int>(
floor((r.z - c.vl_lower_left_[2]) / c.vl_pitch_[2]), c.vl_shape_[2] - 1),
0);
int32_t i_univ = p.lowest_coord().universe();
for (int token :
c.vl_triso_distribution_[lat_ind[0] + lat_ind[1] * c.vl_shape_[0] +
lat_ind[2] * c.vl_shape_[0] * c.vl_shape_[1]]) {
vector<double> triso_center = model::surfaces[abs(token) - 1]->get_center();
double triso_radius = model::surfaces[abs(token) - 1]->get_radius();
if (model::cells
[model::cell_map[model::surfaces[abs(token) - 1]->triso_base_index_]]
->universe_ != i_univ)
continue;
if (abs(token) == abs(p.surface())) {
if (p.surface() < 0) {
p.lowest_coord().cell() =
model::cell_map[model::surfaces[abs(token) - 1]
->triso_particle_index_];
return true;
} else {
p.lowest_coord().cell() = model::cell_map[filled_with_triso_base_];
return true;
}
}
if (pow(r.x - triso_center[0], 2) + pow(r.y - triso_center[1], 2) +
pow(r.z - triso_center[2], 2) <
pow(triso_radius, 2)) {
p.lowest_coord().cell() =
model::cell_map[model::surfaces[abs(token) - 1]->triso_particle_index_];
return true;
}
}
if (model::cells[model::cell_map[filled_with_triso_base_]]->universe_ ==
i_univ) {
p.lowest_coord().cell() = model::cell_map[filled_with_triso_base_];
return true;
}
return false;
}
BoundingBox Universe::bounding_box() const
{

View file

@ -0,0 +1,278 @@
<?xml version='1.0' encoding='utf-8'?>
<model>
<materials>
<material id="1" depletable="true">
<density value="10.5" units="g/cm3"/>
<nuclide name="U235" ao="0.14154"/>
<nuclide name="U238" ao="0.85846"/>
<nuclide name="C0" ao="0.5"/>
<nuclide name="O16" ao="1.5"/>
</material>
<material id="2">
<density value="1.0" units="g/cm3"/>
<nuclide name="C0" ao="1.0"/>
<sab name="c_Graphite"/>
</material>
<material id="3">
<density value="1.9" units="g/cm3"/>
<nuclide name="C0" ao="1.0"/>
<sab name="c_Graphite"/>
</material>
<material id="4">
<density value="3.2" units="g/cm3"/>
<nuclide name="C0" ao="1.0"/>
<nuclide name="Si28" ao="0.9222968"/>
<nuclide name="Si29" ao="0.0468316"/>
<nuclide name="Si30" ao="0.0308716"/>
</material>
<material id="5">
<density value="1.87" units="g/cm3"/>
<nuclide name="C0" ao="1.0"/>
<sab name="c_Graphite"/>
</material>
<material id="6">
<density value="1.1995" units="g/cm3"/>
<nuclide name="C0" ao="1.0"/>
<sab name="c_Graphite"/>
</material>
</materials>
<geometry>
<cell id="1" material="1" region="-1" universe="1"/>
<cell id="2" material="2" region="1 -2" universe="1"/>
<cell id="3" material="3" region="2 -3" universe="1"/>
<cell id="4" material="4" region="3 -4" universe="1"/>
<cell id="5" material="5" region="4" universe="1"/>
<cell id="6" fill="2" region="5 -6 7 -8 9 -10" universe="0"/>
<cell id="107" triso_particle="true" fill="1" region="-111" translation="-0.3347395345150967 0.3180755861660365 0.2414856636730901" universe="3"/>
<cell id="108" triso_particle="true" fill="1" region="-112" translation="-0.22423430693555943 -0.004179177767328068 -0.046240930185910245" universe="3"/>
<cell id="109" triso_particle="true" fill="1" region="-113" translation="0.13878336652768952 0.2643262279645623 -0.3718215483081879" universe="3"/>
<cell id="110" triso_particle="true" fill="1" region="-114" translation="-0.43179788524410323 0.30739295263864075 -0.06155174933292362" universe="3"/>
<cell id="111" triso_particle="true" fill="1" region="-115" translation="0.2401174154902459 -0.45582190815705814 -0.04999802384282931" universe="3"/>
<cell id="112" triso_particle="true" fill="1" region="-116" translation="0.2028198996079864 -0.2483181864269006 0.4076453217796159" universe="3"/>
<cell id="113" triso_particle="true" fill="1" region="-117" translation="0.36750683744331325 -0.4297448705327817 -0.43445431426048664" universe="3"/>
<cell id="114" triso_particle="true" fill="1" region="-118" translation="0.037913118842446136 0.4020410585237264 -0.10875752039644154" universe="3"/>
<cell id="115" triso_particle="true" fill="1" region="-119" translation="-0.2594532519269235 -0.07130227505402231 -0.4311631589752084" universe="3"/>
<cell id="116" triso_particle="true" fill="1" region="-120" translation="-0.24436118578919225 -0.2463916812192289 -0.2574559603173461" universe="3"/>
<cell id="117" triso_particle="true" fill="1" region="-121" translation="-0.03698302711710488 -0.19245493184241047 -0.4380761748290604" universe="3"/>
<cell id="118" triso_particle="true" fill="1" region="-122" translation="0.30905263671908545 0.05168393238830282 0.1302704892646539" universe="3"/>
<cell id="119" triso_particle="true" fill="1" region="-123" translation="-0.2875528135733859 0.45092349384718766 0.3295310471120879" universe="3"/>
<cell id="120" triso_particle="true" fill="1" region="-124" translation="-0.3470752417977842 -0.15316755780280183 0.20276897514248216" universe="3"/>
<cell id="121" triso_particle="true" fill="1" region="-125" translation="0.19334606515602848 0.39956135721490527 -0.07131104153532436" universe="3"/>
<cell id="122" triso_particle="true" fill="1" region="-126" translation="0.30214767719264635 0.155914746052082 -0.1800161282409139" universe="3"/>
<cell id="123" triso_particle="true" fill="1" region="-127" translation="0.08018004492442865 0.3501595252615657 0.3169437365711203" universe="3"/>
<cell id="124" triso_particle="true" fill="1" region="-128" translation="0.00483733774062417 0.08148156718302602 -0.4261416024964468" universe="3"/>
<cell id="125" triso_particle="true" fill="1" region="-129" translation="-0.23552155422132157 0.2722735886359643 -0.07844553364014112" universe="3"/>
<cell id="126" triso_particle="true" fill="1" region="-130" translation="-0.29936172385437887 0.044675266050854034 0.18588381767108564" universe="3"/>
<cell id="127" triso_particle="true" fill="1" region="-131" translation="0.15974177782488064 -0.11470938473074832 -0.055880627694202434" universe="3"/>
<cell id="128" triso_particle="true" fill="1" region="-132" translation="0.007714449992858363 0.2549142140326335 0.019169121324834393" universe="3"/>
<cell id="129" triso_particle="true" fill="1" region="-133" translation="-0.09772496056025104 -0.009435582016802613 -0.43067412048829656" universe="3"/>
<cell id="130" triso_particle="true" fill="1" region="-134" translation="-0.4179373856785991 0.18619630211681182 0.4423583551970065" universe="3"/>
<cell id="131" triso_particle="true" fill="1" region="-135" translation="0.08530970516294267 -0.09740948712101977 -0.3017953102786238" universe="3"/>
<cell id="132" triso_particle="true" fill="1" region="-136" translation="0.002049400245853761 0.44134116166652815 0.24766393451509794" universe="3"/>
<cell id="133" triso_particle="true" fill="1" region="-137" translation="0.036269774055772475 0.3298452926017631 -0.24519275475831015" universe="3"/>
<cell id="134" triso_particle="true" fill="1" region="-138" translation="0.012607957648281654 0.41423389395960075 0.0712211465420014" universe="3"/>
<cell id="135" triso_particle="true" fill="1" region="-139" translation="-0.03741489943578313 -0.21122463840237887 0.0439406213163509" universe="3"/>
<cell id="136" triso_particle="true" fill="1" region="-140" translation="0.41848995567683767 -0.45252329198816527 0.2596863654593894" universe="3"/>
<cell id="137" triso_particle="true" fill="1" region="-141" translation="0.2934048523677787 0.3535474062462105 0.2201808735332913" universe="3"/>
<cell id="138" triso_particle="true" fill="1" region="-142" translation="0.28301757924875504 0.017099968565308377 0.056173125204605934" universe="3"/>
<cell id="139" triso_particle="true" fill="1" region="-143" translation="-0.06766398274549851 -0.40636912111976214 0.3387442970642137" universe="3"/>
<cell id="140" triso_particle="true" fill="1" region="-144" translation="0.06408439016382617 -0.2747970108278255 0.00432158793112436" universe="3"/>
<cell id="141" triso_particle="true" fill="1" region="-145" translation="-0.013801059755509382 -0.13110878745909305 -0.1409156651388792" universe="3"/>
<cell id="142" triso_particle="true" fill="1" region="-146" translation="0.03522733749799645 0.11305459403611595 0.10295023150858529" universe="3"/>
<cell id="143" triso_particle="true" fill="1" region="-147" translation="-0.03831660450870228 -0.43213890207124234 -0.2475465938658846" universe="3"/>
<cell id="144" triso_particle="true" fill="1" region="-148" translation="-0.2955130924417275 0.07732392719766301 0.3305036121112189" universe="3"/>
<cell id="145" triso_particle="true" fill="1" region="-149" translation="0.2732208500986335 0.2719928185927968 0.28969841274831254" universe="3"/>
<cell id="146" triso_particle="true" fill="1" region="-150" translation="-0.2240283063000714 0.31286739394693486 0.15848543253913627" universe="3"/>
<cell id="147" triso_particle="true" fill="1" region="-151" translation="-0.3815491468405315 -0.44246972812920515 -0.4444203429563343" universe="3"/>
<cell id="148" triso_particle="true" fill="1" region="-152" translation="0.23398969274338743 -0.2292785289142914 -0.35751316171201397" universe="3"/>
<cell id="149" triso_particle="true" fill="1" region="-153" translation="0.11425630804159204 -0.14243086791965892 -0.39410867095500923" universe="3"/>
<cell id="150" triso_particle="true" fill="1" region="-154" translation="-0.31161283214278257 0.02506675532845576 -0.30381330173336696" universe="3"/>
<cell id="151" triso_particle="true" fill="1" region="-155" translation="-0.20789683309249835 0.19371057833811733 -0.04147065769319469" universe="3"/>
<cell id="152" triso_particle="true" fill="1" region="-156" translation="-0.10385697059087434 -0.07239894918409101 -0.285600016500173" universe="3"/>
<cell id="153" triso_particle="true" fill="1" region="-157" translation="-0.3581786705662241 0.3660338370759365 0.009261180540203251" universe="3"/>
<cell id="154" triso_particle="true" fill="1" region="-158" translation="-0.43869102165974744 -0.4413950311821534 -0.32366427666439873" universe="3"/>
<cell id="155" triso_particle="true" fill="1" region="-159" translation="0.20034387531341857 -0.3110616389475054 0.18731645229850835" universe="3"/>
<cell id="156" triso_particle="true" fill="1" region="-160" translation="0.1631199405760454 0.04092483075648701 -0.2557909306852396" universe="3"/>
<cell id="157" triso_particle="true" fill="1" region="-161" translation="0.43540678106227226 0.2726458402299813 0.01519685776716928" universe="3"/>
<cell id="158" triso_particle="true" fill="1" region="-162" translation="-0.2534142631841729 0.13595762576986914 -0.09622087197472673" universe="3"/>
<cell id="159" triso_particle="true" fill="1" region="-163" translation="0.06943697893246592 -0.1636494615445378 0.11988276699391809" universe="3"/>
<cell id="160" triso_particle="true" fill="1" region="-164" translation="-0.4039322261129572 -0.18437625312013128 0.42836548044313905" universe="3"/>
<cell id="161" triso_particle="true" fill="1" region="-165" translation="0.34380160059728826 -0.17725304908491335 0.32821993901943003" universe="3"/>
<cell id="162" triso_particle="true" fill="1" region="-166" translation="-0.17361209915820575 0.4021685596198511 0.2232374596397494" universe="3"/>
<cell id="163" triso_particle="true" fill="1" region="-167" translation="0.4231451301030389 0.06434186205946246 -0.3007260993647986" universe="3"/>
<cell id="164" triso_particle="true" fill="1" region="-168" translation="0.3367035644902364 0.43374122870419773 0.1867831868031803" universe="3"/>
<cell id="165" triso_particle="true" fill="1" region="-169" translation="-0.2800343805160589 -0.36214962398859274 0.15193411713913396" universe="3"/>
<cell id="166" triso_particle="true" fill="1" region="-170" translation="-0.18669546779237473 -0.0001831711922081758 -0.15989605296102538" universe="3"/>
<cell id="167" triso_particle="true" fill="1" region="-171" translation="0.3402194900462647 0.36590545585064216 -0.4411858734771481" universe="3"/>
<cell id="168" triso_particle="true" fill="1" region="-172" translation="-0.27386906802598476 -0.1577033844843671 0.4458940167631079" universe="3"/>
<cell id="169" triso_particle="true" fill="1" region="-173" translation="0.25881219398024335 -0.1473079343924702 -0.26272122141336496" universe="3"/>
<cell id="170" triso_particle="true" fill="1" region="-174" translation="0.15971361633210523 0.30916532972595434 0.39566763051861575" universe="3"/>
<cell id="171" triso_particle="true" fill="1" region="-175" translation="-0.014191419448261688 0.4444827844055178 -0.24293668187556428" universe="3"/>
<cell id="172" triso_particle="true" fill="1" region="-176" translation="0.20641337800388493 -0.3802252490537087 -0.30239501318723816" universe="3"/>
<cell id="173" triso_particle="true" fill="1" region="-177" translation="0.3762593158016361 -0.26277761748535117 0.237220865276901" universe="3"/>
<cell id="174" triso_particle="true" fill="1" region="-178" translation="0.09174118398607445 0.31230652516871027 -0.12074712654412828" universe="3"/>
<cell id="175" triso_particle="true" fill="1" region="-179" translation="-0.14621886735567996 -0.1911424043751062 0.33637284849380944" universe="3"/>
<cell id="176" triso_particle="true" fill="1" region="-180" translation="-0.42191934538452835 -0.3907414250589849 0.33522713116909675" universe="3"/>
<cell id="177" triso_particle="true" fill="1" region="-181" translation="0.2637706088079447 0.3007472168799734 -0.14565837160126788" universe="3"/>
<cell id="178" triso_particle="true" fill="1" region="-182" translation="0.06480048668590577 -0.2529397663985018 -0.38291404331638357" universe="3"/>
<cell id="179" triso_particle="true" fill="1" region="-183" translation="-0.21356450485022038 0.35774822105153203 0.059001075831400684" universe="3"/>
<cell id="180" triso_particle="true" fill="1" region="-184" translation="0.3891490235303072 -0.03866224334773988 -0.20398917762840219" universe="3"/>
<cell id="181" triso_particle="true" fill="1" region="-185" translation="0.262761924489481 0.30007174740916553 -0.4464145129224567" universe="3"/>
<cell id="182" triso_particle="true" fill="1" region="-186" translation="0.35252249443257966 -0.4211084519770542 -0.23836565446379523" universe="3"/>
<cell id="183" triso_particle="true" fill="1" region="-187" translation="0.4469091054738229 -0.07231206070759028 -0.3519564856677738" universe="3"/>
<cell id="184" triso_particle="true" fill="1" region="-188" translation="-0.30451046300415074 -0.23672972899292466 0.22338787433963114" universe="3"/>
<cell id="185" triso_particle="true" fill="1" region="-189" translation="-0.3636053393495334 0.37605482493472964 -0.11143715881676097" universe="3"/>
<cell id="186" triso_particle="true" fill="1" region="-190" translation="0.4305267254415768 0.3746434076219761 -0.18857140797960453" universe="3"/>
<cell id="187" triso_particle="true" fill="1" region="-191" translation="-0.22575302045434847 -0.02104725713738881 -0.3660817687133612" universe="3"/>
<cell id="188" triso_particle="true" fill="1" region="-192" translation="0.1392019576325615 -0.42147769461975354 -0.44813161828465553" universe="3"/>
<cell id="189" triso_particle="true" fill="1" region="-193" translation="0.44180531010694923 -0.18717410312521576 0.08841042383901798" universe="3"/>
<cell id="190" triso_particle="true" fill="1" region="-194" translation="0.37846039171541845 0.43011405494529475 0.43009869986651816" universe="3"/>
<cell id="191" triso_particle="true" fill="1" region="-195" translation="-0.35579780507883046 -0.2607405612819519 0.10785219865057927" universe="3"/>
<cell id="192" triso_particle="true" fill="1" region="-196" translation="0.43939686703236547 0.03928703229725711 0.17228776926768086" universe="3"/>
<cell id="193" triso_particle="true" fill="1" region="-197" translation="0.14815941963538226 -0.220556774457988 0.03808687169681996" universe="3"/>
<cell id="194" triso_particle="true" fill="1" region="-198" translation="-0.17639751664264391 -0.23218801498409805 -0.38325689529114226" universe="3"/>
<cell id="195" triso_particle="true" fill="1" region="-199" translation="-0.2006897545765396 0.4425313846143629 -0.04769549879176793" universe="3"/>
<cell id="196" triso_particle="true" fill="1" region="-200" translation="0.13916564434634993 0.13134319648704007 0.4034924551189595" universe="3"/>
<cell id="197" triso_particle="true" fill="1" region="-201" translation="-0.10026688643231585 -0.17688897806343928 -0.15816048485392958" universe="3"/>
<cell id="198" triso_particle="true" fill="1" region="-202" translation="-0.16777897302623124 0.3178018781138999 0.36024947477502567" universe="3"/>
<cell id="199" triso_particle="true" fill="1" region="-203" translation="-0.18052805868481137 -0.15166776712672753 0.040488366683789634" universe="3"/>
<cell id="200" triso_particle="true" fill="1" region="-204" translation="0.07231116694829032 0.08785370537091952 -0.2333627774338999" universe="3"/>
<cell id="201" triso_particle="true" fill="1" region="-205" translation="-0.43909757695745594 -0.2345883610075431 -0.3915341427407233" universe="3"/>
<cell id="202" triso_particle="true" fill="1" region="-206" translation="0.046877953125145755 -0.39282606551755617 -0.3889686751909842" universe="3"/>
<cell id="203" triso_particle="true" fill="1" region="-207" translation="0.1239423066569788 -0.19150287059104332 0.2674951458412387" universe="3"/>
<cell id="204" triso_particle="true" fill="1" region="-208" translation="0.0013087859341976982 0.2700573885244849 -0.3871585540753848" universe="3"/>
<cell id="205" triso_particle="true" fill="1" region="-209" translation="0.4439221700323984 0.2943791575126874 -0.16498774544300332" universe="3"/>
<cell id="206" triso_particle="true" fill="1" region="-210" translation="-0.359903433990582 0.013144978841080679 0.38392127784738483" universe="3"/>
<cell id="207" virtual_lattice="True" lower_left="-0.5 -0.5 -0.5" pitch="0.3333333333333333 0.3333333333333333 0.3333333333333333" shape="3 3 3" material="6" region="111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210" universe="3"/>
<cell id="208" material="6" universe="4"/>
<lattice id="2">
<pitch>1.0 1.0 1.0</pitch>
<outer>4</outer>
<dimension>1 1 1</dimension>
<lower_left>-0.5 -0.5 -0.5</lower_left>
<universes>
3 </universes>
</lattice>
<surface id="1" type="sphere" coeffs="0.0 0.0 0.0 0.02125"/>
<surface id="2" type="sphere" coeffs="0.0 0.0 0.0 0.03125"/>
<surface id="3" type="sphere" coeffs="0.0 0.0 0.0 0.03475"/>
<surface id="4" type="sphere" coeffs="0.0 0.0 0.0 0.03825"/>
<surface id="5" type="x-plane" boundary="reflective" coeffs="-0.5"/>
<surface id="6" type="x-plane" boundary="reflective" coeffs="0.5"/>
<surface id="7" type="y-plane" boundary="reflective" coeffs="-0.5"/>
<surface id="8" type="y-plane" boundary="reflective" coeffs="0.5"/>
<surface id="9" type="z-plane" boundary="reflective" coeffs="-0.5"/>
<surface id="10" type="z-plane" boundary="reflective" coeffs="0.5"/>
<surface id="111" type="sphere" coeffs="-0.3347395345150967 0.3180755861660365 0.2414856636730901 0.04225"/>
<surface id="112" type="sphere" coeffs="-0.22423430693555943 -0.004179177767328068 -0.046240930185910245 0.04225"/>
<surface id="113" type="sphere" coeffs="0.13878336652768952 0.2643262279645623 -0.3718215483081879 0.04225"/>
<surface id="114" type="sphere" coeffs="-0.43179788524410323 0.30739295263864075 -0.06155174933292362 0.04225"/>
<surface id="115" type="sphere" coeffs="0.2401174154902459 -0.45582190815705814 -0.04999802384282931 0.04225"/>
<surface id="116" type="sphere" coeffs="0.2028198996079864 -0.2483181864269006 0.4076453217796159 0.04225"/>
<surface id="117" type="sphere" coeffs="0.36750683744331325 -0.4297448705327817 -0.43445431426048664 0.04225"/>
<surface id="118" type="sphere" coeffs="0.037913118842446136 0.4020410585237264 -0.10875752039644154 0.04225"/>
<surface id="119" type="sphere" coeffs="-0.2594532519269235 -0.07130227505402231 -0.4311631589752084 0.04225"/>
<surface id="120" type="sphere" coeffs="-0.24436118578919225 -0.2463916812192289 -0.2574559603173461 0.04225"/>
<surface id="121" type="sphere" coeffs="-0.03698302711710488 -0.19245493184241047 -0.4380761748290604 0.04225"/>
<surface id="122" type="sphere" coeffs="0.30905263671908545 0.05168393238830282 0.1302704892646539 0.04225"/>
<surface id="123" type="sphere" coeffs="-0.2875528135733859 0.45092349384718766 0.3295310471120879 0.04225"/>
<surface id="124" type="sphere" coeffs="-0.3470752417977842 -0.15316755780280183 0.20276897514248216 0.04225"/>
<surface id="125" type="sphere" coeffs="0.19334606515602848 0.39956135721490527 -0.07131104153532436 0.04225"/>
<surface id="126" type="sphere" coeffs="0.30214767719264635 0.155914746052082 -0.1800161282409139 0.04225"/>
<surface id="127" type="sphere" coeffs="0.08018004492442865 0.3501595252615657 0.3169437365711203 0.04225"/>
<surface id="128" type="sphere" coeffs="0.00483733774062417 0.08148156718302602 -0.4261416024964468 0.04225"/>
<surface id="129" type="sphere" coeffs="-0.23552155422132157 0.2722735886359643 -0.07844553364014112 0.04225"/>
<surface id="130" type="sphere" coeffs="-0.29936172385437887 0.044675266050854034 0.18588381767108564 0.04225"/>
<surface id="131" type="sphere" coeffs="0.15974177782488064 -0.11470938473074832 -0.055880627694202434 0.04225"/>
<surface id="132" type="sphere" coeffs="0.007714449992858363 0.2549142140326335 0.019169121324834393 0.04225"/>
<surface id="133" type="sphere" coeffs="-0.09772496056025104 -0.009435582016802613 -0.43067412048829656 0.04225"/>
<surface id="134" type="sphere" coeffs="-0.4179373856785991 0.18619630211681182 0.4423583551970065 0.04225"/>
<surface id="135" type="sphere" coeffs="0.08530970516294267 -0.09740948712101977 -0.3017953102786238 0.04225"/>
<surface id="136" type="sphere" coeffs="0.002049400245853761 0.44134116166652815 0.24766393451509794 0.04225"/>
<surface id="137" type="sphere" coeffs="0.036269774055772475 0.3298452926017631 -0.24519275475831015 0.04225"/>
<surface id="138" type="sphere" coeffs="0.012607957648281654 0.41423389395960075 0.0712211465420014 0.04225"/>
<surface id="139" type="sphere" coeffs="-0.03741489943578313 -0.21122463840237887 0.0439406213163509 0.04225"/>
<surface id="140" type="sphere" coeffs="0.41848995567683767 -0.45252329198816527 0.2596863654593894 0.04225"/>
<surface id="141" type="sphere" coeffs="0.2934048523677787 0.3535474062462105 0.2201808735332913 0.04225"/>
<surface id="142" type="sphere" coeffs="0.28301757924875504 0.017099968565308377 0.056173125204605934 0.04225"/>
<surface id="143" type="sphere" coeffs="-0.06766398274549851 -0.40636912111976214 0.3387442970642137 0.04225"/>
<surface id="144" type="sphere" coeffs="0.06408439016382617 -0.2747970108278255 0.00432158793112436 0.04225"/>
<surface id="145" type="sphere" coeffs="-0.013801059755509382 -0.13110878745909305 -0.1409156651388792 0.04225"/>
<surface id="146" type="sphere" coeffs="0.03522733749799645 0.11305459403611595 0.10295023150858529 0.04225"/>
<surface id="147" type="sphere" coeffs="-0.03831660450870228 -0.43213890207124234 -0.2475465938658846 0.04225"/>
<surface id="148" type="sphere" coeffs="-0.2955130924417275 0.07732392719766301 0.3305036121112189 0.04225"/>
<surface id="149" type="sphere" coeffs="0.2732208500986335 0.2719928185927968 0.28969841274831254 0.04225"/>
<surface id="150" type="sphere" coeffs="-0.2240283063000714 0.31286739394693486 0.15848543253913627 0.04225"/>
<surface id="151" type="sphere" coeffs="-0.3815491468405315 -0.44246972812920515 -0.4444203429563343 0.04225"/>
<surface id="152" type="sphere" coeffs="0.23398969274338743 -0.2292785289142914 -0.35751316171201397 0.04225"/>
<surface id="153" type="sphere" coeffs="0.11425630804159204 -0.14243086791965892 -0.39410867095500923 0.04225"/>
<surface id="154" type="sphere" coeffs="-0.31161283214278257 0.02506675532845576 -0.30381330173336696 0.04225"/>
<surface id="155" type="sphere" coeffs="-0.20789683309249835 0.19371057833811733 -0.04147065769319469 0.04225"/>
<surface id="156" type="sphere" coeffs="-0.10385697059087434 -0.07239894918409101 -0.285600016500173 0.04225"/>
<surface id="157" type="sphere" coeffs="-0.3581786705662241 0.3660338370759365 0.009261180540203251 0.04225"/>
<surface id="158" type="sphere" coeffs="-0.43869102165974744 -0.4413950311821534 -0.32366427666439873 0.04225"/>
<surface id="159" type="sphere" coeffs="0.20034387531341857 -0.3110616389475054 0.18731645229850835 0.04225"/>
<surface id="160" type="sphere" coeffs="0.1631199405760454 0.04092483075648701 -0.2557909306852396 0.04225"/>
<surface id="161" type="sphere" coeffs="0.43540678106227226 0.2726458402299813 0.01519685776716928 0.04225"/>
<surface id="162" type="sphere" coeffs="-0.2534142631841729 0.13595762576986914 -0.09622087197472673 0.04225"/>
<surface id="163" type="sphere" coeffs="0.06943697893246592 -0.1636494615445378 0.11988276699391809 0.04225"/>
<surface id="164" type="sphere" coeffs="-0.4039322261129572 -0.18437625312013128 0.42836548044313905 0.04225"/>
<surface id="165" type="sphere" coeffs="0.34380160059728826 -0.17725304908491335 0.32821993901943003 0.04225"/>
<surface id="166" type="sphere" coeffs="-0.17361209915820575 0.4021685596198511 0.2232374596397494 0.04225"/>
<surface id="167" type="sphere" coeffs="0.4231451301030389 0.06434186205946246 -0.3007260993647986 0.04225"/>
<surface id="168" type="sphere" coeffs="0.3367035644902364 0.43374122870419773 0.1867831868031803 0.04225"/>
<surface id="169" type="sphere" coeffs="-0.2800343805160589 -0.36214962398859274 0.15193411713913396 0.04225"/>
<surface id="170" type="sphere" coeffs="-0.18669546779237473 -0.0001831711922081758 -0.15989605296102538 0.04225"/>
<surface id="171" type="sphere" coeffs="0.3402194900462647 0.36590545585064216 -0.4411858734771481 0.04225"/>
<surface id="172" type="sphere" coeffs="-0.27386906802598476 -0.1577033844843671 0.4458940167631079 0.04225"/>
<surface id="173" type="sphere" coeffs="0.25881219398024335 -0.1473079343924702 -0.26272122141336496 0.04225"/>
<surface id="174" type="sphere" coeffs="0.15971361633210523 0.30916532972595434 0.39566763051861575 0.04225"/>
<surface id="175" type="sphere" coeffs="-0.014191419448261688 0.4444827844055178 -0.24293668187556428 0.04225"/>
<surface id="176" type="sphere" coeffs="0.20641337800388493 -0.3802252490537087 -0.30239501318723816 0.04225"/>
<surface id="177" type="sphere" coeffs="0.3762593158016361 -0.26277761748535117 0.237220865276901 0.04225"/>
<surface id="178" type="sphere" coeffs="0.09174118398607445 0.31230652516871027 -0.12074712654412828 0.04225"/>
<surface id="179" type="sphere" coeffs="-0.14621886735567996 -0.1911424043751062 0.33637284849380944 0.04225"/>
<surface id="180" type="sphere" coeffs="-0.42191934538452835 -0.3907414250589849 0.33522713116909675 0.04225"/>
<surface id="181" type="sphere" coeffs="0.2637706088079447 0.3007472168799734 -0.14565837160126788 0.04225"/>
<surface id="182" type="sphere" coeffs="0.06480048668590577 -0.2529397663985018 -0.38291404331638357 0.04225"/>
<surface id="183" type="sphere" coeffs="-0.21356450485022038 0.35774822105153203 0.059001075831400684 0.04225"/>
<surface id="184" type="sphere" coeffs="0.3891490235303072 -0.03866224334773988 -0.20398917762840219 0.04225"/>
<surface id="185" type="sphere" coeffs="0.262761924489481 0.30007174740916553 -0.4464145129224567 0.04225"/>
<surface id="186" type="sphere" coeffs="0.35252249443257966 -0.4211084519770542 -0.23836565446379523 0.04225"/>
<surface id="187" type="sphere" coeffs="0.4469091054738229 -0.07231206070759028 -0.3519564856677738 0.04225"/>
<surface id="188" type="sphere" coeffs="-0.30451046300415074 -0.23672972899292466 0.22338787433963114 0.04225"/>
<surface id="189" type="sphere" coeffs="-0.3636053393495334 0.37605482493472964 -0.11143715881676097 0.04225"/>
<surface id="190" type="sphere" coeffs="0.4305267254415768 0.3746434076219761 -0.18857140797960453 0.04225"/>
<surface id="191" type="sphere" coeffs="-0.22575302045434847 -0.02104725713738881 -0.3660817687133612 0.04225"/>
<surface id="192" type="sphere" coeffs="0.1392019576325615 -0.42147769461975354 -0.44813161828465553 0.04225"/>
<surface id="193" type="sphere" coeffs="0.44180531010694923 -0.18717410312521576 0.08841042383901798 0.04225"/>
<surface id="194" type="sphere" coeffs="0.37846039171541845 0.43011405494529475 0.43009869986651816 0.04225"/>
<surface id="195" type="sphere" coeffs="-0.35579780507883046 -0.2607405612819519 0.10785219865057927 0.04225"/>
<surface id="196" type="sphere" coeffs="0.43939686703236547 0.03928703229725711 0.17228776926768086 0.04225"/>
<surface id="197" type="sphere" coeffs="0.14815941963538226 -0.220556774457988 0.03808687169681996 0.04225"/>
<surface id="198" type="sphere" coeffs="-0.17639751664264391 -0.23218801498409805 -0.38325689529114226 0.04225"/>
<surface id="199" type="sphere" coeffs="-0.2006897545765396 0.4425313846143629 -0.04769549879176793 0.04225"/>
<surface id="200" type="sphere" coeffs="0.13916564434634993 0.13134319648704007 0.4034924551189595 0.04225"/>
<surface id="201" type="sphere" coeffs="-0.10026688643231585 -0.17688897806343928 -0.15816048485392958 0.04225"/>
<surface id="202" type="sphere" coeffs="-0.16777897302623124 0.3178018781138999 0.36024947477502567 0.04225"/>
<surface id="203" type="sphere" coeffs="-0.18052805868481137 -0.15166776712672753 0.040488366683789634 0.04225"/>
<surface id="204" type="sphere" coeffs="0.07231116694829032 0.08785370537091952 -0.2333627774338999 0.04225"/>
<surface id="205" type="sphere" coeffs="-0.43909757695745594 -0.2345883610075431 -0.3915341427407233 0.04225"/>
<surface id="206" type="sphere" coeffs="0.046877953125145755 -0.39282606551755617 -0.3889686751909842 0.04225"/>
<surface id="207" type="sphere" coeffs="0.1239423066569788 -0.19150287059104332 0.2674951458412387 0.04225"/>
<surface id="208" type="sphere" coeffs="0.0013087859341976982 0.2700573885244849 -0.3871585540753848 0.04225"/>
<surface id="209" type="sphere" coeffs="0.4439221700323984 0.2943791575126874 -0.16498774544300332 0.04225"/>
<surface id="210" type="sphere" coeffs="-0.359903433990582 0.013144978841080679 0.38392127784738483 0.04225"/>
</geometry>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>100</particles>
<batches>4</batches>
<inactive>0</inactive>
<source type="independent" strength="1.0" particle="neutron">
<space type="point">
<parameters>0.0 0.0 0.0</parameters>
</space>
</source>
</settings>
</model>

View file

@ -0,0 +1,2 @@
k-combined:
1.620170E+00 8.934734E-03

View file

@ -0,0 +1,97 @@
import random
from math import sqrt
import numpy as np
import openmc
import openmc.model
from tests.testing_harness import PyAPITestHarness
class TRISOVirtualLatticeTestHarness(PyAPITestHarness):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Define TRISO matrials
fuel = openmc.Material()
fuel.set_density('g/cm3', 10.5)
fuel.add_nuclide('U235', 0.14154)
fuel.add_nuclide('U238', 0.85846)
fuel.add_nuclide('C0', 0.5)
fuel.add_nuclide('O16', 1.5)
porous_carbon = openmc.Material()
porous_carbon.set_density('g/cm3', 1.0)
porous_carbon.add_nuclide('C0', 1.0)
porous_carbon.add_s_alpha_beta('c_Graphite')
ipyc = openmc.Material()
ipyc.set_density('g/cm3', 1.90)
ipyc.add_nuclide('C0', 1.0)
ipyc.add_s_alpha_beta('c_Graphite')
sic = openmc.Material()
sic.set_density('g/cm3', 3.20)
sic.add_nuclide('C0', 1.0)
sic.add_element('Si', 1.0)
opyc = openmc.Material()
opyc.set_density('g/cm3', 1.87)
opyc.add_nuclide('C0', 1.0)
opyc.add_s_alpha_beta('c_Graphite')
graphite = openmc.Material()
graphite.set_density('g/cm3', 1.1995)
graphite.add_nuclide('C0', 1.0)
graphite.add_s_alpha_beta('c_Graphite')
# Create TRISO particles
spheres = [openmc.Sphere(r=r*1e-4)
for r in [212.5, 312.5, 347.5, 382.5]]
c1 = openmc.Cell(fill=fuel, region=-spheres[0])
c2 = openmc.Cell(fill=porous_carbon, region=+spheres[0] & -spheres[1])
c3 = openmc.Cell(fill=ipyc, region=+spheres[1] & -spheres[2])
c4 = openmc.Cell(fill=sic, region=+spheres[2] & -spheres[3])
c5 = openmc.Cell(fill=opyc, region=+spheres[3])
inner_univ = openmc.Universe(cells=[c1, c2, c3, c4, c5])
# Define box to contain lattice and to pack TRISO particles in
min_x = openmc.XPlane(-0.5, boundary_type='reflective')
max_x = openmc.XPlane(0.5, boundary_type='reflective')
min_y = openmc.YPlane(-0.5, boundary_type='reflective')
max_y = openmc.YPlane(0.5, boundary_type='reflective')
min_z = openmc.ZPlane(-0.5, boundary_type='reflective')
max_z = openmc.ZPlane(0.5, boundary_type='reflective')
box_region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z
box = openmc.Cell(region=box_region)
outer_radius = 422.5*1e-4
centers = openmc.model.pack_spheres(radius=outer_radius,
region=box_region, num_spheres=100, seed=1)
trisos = [openmc.model.TRISO(outer_radius, inner_univ, c)
for c in centers]
# Create lattice
ll, ur = box.region.bounding_box
shape = (3, 3, 3)
pitch = (ur - ll) / shape
lattice = openmc.model.create_triso_lattice(
trisos, ll, pitch, shape, graphite, virtual=True)
box.fill = lattice
root = openmc.Universe(0, cells=[box])
self._model.geometry = openmc.Geometry(root)
settings = openmc.Settings()
settings.batches = 4
settings.inactive = 0
settings.particles = 100
settings.source = openmc.IndependentSource(space=openmc.stats.Point())
self._model.settings = settings
self._model.materials = openmc.Materials([fuel, porous_carbon, ipyc,
sic, opyc, graphite])
def test_triso_virtual_lattice():
harness = TRISOVirtualLatticeTestHarness('statepoint.4.h5', model=openmc.Model())
harness.main()