LCOV - code coverage report
Current view: top level - utils - geodata.hpp (source / functions) Coverage Total Hit
Test: Palace Coverage Report Lines: 80.0 % 15 12
Test Date: 2025-10-23 22:45:05 Functions: 80.0 % 5 4
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
       2              : // SPDX-License-Identifier: Apache-2.0
       3              : 
       4              : #ifndef PALACE_UTILS_GEODATA_HPP
       5              : #define PALACE_UTILS_GEODATA_HPP
       6              : 
       7              : #include <array>
       8              : #include <cmath>
       9              : #include <memory>
      10              : #include <vector>
      11              : #include <mfem.hpp>
      12              : 
      13              : namespace palace
      14              : {
      15              : 
      16              : class IoData;
      17              : 
      18              : namespace mesh
      19              : {
      20              : 
      21              : //
      22              : // Functions for mesh related functionality.
      23              : //
      24              : 
      25              : // Read and partition a serial mesh from file, returning a pointer to the new parallel mesh
      26              : // object, which should be destroyed by the user.
      27              : std::unique_ptr<mfem::ParMesh> ReadMesh(const IoData &iodata, MPI_Comm comm);
      28              : 
      29              : // Refine the provided mesh according to the data in the input file. If levels of refinement
      30              : // are requested, the refined meshes are stored in order of increased refinement. Ownership
      31              : // of the initial coarse mesh is inherited by the fine meshes and it should not be deleted.
      32              : // The fine mesh hierarchy is owned by the user.
      33              : void RefineMesh(const IoData &iodata, std::vector<std::unique_ptr<mfem::ParMesh>> &mesh);
      34              : 
      35              : // Dimensionalize a mesh for use in exporting a mesh. Scales vertices and nodes by L.
      36              : void DimensionalizeMesh(mfem::Mesh &mesh, double L);
      37              : 
      38              : // Nondimensionalize a mesh for use in the solver. Scales vertices and nodes by 1/L.
      39              : void NondimensionalizeMesh(mfem::Mesh &mesh, double L);
      40              : 
      41              : // Struct containing flags for the (global) mesh element types.
      42              : struct ElementTypeInfo
      43              : {
      44              :   bool has_simplices;
      45              :   bool has_hexahedra;
      46              :   bool has_prisms;
      47              :   bool has_pyramids;
      48              :   std::vector<mfem::Geometry::Type> GetGeomTypes() const;
      49              : };
      50              : 
      51              : // Simplified helper for describing the element types in a (Par)Mesh.
      52              : ElementTypeInfo CheckElements(const mfem::Mesh &mesh);
      53              : 
      54              : // Check if a tetrahedral (Par)Mesh is ready for local refinement.
      55              : bool CheckRefinementFlags(const mfem::Mesh &mesh);
      56              : 
      57              : // Helper function to convert a set of attribute numbers to a marker array. The marker array
      58              : // will be of size max_attr and it will contain only zeroes and ones. Ones indicate which
      59              : // attribute numbers are present in the list array. In the special case when list has a
      60              : // single entry equal to -1 the marker array will contain all ones.
      61              : void AttrToMarker(int max_attr, const int *attr_list, int attr_list_size,
      62              :                   mfem::Array<int> &marker, bool skip_invalid = false);
      63              : 
      64              : template <typename T>
      65              : inline void AttrToMarker(int max_attr, const T &attr_list, mfem::Array<int> &marker,
      66              :                          bool skip_invalid = false)
      67              : {
      68              :   const auto size = std::distance(attr_list.begin(), attr_list.end());
      69          473 :   AttrToMarker(max_attr, (size > 0) ? &attr_list[0] : nullptr, size, marker, skip_invalid);
      70          317 : }
      71              : 
      72              : template <typename T>
      73          311 : inline mfem::Array<int> AttrToMarker(int max_attr, const T &attr_list,
      74              :                                      bool skip_invalid = false)
      75              : {
      76              :   mfem::Array<int> marker;
      77              :   AttrToMarker(max_attr, attr_list, marker, skip_invalid);
      78          311 :   return marker;
      79              : }
      80              : 
      81              : // Helper function to construct the axis-aligned bounding box for all elements with the
      82              : // given attribute.
      83              : void GetAxisAlignedBoundingBox(const mfem::ParMesh &mesh, const mfem::Array<int> &marker,
      84              :                                bool bdr, mfem::Vector &min, mfem::Vector &max);
      85              : 
      86              : inline void GetAxisAlignedBoundingBox(const mfem::ParMesh &mesh, int attr, bool bdr,
      87              :                                       mfem::Vector &min, mfem::Vector &max)
      88              : {
      89              :   mfem::Array<int> marker(bdr ? mesh.bdr_attributes.Max() : mesh.attributes.Max());
      90              :   marker = 0;
      91              :   marker[attr - 1] = 1;
      92              :   GetAxisAlignedBoundingBox(mesh, marker, bdr, min, max);
      93              : }
      94              : 
      95           73 : inline void GetAxisAlignedBoundingBox(const mfem::ParMesh &mesh, mfem::Vector &min,
      96              :                                       mfem::Vector &max)
      97              : {
      98           73 :   mfem::Array<int> marker(mesh.attributes.Max());
      99              :   marker = 1;
     100           73 :   GetAxisAlignedBoundingBox(mesh, marker, false, min, max);
     101           73 : }
     102              : 
     103              : // Struct describing a bounding box in terms of the center and face normals. The normals
     104              : // specify the direction from the center of the box.
     105              : struct BoundingBox
     106              : {
     107              :   // The central point of the bounding box.
     108              :   std::array<double, 3> center;
     109              : 
     110              :   // Vectors from center to the midpoint of each face.
     111              :   std::array<std::array<double, 3>, 3> axes;
     112              : 
     113              :   // Whether or not this bounding box is two dimensional.
     114              :   bool planar;
     115              : 
     116              :   // Compute the area of the bounding box spanned by the first two normals.
     117              :   double Area() const;
     118              : 
     119              :   // Compute the volume of the 3D bounding box. Returns zero if planar.
     120              :   double Volume() const;
     121              : 
     122              :   // Compute the normalized axes of the bounding box.
     123              :   std::array<std::array<double, 3>, 3> Normals() const;
     124              : 
     125              :   // Compute the lengths along each axis.
     126              :   std::array<double, 3> Lengths() const;
     127              : 
     128              :   // Compute the deviations in degrees of a vector from each of the axis directions. Angles
     129              :   // are returned in the interval [0, 180].
     130              :   std::array<double, 3> Deviations(const std::array<double, 3> &direction) const;
     131              : };
     132              : 
     133              : // Helper functions for computing bounding boxes from a mesh and markers. These do not need
     134              : // to be axis-aligned. Note: This function only returns a minimum oriented bounding box for
     135              : // points whose convex hull exactly forms a rectangle or rectangular prism, implementing a
     136              : // vastly simplified version of QuickHull for this case. For other shapes, the result is
     137              : // less predictable, and may not even form a bounding box of the sampled point cloud.
     138              : BoundingBox GetBoundingBox(const mfem::ParMesh &mesh, const mfem::Array<int> &marker,
     139              :                            bool bdr);
     140              : 
     141              : inline BoundingBox GetBoundingBox(const mfem::ParMesh &mesh, int attr, bool bdr)
     142              : {
     143              :   mfem::Array<int> marker(bdr ? mesh.bdr_attributes.Max() : mesh.attributes.Max());
     144              :   marker = 0;
     145              :   marker[attr - 1] = 1;
     146              :   return GetBoundingBox(mesh, marker, bdr);
     147              : }
     148              : 
     149              : // Given a mesh and a marker, compute the bounding circle/sphere of the marked elements. In
     150              : // this case the normals of the bounding box object are arbitrary, and the Area and Volume
     151              : // members should not be used, but the Lengths function returns the ball diameter. This
     152              : // function implements Welzl's algorithm.
     153              : BoundingBox GetBoundingBall(const mfem::ParMesh &mesh, const mfem::Array<int> &marker,
     154              :                             bool bdr);
     155              : 
     156              : inline BoundingBox GetBoundingBall(const mfem::ParMesh &mesh, int attr, bool bdr)
     157              : {
     158              :   mfem::Array<int> marker(bdr ? mesh.bdr_attributes.Max() : mesh.attributes.Max());
     159              :   marker = 0;
     160              :   marker[attr - 1] = 1;
     161              :   return GetBoundingBall(mesh, marker, bdr);
     162              : }
     163              : 
     164              : // Helper function for computing the direction aligned length of a marked group.
     165              : double GetProjectedLength(const mfem::ParMesh &mesh, const mfem::Array<int> &marker,
     166              :                           bool bdr, const std::array<double, 3> &dir);
     167              : 
     168              : inline double GetProjectedLength(const mfem::ParMesh &mesh, int attr, bool bdr,
     169              :                                  const std::array<double, 3> &dir)
     170              : {
     171              :   mfem::Array<int> marker(bdr ? mesh.bdr_attributes.Max() : mesh.attributes.Max());
     172              :   marker = 0;
     173              :   marker[attr - 1] = 1;
     174              :   return GetProjectedLength(mesh, marker, bdr, dir);
     175              : }
     176              : 
     177              : // Helper function for computing the closest distance of a marked group to a given point,
     178              : // by brute force searching over the entire point set. Optionally compute the furthest
     179              : // distance instead of the closest.
     180              : double GetDistanceFromPoint(const mfem::ParMesh &mesh, const mfem::Array<int> &marker,
     181              :                             bool bdr, const std::array<double, 3> &origin,
     182              :                             bool max = false);
     183              : 
     184              : inline double GetDistanceFromPoint(const mfem::ParMesh &mesh, int attr, bool bdr,
     185              :                                    const std::array<double, 3> &dir, bool max = false)
     186              : {
     187              :   mfem::Array<int> marker(bdr ? mesh.bdr_attributes.Max() : mesh.attributes.Max());
     188              :   marker = 0;
     189              :   marker[attr - 1] = 1;
     190              :   return GetDistanceFromPoint(mesh, marker, bdr, dir, max);
     191              : }
     192              : 
     193              : // Helper function to compute the average surface normal for all elements with the given
     194              : // attributes.
     195              : mfem::Vector GetSurfaceNormal(const mfem::ParMesh &mesh, const mfem::Array<int> &marker,
     196              :                               bool average = true);
     197              : 
     198           78 : inline mfem::Vector GetSurfaceNormal(const mfem::ParMesh &mesh, int attr,
     199              :                                      bool average = true)
     200              : {
     201              :   const bool bdr = (mesh.Dimension() == mesh.SpaceDimension());
     202           78 :   mfem::Array<int> marker(bdr ? mesh.bdr_attributes.Max() : mesh.attributes.Max());
     203              :   marker = 0;
     204           78 :   marker[attr - 1] = 1;
     205          156 :   return GetSurfaceNormal(mesh, marker, average);
     206              : }
     207              : 
     208            0 : inline mfem::Vector GetSurfaceNormal(const mfem::ParMesh &mesh, bool average = true)
     209              : {
     210              :   const bool bdr = (mesh.Dimension() == mesh.SpaceDimension());
     211            0 :   const auto &attributes = bdr ? mesh.bdr_attributes : mesh.attributes;
     212            0 :   return GetSurfaceNormal(mesh, AttrToMarker(attributes.Max(), attributes), average);
     213              : }
     214              : 
     215              : // Helper functions to compute the volume or area for all domain or boundary elements with
     216              : // the given attributes.
     217              : double GetSurfaceArea(const mfem::ParMesh &mesh, const mfem::Array<int> &marker);
     218              : 
     219              : inline double GetSurfaceArea(const mfem::ParMesh &mesh, int attr)
     220              : {
     221              :   mfem::Array<int> marker(mesh.bdr_attributes.Max());
     222              :   marker = 0;
     223              :   marker[attr - 1] = 1;
     224              :   return GetSurfaceArea(mesh, marker);
     225              : }
     226              : 
     227              : double GetVolume(const mfem::ParMesh &mesh, const mfem::Array<int> &marker);
     228              : 
     229              : inline double GetVolume(const mfem::ParMesh &mesh, int attr)
     230              : {
     231              :   mfem::Array<int> marker(mesh.attributes.Max());
     232              :   marker = 0;
     233              :   marker[attr - 1] = 1;
     234              :   return GetVolume(mesh, marker);
     235              : }
     236              : 
     237              : // Helper function responsible for rebalancing the mesh, and optionally writing meshes from
     238              : // the intermediate stages to disk. Returns the imbalance ratio before rebalancing.
     239              : double RebalanceMesh(const IoData &iodata, std::unique_ptr<mfem::ParMesh> &mesh);
     240              : 
     241              : // Helper for creating a hexahedral mesh from a tetrahedral mesh.
     242              : mfem::Mesh MeshTetToHex(const mfem::Mesh &orig_mesh);
     243              : 
     244              : }  // namespace mesh
     245              : 
     246              : }  // namespace palace
     247              : 
     248              : #endif  // PALACE_UTILS_GEODATA_HPP
        

Generated by: LCOV version 2.0-1