From 73c4d97a3770762b7521602e0103843dafed5767 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 13 May 2019 13:04:22 -0500 Subject: [PATCH 1/9] Add Position::rotate method --- include/openmc/position.h | 7 +++++-- src/particle.cpp | 4 +--- src/position.cpp | 10 ++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/openmc/position.h b/include/openmc/position.h index 728763f25..4f0ed8a9a 100644 --- a/include/openmc/position.h +++ b/include/openmc/position.h @@ -55,13 +55,16 @@ struct Position { //! Dot product of two vectors //! \param[in] other Vector to take dot product with //! \result Resulting dot product - inline double dot(Position other) { + inline double dot(Position other) const { return x*other.x + y*other.y + z*other.z; } - inline double norm() { + inline double norm() const { return std::sqrt(x*x + y*y + z*z); } + //! Rotate the position based on a rotation matrix + Position rotate(const std::vector& rotation) const; + // Data members double x = 0.; double y = 0.; diff --git a/src/particle.cpp b/src/particle.cpp index cbc6217ca..a6dbe84ff 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -337,9 +337,7 @@ Particle::transport() // If next level is rotated, apply rotation matrix const auto& m {model::cells[coord_[j].cell]->rotation_}; const auto& u {coord_[j].u}; - coord_[j + 1].u.x = m[3]*u.x + m[4]*u.y + m[5]*u.z; - coord_[j + 1].u.y = m[6]*u.x + m[7]*u.y + m[8]*u.z; - coord_[j + 1].u.z = m[9]*u.x + m[10]*u.y + m[11]*u.z; + coord_[j + 1].u = u.rotate(m); } else { // Otherwise, copy this level's direction coord_[j+1].u = coord_[j].u; diff --git a/src/position.cpp b/src/position.cpp index 8ab97c96d..d7175912b 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -84,4 +84,14 @@ Position::operator-() const return {-x, -y, -z}; } +Position +Position::rotate(const std::vector& rotation) const +{ + return { + x*rotation[3] + y*rotation[4] + z*rotation[5], + x*rotation[6] + y*rotation[7] + z*rotation[8], + x*rotation[9] + y*rotation[10] + z*rotation[11] + }; +} + } // namespace openmc From b2ad4d37dd7c87a92a72dc448b857d15514eef9a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 14 May 2019 08:47:57 -0500 Subject: [PATCH 2/9] Overload operator<< for Position --- include/openmc/position.h | 3 +++ src/position.cpp | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/include/openmc/position.h b/include/openmc/position.h index 4f0ed8a9a..2be72b27c 100644 --- a/include/openmc/position.h +++ b/include/openmc/position.h @@ -3,6 +3,7 @@ #include #include // for sqrt +#include #include // for out_of_range #include @@ -94,6 +95,8 @@ inline bool operator==(Position a, Position b) inline bool operator!=(Position a, Position b) {return a.x != b.x || a.y != b.y || a.z != b.z;} +std::ostream& operator<<(std::ostream& os, Position a); + //============================================================================== //! Type representing a vector direction in Cartesian coordinates //============================================================================== diff --git a/src/position.cpp b/src/position.cpp index d7175912b..1215bfb12 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -94,4 +94,11 @@ Position::rotate(const std::vector& rotation) const }; } +std::ostream& +operator<<(std::ostream& os, Position r) +{ + os << "(" << r.x << ", " << r.y << ", " << r.z << ")"; + return os; +} + } // namespace openmc From 3274c25969895292044c9a235a044c6591098350 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 14 May 2019 09:08:28 -0500 Subject: [PATCH 3/9] Add ability to translate/rotate a cell filled with a lattice --- openmc/cell.py | 4 -- src/geometry.cpp | 114 ++++++++++++++++++++++++++--------------------- src/particle.cpp | 1 + 3 files changed, 64 insertions(+), 55 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index 8381fa8d8..3fd70b345 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -227,10 +227,6 @@ class Cell(IDManagerMixin): @rotation.setter def rotation(self, rotation): - if not isinstance(self.fill, openmc.Universe): - raise TypeError('Cell rotation can only be applied if the cell ' - 'is filled with a Universe.') - cv.check_type('cell rotation', rotation, Iterable, Real) cv.check_length('cell rotation', rotation, 3) self._rotation = np.asarray(rotation) diff --git a/src/geometry.cpp b/src/geometry.cpp index aec272ae1..a680d2bb7 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -170,32 +170,21 @@ find_cell_inner(Particle* p, const NeighborList* neighbor_list) //! Found a lower universe, update this coord level then search the next. // Set the lower coordinate level universe. - p->coord_[p->n_coord_].universe = c.fill_; + auto& coord {p->coord_[p->n_coord_]}; + coord.universe = c.fill_; // Set the position and direction. - p->coord_[p->n_coord_].r = p->coord_[p->n_coord_-1].r; - p->coord_[p->n_coord_].u = p->coord_[p->n_coord_-1].u; + coord.r = p->r_local(); + coord.u = p->u_local(); // Apply translation. - p->coord_[p->n_coord_].r -= c.translation_; + coord.r -= c.translation_; // Apply rotation. if (!c.rotation_.empty()) { - Position r = p->coord_[p->n_coord_].r; - p->coord_[p->n_coord_].r.x = r.x*c.rotation_[3] + r.y*c.rotation_[4] - + r.z*c.rotation_[5]; - p->coord_[p->n_coord_].r.y = r.x*c.rotation_[6] + r.y*c.rotation_[7] - + r.z*c.rotation_[8]; - p->coord_[p->n_coord_].r.z = r.x*c.rotation_[9] + r.y*c.rotation_[10] - + r.z*c.rotation_[11]; - Direction u = p->coord_[p->n_coord_].u; - p->coord_[p->n_coord_].u.x = u.x*c.rotation_[3] + u.y*c.rotation_[4] - + u.z*c.rotation_[5]; - p->coord_[p->n_coord_].u.y = u.x*c.rotation_[6] + u.y*c.rotation_[7] - + u.z*c.rotation_[8]; - p->coord_[p->n_coord_].u.z = u.x*c.rotation_[9] + u.y*c.rotation_[10] - + u.z*c.rotation_[11]; - p->coord_[p->n_coord_].rotated = true; + coord.r = coord.r.rotate(c.rotation_); + coord.u = coord.u.rotate(c.rotation_); + coord.rotated = true; } // Update the coordinate level and recurse. @@ -208,26 +197,39 @@ find_cell_inner(Particle* p, const NeighborList* neighbor_list) Lattice& lat {*model::lattices[c.fill_]}; - // Determine lattice indices. - auto i_xyz = lat.get_indices(p->r_local(), p->u_local()); + // Set the position and direction. + auto& coord {p->coord_[p->n_coord_]}; + coord.r = p->r_local(); + coord.u = p->u_local(); - // Store lower level coordinates. - Position r = lat.get_local_position(p->r_local(), i_xyz); - p->coord_[p->n_coord_].r = r; - p->coord_[p->n_coord_].u = p->u_local(); + // Apply translation. + coord.r -= c.translation_; + + // Apply rotation. + if (!c.rotation_.empty()) { + coord.r = coord.r.rotate(c.rotation_); + coord.u = coord.u.rotate(c.rotation_); + coord.rotated = true; + } + + // Determine lattice indices. + auto i_xyz = lat.get_indices(coord.r, coord.u); + + // Get local position in appropriate lattice cell + coord.r = lat.get_local_position(coord.r, i_xyz); // Set lattice indices. - p->coord_[p->n_coord_].lattice = c.fill_; - p->coord_[p->n_coord_].lattice_x = i_xyz[0]; - p->coord_[p->n_coord_].lattice_y = i_xyz[1]; - p->coord_[p->n_coord_].lattice_z = i_xyz[2]; + coord.lattice = c.fill_; + coord.lattice_x = i_xyz[0]; + coord.lattice_y = i_xyz[1]; + coord.lattice_z = i_xyz[2]; // Set the lower coordinate level universe. if (lat.are_valid_indices(i_xyz)) { - p->coord_[p->n_coord_].universe = lat[i_xyz]; + coord.universe = lat[i_xyz]; } else { if (lat.outer_ != NO_OUTER_UNIVERSE) { - p->coord_[p->n_coord_].universe = lat.outer_; + coord.universe = lat.outer_; } else { std::stringstream err_msg; err_msg << "Particle " << p->id_ << " is outside lattice " @@ -294,27 +296,32 @@ find_cell(Particle* p, bool use_neighbor_lists) void cross_lattice(Particle* p, const BoundaryInfo& boundary) { - auto& lat {*model::lattices[p->coord_[p->n_coord_-1].lattice]}; + auto& coord {p->coord_[p->n_coord_ - 1]}; + auto& lat {*model::lattices[coord.lattice]}; if (settings::verbosity >= 10 || simulation::trace) { std::stringstream msg; msg << " Crossing lattice " << lat.id_ << ". Current position (" - << p->coord_[p->n_coord_-1].lattice_x << "," - << p->coord_[p->n_coord_-1].lattice_y << "," - << p->coord_[p->n_coord_-1].lattice_z << ")"; + << coord.lattice_x << "," << coord.lattice_y << "," + << coord.lattice_z << "). r=" << p->r(); write_message(msg, 1); } // Set the lattice indices. - p->coord_[p->n_coord_-1].lattice_x += boundary.lattice_translation[0]; - p->coord_[p->n_coord_-1].lattice_y += boundary.lattice_translation[1]; - p->coord_[p->n_coord_-1].lattice_z += boundary.lattice_translation[2]; - std::array i_xyz {p->coord_[p->n_coord_-1].lattice_x, - p->coord_[p->n_coord_-1].lattice_y, - p->coord_[p->n_coord_-1].lattice_z}; + coord.lattice_x += boundary.lattice_translation[0]; + coord.lattice_y += boundary.lattice_translation[1]; + coord.lattice_z += boundary.lattice_translation[2]; + std::array i_xyz {coord.lattice_x, coord.lattice_y, coord.lattice_z}; // Set the new coordinate position. - p->r_local() = lat.get_local_position(p->coord_[p->n_coord_-2].r, i_xyz); + const auto& upper_coord {p->coord_[p->n_coord_ - 2]}; + const auto& cell {model::cells[upper_coord.cell]}; + Position r = upper_coord.r; + r -= cell->translation_; + if (!cell->rotation_.empty()) { + r = r.rotate(cell->rotation_); + } + p->r_local() = lat.get_local_position(r, i_xyz); if (!lat.are_valid_indices(i_xyz)) { // The particle is outside the lattice. Search for it from the base coords. @@ -359,9 +366,10 @@ BoundaryInfo distance_to_boundary(Particle* p) // Loop over each coordinate level. for (int i = 0; i < p->n_coord_; i++) { - Position r {p->coord_[i].r}; - Direction u {p->coord_[i].u}; - Cell& c {*model::cells[p->coord_[i].cell]}; + const auto& coord {p->coord_[i]}; + Position r {coord.r}; + Direction u {coord.u}; + Cell& c {*model::cells[coord.cell]}; // Find the oncoming surface in this cell and the distance to it. auto surface_distance = c.distance(r, u, p->surface_); @@ -369,10 +377,9 @@ BoundaryInfo distance_to_boundary(Particle* p) level_surf_cross = surface_distance.second; // Find the distance to the next lattice tile crossing. - if (p->coord_[i].lattice != C_NONE) { - auto& lat {*model::lattices[p->coord_[i].lattice]}; - std::array i_xyz {p->coord_[i].lattice_x, p->coord_[i].lattice_y, - p->coord_[i].lattice_z}; + if (coord.lattice != C_NONE) { + auto& lat {*model::lattices[coord.lattice]}; + std::array i_xyz {coord.lattice_x, coord.lattice_y, coord.lattice_z}; //TODO: refactor so both lattice use the same position argument (which //also means the lat.type attribute can be removed) std::pair> lattice_distance; @@ -381,8 +388,13 @@ BoundaryInfo distance_to_boundary(Particle* p) lattice_distance = lat.distance(r, u, i_xyz); break; case LatticeType::hex: - Position r_hex {p->coord_[i-1].r.x, p->coord_[i-1].r.y, - p->coord_[i].r.z}; + auto& cell_above {model::cells[p->coord_[i-1].cell]}; + Position r_hex {p->coord_[i-1].r}; + r_hex -= cell_above->translation_; + if (coord.rotated) { + r_hex = r_hex.rotate(cell_above->rotation_); + } + r_hex.z = coord.r.z; lattice_distance = lat.distance(r_hex, u, i_xyz); break; } diff --git a/src/particle.cpp b/src/particle.cpp index a6dbe84ff..7d862750d 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -41,6 +41,7 @@ LocalCoord::reset() lattice = C_NONE; lattice_x = 0; lattice_y = 0; + lattice_z = 0; rotated = false; } From 4cc90ad589832790bd98b2b86c02a79048314d57 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 15 May 2019 11:30:19 -0500 Subject: [PATCH 4/9] Add rotated lattice test --- .../lattice_rotated/__init__.py | 0 .../lattice_rotated/inputs_true.dat | 71 ++++++++++++++++ .../lattice_rotated/results_true.dat | 2 + .../regression_tests/lattice_rotated/test.py | 85 +++++++++++++++++++ 4 files changed, 158 insertions(+) create mode 100644 tests/regression_tests/lattice_rotated/__init__.py create mode 100644 tests/regression_tests/lattice_rotated/inputs_true.dat create mode 100644 tests/regression_tests/lattice_rotated/results_true.dat create mode 100644 tests/regression_tests/lattice_rotated/test.py diff --git a/tests/regression_tests/lattice_rotated/__init__.py b/tests/regression_tests/lattice_rotated/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/lattice_rotated/inputs_true.dat b/tests/regression_tests/lattice_rotated/inputs_true.dat new file mode 100644 index 000000000..8ee34b4f3 --- /dev/null +++ b/tests/regression_tests/lattice_rotated/inputs_true.dat @@ -0,0 +1,71 @@ + + + + + + + + + + + + 1.25 + 30 +
0.0 0.0
+ + 2 + 1 1 +1 2 1 + 1 1 +1 2 1 + 1 1 +1 1 1 + 1 1 + 1 +
+ + 1.25 1.25 + 30 + 4 4 + -2.5 -2.5 + +2 2 2 2 +1 1 1 1 +1 1 1 1 +1 1 1 1 + + + + + + +
+ + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 5 + 0 + + + 0.0 0.0 0.0 + + + diff --git a/tests/regression_tests/lattice_rotated/results_true.dat b/tests/regression_tests/lattice_rotated/results_true.dat new file mode 100644 index 000000000..b92298cc2 --- /dev/null +++ b/tests/regression_tests/lattice_rotated/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +4.538090E-01 2.452457E-02 diff --git a/tests/regression_tests/lattice_rotated/test.py b/tests/regression_tests/lattice_rotated/test.py new file mode 100644 index 000000000..9cab92e1e --- /dev/null +++ b/tests/regression_tests/lattice_rotated/test.py @@ -0,0 +1,85 @@ +import numpy as np +import openmc + +from tests.testing_harness import PyAPITestHarness + + +def rotated_lattice_model(): + model = openmc.model.Model() + + # Create some materials + fuel1 = openmc.Material() + fuel1.set_density('g/cm3', 10.0) + fuel1.add_nuclide('U235', 1.0) + fuel2 = openmc.Material() + fuel2.set_density('g/cm3', 10.0) + fuel2.add_nuclide('U238', 1.0) + water = openmc.Material() + water.set_density('g/cm3', 1.0) + water.add_nuclide('H1', 2.0) + water.add_nuclide('O16', 1.0) + water.add_s_alpha_beta('c_H_in_H2O') + model.materials.extend([fuel1, fuel2, water]) + + # Create universes for lattices + r_pin = openmc.ZCylinder(r=0.25) + fuel_cell = openmc.Cell(fill=fuel1, region=-r_pin) + water_cell = openmc.Cell(fill=water, region=+r_pin) + pin_universe = openmc.Universe(cells=(fuel_cell, water_cell)) + r_big_pin = openmc.ZCylinder(r=0.5) + fuel2_cell = openmc.Cell(fill=fuel2, region=-r_big_pin) + water2_cell = openmc.Cell(fill=water, region=+r_big_pin) + big_pin_universe = openmc.Universe(cells=(fuel2_cell, water2_cell)) + all_water_cell = openmc.Cell(fill=water) + outer_universe = openmc.Universe(30, cells=(all_water_cell,)) + + # Create hexagonal lattice + pitch = 1.25 + hexlat = openmc.HexLattice() + hexlat.center = (0., 0.) + hexlat.pitch = [pitch] + hexlat.outer = outer_universe + outer_ring = [big_pin_universe] + [pin_universe]*11 + middle_ring = [big_pin_universe] + [pin_universe]*5 + inner_ring = [big_pin_universe] + hexlat.universes = [outer_ring, middle_ring, inner_ring] + + # Create rectangular lattice + rectlat = openmc.RectLattice() + rectlat.center = (0., 0.) + rectlat.pitch = (pitch, pitch) + rectlat.lower_left = (-2*pitch, -2*pitch) + rectlat.outer = outer_universe + rectlat.universes = np.full((4, 4), pin_universe) + rectlat.universes[0] = big_pin_universe + + # Create cell filled with translated/rotated rectangular lattice on left + left_cyl = openmc.ZCylinder(x0=-4.0, r=4.0) + left_cell = openmc.Cell(fill=rectlat, region=-left_cyl) + left_cell.translation = (-4.0, 0.0, 0.0) + left_cell.rotation = (0.0, 0.0, 45.0) + + # Create cell filled with translated/rotated hexagonal lattice on right + right_cyl = openmc.ZCylinder(x0=4.0, r=4.0) + right_cell = openmc.Cell(fill=hexlat, region=-right_cyl) + right_cell.translation = (4.0, 0.0, 0.0) + right_cell.rotation = (0.0, 0.0, 30.0) + + # Finish up with the geometry + outer_cyl = openmc.ZCylinder(r=8.0, boundary_type='vacuum') + main_cell = openmc.Cell(fill=water, region=-outer_cyl & +left_cyl & +right_cyl) + model.geometry = openmc.Geometry([main_cell, left_cell, right_cell]) + + model.settings.batches = 5 + model.settings.inactive = 0 + model.settings.particles = 1000 + model.settings.source = openmc.Source(space=openmc.stats.Point()) + model.settings.export_to_xml() + + return model + + +def test(): + model = rotated_lattice_model() + harness = PyAPITestHarness('statepoint.5.h5', model) + harness.main() From cf4f3e93cbe7a52ec1403c5eb5951980a9a192b8 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 15 May 2019 11:33:40 -0500 Subject: [PATCH 5/9] Remove lattice_mixed test (replaced by lattice_rotated) --- .../lattice_mixed/__init__.py | 0 .../lattice_mixed/geometry.xml | 156 ------------------ .../lattice_mixed/materials.xml | 42 ----- .../regression_tests/lattice_mixed/plots.xml | 32 ---- .../lattice_mixed/results_true.dat | 2 - .../lattice_mixed/settings.xml | 14 -- tests/regression_tests/lattice_mixed/test.py | 6 - 7 files changed, 252 deletions(-) delete mode 100644 tests/regression_tests/lattice_mixed/__init__.py delete mode 100644 tests/regression_tests/lattice_mixed/geometry.xml delete mode 100644 tests/regression_tests/lattice_mixed/materials.xml delete mode 100644 tests/regression_tests/lattice_mixed/plots.xml delete mode 100644 tests/regression_tests/lattice_mixed/results_true.dat delete mode 100644 tests/regression_tests/lattice_mixed/settings.xml delete mode 100644 tests/regression_tests/lattice_mixed/test.py diff --git a/tests/regression_tests/lattice_mixed/__init__.py b/tests/regression_tests/lattice_mixed/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/lattice_mixed/geometry.xml b/tests/regression_tests/lattice_mixed/geometry.xml deleted file mode 100644 index 41aa05d41..000000000 --- a/tests/regression_tests/lattice_mixed/geometry.xml +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 011 - 011 011 - 011 011 011 - 011 011 011 011 - 011 011 011 011 011 - 011 011 011 011 011 011 - 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 055 011 011 011 011 011 - 011 011 011 055 011 011 055 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 055 011 011 055 011 055 011 011 - 011 011 011 011 055 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 055 011 011 011 - 011 011 055 011 011 051 011 011 055 011 011 - 011 011 011 055 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 055 011 011 011 011 - 011 011 055 011 055 011 011 055 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 055 011 011 055 011 011 011 - 011 011 011 011 011 055 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 - 011 011 011 011 011 011 - 011 011 011 011 011 - 011 011 011 011 - 011 011 011 - 011 011 - 011 - - - - - - - - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 102 102 102 102 102 102 - 102 102 102 102 - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/lattice_mixed/materials.xml b/tests/regression_tests/lattice_mixed/materials.xml deleted file mode 100644 index c7649fcf9..000000000 --- a/tests/regression_tests/lattice_mixed/materials.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/lattice_mixed/plots.xml b/tests/regression_tests/lattice_mixed/plots.xml deleted file mode 100644 index 903d69aef..000000000 --- a/tests/regression_tests/lattice_mixed/plots.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - xy_cell - 0 0 0 - 30 30 - 500 500 - - - - xy_material - 0 0 0 - 30 30 - 500 500 - - - - yz_cell - 0 0 0 - 50 400 - 500 4000 - - - - yz_material - 0 0 0 - 5 5 - 500 500 - - - diff --git a/tests/regression_tests/lattice_mixed/results_true.dat b/tests/regression_tests/lattice_mixed/results_true.dat deleted file mode 100644 index 09af26768..000000000 --- a/tests/regression_tests/lattice_mixed/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -9.877395E-01 1.744626E-02 diff --git a/tests/regression_tests/lattice_mixed/settings.xml b/tests/regression_tests/lattice_mixed/settings.xml deleted file mode 100644 index 69d50204e..000000000 --- a/tests/regression_tests/lattice_mixed/settings.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - eigenvalue - 10 - 5 - 500 - - - - -8.0 -8.0 -176 - 8.0 8.0 176 - - - diff --git a/tests/regression_tests/lattice_mixed/test.py b/tests/regression_tests/lattice_mixed/test.py deleted file mode 100644 index 3df1d7a4f..000000000 --- a/tests/regression_tests/lattice_mixed/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_lattice_mixed(): - harness = TestHarness('statepoint.10.h5') - harness.main() From 1bdb92ff10bd34f74a52f0f2dc806848a3dd3d63 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 15 May 2019 12:57:08 -0500 Subject: [PATCH 6/9] Add hexagonal lattice example notebook --- docs/source/examples/hexagonal.rst | 13 + docs/source/examples/index.rst | 19 +- examples/jupyter/hexagonal-lattice.ipynb | 300 +++++++++++++++++++++++ openmc/mgxs/__init__.py | 3 +- 4 files changed, 329 insertions(+), 6 deletions(-) create mode 100644 docs/source/examples/hexagonal.rst create mode 100644 examples/jupyter/hexagonal-lattice.ipynb diff --git a/docs/source/examples/hexagonal.rst b/docs/source/examples/hexagonal.rst new file mode 100644 index 000000000..8955fdb3f --- /dev/null +++ b/docs/source/examples/hexagonal.rst @@ -0,0 +1,13 @@ +.. _notebook_hexagonal: + +=========================== +Modeling Hexagonal Lattices +=========================== + +.. only:: html + + .. notebook:: ../../../examples/jupyter/hexagonal-lattice.ipynb + +.. only:: latex + + IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/index.rst b/docs/source/examples/index.rst index bcb1b1ad8..dd73706e5 100644 --- a/docs/source/examples/index.rst +++ b/docs/source/examples/index.rst @@ -8,9 +8,9 @@ The following series of `Jupyter `_ Notebooks provide examples for how to use various features of OpenMC by leveraging the :ref:`pythonapi`. ------------ -Basic Usage ------------ +------------- +General Usage +------------- .. toctree:: :maxdepth: 1 @@ -21,11 +21,20 @@ Basic Usage tally-arithmetic expansion-filters search - triso - candu nuclear-data nuclear-data-resonance-covariance +-------- +Geometry +-------- + +.. toctree:: + :maxdepth: 1 + + hexagonal + triso + candu + ------------------------------------ Multi-Group Cross Section Generation ------------------------------------ diff --git a/examples/jupyter/hexagonal-lattice.ipynb b/examples/jupyter/hexagonal-lattice.ipynb new file mode 100644 index 000000000..1865007de --- /dev/null +++ b/examples/jupyter/hexagonal-lattice.ipynb @@ -0,0 +1,300 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this example, we will create a hexagonal lattice and show how the orientation can be changed via the cell rotation property. Let's first just set up some materials and universes that we will use to fill the lattice." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "import openmc" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "fuel = openmc.Material(name='fuel')\n", + "fuel.add_nuclide('U235', 1.0)\n", + "fuel.set_density('g/cm3', 10.0)\n", + "\n", + "fuel2 = openmc.Material(name='fuel2')\n", + "fuel2.add_nuclide('U238', 1.0)\n", + "fuel2.set_density('g/cm3', 10.0)\n", + "\n", + "water = openmc.Material(name='water')\n", + "water.add_nuclide('H1', 2.0)\n", + "water.add_nuclide('O16', 1.0)\n", + "water.set_density('g/cm3', 1.0)\n", + "\n", + "mats = openmc.Materials((fuel, fuel2, water))\n", + "mats.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With our three materials, we will set up two universes that represent pin-cells: one with a small pin and one with a big pin. Since we will be using these universes in a lattice, it's always a good idea to have an \"outer\" universe as well that is applied outside the defined lattice." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "r_pin = openmc.ZCylinder(r=0.25)\n", + "fuel_cell = openmc.Cell(fill=fuel, region=-r_pin)\n", + "water_cell = openmc.Cell(fill=water, region=+r_pin)\n", + "pin_universe = openmc.Universe(cells=(fuel_cell, water_cell))\n", + "\n", + "r_big_pin = openmc.ZCylinder(r=0.5)\n", + "fuel2_cell = openmc.Cell(fill=fuel2, region=-r_big_pin)\n", + "water2_cell = openmc.Cell(fill=water, region=+r_big_pin)\n", + "big_pin_universe = openmc.Universe(cells=(fuel2_cell, water2_cell))\n", + "\n", + "all_water_cell = openmc.Cell(fill=water)\n", + "outer_universe = openmc.Universe(cells=(all_water_cell,))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's create a hexagonal lattice using the `HexLattice` class:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "lat = openmc.HexLattice()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We need to set the `center` of the lattice, the `pitch`, an `outer` universe (which is applied to all lattice elements outside of those that are defined), and a list of `universes`. Let's start with the easy ones first. Note that for a 2D lattice, we only need to specify a single number for the pitch." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "lat.center = (0., 0.)\n", + "lat.pitch = (1.25,)\n", + "lat.outer = outer_universe" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we need to set the `universes` property on our lattice. It needs to be set to a list of lists of Universes, where each list of Universes corresponds to a ring of the lattice. The rings are ordered from outermost to innermost, and within each ring the indexing starts at the \"top\". To help visualize the proper indices, we can use the `show_indices()` helper method." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " (0, 0)\n", + " (0,11) (0, 1)\n", + "(0,10) (1, 0) (0, 2)\n", + " (1, 5) (1, 1)\n", + "(0, 9) (2, 0) (0, 3)\n", + " (1, 4) (1, 2)\n", + "(0, 8) (1, 3) (0, 4)\n", + " (0, 7) (0, 5)\n", + " (0, 6)\n" + ] + } + ], + "source": [ + "print(lat.show_indices(num_rings=3))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's set up a lattice where the first element in each ring is the big pin universe and all other elements are regular pin universes. From the diagram above, we see that the outer ring has 12 elements, the middle ring has 6, and the innermost degenerate ring has a single element." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HexLattice\n", + "\tID =\t4\n", + "\tName =\t\n", + "\t# Rings =\t3\n", + "\t# Axial =\tNone\n", + "\tCenter =\t(0.0, 0.0)\n", + "\tPitch =\t(1.25,)\n", + "\tOuter =\t3\n", + "\tUniverses \n", + " 2\n", + " 1 1\n", + "1 2 1\n", + " 1 1\n", + "1 2 1\n", + " 1 1\n", + "1 1 1\n", + " 1 1\n", + " 1\n" + ] + } + ], + "source": [ + "outer_ring = [big_pin_universe] + [pin_universe]*11\n", + "middle_ring = [big_pin_universe] + [pin_universe]*5\n", + "inner_ring = [big_pin_universe]\n", + "lat.universes = [outer_ring, middle_ring, inner_ring]\n", + "print(lat)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's put our lattice inside a circular cell that will serve as the top-level cell for our geometry." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "outer_surface = openmc.ZCylinder(r=4.0, boundary_type='vacuum')\n", + "main_cell = openmc.Cell(fill=lat, region=-outer_surface)\n", + "geom = openmc.Geometry([main_cell])\n", + "geom.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's create a plot to see what our geometry looks like." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p = openmc.Plot.from_geometry(geom)\n", + "p.color_by = 'material'\n", + "p.colors = colors = {\n", + " water: 'blue',\n", + " fuel: 'olive',\n", + " fuel2: 'yellow'\n", + "}\n", + "p.to_ipython_image()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At this point, if we wanted to simulate the model, we would need to create an instance of `openmc.Settings`, export it to XML, and run." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Rotating the lattice\n", + "\n", + "Now let's say we want our hexagonal lattice orientated such that flat sides of each lattice element are parallel to the y-axis instead of the x-axis. This can be achieved by rotating the cell that contains the lattice by 30 degrees." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Rotate the main cell and re-export the geometry\n", + "main_cell.rotation = (0., 0., 30.)\n", + "geom.export_to_xml()\n", + "\n", + "# Run OpenMC in plotting mode\n", + "p.to_ipython_image()" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/openmc/mgxs/__init__.py b/openmc/mgxs/__init__.py index e505c7ebc..886cc904a 100644 --- a/openmc/mgxs/__init__.py +++ b/openmc/mgxs/__init__.py @@ -7,6 +7,7 @@ from openmc.mgxs.mdgxs import * GROUP_STRUCTURES = {} """Dictionary of commonly used energy group structures: + - "CASMO-X" (where X is 2, 4, 8, 16, 25, 40 or 70) from the CASMO_ lattice physics code - "XMAS-172_" designed for LWR analysis ([SAR1990]_, [SAN2004]_) @@ -19,7 +20,7 @@ GROUP_STRUCTURES = {} .. _XMAS-172: https://www-nds.iaea.org/wimsd/energy.htm .. _SHEM-361: https://www.polymtl.ca/merlin/libraries.htm .. _activation: https://fispact.ukaea.uk/wiki/Keyword:GETXS -.. _CCFE-709: https://fispact.ukaea.uk/wiki/CCFE-709_group_structure +.. _CCFE-709: https://fispact.ukaea.uk/wiki/CCFE-709_group_structure .. _UKAEA-1102: https://fispact.ukaea.uk/wiki/UKAEA-1102_group_structure .. [SAR1990] Sartori, E., OECD/NEA Data Bank: Standard Energy Group Structures of Cross Section Libraries for Reactor Shielding, Reactor Cell and Fusion From 11eb891e21fdfd822d2bee175280bc315a46ac3d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 29 May 2019 15:09:12 -0500 Subject: [PATCH 7/9] Add a LocalCoord::rotate method as suggested by @pshriwise --- include/openmc/particle.h | 12 ++++++++---- src/geometry.cpp | 8 ++------ src/particle.cpp | 8 ++++++++ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/openmc/particle.h b/include/openmc/particle.h index 62923c11f..a2b7ce557 100644 --- a/include/openmc/particle.h +++ b/include/openmc/particle.h @@ -9,6 +9,7 @@ #include // for unique_ptr #include #include +#include #include "openmc/constants.h" #include "openmc/position.h" @@ -38,7 +39,13 @@ constexpr double CACHE_INVALID {-1.0}; // Class declarations //============================================================================== -struct LocalCoord { +class LocalCoord { +public: + void rotate(const std::vector& rotation); + + //! clear data from a single coordinate level + void reset(); + Position r; //!< particle position Direction u; //!< particle direction int cell {-1}; @@ -48,9 +55,6 @@ struct LocalCoord { int lattice_y {-1}; int lattice_z {-1}; bool rotated {false}; //!< Is the level rotated? - - //! clear data from a single coordinate level - void reset(); }; //============================================================================== diff --git a/src/geometry.cpp b/src/geometry.cpp index a680d2bb7..fbb048650 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -182,9 +182,7 @@ find_cell_inner(Particle* p, const NeighborList* neighbor_list) // Apply rotation. if (!c.rotation_.empty()) { - coord.r = coord.r.rotate(c.rotation_); - coord.u = coord.u.rotate(c.rotation_); - coord.rotated = true; + coord.rotate(c.rotation_); } // Update the coordinate level and recurse. @@ -207,9 +205,7 @@ find_cell_inner(Particle* p, const NeighborList* neighbor_list) // Apply rotation. if (!c.rotation_.empty()) { - coord.r = coord.r.rotate(c.rotation_); - coord.u = coord.u.rotate(c.rotation_); - coord.rotated = true; + coord.rotate(c.rotation_); } // Determine lattice indices. diff --git a/src/particle.cpp b/src/particle.cpp index 7d862750d..988130ec2 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -33,6 +33,14 @@ namespace openmc { // LocalCoord implementation //============================================================================== +void +LocalCoord::rotate(const std::vector& rotation) +{ + this->r = this->r.rotate(rotation); + this->u = this->u.rotate(rotation); + this->rotated = true; +} + void LocalCoord::reset() { From da5f7440b12b538f8469516a1548ead72b04857c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 8 Jun 2019 07:48:26 -0500 Subject: [PATCH 8/9] Remove get_ from get_hexagonal_prism, get_rectangular_prism --- docs/source/pythonapi/model.rst | 4 +-- examples/jupyter/expansion-filters.ipynb | 2 +- examples/jupyter/pincell.ipynb | 4 +-- openmc/__init__.py | 2 +- openmc/model/funcs.py | 31 ++++++++++++++++--- .../lattice_hex_coincident/test.py | 8 ++--- tests/regression_tests/lattice_hex_x/test.py | 8 ++--- tests/unit_tests/test_filters.py | 2 +- tests/unit_tests/test_geometry.py | 14 ++++----- 9 files changed, 49 insertions(+), 26 deletions(-) diff --git a/docs/source/pythonapi/model.rst b/docs/source/pythonapi/model.rst index 14f4a4beb..ee038987b 100644 --- a/docs/source/pythonapi/model.rst +++ b/docs/source/pythonapi/model.rst @@ -12,8 +12,8 @@ Convenience Functions openmc.model.borated_water openmc.model.cylinder_from_points - openmc.model.get_hexagonal_prism - openmc.model.get_rectangular_prism + openmc.model.hexagonal_prism + openmc.model.rectangular_prism openmc.model.subdivide TRISO Fuel Modeling diff --git a/examples/jupyter/expansion-filters.ipynb b/examples/jupyter/expansion-filters.ipynb index 7870faffe..69d315e24 100644 --- a/examples/jupyter/expansion-filters.ipynb +++ b/examples/jupyter/expansion-filters.ipynb @@ -62,7 +62,7 @@ "source": [ "# Define surfaces used to construct regions\n", "zmin, zmax = -10., 10.\n", - "box = openmc.model.get_rectangular_prism(10., 10., boundary_type='reflective')\n", + "box = openmc.model.rectangular_prism(10., 10., boundary_type='reflective')\n", "bottom = openmc.ZPlane(z0=zmin, boundary_type='vacuum')\n", "boron_lower = openmc.ZPlane(z0=-0.5)\n", "boron_upper = openmc.ZPlane(z0=0.5)\n", diff --git a/examples/jupyter/pincell.ipynb b/examples/jupyter/pincell.ipynb index 72b65a265..f8641db13 100644 --- a/examples/jupyter/pincell.ipynb +++ b/examples/jupyter/pincell.ipynb @@ -903,8 +903,8 @@ } ], "source": [ - "box = openmc.get_rectangular_prism(width=pitch, height=pitch,\n", - " boundary_type='reflective')\n", + "box = openmc.rectangular_prism(width=pitch, height=pitch,\n", + " boundary_type='reflective')\n", "type(box)" ] }, diff --git a/openmc/__init__.py b/openmc/__init__.py index 715550302..1661c4ac4 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -32,6 +32,6 @@ from openmc.polynomial import * from . import examples # Import a few convencience functions that used to be here -from openmc.model import get_rectangular_prism, get_hexagonal_prism +from openmc.model import rectangular_prism, hexagonal_prism __version__ = '0.10.0' diff --git a/openmc/model/funcs.py b/openmc/model/funcs.py index 5f2db4d30..143033eca 100644 --- a/openmc/model/funcs.py +++ b/openmc/model/funcs.py @@ -3,6 +3,7 @@ from collections.abc import Iterable from math import sqrt from numbers import Real from functools import partial +from warnings import warn from openmc import XPlane, YPlane, Plane, ZCylinder, Quadric from openmc.checkvalue import check_type, check_value @@ -101,10 +102,14 @@ def borated_water(boron_ppm, temperature=293., pressure=0.1013, temp_unit='K', return out -def get_rectangular_prism(width, height, axis='z', origin=(0., 0.), - boundary_type='transmission', corner_radius=0.): +def rectangular_prism(width, height, axis='z', origin=(0., 0.), + boundary_type='transmission', corner_radius=0.): """Get an infinite rectangular prism from four planar surfaces. + .. versionchanged:: 0.11 + This function was renamed from `get_rectangular_prism` to + `rectangular_prism`. + Parameters ---------- width: float @@ -202,10 +207,21 @@ def get_rectangular_prism(width, height, axis='z', origin=(0., 0.), return prism -def get_hexagonal_prism(edge_length=1., orientation='y', origin=(0., 0.), - boundary_type='transmission', corner_radius=0.): +def get_rectangular_prism(*args, **kwargs): + warn("get_rectangular_prism(...) has been renamed rectangular_prism(...). " + "Future versions of OpenMC will not accept get_rectangular_prism.", + FutureWarning) + return rectangular_prism(*args, **kwargs) + + +def hexagonal_prism(edge_length=1., orientation='y', origin=(0., 0.), + boundary_type='transmission', corner_radius=0.): """Create a hexagon region from six surface planes. + .. versionchanged:: 0.11 + This function was renamed from `get_hexagonal_prism` to + `hexagonal_prism`. + Parameters ---------- edge_length : float @@ -346,6 +362,13 @@ def get_hexagonal_prism(edge_length=1., orientation='y', origin=(0., 0.), return prism +def get_hexagonal_prism(*args, **kwargs): + warn("get_hexagonal_prism(...) has been renamed hexagonal_prism(...). " + "Future versions of OpenMC will not accept get_hexagonal_prism.", + FutureWarning) + return hexagonal_prism(*args, **kwargs) + + def cylinder_from_points(p1, p2, r, **kwargs): """Return cylinder defined by two points passing through its center. diff --git a/tests/regression_tests/lattice_hex_coincident/test.py b/tests/regression_tests/lattice_hex_coincident/test.py index eaea74b19..30bc470f2 100644 --- a/tests/regression_tests/lattice_hex_coincident/test.py +++ b/tests/regression_tests/lattice_hex_coincident/test.py @@ -103,10 +103,10 @@ class HexLatticeCoincidentTestHarness(PyAPITestHarness): inf_mat_univ = openmc.Universe(cells=[inf_mat,]) # a hex surface for the core to go inside of - hexprism = openmc.model.get_hexagonal_prism(edge_length=edge_length, - origin=(0.0, 0.0), - boundary_type = 'reflective', - orientation='x') + hexprism = openmc.model.hexagonal_prism(edge_length=edge_length, + origin=(0.0, 0.0), + boundary_type = 'reflective', + orientation='x') pincell_only_lattice = openmc.HexLattice(name="regular fuel assembly") pincell_only_lattice.center = (0., 0.) diff --git a/tests/regression_tests/lattice_hex_x/test.py b/tests/regression_tests/lattice_hex_x/test.py index 538f790da..ecb27c9c2 100644 --- a/tests/regression_tests/lattice_hex_x/test.py +++ b/tests/regression_tests/lattice_hex_x/test.py @@ -139,10 +139,10 @@ class HexLatticeOXTestHarness(PyAPITestHarness): # a hex surface for the core to go inside of - hexprism = openmc.model.get_hexagonal_prism(edge_length=edge_length, - origin=(0.0, 0.0), - boundary_type='reflective', - orientation='x') + hexprism = openmc.model.hexagonal_prism(edge_length=edge_length, + origin=(0.0, 0.0), + boundary_type='reflective', + orientation='x') region = hexprism & +fuel_bottom & -fuel_top inf_mat = openmc.Cell(cell_id=12) diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index 5817c4c3d..676ee452e 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -11,7 +11,7 @@ def box_model(): m.add_nuclide('U235', 1.0) m.set_density('g/cm3', 1.0) - box = openmc.model.get_rectangular_prism(10., 10., boundary_type='vacuum') + box = openmc.model.rectangular_prism(10., 10., boundary_type='vacuum') c = openmc.Cell(fill=m, region=box) model.geometry.root_universe = openmc.Universe(cells=[c]) diff --git a/tests/unit_tests/test_geometry.py b/tests/unit_tests/test_geometry.py index f3718630a..69211f72e 100644 --- a/tests/unit_tests/test_geometry.py +++ b/tests/unit_tests/test_geometry.py @@ -204,9 +204,9 @@ def test_get_by_name(): def test_hex_prism(): - hex_prism = openmc.model.get_hexagonal_prism(edge_length=5.0, - origin=(0.0, 0.0), - orientation='y') + hex_prism = openmc.model.hexagonal_prism(edge_length=5.0, + origin=(0.0, 0.0), + orientation='y') # clear checks assert (0.0, 0.0, 0.0) in hex_prism assert (10.0, 10.0, 10.0) not in hex_prism @@ -214,10 +214,10 @@ def test_hex_prism(): assert (0.0, 5.01, 0.0) not in hex_prism assert (0.0, 4.99, 0.0) in hex_prism - rounded_hex_prism = openmc.model.get_hexagonal_prism(edge_length=5.0, - origin=(0.0, 0.0), - orientation='y', - corner_radius=1.0) + rounded_hex_prism = openmc.model.hexagonal_prism(edge_length=5.0, + origin=(0.0, 0.0), + orientation='y', + corner_radius=1.0) # clear checks assert (0.0, 0.0, 0.0) in rounded_hex_prism From 8b83f0c8477aa48cf55033b48e026fdadf2f6770 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 8 Jun 2019 07:51:05 -0500 Subject: [PATCH 9/9] Update hexagonal lattice example notebook --- examples/jupyter/hexagonal-lattice.ipynb | 84 ++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 6 deletions(-) diff --git a/examples/jupyter/hexagonal-lattice.ipynb b/examples/jupyter/hexagonal-lattice.ipynb index 1865007de..e0a48e236 100644 --- a/examples/jupyter/hexagonal-lattice.ipynb +++ b/examples/jupyter/hexagonal-lattice.ipynb @@ -152,6 +152,7 @@ "HexLattice\n", "\tID =\t4\n", "\tName =\t\n", + "\tOrientation =\ty\n", "\t# Rings =\t3\n", "\t# Axial =\tNone\n", "\tCenter =\t(0.0, 0.0)\n", @@ -211,7 +212,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "" ] @@ -243,9 +244,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Rotating the lattice\n", + "## Lattice orientation\n", "\n", - "Now let's say we want our hexagonal lattice orientated such that flat sides of each lattice element are parallel to the y-axis instead of the x-axis. This can be achieved by rotating the cell that contains the lattice by 30 degrees." + "Now let's say we want our hexagonal lattice orientated such that two sides of the lattice are parallel to the x-axis. This can be achieved by two means: either we can rotate the cell that contains the lattice, or we can can change the `HexLattice.orientation` attribute. By default, the `orientation` is set to \"y\", indicating that two sides of the lattice are parallel to the y-axis, but we can also change it to \"x\" to make them parallel to the x-axis." ] }, { @@ -255,7 +256,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "" ] @@ -266,13 +267,84 @@ } ], "source": [ - "# Rotate the main cell and re-export the geometry\n", - "main_cell.rotation = (0., 0., 30.)\n", + "# Change the orientation of the lattice and re-export the geometry\n", + "lat.orientation = 'x'\n", "geom.export_to_xml()\n", "\n", "# Run OpenMC in plotting mode\n", "p.to_ipython_image()" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When we change the orientation to 'x', you can see that the first universe in each ring starts to the right along the x-axis. As before, the universes are defined in a clockwise fashion around each ring. To see the proper indices for a hexagonal lattice in this orientation, we can again call `show_indices` but pass an extra orientation argument:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " (0, 8) (0, 9) (0,10)\n", + "\n", + " (0, 7) (1, 4) (1, 5) (0,11)\n", + "\n", + "(0, 6) (1, 3) (2, 0) (1, 0) (0, 0)\n", + "\n", + " (0, 5) (1, 2) (1, 1) (0, 1)\n", + "\n", + " (0, 4) (0, 3) (0, 2)\n" + ] + } + ], + "source": [ + "print(lat.show_indices(3, orientation='x'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Hexagonal prisms\n", + "\n", + "OpenMC also contains a convenience function that can create a hexagonal prism representing the interior region of six surfaces defining a hexagon. This can be useful as a bounding surface of a hexagonal lattice. For example, if we wanted the outer boundary of our geometry to be hexagonal, we could change the `region` of the main cell:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "main_cell.region = openmc.model.hexagonal_prism(\n", + " edge_length=3*lat.pitch[0],\n", + " orientation='x',\n", + " boundary_type='vacuum'\n", + ")\n", + "geom.export_to_xml()\n", + "\n", + "# Run OpenMC in plotting mode\n", + "p.color_by = 'cell'\n", + "p.to_ipython_image()" + ] } ], "metadata": {