VTK-m  2.0
CellEdgeRatioMetric.h
Go to the documentation of this file.
1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 // This software is distributed WITHOUT ANY WARRANTY; without even
6 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
7 // PURPOSE. See the above copyright notice for more information.
8 //
9 // Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10 // Copyright 2014 UT-Battelle, LLC.
11 // Copyright 2014 Los Alamos National Security.
12 //
13 // Under the terms of Contract DE-NA0003525 with NTESS,
14 // the U.S. Government retains certain rights in this software.
15 //
16 // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
17 // Laboratory (LANL), the U.S. Government retains certain rights in
18 // this software.
19 //============================================================================
20 #ifndef vtk_m_worklet_cellmetrics_CellEdgeRatioMetric_h
21 #define vtk_m_worklet_cellmetrics_CellEdgeRatioMetric_h
22 
23 /*
24  * Mesh quality metric functions that compute the edge ratio of mesh cells.
25  * The edge ratio of a cell is defined as the length (magnitude) of the longest
26  * cell edge divided by the length of the shortest cell edge.
27  *
28  * These metric computations are adapted from the VTK implementation of the Verdict library,
29  * which provides a set of mesh/cell metrics for evaluating the geometric qualities of regions
30  * of mesh spaces.
31  *
32  * The edge ratio computations for a pyramid cell types is not defined in the
33  * VTK implementation, but is provided here.
34  *
35  * See: The Verdict Library Reference Manual (for per-cell-type metric formulae)
36  * See: vtk/ThirdParty/verdict/vtkverdict (for VTK code implementation of this metric)
37  */
38 
39 #include "vtkm/CellShape.h"
40 #include "vtkm/CellTraits.h"
41 #include "vtkm/VecTraits.h"
42 #include "vtkm/VectorAnalysis.h"
43 #include "vtkm/exec/FunctorBase.h"
44 
45 #define UNUSED(expr) (void)(expr);
46 
47 namespace vtkm
48 {
49 namespace worklet
50 {
51 namespace cellmetrics
52 {
53 
55 
56 
57 template <typename OutType, typename VecType>
58 VTKM_EXEC inline OutType ComputeEdgeRatio(const VecType& edges)
59 {
60  const vtkm::Id numEdges = edges.GetNumberOfComponents();
61 
62  //Compare edge lengths to determine the longest and shortest
63  //TODO: Could we use lambda expression here?
64 
65  FloatType e0Len = (FloatType)vtkm::MagnitudeSquared(edges[0]);
66  FloatType currLen, minLen = e0Len, maxLen = e0Len;
67  for (int i = 1; i < numEdges; i++)
68  {
69  currLen = (FloatType)vtkm::MagnitudeSquared(edges[i]);
70  if (currLen < minLen)
71  minLen = currLen;
72  if (currLen > maxLen)
73  maxLen = currLen;
74  }
75 
76  if (minLen < vtkm::NegativeInfinity<FloatType>())
77  return vtkm::Infinity<OutType>();
78 
79  //Take square root because we only did magnitude squared before
80  OutType edgeRatio = (OutType)vtkm::Sqrt(maxLen / minLen);
81  if (edgeRatio > 0)
82  return vtkm::Min(edgeRatio, vtkm::Infinity<OutType>()); //normal case
83 
84  return vtkm::Max(edgeRatio, OutType(-1) * vtkm::Infinity<OutType>());
85 }
86 
87 
88 // ========================= Unsupported cells ==================================
89 
90 // By default, cells have zero shape unless the shape type template is specialized below.
91 template <typename OutType, typename PointCoordVecType, typename CellShapeType>
93  const PointCoordVecType& pts,
94  CellShapeType shape,
96 {
97  UNUSED(numPts);
98  UNUSED(pts);
99  UNUSED(shape);
100  return OutType(0.0);
101 }
102 
103 // ========================= 2D cells ==================================
104 
105 
106 // Compute the edge ratio of a line.
107 // Formula: Maximum edge length divided by minimum edge length
108 // Trivially equals 1, since only a single edge
109 template <typename OutType, typename PointCoordVecType>
111  const PointCoordVecType& pts,
112  vtkm::CellShapeTagLine,
113  vtkm::ErrorCode& ec)
114 {
115  UNUSED(pts);
116  if (numPts < 2)
117  {
119  return OutType(0.0);
120  }
121  return OutType(1.0);
122 }
123 
124 // Compute the edge ratio of a triangle.
125 // Formula: Maximum edge length divided by minimum edge length
126 // Equals 1 for an equilateral unit triangle
127 // Acceptable range: [1,1.3]
128 // Full range: [1,FLOAT_MAX]
129 template <typename OutType, typename PointCoordVecType>
131  const PointCoordVecType& pts,
132  vtkm::CellShapeTagTriangle,
133  vtkm::ErrorCode& ec)
134 {
135  if (numPts != 3)
136  {
138  return OutType(0.0);
139  }
140 
141  const vtkm::IdComponent numEdges = 3; //pts.GetNumberOfComponents();
142 
143  //The 3 edges of a triangle
144  using Edge = typename PointCoordVecType::ComponentType;
145  const Edge TriEdges[3] = { pts[1] - pts[0], pts[2] - pts[1], pts[0] - pts[2] };
146  return vtkm::worklet::cellmetrics::ComputeEdgeRatio<OutType>(vtkm::make_VecC(TriEdges, numEdges));
147 }
148 
149 
150 // Compute the edge ratio of a quadrilateral.
151 // Formula: Maximum edge length divided by minimum edge length
152 // Equals 1 for a unit square
153 // Acceptable range: [1,1.3]
154 // Full range: [1,FLOAT_MAX]
155 template <typename OutType, typename PointCoordVecType>
157  const PointCoordVecType& pts,
158  vtkm::CellShapeTagQuad,
159  vtkm::ErrorCode& ec)
160 {
161  if (numPts != 4)
162  {
164  return OutType(0.0);
165  }
166 
167  vtkm::IdComponent numEdges = 4; //pts.GetNumberOfComponents();
168 
169  //The 4 edges of a quadrilateral
170  using Edge = typename PointCoordVecType::ComponentType;
171  const Edge QuadEdges[4] = { pts[1] - pts[0], pts[2] - pts[1], pts[3] - pts[2], pts[0] - pts[3] };
172 
173  return vtkm::worklet::cellmetrics::ComputeEdgeRatio<OutType>(
174  vtkm::make_VecC(QuadEdges, numEdges));
175 }
176 
177 
178 
179 // ============================= 3D Volume cells ==================================i
180 
181 // Compute the edge ratio of a tetrahedron.
182 // Formula: Maximum edge length divided by minimum edge length
183 // Equals 1 for a unit equilateral tetrahedron
184 // Acceptable range: [1,3]
185 // Full range: [1,FLOAT_MAX]
186 template <typename OutType, typename PointCoordVecType>
188  const PointCoordVecType& pts,
189  vtkm::CellShapeTagTetra,
190  vtkm::ErrorCode& ec)
191 {
192  if (numPts != 4)
193  {
195  return OutType(0.0);
196  }
197 
198  vtkm::IdComponent numEdges = 6; //pts.GetNumberOfComponents();
199 
200  //The 6 edges of a tetrahedron
201  using Edge = typename PointCoordVecType::ComponentType;
202  const Edge TetEdges[6] = { pts[1] - pts[0], pts[2] - pts[1], pts[0] - pts[2],
203  pts[3] - pts[0], pts[3] - pts[1], pts[3] - pts[2] };
204 
205  return vtkm::worklet::cellmetrics::ComputeEdgeRatio<OutType>(vtkm::make_VecC(TetEdges, numEdges));
206 }
207 
208 
209 // Compute the edge ratio of a hexahedron.
210 // Formula: Maximum edge length divided by minimum edge length
211 // Equals 1 for a unit cube
212 // Full range: [1,FLOAT_MAX]
213 template <typename OutType, typename PointCoordVecType>
215  const PointCoordVecType& pts,
216  vtkm::CellShapeTagHexahedron,
217  vtkm::ErrorCode& ec)
218 {
219  if (numPts != 8)
220  {
222  return OutType(0.0);
223  }
224 
225  vtkm::IdComponent numEdges = 12; //pts.GetNumberOfComponents();
226 
227  //The 12 edges of a hexahedron
228  using Edge = typename PointCoordVecType::ComponentType;
229  const Edge HexEdges[12] = { pts[1] - pts[0], pts[2] - pts[1], pts[3] - pts[2], pts[0] - pts[3],
230  pts[5] - pts[4], pts[6] - pts[5], pts[7] - pts[6], pts[4] - pts[7],
231  pts[4] - pts[0], pts[5] - pts[1], pts[6] - pts[2], pts[7] - pts[3] };
232 
233  return vtkm::worklet::cellmetrics::ComputeEdgeRatio<OutType>(vtkm::make_VecC(HexEdges, numEdges));
234 }
235 
236 
237 // Compute the edge ratio of a wedge/prism.
238 // Formula: Maximum edge length divided by minimum edge length
239 // Equals 1 for a right unit wedge
240 // Full range: [1,FLOAT_MAX]
241 template <typename OutType, typename PointCoordVecType>
243  const PointCoordVecType& pts,
244  vtkm::CellShapeTagWedge,
245  vtkm::ErrorCode& ec)
246 {
247  if (numPts != 6)
248  {
250  return OutType(0.0);
251  }
252 
253  vtkm::IdComponent numEdges = 9; //pts.GetNumberOfComponents();
254 
255  //The 9 edges of a wedge/prism
256  using Edge = typename PointCoordVecType::ComponentType;
257  const Edge WedgeEdges[9] = { pts[1] - pts[0], pts[2] - pts[1], pts[0] - pts[2],
258  pts[4] - pts[3], pts[5] - pts[4], pts[3] - pts[5],
259  pts[3] - pts[0], pts[4] - pts[1], pts[5] - pts[2] };
260 
261  return vtkm::worklet::cellmetrics::ComputeEdgeRatio<OutType>(
262  vtkm::make_VecC(WedgeEdges, numEdges));
263 }
264 
265 // Compute the edge ratio of a pyramid.
266 // Formula: Maximum edge length divided by minimum edge length
267 // TODO: Equals 1 for a right unit (square base?) pyramid (?)
268 // Full range: [1,FLOAT_MAX]
269 // TODO: Verdict/VTK don't define this metric for a pyramid. What does VisIt output?
270 template <typename OutType, typename PointCoordVecType>
272  const PointCoordVecType& pts,
273  vtkm::CellShapeTagPyramid,
274  vtkm::ErrorCode& ec)
275 {
276  if (numPts != 5)
277  {
279  return OutType(0.0);
280  }
281 
282  vtkm::IdComponent numEdges = 8; // pts.GetNumberOfComponents();
283 
284  //The 8 edges of a pyramid (4 quadrilateral base edges + 4 edges to apex)
285  using Edge = typename PointCoordVecType::ComponentType;
286  const Edge PyramidEdges[8] = {
287  pts[1] - pts[0], pts[2] - pts[1], pts[2] - pts[3], pts[3] - pts[0],
288  pts[4] - pts[0], pts[4] - pts[1], pts[4] - pts[2], pts[4] - pts[3]
289  };
290 
291  return vtkm::worklet::cellmetrics::ComputeEdgeRatio<OutType>(
292  vtkm::make_VecC(PyramidEdges, numEdges));
293 }
294 
295 
296 
297 } // namespace cellmetrics
298 } // namespace worklet
299 } // namespace vtkm
300 
301 #endif // vtk_m_worklet_cellmetrics_CellEdgeRatioMetric_h
vtkm::Sqrt
VTKM_EXEC_CONT vtkm::Float32 Sqrt(vtkm::Float32 x)
Compute the square root of x.
Definition: Math.h:958
vtkm::ErrorCode
ErrorCode
Definition: ErrorCode.h:19
vtkm::MagnitudeSquared
VTKM_EXEC_CONT detail::FloatingPointReturnType< T >::Type MagnitudeSquared(const T &x)
Returns the square of the magnitude of a vector.
Definition: VectorAnalysis.h:64
VTKM_EXEC
#define VTKM_EXEC
Definition: ExportMacros.h:51
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::IdComponent
vtkm::Int32 IdComponent
Represents a component ID (index of component in a vector).
Definition: Types.h:168
vtkm::worklet::cellmetrics::ComputeEdgeRatio
VTKM_EXEC OutType ComputeEdgeRatio(const VecType &edges)
Definition: CellEdgeRatioMetric.h:58
vtkm::worklet::cellmetrics::FloatType
vtkm::FloatDefault FloatType
Definition: CellAspectFrobeniusMetric.h:50
CellShape.h
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
VectorAnalysis.h
UNUSED
#define UNUSED(expr)
Definition: CellEdgeRatioMetric.h:45
vtkm::ErrorCode::InvalidCellMetric
@ InvalidCellMetric
FunctorBase.h
vtkm::FloatDefault
vtkm::Float32 FloatDefault
The floating point type to use when no other precision is specified.
Definition: Types.h:198
CellTraits.h
VecTraits.h
vtkm::worklet::cellmetrics::CellEdgeRatioMetric
VTKM_EXEC OutType CellEdgeRatioMetric(const vtkm::IdComponent &numPts, const PointCoordVecType &pts, CellShapeType shape, vtkm::ErrorCode &)
Definition: CellEdgeRatioMetric.h:92
vtkm::ErrorCode::InvalidNumberOfPoints
@ InvalidNumberOfPoints