From ea79fa079f6a71daac16a8d8f426c05564d4201b Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Wed, 18 Aug 2021 15:49:58 -0500 Subject: [PATCH 1/9] Allow constant scaling factor to be applied to libMesh unstructured meshes. Refs #1872 --- include/openmc/mesh.h | 7 ++++++- src/mesh.cpp | 25 ++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index d3ca900cf5..7a55b5f206 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -492,7 +492,7 @@ class LibMesh : public UnstructuredMesh { public: // Constructors LibMesh(pugi::xml_node node); - LibMesh(const std::string& filename); + LibMesh(const std::string& filename, const double length_multiplier = 1.0); // Overridden Methods void bins_crossed(Position r0, Position r1, const Direction& u, @@ -533,6 +533,9 @@ private: //! Translate an element pointer to a bin index int get_bin_from_element(const libMesh::Elem* elem) const; + //! Set the length multiplier to apply to each point in the mesh + void set_length_multiplier(const double length_multiplier); + // Data members unique_ptr m_; //!< pointer to the libMesh mesh instance vector> @@ -547,6 +550,8 @@ private: libMesh::BoundingBox bbox_; //!< bounding box of the mesh libMesh::dof_id_type first_element_id_; //!< id of the first element in the mesh + double length_multiplier_ {1.0}; //!< Constant multiplication factor to apply to mesh coordinates + bool specified_length_multiplier_ {false}; }; #endif diff --git a/src/mesh.cpp b/src/mesh.cpp index 4798bfcf56..7770dfb865 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -35,6 +35,7 @@ #ifdef LIBMESH #include "libmesh/mesh_tools.h" #include "libmesh/numeric_vector.h" +#include "libmesh/mesh_modification.h" #endif namespace openmc { @@ -2141,15 +2142,32 @@ void MOABMesh::write(const std::string& base_filename) const LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) { + // check if a length unit multiplier was specified + if (check_for_node(node, "length_multiplier")) { + length_multiplier_ = std::stod(get_node_value(node, "length_multiplier")); + specified_length_multiplier_ = true; + } + initialize(); } -LibMesh::LibMesh(const std::string& filename) +LibMesh::LibMesh(const std::string& filename, const double length_multiplier) { filename_ = filename; + + if (length_multiplier != 1.0) { + set_length_multiplier(length_multiplier); + } + initialize(); } +void LibMesh::set_length_multiplier(const double length_multiplier) +{ + length_multiplier_ = length_multiplier; + specified_length_multiplier_ = true; +} + void LibMesh::initialize() { if (!settings::libmesh_comm) { @@ -2162,6 +2180,11 @@ void LibMesh::initialize() m_ = make_unique(*settings::libmesh_comm, n_dimension_); m_->read(filename_); + + if (specified_length_multiplier_) { + libMesh::MeshTools::Modification::scale(*m_, length_multiplier_); + } + m_->prepare_for_use(); // ensure that the loaded mesh is 3 dimensional From 9165a836fe8aa49031ab00fcabb5acdcebe07602 Mon Sep 17 00:00:00 2001 From: April Novak Date: Thu, 19 Aug 2021 16:08:57 -0500 Subject: [PATCH 2/9] Apply suggestions from code review Co-authored-by: Patrick Shriwise --- include/openmc/mesh.h | 2 +- src/mesh.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index 7a55b5f206..d14987d6d6 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -492,7 +492,7 @@ class LibMesh : public UnstructuredMesh { public: // Constructors LibMesh(pugi::xml_node node); - LibMesh(const std::string& filename, const double length_multiplier = 1.0); + LibMesh(const std::string& filename, double length_multiplier = 1.0); // Overridden Methods void bins_crossed(Position r0, Position r1, const Direction& u, diff --git a/src/mesh.cpp b/src/mesh.cpp index 7770dfb865..20a49b1d97 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2151,7 +2151,7 @@ LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) initialize(); } -LibMesh::LibMesh(const std::string& filename, const double length_multiplier) +LibMesh::LibMesh(const std::string& filename, double length_multiplier) { filename_ = filename; @@ -2162,7 +2162,7 @@ LibMesh::LibMesh(const std::string& filename, const double length_multiplier) initialize(); } -void LibMesh::set_length_multiplier(const double length_multiplier) +void LibMesh::set_length_multiplier(double length_multiplier) { length_multiplier_ = length_multiplier; specified_length_multiplier_ = true; From a6140709ccbab764bb82d32322211843c71e6ba5 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Sat, 11 Sep 2021 08:02:19 -0500 Subject: [PATCH 3/9] Allowing a scaling factor for MOAB meshes too. --- include/openmc/mesh.h | 16 +++++++----- src/mesh.cpp | 59 +++++++++++++++++++++++++++++++++---------- 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index d14987d6d6..d34ad2087b 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -331,6 +331,15 @@ public: true}; //!< Write tallies onto the unstructured mesh at the end of a run std::string filename_; //!< Path to unstructured mesh file +protected: + //! Set the length multiplier to apply to each point in the mesh + void set_length_multiplier(const double length_multiplier); + + // Data members + double length_multiplier_ { + 1.0}; //!< Constant multiplication factor to apply to mesh coordinates + bool specified_length_multiplier_ {false}; + private: //! Setup method for the mesh. Builds data structures, //! sets up element mapping, creates bounding boxes, etc. @@ -344,7 +353,7 @@ public: // Constructors MOABMesh() = default; MOABMesh(pugi::xml_node); - MOABMesh(const std::string& filename); + MOABMesh(const std::string& filename, double length_multiplier = 1.0); MOABMesh(std::shared_ptr external_mbi); // Overridden Methods @@ -533,9 +542,6 @@ private: //! Translate an element pointer to a bin index int get_bin_from_element(const libMesh::Elem* elem) const; - //! Set the length multiplier to apply to each point in the mesh - void set_length_multiplier(const double length_multiplier); - // Data members unique_ptr m_; //!< pointer to the libMesh mesh instance vector> @@ -550,8 +556,6 @@ private: libMesh::BoundingBox bbox_; //!< bounding box of the mesh libMesh::dof_id_type first_element_id_; //!< id of the first element in the mesh - double length_multiplier_ {1.0}; //!< Constant multiplication factor to apply to mesh coordinates - bool specified_length_multiplier_ {false}; }; #endif diff --git a/src/mesh.cpp b/src/mesh.cpp index 20a49b1d97..642e0e9d9d 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -172,6 +172,12 @@ UnstructuredMesh::UnstructuredMesh(pugi::xml_node node) : Mesh(node) } } + // check if a length unit multiplier was specified + if (check_for_node(node, "length_multiplier")) { + length_multiplier_ = std::stod(get_node_value(node, "length_multiplier")); + specified_length_multiplier_ = true; + } + // get the filename of the unstructured mesh to load if (check_for_node(node, "filename")) { filename_ = get_node_value(node, "filename"); @@ -222,6 +228,12 @@ void UnstructuredMesh::to_hdf5(hid_t group) const close_group(mesh_group); } +void UnstructuredMesh::set_length_multiplier(double length_multiplier) +{ + length_multiplier_ = length_multiplier; + specified_length_multiplier_ = true; +} + void StructuredMesh::get_indices(Position r, int* ijk, bool* in_mesh) const { *in_mesh = true; @@ -1586,9 +1598,14 @@ MOABMesh::MOABMesh(pugi::xml_node node) : UnstructuredMesh(node) initialize(); } -MOABMesh::MOABMesh(const std::string& filename) +MOABMesh::MOABMesh(const std::string& filename, double length_multiplier) { filename_ = filename; + + if (length_multiplier != 1.0) { + set_length_multiplier(length_multiplier); + } + initialize(); } @@ -1635,6 +1652,34 @@ void MOABMesh::initialize() fatal_error("Failed to add tetrahedra to an entity set."); } + if (specified_length_multiplier_) { + // get the connectivity of all tets + moab::Range adj; + rval = mbi_->get_adjacencies(ehs_, 0, true, adj, moab::Interface::UNION); + if (rval != moab::MB_SUCCESS) { + fatal_error("Failed to get adjacent vertices of tetrahedra."); + } + // scale all vertex coords by multiplier (done individually so not all + // coordinates are in memory twice at once) + for (auto vert : adj) { + // retrieve coords + std::array coord; + rval = mbi_->get_coords(&vert, 1, coord.data()); + if (rval != moab::MB_SUCCESS) { + fatal_error("Could not get coordinates of vertex."); + } + // scale coords + for (auto& c : coord) { + c *= length_multiplier_; + } + // set new coords + rval = mbi_->set_coords(&vert, 1, coord.data()); + if (rval != moab::MB_SUCCESS) { + fatal_error("Failed to set new vertex coordinates"); + } + } + } + // build acceleration data structures compute_barycentric_data(ehs_); build_kdtree(ehs_); @@ -2142,12 +2187,6 @@ void MOABMesh::write(const std::string& base_filename) const LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) { - // check if a length unit multiplier was specified - if (check_for_node(node, "length_multiplier")) { - length_multiplier_ = std::stod(get_node_value(node, "length_multiplier")); - specified_length_multiplier_ = true; - } - initialize(); } @@ -2162,12 +2201,6 @@ LibMesh::LibMesh(const std::string& filename, double length_multiplier) initialize(); } -void LibMesh::set_length_multiplier(double length_multiplier) -{ - length_multiplier_ = length_multiplier; - specified_length_multiplier_ = true; -} - void LibMesh::initialize() { if (!settings::libmesh_comm) { From 95c1143cfca90714d3c5b27e57bd6d359322e328 Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Wed, 15 Sep 2021 10:20:57 -0500 Subject: [PATCH 4/9] Add length_multiplier to python API. Refs #1872 --- docs/source/io_formats/tallies.rst | 4 ++++ openmc/mesh.py | 26 +++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/source/io_formats/tallies.rst b/docs/source/io_formats/tallies.rst index ad72273690..7f95f29850 100644 --- a/docs/source/io_formats/tallies.rst +++ b/docs/source/io_formats/tallies.rst @@ -318,6 +318,10 @@ attributes/sub-elements: :dimension: The number of mesh cells in each direction. (For regular mesh only.) + :length_multiplier: + A multiplicative factor to apply to the mesh coordinates in all directions. + (For unstructured mesh only.) + :lower_left: The lower-left corner of the structured mesh. If only two coordinates are given, it is assumed that the mesh is an x-y mesh. (For regular mesh only.) diff --git a/openmc/mesh.py b/openmc/mesh.py index 0e35aa6fea..f542ac5fe1 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -611,6 +611,8 @@ class UnstructuredMesh(MeshBase): ---------- filename : str Location of the unstructured mesh file + length_multiplier: float + Constant multiplier to apply to mesh coordinates mesh_id : int Unique identifier for the mesh name : str @@ -626,11 +628,16 @@ class UnstructuredMesh(MeshBase): Name of the mesh filename : str Name of the file containing the unstructured mesh + length_multiplier: float + Multiplicative factor to apply to mesh coordinates library : str Mesh library used for the unstructured mesh tally output : bool Indicates whether or not automatic tally output should be generated for this mesh + specified_length_multiplier: bool + Indicates whether a non-unity length multiplier has been + applied to this mesh volumes : Iterable of float Volumes of the unstructured mesh elements total_volume : float @@ -639,13 +646,15 @@ class UnstructuredMesh(MeshBase): An iterable of element centroid coordinates, e.g. [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0), ...] """ - def __init__(self, filename, library, mesh_id=None, name=''): + def __init__(self, filename, library, mesh_id=None, name='', length_multiplier=1.0): super().__init__(mesh_id, name) self.filename = filename self._volumes = None self._centroids = None self.library = library self._output = True + self._specified_length_multiplier = False + self.length_multiplier = length_multiplier @property def filename(self): @@ -713,6 +722,18 @@ class UnstructuredMesh(MeshBase): Iterable, Real) self._centroids = centroids + @property + def length_multiplier(self): + return self._length_multiplier + + @length_multiplier.setter + def length_multiplier(self, length_multiplier): + cv.check_type("Unstructured mesh length multiplier", length_multiplier, Real) + self._length_multiplier = length_multiplier + + if (self._length_multiplier != 1.0): + self._specified_length_multiplier = True + def __repr__(self): string = super().__repr__() string += '{: <16}=\t{}\n'.format('\tFilename', self.filename) @@ -836,6 +857,9 @@ class UnstructuredMesh(MeshBase): subelement = ET.SubElement(element, "filename") subelement.text = self.filename + if (self._specified_length_multiplier): + element.set("length_multiplier", str(self.length_multiplier)) + return element @classmethod From 2c9ae96c1d94613d697fb02cad7c1967d32d1503 Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Wed, 15 Sep 2021 10:27:10 -0500 Subject: [PATCH 5/9] Add length multiplier to vtk writing. Refs #1872 --- openmc/mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index f542ac5fe1..bf7954fd41 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -784,7 +784,7 @@ class UnstructuredMesh(MeshBase): for centroid in self.centroids: # create a point for each centroid - point_id = points.InsertNextPoint(centroid) + point_id = points.InsertNextPoint(centroid * self.length_multiplier) # create a cell of type "Vertex" for each point cell_id = vertices.InsertNextCell(cell_dim, (point_id,)) From 58dd23b06af4ba3cca15c04f3846d2ac1ff0e040 Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Wed, 15 Sep 2021 10:31:15 -0500 Subject: [PATCH 6/9] Add length multiplier to from_xml. Refs #1872 --- openmc/mesh.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index bf7954fd41..c72152690c 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -879,5 +879,6 @@ class UnstructuredMesh(MeshBase): mesh_id = int(get_text(elem, 'id')) filename = get_text(elem, 'filename') library = get_text(elem, 'library') + length_multiplier = float(get_text(elem, 'length_multiplier', 1.0)) - return cls(filename, library, mesh_id) + return cls(filename, library, mesh_id, '', length_multiplier) From 796de48e5dd74e37c261a133a62521cc880ecfff Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Mon, 20 Sep 2021 10:58:48 -0500 Subject: [PATCH 7/9] Get length multiplier from HDF5. Refs #1872 --- openmc/mesh.py | 1 + src/mesh.cpp | 20 +++++++++----------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index c72152690c..6dde9277ca 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -215,6 +215,7 @@ class RegularMesh(MeshBase): mesh.lower_left = group['lower_left'][()] mesh.upper_right = group['upper_right'][()] mesh.width = group['width'][()] + mesh.length_multiplier = group['length_multiplier'][()] if 'length_multiplier' in group else 1.0 return mesh diff --git a/src/mesh.cpp b/src/mesh.cpp index 642e0e9d9d..b538bca47c 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -225,13 +225,19 @@ void UnstructuredMesh::to_hdf5(hid_t group) const write_dataset(mesh_group, "volumes", tet_vols); write_dataset(mesh_group, "centroids", centroids); + + if (specified_length_multiplier_) + write_dataset(mesh_group, "length_multiplier", length_multiplier_); + close_group(mesh_group); } void UnstructuredMesh::set_length_multiplier(double length_multiplier) { length_multiplier_ = length_multiplier; - specified_length_multiplier_ = true; + + if (length_multiplier_ != 1.0) + specified_length_multiplier_ = true; } void StructuredMesh::get_indices(Position r, int* ijk, bool* in_mesh) const @@ -1601,11 +1607,7 @@ MOABMesh::MOABMesh(pugi::xml_node node) : UnstructuredMesh(node) MOABMesh::MOABMesh(const std::string& filename, double length_multiplier) { filename_ = filename; - - if (length_multiplier != 1.0) { - set_length_multiplier(length_multiplier); - } - + set_length_multiplier(length_multiplier); initialize(); } @@ -2193,11 +2195,7 @@ LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) LibMesh::LibMesh(const std::string& filename, double length_multiplier) { filename_ = filename; - - if (length_multiplier != 1.0) { - set_length_multiplier(length_multiplier); - } - + set_length_multiplier(length_multiplier); initialize(); } From e63c414e219c781e9dad8934ca124c4ea4ad0daf Mon Sep 17 00:00:00 2001 From: April Novak Date: Sat, 25 Sep 2021 09:18:31 -0500 Subject: [PATCH 8/9] Apply suggestions from code review Co-authored-by: Patrick Shriwise --- openmc/mesh.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 6dde9277ca..372069cbba 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -215,7 +215,8 @@ class RegularMesh(MeshBase): mesh.lower_left = group['lower_left'][()] mesh.upper_right = group['upper_right'][()] mesh.width = group['width'][()] - mesh.length_multiplier = group['length_multiplier'][()] if 'length_multiplier' in group else 1.0 + if 'length_multiplier' in group: + mesh.length_multiplier = group['length_multiplier'][()] return mesh @@ -647,7 +648,8 @@ class UnstructuredMesh(MeshBase): An iterable of element centroid coordinates, e.g. [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0), ...] """ - def __init__(self, filename, library, mesh_id=None, name='', length_multiplier=1.0): + def __init__(self, filename, library, mesh_id=None, name='', + length_multiplier=1.0): super().__init__(mesh_id, name) self.filename = filename self._volumes = None @@ -729,7 +731,9 @@ class UnstructuredMesh(MeshBase): @length_multiplier.setter def length_multiplier(self, length_multiplier): - cv.check_type("Unstructured mesh length multiplier", length_multiplier, Real) + cv.check_type("Unstructured mesh length multiplier", + length_multiplier, + Real) self._length_multiplier = length_multiplier if (self._length_multiplier != 1.0): From 25d0a5f9af9d597803c7d65bed51f483d5b57602 Mon Sep 17 00:00:00 2001 From: aprilnovak Date: Sat, 25 Sep 2021 09:20:33 -0500 Subject: [PATCH 9/9] Change ordering in doc string. Refs #1872 --- openmc/mesh.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 372069cbba..4e1e9565a9 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -215,8 +215,6 @@ class RegularMesh(MeshBase): mesh.lower_left = group['lower_left'][()] mesh.upper_right = group['upper_right'][()] mesh.width = group['width'][()] - if 'length_multiplier' in group: - mesh.length_multiplier = group['length_multiplier'][()] return mesh @@ -613,14 +611,12 @@ class UnstructuredMesh(MeshBase): ---------- filename : str Location of the unstructured mesh file - length_multiplier: float - Constant multiplier to apply to mesh coordinates mesh_id : int Unique identifier for the mesh name : str Name of the mesh - size : int - Number of elements in the unstructured mesh + length_multiplier: float + Constant multiplier to apply to mesh coordinates Attributes ---------- @@ -732,7 +728,7 @@ class UnstructuredMesh(MeshBase): @length_multiplier.setter def length_multiplier(self, length_multiplier): cv.check_type("Unstructured mesh length multiplier", - length_multiplier, + length_multiplier, Real) self._length_multiplier = length_multiplier @@ -843,6 +839,9 @@ class UnstructuredMesh(MeshBase): mesh.centroids = np.reshape(centroids, (vol_data.shape[0], 3)) mesh.size = mesh.volumes.size + if 'length_multiplier' in group: + mesh.length_multiplier = group['length_multiplier'][()] + return mesh def to_xml_element(self):