Merge topic 'jacobian-cellmetric'

f9d02b374 remove file that should not have been checked in
d59917473 rename half variable to avoid shadowing CUDA global
954e25874 fix problem with filename
91f7e763b fix copyright, warnings, cmake for Jacobian-cellmetric branch
e040ea05e formatting suggestions from KMorel
f4edb6a8e remove trailing whitespace
ccedb5aac Jacobian working, unit test working
560aa1f67 add support for outputname
...

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !1855
This commit is contained in:
Hank 2019-09-18 16:08:20 +00:00 committed by Kitware Robot
commit 0eb767dc5f
10 changed files with 2160 additions and 493 deletions

@ -21,6 +21,11 @@
set(headers
CellDiagonalRatioMetric.h
CellEdgeRatioMetric.h
CellJacobianMetric.h
TypeOfCellHexahedral.h
TypeOfCellQuadrilateral.h
TypeOfCellTetrahedral.h
TypeOfCellTriangle.h
)

@ -0,0 +1,187 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_exec_cellmetrics_Jacobian_h
#define vtk_m_exec_cellmetrics_Jacobian_h
/*
* Mesh quality metric functions that computes the Jacobian of mesh cells.
*
* These metric computations are adapted from the VTK implementation of the Verdict library,
* which provides a set of mesh/cell metrics for evaluating the geometric qualities of regions
* of mesh spaces.
*
* See: The Verdict Library Reference Manual (for per-cell-type metric formulae)
* See: vtk/ThirdParty/verdict/vtkverdict (for VTK code implementation of this metric)
*/
#include "TypeOfCellHexahedral.h"
#include "TypeOfCellQuadrilateral.h"
#include "TypeOfCellTetrahedral.h"
#include "TypeOfCellTriangle.h"
#include "vtkm/CellShape.h"
#include "vtkm/CellTraits.h"
#include "vtkm/VecTraits.h"
#include "vtkm/VectorAnalysis.h"
#include "vtkm/exec/FunctorBase.h"
#define UNUSED(expr) (void)(expr);
namespace vtkm
{
namespace exec
{
namespace cellmetrics
{
// ========================= Unsupported cells ==================================
// By default, cells return the metric 0.0 unless the shape type template is specialized below.
template <typename OutType, typename PointCoordVecType, typename CellShapeType>
VTKM_EXEC OutType CellJacobianMetric(const vtkm::IdComponent& numPts,
const PointCoordVecType& pts,
CellShapeType shape,
const vtkm::exec::FunctorBase&)
{
UNUSED(numPts);
UNUSED(pts);
UNUSED(shape);
return OutType(0.0);
}
// ========================= 2D cells ==================================
// Compute the Jacobian of a quadrilateral.
// Formula: min{Jacobian at each vertex}
// Equals 1 for a unit square
// Acceptable range: [0,FLOAT_MAX]
// Normal range: [0,FLOAT_MAX]
// Full range: [FLOAT_MIN,FLOAT_MAX]
template <typename OutType, typename PointCoordVecType>
VTKM_EXEC OutType CellJacobianMetric(const vtkm::IdComponent& numPts,
const PointCoordVecType& pts,
vtkm::CellShapeTagQuad,
const vtkm::exec::FunctorBase& worklet)
{
if (numPts != 4)
{
worklet.RaiseError("Jacobian metric(quad) requires 4 points.");
return OutType(0.0);
}
using Scalar = OutType;
using CollectionOfPoints = PointCoordVecType;
using Vector = typename PointCoordVecType::ComponentType;
const Scalar alpha0 = GetQuadAlpha0<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar alpha1 = GetQuadAlpha1<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar alpha2 = GetQuadAlpha2<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar alpha3 = GetQuadAlpha3<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar q = vtkm::Min(alpha0, vtkm::Min(alpha1, vtkm::Min(alpha2, alpha3)));
return q;
}
// ============================= 3D Volume cells ==================================
// Compute the Jacobian of a hexahedron.
// Formula: min{ {Alpha_i for i in 1..7}, Alpha_8/64}
// -Alpha_i -> Jacobian determinant at respective vertex
// -Alpha_8 -> Jacobian at center
// Equals 1 for a unit cube
// Acceptable Range: [0, FLOAT_MAX]
// Normal Range: [0, FLOAT_MAX]
// Full range: [FLOAT_MIN ,FLOAT_MAX]
template <typename OutType, typename PointCoordVecType>
VTKM_EXEC OutType CellJacobianMetric(const vtkm::IdComponent& numPts,
const PointCoordVecType& pts,
vtkm::CellShapeTagHexahedron,
const vtkm::exec::FunctorBase& worklet)
{
if (numPts != 8)
{
worklet.RaiseError("Jacobian metric(hexahedron) requires 8 points.");
return OutType(0.0);
}
using Scalar = OutType;
using CollectionOfPoints = PointCoordVecType;
using Vector = typename PointCoordVecType::ComponentType;
const Scalar alpha0 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(0));
const Scalar alpha1 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(1));
const Scalar alpha2 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(2));
const Scalar alpha3 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(3));
const Scalar alpha4 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(4));
const Scalar alpha5 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(5));
const Scalar alpha6 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(6));
const Scalar alpha7 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(7));
const Scalar alpha8 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(8));
const Scalar alpha8Div64 = alpha8 / Scalar(64.0);
const Scalar q = vtkm::Min(
alpha0,
vtkm::Min(
alpha1,
vtkm::Min(
alpha2,
vtkm::Min(
alpha3,
vtkm::Min(alpha4,
vtkm::Min(alpha5, vtkm::Min(alpha6, vtkm::Min(alpha7, alpha8Div64))))))));
return q;
}
// Compute the Jacobian of a tetrahedron.
// Formula: (L2 x L0) * L3
// Equals Sqrt(2) / 2 for unit equilateral tetrahedron
// Acceptable Range: [0, FLOAT_MAX]
// Normal Range: [0, FLOAT_MAX]
// Full range: [FLOAT_MIN,FLOAT_MAX]
template <typename OutType, typename PointCoordVecType>
VTKM_EXEC OutType CellJacobianMetric(const vtkm::IdComponent& numPts,
const PointCoordVecType& pts,
vtkm::CellShapeTagTetra,
const vtkm::exec::FunctorBase& worklet)
{
if (numPts != 4)
{
worklet.RaiseError("Jacobian metric (tetra) requires 4 points");
return OutType(0.0);
}
using Scalar = OutType;
using CollectionOfPoints = PointCoordVecType;
using Vector = typename PointCoordVecType::ComponentType;
const Vector L0 = GetTetraL0<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L2 = GetTetraL2<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L3 = GetTetraL3<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar q = vtkm::Dot(vtkm::Cross(L2, L0), L3);
return q;
}
} // namespace cellmetrics
} // namespace exec
} // namespace vtkm
#endif // vtk_m_exec_cellmetrics_CellJacobianMetric_h

@ -0,0 +1,782 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_exec_cellmetrics_TypeOfCellHexahedral
#define vtk_m_exec_cellmetrics_TypeOfCellHexahedral
/**
* The Verdict manual defines a set of commonly
* used components of a hexahedra (hex). For example,
* area, edge lengths, and so forth.
*
* These definitions can be found starting on
* page 77 of the Verdict manual.
*
* This file contains a set of functions which
* implement return the values of those commonly
* used components for subsequent use in metrics.
*/
/**
* Returns the L0 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL0(const CollectionOfPoints& pts)
{
const Vector L0(pts[1] - pts[0]);
return L0;
}
/**
* Returns the L1 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL1(const CollectionOfPoints& pts)
{
const Vector L1(pts[2] - pts[1]);
return L1;
}
/**
* Returns the L2 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL2(const CollectionOfPoints& pts)
{
const Vector L2(pts[3] - pts[2]);
return L2;
}
/**
* Returns the L3 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL3(const CollectionOfPoints& pts)
{
const Vector L3(pts[3] - pts[0]);
return L3;
}
/**
* Returns the L4 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL4(const CollectionOfPoints& pts)
{
const Vector L4(pts[4] - pts[0]);
return L4;
}
/**
* Returns the L5 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL5(const CollectionOfPoints& pts)
{
const Vector L5(pts[5] - pts[1]);
return L5;
}
/**
* Returns the L6 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL6(const CollectionOfPoints& pts)
{
const Vector L6(pts[6] - pts[2]);
return L6;
}
/**
* Returns the L7 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL7(const CollectionOfPoints& pts)
{
const Vector L7(pts[7] - pts[3]);
return L7;
}
/**
* Returns the L8 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL8(const CollectionOfPoints& pts)
{
const Vector L8(pts[5] - pts[4]);
return L8;
}
/**
* Returns the L9 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL9(const CollectionOfPoints& pts)
{
const Vector L9(pts[6] - pts[5]);
return L9;
}
/**
* Returns the L10 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL10(const CollectionOfPoints& pts)
{
const Vector L10(pts[7] - pts[6]);
return L10;
}
/**
* Returns the L11 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexL11(const CollectionOfPoints& pts)
{
const Vector L11(pts[7] - pts[4]);
return L11;
}
/**
* Returns the L0 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL0Magnitude(const CollectionOfPoints& pts)
{
const Scalar l0 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL0<Scalar, Vector, CollectionOfPoints>(pts)));
return l0;
}
/**
* Returns the L1 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL1Magnitude(const CollectionOfPoints& pts)
{
const Scalar l1 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL1<Scalar, Vector, CollectionOfPoints>(pts)));
return l1;
}
/**
* Returns the L2 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL2Magnitude(const CollectionOfPoints& pts)
{
const Scalar l2 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL2<Scalar, Vector, CollectionOfPoints>(pts)));
return l2;
}
/**
* Returns the L3 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL3Magnitude(const CollectionOfPoints& pts)
{
const Scalar l3 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL3<Scalar, Vector, CollectionOfPoints>(pts)));
return l3;
}
/**
* Returns the L4 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL4Magnitude(const CollectionOfPoints& pts)
{
const Scalar l4 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL4<Scalar, Vector, CollectionOfPoints>(pts)));
return l4;
}
/**
* Returns the L5 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL5Magnitude(const CollectionOfPoints& pts)
{
const Scalar l5 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL5<Scalar, Vector, CollectionOfPoints>(pts)));
return l5;
}
/**
* Returns the L6 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL6Magnitude(const CollectionOfPoints& pts)
{
const Scalar l6 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL6<Scalar, Vector, CollectionOfPoints>(pts)));
return l6;
}
/**
* Returns the L7 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL7Magnitude(const CollectionOfPoints& pts)
{
const Scalar l7 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL7<Scalar, Vector, CollectionOfPoints>(pts)));
return l7;
}
/**
* Returns the L8 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL8Magnitude(const CollectionOfPoints& pts)
{
const Scalar l8 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL8<Scalar, Vector, CollectionOfPoints>(pts)));
return l8;
}
/**
* Returns the L9 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL9Magnitude(const CollectionOfPoints& pts)
{
const Scalar l9 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL9<Scalar, Vector, CollectionOfPoints>(pts)));
return l9;
}
/**
* Returns the L10 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL10Magnitude(const CollectionOfPoints& pts)
{
const Scalar l10 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL10<Scalar, Vector, CollectionOfPoints>(pts)));
return l10;
}
/**
* Returns the L11 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexL11Magnitude(const CollectionOfPoints& pts)
{
const Scalar l11 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexL11<Scalar, Vector, CollectionOfPoints>(pts)));
return l11;
}
/**
* Returns the Max of the magnitude of each vector which makes up the sides of the Hex.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexLMax(const CollectionOfPoints& pts)
{
const Scalar l0 = GetHexL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l1 = GetHexL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l2 = GetHexL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l3 = GetHexL3Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l4 = GetHexL4Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l5 = GetHexL5Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l6 = GetHexL6Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l7 = GetHexL7Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l8 = GetHexL8Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l9 = GetHexL9Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l10 = GetHexL10Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l11 = GetHexL11Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar lmax = vtkm::Max(
l0,
vtkm::Max(
l1,
vtkm::Max(
l2,
vtkm::Max(
l3,
vtkm::Max(
l4,
vtkm::Max(
l5,
vtkm::Max(l6, vtkm::Max(l7, vtkm::Max(l8, vtkm::Max(l9, vtkm::Max(l10, l11)))))))))));
return lmax;
}
/**
* Returns the Min of the magnitude of each vector which makes up the sides of the Hex.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexLMin(const CollectionOfPoints& pts)
{
const Scalar l0 = GetHexL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l1 = GetHexL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l2 = GetHexL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l3 = GetHexL3Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l4 = GetHexL4Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l5 = GetHexL5Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l6 = GetHexL6Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l7 = GetHexL7Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l8 = GetHexL8Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l9 = GetHexL9Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l10 = GetHexL10Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l11 = GetHexL11Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar lmin = vtkm::Min(
l0,
vtkm::Min(
l1,
vtkm::Min(
l2,
vtkm::Min(
l3,
vtkm::Min(
l4,
vtkm::Min(
l5,
vtkm::Min(l6, vtkm::Min(l7, vtkm::Min(l8, vtkm::Min(l9, vtkm::Min(l10, l11)))))))))));
return lmin;
}
/**
* Returns the D0 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexD0(const CollectionOfPoints& pts)
{
const Vector D0((pts[6] - pts[0]));
return D0;
}
/**
* Returns the D1 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexD1(const CollectionOfPoints& pts)
{
const Vector D1(pts[7] - pts[1]);
return D1;
}
/**
* Returns the D2 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexD2(const CollectionOfPoints& pts)
{
const Vector D2(pts[4] - pts[2]);
return D2;
}
/**
* Returns the D3 vector, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the hexahedra.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexD3(const CollectionOfPoints& pts)
{
const Vector D3(pts[5] - pts[3]);
return D3;
}
/**
* Returns the D0 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexD0Magnitude(const CollectionOfPoints& pts)
{
const Scalar d0 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexD0<Scalar, Vector, CollectionOfPoints>(pts)));
return d0;
}
/**
* Returns the D1 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexD1Magnitude(const CollectionOfPoints& pts)
{
const Scalar d1 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexD1<Scalar, Vector, CollectionOfPoints>(pts)));
return d1;
}
/**
* Returns the D2 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexD2Magnitude(const CollectionOfPoints& pts)
{
const Scalar d2 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexD2<Scalar, Vector, CollectionOfPoints>(pts)));
return d2;
}
/**
* Returns the D3 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexD3Magnitude(const CollectionOfPoints& pts)
{
const Scalar d3 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetHexD3<Scalar, Vector, CollectionOfPoints>(pts)));
return d3;
}
/**
* Returns the Min of the magnitude of each vector which makes up the sides of the Hex.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexDMin(const CollectionOfPoints& pts)
{
const Scalar d0 = GetHexD0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar d1 = GetHexD1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar d2 = GetHexD2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar d3 = GetHexD3Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar dmin = vtkm::Min(d0, vtkm::Min(d1, vtkm::Min(d2, d3)));
return dmin;
}
/**
* Returns the Min of the magnitude of each vector which makes up the sides of the Hex.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexDMax(const CollectionOfPoints& pts)
{
const Scalar d0 = GetHexD0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar d1 = GetHexD1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar d2 = GetHexD2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar d3 = GetHexD3Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar dmax = vtkm::Max(d0, vtkm::Max(d1, vtkm::Max(d2, d3)));
return dmax;
}
/**
* Returns the X1 vector defined in the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexX1(const CollectionOfPoints& pts)
{
const Vector X1((pts[1] - pts[0]) + (pts[2] - pts[3]) + (pts[5] - pts[4]) + (pts[6] - pts[7]));
return X1;
}
/**
* Returns the X2 vector defined in the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexX2(const CollectionOfPoints& pts)
{
const Vector X2((pts[3] - pts[0]) + (pts[2] - pts[1]) + (pts[7] - pts[4]) + (pts[6] - pts[5]));
return X2;
}
/**
* Returns the X3 vector defined in the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetHexX3(const CollectionOfPoints& pts)
{
const Vector X3((pts[4] - pts[0]) + (pts[5] - pts[1]) + (pts[6] - pts[2]) + (pts[7] - pts[3]));
return X3;
}
/**
* Returns the A_i matrix defined in the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \param [in] index The index of A to load.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC vtkm::Vec<Vector, 3> GetHexAi(const CollectionOfPoints& pts, const vtkm::Id& index)
{
const Scalar neg1(-1.0);
if (index == 0)
{
const Vector v0 = GetHexL0<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v1 = GetHexL3<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v2 = GetHexL4<Scalar, Vector, CollectionOfPoints>(pts);
const vtkm::Vec<Vector, 3> A = { v0, v1, v2 };
return A;
}
else if (index == 1)
{
const Vector v0 = GetHexL1<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v1 = neg1 * GetHexL0<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v2 = GetHexL5<Scalar, Vector, CollectionOfPoints>(pts);
const vtkm::Vec<Vector, 3> A = { v0, v1, v2 };
return A;
}
else if (index == 2)
{
const Vector v0 = GetHexL2<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v1 = neg1 * GetHexL1<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v2 = GetHexL6<Scalar, Vector, CollectionOfPoints>(pts);
const vtkm::Vec<Vector, 3> A = { v0, v1, v2 };
return A;
}
else if (index == 3)
{
const Vector v0 = neg1 * GetHexL3<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v1 = neg1 * GetHexL2<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v2 = GetHexL7<Scalar, Vector, CollectionOfPoints>(pts);
const vtkm::Vec<Vector, 3> A = { v0, v1, v2 };
return A;
}
else if (index == 4)
{
const Vector v0 = GetHexL11<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v1 = GetHexL8<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v2 = neg1 * GetHexL4<Scalar, Vector, CollectionOfPoints>(pts);
const vtkm::Vec<Vector, 3> A = { v0, v1, v2 };
return A;
}
else if (index == 5)
{
const Vector v0 = neg1 * GetHexL8<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v1 = GetHexL9<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v2 = neg1 * GetHexL5<Scalar, Vector, CollectionOfPoints>(pts);
const vtkm::Vec<Vector, 3> A = { v0, v1, v2 };
return A;
}
else if (index == 6)
{
const Vector v0 = neg1 * GetHexL9<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v1 = GetHexL10<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v2 = neg1 * GetHexL6<Scalar, Vector, CollectionOfPoints>(pts);
const vtkm::Vec<Vector, 3> A = { v0, v1, v2 };
return A;
}
else if (index == 7)
{
const Vector v0 = neg1 * GetHexL10<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v1 = neg1 * GetHexL11<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v2 = neg1 * GetHexL7<Scalar, Vector, CollectionOfPoints>(pts);
const vtkm::Vec<Vector, 3> A = { v0, v1, v2 };
return A;
}
else
{
const Vector v0 = GetHexX1<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v1 = GetHexX2<Scalar, Vector, CollectionOfPoints>(pts);
const Vector v2 = GetHexX3<Scalar, Vector, CollectionOfPoints>(pts);
const vtkm::Vec<Vector, 3> A = { v0, v1, v2 };
return A;
}
}
/**
* Returns ||A_i||^2 as defined in the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \param [in] index The index of A to load.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexAiNormSquared(const CollectionOfPoints& pts, const vtkm::Id& index)
{
const vtkm::Vec<Vector, 3> Ai = GetHexAi<Scalar, Vector, CollectionOfPoints>(pts, index);
const Scalar magSquared0 = vtkm::MagnitudeSquared(Ai[0]);
const Scalar magSquared1 = vtkm::MagnitudeSquared(Ai[1]);
const Scalar magSquared2 = vtkm::MagnitudeSquared(Ai[2]);
const Scalar AiNormSquared = magSquared0 + magSquared1 + magSquared2;
return AiNormSquared;
}
/**
* Returns ||adj(A_i)||^2 as defined in the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \param [in] index The index of A to load.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexAiAdjNormSquared(const CollectionOfPoints& pts, const vtkm::Id& index)
{
const vtkm::Vec<Vector, 3> Ai = GetHexAi<Scalar, Vector, CollectionOfPoints>(pts, index);
const Scalar magSquared0 = vtkm::MagnitudeSquared(vtkm::Cross(Ai[0], Ai[1]));
const Scalar magSquared1 = vtkm::MagnitudeSquared(vtkm::Cross(Ai[1], Ai[2]));
const Scalar magSquared2 = vtkm::MagnitudeSquared(vtkm::Cross(Ai[2], Ai[0]));
const Scalar AiAdjNormSquared = magSquared0 + magSquared1 + magSquared2;
return AiAdjNormSquared;
}
/**
* Returns alpha_i, the determinant of A_i, as defined in the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \param [in] index The index of A to load.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexAlphai(const CollectionOfPoints& pts, const vtkm::Id& index)
{
const vtkm::Vec<Vector, 3> Ai = GetHexAi<Scalar, Vector, CollectionOfPoints>(pts, index);
const Scalar alpha_i = vtkm::Dot(Ai[0], vtkm::Cross(Ai[1], Ai[2]));
return alpha_i;
}
/**
* Returns hat{A}_i, the "normalized" version of A_i, as defined in the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \param [in] index The index of A to load.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC vtkm::Vec<Vector, 3> GetHexAiHat(const CollectionOfPoints& pts, const vtkm::Id& index)
{
const vtkm::Vec<Vector, 3> Ai = GetHexAi<Scalar, Vector, CollectionOfPoints>(pts, index);
const Vector v0hat = Ai[0] / vtkm::Sqrt(vtkm::MagnitudeSquared(Ai[0]));
const Vector v1hat = Ai[1] / vtkm::Sqrt(vtkm::MagnitudeSquared(Ai[1]));
const Vector v2hat = Ai[2] / vtkm::Sqrt(vtkm::MagnitudeSquared(Ai[2]));
const vtkm::Vec<Vector, 3> Ahat = { v0hat, v1hat, v2hat };
return Ahat;
}
/**
* Returns hat{alpha}_i, the determinant of hat{A}_i, as defined in the verdict manual.
*
* \param [in] pts The eight points which define the Hex.
* \param [in] index The index of A to load.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetHexAlphaiHat(const CollectionOfPoints& pts, const vtkm::Id& index)
{
const vtkm::Vec<Vector, 3> Ai = GetHexAiHat<Scalar, Vector, CollectionOfPoints>(pts, index);
const Scalar hatAlpha_i = vtkm::Dot(Ai[0], vtkm::Cross(Ai[1], Ai[2]));
return hatAlpha_i;
}
#endif

@ -0,0 +1,487 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_exec_cellmetrics_TypeOfCellQuadrilateral
#define vtk_m_exec_cellmetrics_TypeOfCellQuadrilateral
/**
* The Verdict manual defines a set of commonly
* used components of a quadrilateral (quad). For example,
* area, side lengths, and so forth.
*
* These definitions can be found starting on
* page 32 of the Verdict manual.
*
* This file contains a set of functions which
* implement return the values of those commonly
* used components for subsequent use in metrics.
*/
/**
* Returns the L0 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadL0(const CollectionOfPoints& pts)
{
const Vector L0(pts[1] - pts[0]);
return L0;
}
/**
* Returns the L1 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadL1(const CollectionOfPoints& pts)
{
const Vector L1(pts[2] - pts[1]);
return L1;
}
/**
* Returns the L2 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadL2(const CollectionOfPoints& pts)
{
const Vector L2(pts[3] - pts[2]);
return L2;
}
/**
* Returns the L3 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadL3(const CollectionOfPoints& pts)
{
const Vector L3(pts[0] - pts[3]);
return L3;
}
/**
* Returns the L0 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Quad.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadL0Magnitude(const CollectionOfPoints& pts)
{
const Scalar l0 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetQuadL0<Scalar, Vector, CollectionOfPoints>(pts)));
return l0;
}
/**
* Returns the L1 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Quad.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadL1Magnitude(const CollectionOfPoints& pts)
{
const Scalar l1 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetQuadL1<Scalar, Vector, CollectionOfPoints>(pts)));
return l1;
}
/**
* Returns the L2 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Quad.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadL2Magnitude(const CollectionOfPoints& pts)
{
const Scalar l2 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetQuadL2<Scalar, Vector, CollectionOfPoints>(pts)));
return l2;
}
/**
* Returns the L3 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Quad.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadL3Magnitude(const CollectionOfPoints& pts)
{
const Scalar l3 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetQuadL3<Scalar, Vector, CollectionOfPoints>(pts)));
return l3;
}
/**
* Returns the Max of the magnitude of each vector which makes up the sides of the Quad.
*
* \param [in] pts The four points which define the Quad.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadLMax(const CollectionOfPoints& pts)
{
const Scalar l0 = GetQuadL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l1 = GetQuadL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l2 = GetQuadL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l3 = GetQuadL3Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar lmax = vtkm::Max(l0, vtkm::Max(l1, vtkm::Max(l2, l3)));
return lmax;
}
/**
* Returns the Min of the magnitude of each vector which makes up the sides of the Quad.
*
* \param [in] pts The four points which define the Quad.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadLMin(const CollectionOfPoints& pts)
{
const Scalar l0 = GetQuadL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l1 = GetQuadL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l2 = GetQuadL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l3 = GetQuadL3Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar lmin = vtkm::Min(l0, vtkm::Min(l1, vtkm::Min(l2, l3)));
return lmin;
}
/**
* Returns the D0 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadD0(const CollectionOfPoints& pts)
{
const Vector D0(pts[2] - pts[0]);
return D0;
}
/**
* Returns the D1 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadD1(const CollectionOfPoints& pts)
{
const Vector D1(pts[3] - pts[1]);
return D1;
}
/**
* Returns the D0 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Quad.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadD0Magnitude(const CollectionOfPoints& pts)
{
const Scalar d0 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetQuadD0<Scalar, Vector, CollectionOfPoints>(pts)));
return d0;
}
/**
* Returns the D0 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Quad.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadD1Magnitude(const CollectionOfPoints& pts)
{
const Scalar d1 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetQuadD1<Scalar, Vector, CollectionOfPoints>(pts)));
return d1;
}
/**
* Returns the Max of the magnitude of each vector which makes up the diagonals of the Quad.
*
* \param [in] pts The four points which define the Quad.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadDMax(const CollectionOfPoints& pts)
{
const Scalar d0 = GetQuadD0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar d1 = GetQuadD1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar dmax = vtkm::Max(d0, d1);
return dmax;
}
/**
* Returns the X0 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadX0(const CollectionOfPoints& pts)
{
const Vector X0((pts[1] - pts[0]) + (pts[2] - pts[3]));
return X0;
}
/**
* Returns the X1 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadX1(const CollectionOfPoints& pts)
{
const Vector X1((pts[2] - pts[1]) + (pts[3] - pts[0]));
return X1;
}
/**
* Returns the N0 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadN0(const CollectionOfPoints& pts)
{
const Vector A = GetQuadL3<Scalar, Vector, CollectionOfPoints>(pts);
const Vector B = GetQuadL0<Scalar, Vector, CollectionOfPoints>(pts);
const Vector N0 = vtkm::Cross(A, B);
return N0;
}
/**
* Returns the N1 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadN1(const CollectionOfPoints& pts)
{
const Vector A = GetQuadL0<Scalar, Vector, CollectionOfPoints>(pts);
const Vector B = GetQuadL1<Scalar, Vector, CollectionOfPoints>(pts);
const Vector N1 = vtkm::Cross(A, B);
return N1;
}
/**
* Returns the N2 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadN2(const CollectionOfPoints& pts)
{
const Vector A = GetQuadL1<Scalar, Vector, CollectionOfPoints>(pts);
const Vector B = GetQuadL2<Scalar, Vector, CollectionOfPoints>(pts);
const Vector N2 = vtkm::Cross(A, B);
return N2;
}
/**
* Returns the N3 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadN3(const CollectionOfPoints& pts)
{
const Vector A = GetQuadL2<Scalar, Vector, CollectionOfPoints>(pts);
const Vector B = GetQuadL3<Scalar, Vector, CollectionOfPoints>(pts);
const Vector N3 = vtkm::Cross(A, B);
return N3;
}
/**
* Returns the normal center vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadNc(const CollectionOfPoints& pts)
{
const Vector A = GetQuadX0<Scalar, Vector, CollectionOfPoints>(pts);
const Vector B = GetQuadX1<Scalar, Vector, CollectionOfPoints>(pts);
const Vector Nc = vtkm::Cross(A, B);
return Nc;
}
/**
* Returns the normalized N0 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadN0Normalized(const CollectionOfPoints& pts)
{
return vtkm::Normal(GetQuadN0<Scalar, Vector, CollectionOfPoints>(pts));
}
/**
* Returns the normalized N1 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadN1Normalized(const CollectionOfPoints& pts)
{
return vtkm::Normal(GetQuadN1<Scalar, Vector, CollectionOfPoints>(pts));
}
/**
* Returns the normalized N2 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadN2Normalized(const CollectionOfPoints& pts)
{
return vtkm::Normal(GetQuadN2<Scalar, Vector, CollectionOfPoints>(pts));
}
/**
* Returns the normalized N3 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadN3Normalized(const CollectionOfPoints& pts)
{
return vtkm::Normal(GetQuadN3<Scalar, Vector, CollectionOfPoints>(pts));
}
/**
* Returns the normalized Nc vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetQuadNcNormalized(const CollectionOfPoints& pts)
{
return vtkm::Normal(GetQuadNc<Scalar, Vector, CollectionOfPoints>(pts));
}
/**
* Returns the alpha0 scalar, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the scalar.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadAlpha0(const CollectionOfPoints& pts)
{
const Vector normalizedCenterNormal =
GetQuadNcNormalized<Scalar, Vector, CollectionOfPoints>(pts);
const Vector N0 = GetQuadN0<Scalar, Vector, CollectionOfPoints>(pts);
return vtkm::Dot(normalizedCenterNormal, N0);
}
/**
* Returns the alpha1 scalar, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the scalar.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadAlpha1(const CollectionOfPoints& pts)
{
const Vector normalizedCenterNormal =
GetQuadNcNormalized<Scalar, Vector, CollectionOfPoints>(pts);
const Vector N1 = GetQuadN1<Scalar, Vector, CollectionOfPoints>(pts);
return vtkm::Dot(normalizedCenterNormal, N1);
}
/**
* Returns the alpha2 scalar, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the scalar.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadAlpha2(const CollectionOfPoints& pts)
{
const Vector normalizedCenterNormal =
GetQuadNcNormalized<Scalar, Vector, CollectionOfPoints>(pts);
const Vector N2 = GetQuadN2<Scalar, Vector, CollectionOfPoints>(pts);
return vtkm::Dot(normalizedCenterNormal, N2);
}
/**
* Returns the alpha3 scalar, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the scalar.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadAlpha3(const CollectionOfPoints& pts)
{
const Vector normalizedCenterNormal =
GetQuadNcNormalized<Scalar, Vector, CollectionOfPoints>(pts);
const Vector N3 = GetQuadN3<Scalar, Vector, CollectionOfPoints>(pts);
return vtkm::Dot(normalizedCenterNormal, N3);
}
/**
* Returns the area of the quad, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the area.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetQuadArea(const CollectionOfPoints& pts)
{
const Scalar quarter(0.25);
const Scalar a0 = GetQuadAlpha0<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar a1 = GetQuadAlpha1<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar a2 = GetQuadAlpha2<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar a3 = GetQuadAlpha3<Scalar, Vector, CollectionOfPoints>(pts);
return quarter * (a0 + a1 + a2 + a3);
}
#endif

@ -0,0 +1,314 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_exec_cellmetrics_TypeOfCellTetrahedral
#define vtk_m_exec_cellmetrics_TypeOfCellTetrahedral
/**
* Returns the L0 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetTetraL0(const CollectionOfPoints& pts)
{
const Vector L0(pts[1] - pts[0]);
return L0;
}
/**
* Returns the L1 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetTetraL1(const CollectionOfPoints& pts)
{
const Vector L1(pts[2] - pts[1]);
return L1;
}
/**
* Returns the L2 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetTetraL2(const CollectionOfPoints& pts)
{
const Vector L2(pts[0] - pts[2]);
return L2;
}
/**
* Returns the L3 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetTetraL3(const CollectionOfPoints& pts)
{
const Vector L3(pts[3] - pts[0]);
return L3;
}
/**
* Returns the L4 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetTetraL4(const CollectionOfPoints& pts)
{
const Vector L4(pts[3] - pts[1]);
return L4;
}
/**
* Returns the L5 vector, as defined by the verdict manual.
*
* \param [in] pts The four points which define the quadrilateral.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetTetraL5(const CollectionOfPoints& pts)
{
const Vector L5(pts[3] - pts[2]);
return L5;
}
/**
* Returns the L0 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraL0Magnitude(const CollectionOfPoints& pts)
{
const Scalar l0 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetTetraL0<Scalar, Vector, CollectionOfPoints>(pts)));
return l0;
}
/**
* Returns the L1 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraL1Magnitude(const CollectionOfPoints& pts)
{
const Scalar l1 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetTetraL1<Scalar, Vector, CollectionOfPoints>(pts)));
return l1;
}
/**
* Returns the L2 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraL2Magnitude(const CollectionOfPoints& pts)
{
const Scalar l2 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetTetraL2<Scalar, Vector, CollectionOfPoints>(pts)));
return l2;
}
/**
* Returns the L3 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraL3Magnitude(const CollectionOfPoints& pts)
{
const Scalar l3 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetTetraL3<Scalar, Vector, CollectionOfPoints>(pts)));
return l3;
}
/**
* Returns the L4 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraL4Magnitude(const CollectionOfPoints& pts)
{
const Scalar l4 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetTetraL4<Scalar, Vector, CollectionOfPoints>(pts)));
return l4;
}
/**
* Returns the L5 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraL5Magnitude(const CollectionOfPoints& pts)
{
const Scalar l5 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetTetraL5<Scalar, Vector, CollectionOfPoints>(pts)));
return l5;
}
/**
* Returns the Max of the magnitude of each vector which makes up the edges of the Tetra.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the max.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraLMax(const CollectionOfPoints& pts)
{
const Scalar l0 = GetTetraL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l1 = GetTetraL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l2 = GetTetraL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l3 = GetTetraL3Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l4 = GetTetraL4Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l5 = GetTetraL5Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar lmax = vtkm::Max(l0, vtkm::Max(l1, vtkm::Max(l2, vtkm::Max(l3, vtkm::Max(l4, l5)))));
return lmax;
}
/**
* Returns the Min of the magnitude of each vector which makes up the sides of the Tetra.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the min.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraLMin(const CollectionOfPoints& pts)
{
const Scalar l0 = GetTetraL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l1 = GetTetraL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l2 = GetTetraL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l3 = GetTetraL3Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l4 = GetTetraL4Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l5 = GetTetraL5Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar lmin = vtkm::Min(l0, vtkm::Min(l1, vtkm::Min(l2, vtkm::Min(l3, vtkm::Min(l4, l5)))));
return lmin;
}
/**
* Returns the surface area of the Tetra.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the area.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraArea(const CollectionOfPoints& pts)
{
const Vector L0 = GetTetraL0<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L1 = GetTetraL1<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L2 = GetTetraL2<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L3 = GetTetraL3<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L4 = GetTetraL4<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar a = vtkm::Sqrt(vtkm::MagnitudeSquared(vtkm::Cross(L2, L0)));
const Scalar b = vtkm::Sqrt(vtkm::MagnitudeSquared(vtkm::Cross(L3, L0)));
const Scalar c = vtkm::Sqrt(vtkm::MagnitudeSquared(vtkm::Cross(L4, L1)));
const Scalar d = vtkm::Sqrt(vtkm::MagnitudeSquared(vtkm::Cross(L3, L2)));
const Scalar hhalf(0.5);
const Scalar area = hhalf * (a + b + c + d);
return area;
}
/**
* Returns the volume of the Tetra.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the volume.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraVolume(const CollectionOfPoints& pts)
{
const Vector L0 = GetTetraL0<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L2 = GetTetraL2<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L3 = GetTetraL3<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar six(6.0);
return vtkm::Dot(vtkm::Cross(L2, L0), L3) / six;
}
/**
* Returns the inradius of the Tetra.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the inradius.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraInradius(const CollectionOfPoints& pts)
{
const Scalar three(3.0);
const Scalar volume = GetTetraVolume<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar area = GetTetraArea<Scalar, Vector, CollectionOfPoints>(pts);
return (three * volume) / area;
}
/**
* Returns the circumradius of the Tetra.
*
* \param [in] pts The four points which define the Tetra.
* \return Returns the circumradius.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTetraCircumradius(const CollectionOfPoints& pts)
{
const Vector L0 = GetTetraL0<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L1 = GetTetraL1<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L2 = GetTetraL2<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L3 = GetTetraL3<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L4 = GetTetraL4<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l0l0 = vtkm::MagnitudeSquared(L0);
const Scalar l2l2 = vtkm::MagnitudeSquared(L2);
const Scalar l3l3 = vtkm::MagnitudeSquared(L3);
const Vector A = l3l3 * vtkm::Cross(L2, L0);
const Vector B = l2l2 * vtkm::Cross(L3, L0);
const Vector C = l0l0 * vtkm::Cross(L3, L2);
const Vector D(A + B + C);
const Scalar d = vtkm::Sqrt(vtkm::MagnitudeSquared(D));
const Scalar twelve(12.0);
const Scalar volume = GetTetraVolume<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar circumradius = d / (twelve * volume);
return circumradius;
}
#endif

@ -0,0 +1,211 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_exec_cellmetrics_TypeOfCellTriangle
#define vtk_m_exec_cellmetrics_TypeOfCellTriangle
/**
* The Verdict manual defines a set of commonly
* used components of a triangle. For example,
* area, side lengths, and so forth.
*
* These definitions can be found starting on
* page 17 of the Verdict manual.
*
* This file contains a set of functions which
* implement return the values of those commonly
* used components for subsequent use in metrics.
*/
/**
* Returns the L0 vector, as defined by the verdict manual.
*
* \param [in] pts The three points which define the triangle.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetTriangleL0(const CollectionOfPoints& pts)
{
const Vector L0(pts[2] - pts[1]);
return L0;
}
/**
* Returns the L1 vector, as defined by the verdict manual.
*
* \param [in] pts The three points which define the triangle.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetTriangleL1(const CollectionOfPoints& pts)
{
const Vector L1(pts[0] - pts[2]);
return L1;
}
/**
* Returns the L2 vector, as defined by the verdict manual.
*
* \param [in] pts The three points which define the triangle.
* \return Returns the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Vector GetTriangleL2(const CollectionOfPoints& pts)
{
const Vector L2(pts[1] - pts[0]);
return L2;
}
/**
* Returns the L0 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The three points which define the triangle.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTriangleL0Magnitude(const CollectionOfPoints& pts)
{
const Scalar l0 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetTriangleL0<Scalar, Vector, CollectionOfPoints>(pts)));
return l0;
}
/**
* Returns the L1 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The three points which define the triangle.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTriangleL1Magnitude(const CollectionOfPoints& pts)
{
const Scalar l1 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetTriangleL1<Scalar, Vector, CollectionOfPoints>(pts)));
return l1;
}
/**
* Returns the L2 vector's magnitude, as defined by the verdict manual.
*
* \param [in] pts The three points which define the triangle.
* \return Returns the magnitude of the vector.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTriangleL2Magnitude(const CollectionOfPoints& pts)
{
const Scalar l2 =
vtkm::Sqrt(vtkm::MagnitudeSquared(GetTriangleL2<Scalar, Vector, CollectionOfPoints>(pts)));
return l2;
}
/**
* Returns the Max of the magnitude of each vector which makes up the sides of the triangle.
*
* That is to say, the length of the longest side.
*
* \param [in] pts The three points which define the verticies of the triangle.
*
* \return Returns the max of the triangle side lengths.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTriangleLMax(const CollectionOfPoints& pts)
{
const Scalar l0 = GetTriangleL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l1 = GetTriangleL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l2 = GetTriangleL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar lmax = vtkm::Max(l0, vtkm::Max(l1, l2));
return lmax;
}
/**
* Returns the Min of the magnitude of each vector which makes up the sides of the triangle.
*
* That is to say, the length of the shortest side.
*
* \param [in] pts The three points which define the verticies of the triangle.
*
* \return Returns the max of the triangle side lengths.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTriangleLMin(const CollectionOfPoints& pts)
{
const Scalar l0 = GetTriangleL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l1 = GetTriangleL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l2 = GetTriangleL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar lmin = vtkm::Min(l0, vtkm::Min(l1, l2));
return lmin;
}
/**
* Returns the area of the triangle.
*
* \param [in] pts The three points which define the verticies of the triangle.
*
* \return Returns the are of the triangle..
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTriangleArea(const CollectionOfPoints& pts)
{
const Vector L0 = GetTriangleL0<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L1 = GetTriangleL1<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar hhalf(0.5);
const Scalar crossProductMagnitude = vtkm::Sqrt(vtkm::MagnitudeSquared(vtkm::Cross(L0, L1)));
const Scalar area = hhalf * crossProductMagnitude;
return area;
}
/**
* Returns the radius of a circle inscribed within the given triangle. This is commonly denoted as 'r'.
*
* \param [in] pts The three points which define the verticies of the triangle.
*
* \return Returns the inradius.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTriangleInradius(const CollectionOfPoints& pts)
{
const Scalar two(2.0);
const Scalar area = GetTriangleArea<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l0 = GetTriangleL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l1 = GetTriangleL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l2 = GetTriangleL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar inradius = (two * area) / (l0 + l1 + l2);
return inradius;
}
/**
* Returns the radius of a circle circumscribed around the given triangle. This is commonly denoted as 'R'.
*
* \param [in] pts The three points which define the verticies of the triangle.
*
* \return Returns the circumradius.
*/
template <typename Scalar, typename Vector, typename CollectionOfPoints>
VTKM_EXEC Scalar GetTriangleCircumradius(const CollectionOfPoints& pts)
{
const Scalar four(4.0);
const Scalar area = GetTriangleArea<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l0 = GetTriangleL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l1 = GetTriangleL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar l2 = GetTriangleL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar circumradius = (l0 * l1 * l2) / (four * area);
return circumradius;
}
#endif

@ -33,26 +33,36 @@ namespace filter
//Names of the available cell metrics, for use in
//the output dataset fields
//TODO: static const?
static const std::string MetricNames[] = { "empty",
"diagonalRatio",
"edgeRatio",
//"skew",
"oddy",
"relativeSizeSquared",
"volume" };
static const std::string MetricNames[] = {
"area", "aspectGamma", "aspectRatio", "condition", "diagonalRatio", "jacobian",
"minAngle", "maxAngle", "oddy", "relativeSize", "scaledJacobian", "shape",
"shear", "skew", "stretch", "taper", "volume", "warpage"
};
//Different cell metrics available to use
//TODO: static const?
//This must follow the same order as the MetricNames above
enum class CellMetric
{
EMPTY, //0
AREA,
ASPECT_GAMMA,
ASPECT_RATIO,
CONDITION,
DIAGONAL_RATIO,
EDGE_RATIO,
JACOBIAN,
MIN_ANGLE,
MAX_ANGLE,
ODDY,
RELATIVE_SIZE,
SCALED_JACOBIAN,
SHAPE,
SHEAR,
SKEW,
STRETCH,
TAPER,
VOLUME,
NUMBER_OF_CELL_METRICS //(num metrics = NUMBER_OF_CELL_METRICS - 2)
WARPAGE,
NUMBER_OF_CELL_METRICS,
EMPTY
};
/** \brief Computes the quality of an unstructured cell-based mesh. The quality is defined in terms of the
@ -68,9 +78,8 @@ class MeshQuality : public vtkm::filter::FilterCell<MeshQuality>
public:
using SupportedTypes = vtkm::TypeListTagFieldVec3;
using ShapeMetricsVecType = std::vector<vtkm::Pair<vtkm::UInt8, CellMetric>>;
VTKM_CONT MeshQuality(const ShapeMetricsVecType& metrics);
VTKM_CONT MeshQuality(CellMetric);
void SetOutputName(const std::string& s) { this->OutputName = s; };
template <typename T, typename StorageType, typename DerivedPolicy>
VTKM_CONT vtkm::cont::DataSet DoExecute(
@ -80,10 +89,8 @@ public:
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
private:
//A user-assigned cell metric per shape/cell type
//Empty metric if not provided by user
//Length of vector is the number of different VTK-m cell types
std::vector<CellMetric> CellTypeMetrics;
CellMetric MyMetric;
std::string OutputName;
};
} // namespace filter

@ -56,14 +56,16 @@ void MeshQualityDebug(const vtkm::cont::ArrayHandle<T, S>& vtkmNotUsed(outputArr
} // namespace debug
inline VTKM_CONT MeshQuality::MeshQuality(
const std::vector<vtkm::Pair<vtkm::UInt8, CellMetric>>& metrics)
inline VTKM_CONT MeshQuality::MeshQuality(CellMetric metric)
: vtkm::filter::FilterCell<MeshQuality>()
{
this->SetUseCoordinateSystemAsField(true);
this->CellTypeMetrics.assign(vtkm::NUMBER_OF_CELL_SHAPES, CellMetric::EMPTY);
for (auto p : metrics)
this->CellTypeMetrics[p.first] = p.second;
this->MyMetric = metric;
if (this->MyMetric < CellMetric::AREA || this->MyMetric >= CellMetric::NUMBER_OF_CELL_METRICS)
{
VTKM_ASSERT(true);
}
this->OutputName = MetricNames[(int)this->MyMetric];
}
template <typename T, typename StorageType, typename DerivedPolicy>
@ -75,187 +77,22 @@ inline VTKM_CONT vtkm::cont::DataSet MeshQuality::DoExecute(
{
VTKM_ASSERT(fieldMeta.IsPointField());
using Algorithm = vtkm::cont::Algorithm;
using ShapeHandle = vtkm::cont::ArrayHandle<vtkm::UInt8>;
using IdHandle = vtkm::cont::ArrayHandle<vtkm::Id>;
using QualityWorklet = vtkm::worklet::MeshQuality<CellMetric>;
using FieldStatsWorklet = vtkm::worklet::FieldStatistics<T>;
//TODO: Should other cellset types be supported?
vtkm::cont::CellSetExplicit<> cellSet;
input.GetCellSet().CopyTo(cellSet);
ShapeHandle cellShapes =
cellSet.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
//Obtain the frequency counts of each cell type in the input dataset
IdHandle uniqueCellCounts;
ShapeHandle uniqueCellShapes, sortedShapes;
Algorithm::Copy(cellShapes, sortedShapes);
Algorithm::Sort(sortedShapes);
Algorithm::ReduceByKey(
sortedShapes,
vtkm::cont::make_ArrayHandleConstant(vtkm::Id(1), cellShapes.GetNumberOfValues()),
uniqueCellShapes,
uniqueCellCounts,
vtkm::Add());
const vtkm::Id numUniqueShapes = uniqueCellShapes.GetNumberOfValues();
auto uniqueCellShapesPortal = uniqueCellShapes.GetPortalConstControl();
auto numCellsPerShapePortal = uniqueCellCounts.GetPortalConstControl();
std::vector<vtkm::Id> tempCounts(vtkm::NUMBER_OF_CELL_SHAPES);
for (vtkm::Id i = 0; i < numUniqueShapes; i++)
{
tempCounts[uniqueCellShapesPortal.Get(i)] = numCellsPerShapePortal.Get(i);
}
IdHandle cellShapeCounts = vtkm::cont::make_ArrayHandle(tempCounts);
//Invoke the MeshQuality worklet
vtkm::cont::ArrayHandle<T> outArray;
vtkm::cont::ArrayHandle<CellMetric> cellMetrics = vtkm::cont::make_ArrayHandle(CellTypeMetrics);
this->Invoke(QualityWorklet{},
vtkm::filter::ApplyPolicyCellSet(cellSet, policy),
cellShapeCounts,
cellMetrics,
points,
outArray);
vtkm::worklet::MeshQuality<CellMetric> qualityWorklet;
qualityWorklet.SetMetric(this->MyMetric);
this->Invoke(qualityWorklet, vtkm::filter::ApplyPolicyCellSet(cellSet, policy), points, outArray);
//Build the output dataset: a separate field for each cell type that has a specified metric
vtkm::cont::DataSet result;
result.CopyStructure(input); //clone of the input dataset
auto cellShapePortal = cellShapes.GetPortalConstControl();
auto metricValuesPortal = outArray.GetPortalConstControl();
const vtkm::Id numCells = outArray.GetNumberOfValues();
T currMetric = 0;
vtkm::UInt8 currShape = 0;
//Output metric values stored in separate containers
//based on shape type. Unsupported shape types in VTK-m
//are represented with an empty "placeholder" container.
std::vector<std::vector<T>> metricValsPerShape = {
{ /*placeholder*/ }, { /*vertices*/ }, { /*placeholder*/ }, { /*lines*/ },
{ /*placeholder*/ }, { /*triangles*/ }, { /*placeholder*/ }, { /*polygons*/ },
{ /*placeholder*/ }, { /*quads*/ }, { /*tetrahedrons*/ }, { /*placeholder*/ },
{ /*hexahedrons*/ }, { /*wedges*/ }, { /*pyramids*/ }
};
for (vtkm::Id metricArrayIndex = 0; metricArrayIndex < numCells; metricArrayIndex++)
{
currShape = cellShapePortal.Get(metricArrayIndex);
currMetric = metricValuesPortal.Get(metricArrayIndex);
metricValsPerShape[currShape].emplace_back(currMetric);
}
//Compute the mesh quality for each shape type. This consists
//of computing the summary statistics of the metric values for
//each cell of the given shape type.
std::string fieldName = "", metricName = "";
vtkm::UInt8 cellShape = 0;
vtkm::Id cellCount = 0;
bool skipShape = false;
for (vtkm::Id shapeIndex = 0; shapeIndex < numUniqueShapes; shapeIndex++)
{
cellShape = uniqueCellShapesPortal.Get(shapeIndex);
cellCount = numCellsPerShapePortal.Get(shapeIndex);
metricName = MetricNames[static_cast<vtkm::UInt8>(CellTypeMetrics[cellShape])];
//Skip over shapes with an empty/unspecified metric;
//don't include a field for them
if (CellTypeMetrics[cellShape] == CellMetric::EMPTY)
continue;
switch (cellShape)
{
case vtkm::CELL_SHAPE_EMPTY:
skipShape = true;
break;
case vtkm::CELL_SHAPE_VERTEX:
fieldName = "vertices";
break;
case vtkm::CELL_SHAPE_LINE:
fieldName = "lines";
break;
case vtkm::CELL_SHAPE_TRIANGLE:
fieldName = "triangles";
break;
case vtkm::CELL_SHAPE_POLYGON:
fieldName = "polygons";
break;
case vtkm::CELL_SHAPE_QUAD:
fieldName = "quads";
break;
case vtkm::CELL_SHAPE_TETRA:
fieldName = "tetrahedrons";
break;
case vtkm::CELL_SHAPE_HEXAHEDRON:
fieldName = "hexahedrons";
break;
case vtkm::CELL_SHAPE_WEDGE:
fieldName = "wedges";
break;
case vtkm::CELL_SHAPE_PYRAMID:
fieldName = "pyramids";
break;
default:
skipShape = true;
break;
}
//Skip over shapes of empty cell type; don't include a field for them
if (skipShape)
continue;
fieldName += "-" + metricName;
auto shapeMetricVals = metricValsPerShape[cellShape];
auto shapeMetricValsHandle = vtkm::cont::make_ArrayHandle(std::move(shapeMetricVals));
//Invoke the field stats worklet on the array of metric values for this shape type
typename FieldStatsWorklet::StatInfo statinfo;
FieldStatsWorklet().Run(shapeMetricValsHandle, statinfo);
//Retrieve summary stats from the output stats struct.
//These stats define the mesh quality with respect to this shape type.
vtkm::cont::ArrayHandle<T> shapeMeshQuality;
shapeMeshQuality.Allocate(5);
{
auto portal = shapeMeshQuality.GetPortalControl();
portal.Set(0, T(cellCount));
portal.Set(1, statinfo.mean);
portal.Set(2, statinfo.variance);
portal.Set(3, statinfo.minimum);
portal.Set(4, statinfo.maximum);
}
//Append the summary stats into the output dataset as a new field
result.AddField(vtkm::cont::make_FieldCell(fieldName, shapeMeshQuality));
#ifdef DEBUG_PRINT
std::cout << "-----------------------------------------------------\n"
<< "Mesh quality of " << fieldName << ":\n"
<< "Number of cells: " << cellCount << "\n"
<< "Mean: " << statinfo.mean << "\n"
<< "Variance: " << statinfo.variance << "\n"
<< "Minimum: " << statinfo.minimum << "\n"
<< "Maximum: " << statinfo.maximum << "\n"
<< "-----------------------------------------------------\n";
#endif
}
#ifdef DEBUG_PRINT
auto metricValsPortal = outArray.GetPortalConstControl();
std::cout << "-----------------------------------------------------\n"
<< "Metric values - all cells:\n";
for (vtkm::Id v = 0; v < outArray.GetNumberOfValues(); v++)
std::cout << metricValsPortal.Get(v) << "\n";
std::cout << "-----------------------------------------------------\n";
#endif
//Append the metric values of all cells into the output
//dataset as a new field
const std::string s = "allCells-metricValues";
result.AddField(vtkm::cont::make_FieldCell(s, outArray));
result.AddField(vtkm::cont::make_FieldCell(this->OutputName, outArray));
return result;
}

@ -17,6 +17,7 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <stdio.h>
#include <string>
#include <typeinfo>
#include <vector>
@ -30,8 +31,8 @@
#include <vtkm/io/writer/VTKDataSetWriter.h>
//Adapted from vtkm/cont/testing/MakeTestDataSet.h
//Modified the content of the Make3DExplicitDataSetZoo() function
inline vtkm::cont::DataSet Make3DExplicitDataSet()
//Modified the content of the MakeExplicitDataSetZoo() function
inline vtkm::cont::DataSet MakeExplicitDataSet()
{
vtkm::cont::DataSet dataSet;
vtkm::cont::DataSetBuilderExplicit dsb;
@ -39,14 +40,11 @@ inline vtkm::cont::DataSet Make3DExplicitDataSet()
using CoordType = vtkm::Vec3f_64;
std::vector<CoordType> coords = {
{ 0.00, 0.00, 0.00 }, { 1.00, 0.00, 0.00 }, { 2.00, 0.00, 0.00 }, { 0.00, 0.00, 1.00 },
{ 1.00, 0.00, 1.00 }, { 2.00, 0.00, 1.00 }, { 0.00, 1.00, 0.00 }, { 1.00, 1.00, 0.00 },
{ 2.00, 1.00, 0.00 }, { 0.00, 1.00, 1.00 }, { 1.00, 1.00, 1.00 }, { 2.00, 1.00, 1.00 },
{ 0.00, 2.00, 0.00 }, { 1.00, 2.00, 0.00 }, { 2.00, 2.00, 0.00 }, { 0.00, 2.00, 1.00 },
{ 1.00, 2.00, 1.00 }, { 2.00, 2.00, 1.00 }, { 1.00, 3.00, 1.00 }, { 2.75, 0.00, 1.00 },
{ 3.00, 0.00, 0.75 }, { 3.00, 0.25, 1.00 }, { 3.00, 1.00, 1.00 }, { 3.00, 1.00, 0.00 },
{ 2.57, 2.00, 1.00 }, { 3.00, 1.75, 1.00 }, { 3.00, 1.75, 0.75 }, { 3.00, 0.00, 0.00 },
{ 2.57, 0.42, 0.57 }, { 2.59, 1.43, 0.71 }
{ 0, 0, 0 }, { 3, 0, 0 }, { 2, 2, 0 }, { 4, 0, 0 }, { 7, 0, 0 }, { 7, 2, 0 },
{ 6, 2, 0 }, { 8, 0, 0 }, { 11, 0, 0 }, { 9, 2, 0 }, { 9, 1, 1 }, { 9, 3, 0 },
{ 11, 3, 0 }, { 11, 5, 0 }, { 9, 5, 0 }, { 10, 4, 1 }, { 12, 0, 0 }, { 12, 3, 0 },
{ 12, 2, 1 }, { 15, 0, 0 }, { 15, 3, 0 }, { 15, 1, 1 }, { 16, 0, 0 }, { 18, 0, 0 },
{ 18, 2, 0 }, { 16, 2, 0 }, { 17, 1, 1 }, { 19, 1, 1 }, { 19, 3, 1 }, { 17, 3, 1 }
};
std::vector<vtkm::UInt8> shapes;
@ -55,144 +53,64 @@ inline vtkm::cont::DataSet Make3DExplicitDataSet()
//Construct the shapes/cells of the dataset
//This is a zoo of points, lines, polygons, and polyhedra
shapes.push_back(vtkm::CELL_SHAPE_HEXAHEDRON);
numindices.push_back(8);
shapes.push_back(vtkm::CELL_SHAPE_TRIANGLE);
numindices.push_back(3);
conn.push_back(0);
conn.push_back(1);
conn.push_back(2);
shapes.push_back(vtkm::CELL_SHAPE_QUAD);
numindices.push_back(4);
conn.push_back(3);
conn.push_back(4);
conn.push_back(1);
conn.push_back(5);
conn.push_back(6);
shapes.push_back(vtkm::CELL_SHAPE_TETRA);
numindices.push_back(4);
conn.push_back(7);
conn.push_back(8);
conn.push_back(9);
conn.push_back(10);
conn.push_back(7);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(11);
conn.push_back(12);
conn.push_back(13);
conn.push_back(14);
conn.push_back(15);
shapes.push_back(vtkm::CELL_SHAPE_WEDGE);
numindices.push_back(6);
conn.push_back(16);
conn.push_back(17);
conn.push_back(18);
conn.push_back(19);
conn.push_back(20);
conn.push_back(21);
shapes.push_back(vtkm::CELL_SHAPE_HEXAHEDRON);
numindices.push_back(8);
conn.push_back(1);
conn.push_back(4);
conn.push_back(5);
conn.push_back(2);
conn.push_back(7);
conn.push_back(10);
conn.push_back(11);
conn.push_back(8);
shapes.push_back(vtkm::CELL_SHAPE_TETRA);
numindices.push_back(4);
conn.push_back(24);
conn.push_back(26);
conn.push_back(25);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_TETRA);
numindices.push_back(4);
conn.push_back(8);
conn.push_back(17);
conn.push_back(11);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(24);
conn.push_back(17);
conn.push_back(8);
conn.push_back(23);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(25);
conn.push_back(22);
conn.push_back(11);
conn.push_back(17);
conn.push_back(23);
conn.push_back(24);
conn.push_back(25);
conn.push_back(26);
conn.push_back(27);
conn.push_back(28);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_WEDGE);
numindices.push_back(6);
conn.push_back(8);
conn.push_back(14);
conn.push_back(17);
conn.push_back(7);
conn.push_back(13);
conn.push_back(16);
shapes.push_back(vtkm::CELL_SHAPE_WEDGE);
numindices.push_back(6);
conn.push_back(11);
conn.push_back(8);
conn.push_back(17);
conn.push_back(10);
conn.push_back(7);
conn.push_back(16);
shapes.push_back(vtkm::CELL_SHAPE_VERTEX);
numindices.push_back(1);
conn.push_back(0);
shapes.push_back(vtkm::CELL_SHAPE_VERTEX);
numindices.push_back(1);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_LINE);
numindices.push_back(2);
conn.push_back(0);
conn.push_back(1);
shapes.push_back(vtkm::CELL_SHAPE_LINE);
numindices.push_back(2);
conn.push_back(15);
conn.push_back(16);
shapes.push_back(vtkm::CELL_SHAPE_TRIANGLE);
numindices.push_back(3);
conn.push_back(2);
conn.push_back(4);
conn.push_back(15);
shapes.push_back(vtkm::CELL_SHAPE_TRIANGLE);
numindices.push_back(3);
conn.push_back(5);
conn.push_back(6);
conn.push_back(7);
shapes.push_back(vtkm::CELL_SHAPE_QUAD);
numindices.push_back(4);
conn.push_back(0);
conn.push_back(3);
conn.push_back(5);
conn.push_back(2);
shapes.push_back(vtkm::CELL_SHAPE_QUAD);
numindices.push_back(4);
conn.push_back(5);
conn.push_back(4);
conn.push_back(10);
conn.push_back(11);
shapes.push_back(vtkm::CELL_SHAPE_POLYGON);
numindices.push_back(3);
conn.push_back(4);
conn.push_back(7);
conn.push_back(1);
shapes.push_back(vtkm::CELL_SHAPE_POLYGON);
numindices.push_back(4);
conn.push_back(1);
conn.push_back(6);
conn.push_back(7);
conn.push_back(2);
dataSet = dsb.Create(coords, shapes, numindices, conn, "coordinates");
return dataSet;
}
template <typename T>
std::vector<std::string> TestMeshQualityFilter(const vtkm::cont::DataSet& input,
const std::vector<vtkm::Float64>& expectedVals,
T filter)
bool TestMeshQualityFilter(const vtkm::cont::DataSet& input,
const std::vector<vtkm::FloatDefault>& expectedVals,
const std::string& outputname,
vtkm::filter::MeshQuality& filter)
{
std::vector<std::string> errors;
vtkm::cont::DataSet output;
try
{
@ -200,173 +118,93 @@ std::vector<std::string> TestMeshQualityFilter(const vtkm::cont::DataSet& input,
}
catch (vtkm::cont::ErrorExecution&)
{
errors.push_back("Error occured while executing filter. Exiting...");
return errors;
return true;
}
//Test the computed metric values (for all cells) and expected metric
//values for equality.
const vtkm::Id numFields = output.GetNumberOfFields();
vtkm::cont::testing::TestEqualResult result = vtkm::cont::testing::test_equal_ArrayHandles(
vtkm::cont::make_ArrayHandle(expectedVals), output.GetField(numFields - 1).GetData());
if (!result)
result.PushMessage(std::string("Data doesn't match"));
return result.GetMessages();
}
//Either an error occurred during execution of the
//filter, or mismatches exist between the expected output
//and the computed filter output.
void CheckForErrors(const std::vector<std::string>& messages)
{
if (!messages.empty())
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
output.GetField(outputname).GetData().CopyTo(values);
auto portal1 = values.GetPortalConstControl();
if (portal1.GetNumberOfValues() != (vtkm::Id)expectedVals.size())
{
std::cout << "FAIL\n";
for (std::string m : messages)
std::cout << m << "\n";
printf("Number of expected values for %s does not match.\n", outputname.c_str());
return true;
}
else
std::cout << "SUCCESS\n";
std::vector<std::string> cellTypes = { "triangle", "quadrilateral", "tetrahedron",
"pyramid", "wedge", "hexahedron" };
bool anyFailures = false;
for (unsigned long i = 0; i < expectedVals.size(); i++)
{
vtkm::Id id = (vtkm::Id)i;
if (portal1.Get(id) != expectedVals[i])
{
printf("Metric \"%s\" for cell type \"%s\" does not match. Expected %f and got %f\n",
outputname.c_str(),
cellTypes[i].c_str(),
expectedVals[i],
portal1.Get(id));
anyFailures = true;
}
}
return anyFailures;
}
int TestMeshQuality()
{
using FloatVec = std::vector<vtkm::Float64>;
using PairVec = std::vector<vtkm::Pair<vtkm::UInt8, vtkm::filter::CellMetric>>;
using StringVec = std::vector<std::string>;
using CharVec = std::vector<vtkm::UInt8>;
using QualityFilter = vtkm::filter::MeshQuality;
using FloatVec = std::vector<vtkm::FloatDefault>;
//Test variables
vtkm::cont::DataSet input = Make3DExplicitDataSet();
std::unique_ptr<QualityFilter> filter;
std::string metricSuffix;
StringVec fieldNames;
CharVec testedShapes;
PairVec shapeMetricPairs;
FloatVec expectedValues;
vtkm::cont::DataSet input = MakeExplicitDataSet();
/***************************************************
* Test 1: Volume metric
***************************************************/
int numFailures = 0;
bool testFailed = false;
std::cout << "Testing MeshQuality filter: Volume metric"
<< "\n++++++++++++++++++++++++++++++++++++++++++++++++++\n";
std::vector<FloatVec> expectedValues;
std::vector<vtkm::filter::CellMetric> metrics;
std::vector<std::string> metricName;
//Assign a cell metric to compute for each different
//shape type that may exist in the input dataset. If no metric
//is specified for a shape type, then it is assumed to be EMPTY
//and no metric is computed.
testedShapes = { vtkm::CELL_SHAPE_TETRA, vtkm::CELL_SHAPE_HEXAHEDRON, vtkm::CELL_SHAPE_WEDGE,
vtkm::CELL_SHAPE_PYRAMID, vtkm::CELL_SHAPE_POLYGON, vtkm::CELL_SHAPE_LINE,
vtkm::CELL_SHAPE_QUAD, vtkm::CELL_SHAPE_TRIANGLE };
shapeMetricPairs.clear();
for (auto s : testedShapes)
shapeMetricPairs.push_back(vtkm::make_Pair(s, vtkm::filter::CellMetric::VOLUME));
/*
FloatVec volumeExpectedValues = { 0, 0, 1, (float) 1.333333333, 4, 4 };
expectedValues.push_back(volumeExpectedValues);
metrics.push_back(vtkm::filter::CellMetric::VOLUME);
metricName.push_back("volume");
*/
//The ground truth metric value for each cell in the input dataset.
//These values are generated from VisIt using the equivalent pseudocolor
//mesh quality metric.
expectedValues = { 1, 1, 0.0100042, 0.0983333, 0.0732667, 0.0845833, -0.5, -0.5, 0,
0, 1, 1, 1.5, 0.7071068, 2, 1, 0.5, 1 };
FloatVec jacobianExpectedValues = { 0, 2, 6, 0, 0, 4 };
expectedValues.push_back(jacobianExpectedValues);
metrics.push_back(vtkm::filter::CellMetric::JACOBIAN);
metricName.push_back("jacobian");
filter.reset(new QualityFilter(shapeMetricPairs));
std::vector<std::string> errors =
TestMeshQualityFilter<QualityFilter>(input, expectedValues, *filter);
std::cout << "Volume metric test: ";
CheckForErrors(errors);
/*
FloatVec diagonalRatioExpectedValues = { -1, -1, -1, -1, -1, (float) 0.39 };
expectedValues.push_back(diagonalRatioExpectedValues);
metrics.push_back(vtkm::filter::CellMetric::DIAGONAL_RATIO);
metricName.push_back("diagonalRatio");
*/
/***************************************************
* Test 2: Edge Ratio metric
***************************************************/
std::cout << "\nTesting MeshQuality filter: Edge Ratio metric"
<< "\n++++++++++++++++++++++++++++++++++++++++++++++++++\n";
testedShapes = { vtkm::CELL_SHAPE_TETRA, vtkm::CELL_SHAPE_HEXAHEDRON, vtkm::CELL_SHAPE_WEDGE,
vtkm::CELL_SHAPE_PYRAMID, vtkm::CELL_SHAPE_POLYGON, vtkm::CELL_SHAPE_LINE,
vtkm::CELL_SHAPE_QUAD, vtkm::CELL_SHAPE_TRIANGLE };
shapeMetricPairs.clear();
for (auto s : testedShapes)
shapeMetricPairs.push_back(vtkm::make_Pair(s, vtkm::filter::CellMetric::EDGE_RATIO));
expectedValues = { 1, 1, 2.55938, 1.80027, 2.59323, 1.73099, 1.41421, 1.41421, 0,
0, 1, 1, 2.12132, 2.44949, 2, 1, 1.41421, 1.41421 };
filter.reset(new QualityFilter(shapeMetricPairs));
errors = TestMeshQualityFilter<QualityFilter>(input, expectedValues, *filter);
std::cout << "Edge ratio metric test: ";
CheckForErrors(errors);
/***************************************************
* Test 3: Diagonal Ratio metric
***************************************************/
std::cout << "Testing MeshQuality filter: Diagonal Ratio metric"
<< "\n++++++++++++++++++++++++++++++++++++++++++++++++++\n";
testedShapes = { vtkm::CELL_SHAPE_HEXAHEDRON, vtkm::CELL_SHAPE_POLYGON, vtkm::CELL_SHAPE_QUAD };
shapeMetricPairs.clear();
for (auto s : testedShapes)
shapeMetricPairs.push_back(vtkm::make_Pair(s, vtkm::filter::CellMetric::DIAGONAL_RATIO));
expectedValues = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 2.23607 };
filter.reset(new QualityFilter(shapeMetricPairs));
errors = TestMeshQualityFilter<QualityFilter>(input, expectedValues, *filter);
std::cout << "Diagonal ratio metric test: ";
CheckForErrors(errors);
#if 0
/***************************************************
* Test 4: Oddy metric
***************************************************/
std::cout << "Testing MeshQuality filter: Oddy metric"
<< "\n++++++++++++++++++++++++++++++++++++++++++++++++++\n";
testedShapes = {vtkm::CELL_SHAPE_HEXAHEDRON, vtkm::CELL_SHAPE_POLYGON,
vtkm::CELL_SHAPE_QUAD};
shapeMetricPairs.clear();
for (auto s : testedShapes)
shapeMetricPairs.push_back(vtkm::make_Pair(s, vtkm::filter::CellMetric::ODDY));
expectedValues = {0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1.125, 0,
0, 2.5}; /*(all cells, volume value)*/
filter.reset(new QualityFilter(shapeMetricPairs));
errors = TestMeshQualityFilter<QualityFilter>(input, expectedValues, *filter);
std::cout << "Oddy metric test: ";
CheckForErrors(errors);
/***************************************************
* Test 4: Relative Size Squared metric
***************************************************/
std::cout << "Testing MeshQuality filter: Relative Size Squared metric"
<< "\n++++++++++++++++++++++++++++++++++++++++++++++++++\n";
testedShapes = {vtkm::CELL_SHAPE_HEXAHEDRON, vtkm::CELL_SHAPE_POLYGON,
vtkm::CELL_SHAPE_QUAD, vtkm::CELL_SHAPE_TRIANGLE,
vtkm::CELL_SHAPE_TETRA};
shapeMetricPairs.clear();
for (auto s : testedShapes)
shapeMetricPairs.push_back(vtkm::make_Pair(s, vtkm::filter::CellMetric::RELATIVE_SIZE));
expectedValues = {1, 1, 0.0341086, 0.303456, 0, 0, 0,
0, 0, 0, 0, 0, 0.361898, 0.614047, 1, 1,
0.307024, 1};
filter.reset(new QualityFilter(shapeMetricPairs));
errors = TestMeshQualityFilter<QualityFilter>(input, expectedValues, *filter);
std::cout << "Relative Size Square metric test: ";
CheckForErrors(errors);
#endif
unsigned long numTests = (unsigned long)metrics.size();
for (unsigned long i = 0; i < numTests; i++)
{
printf("Testing metric %s\n", metricName[i].c_str());
vtkm::filter::MeshQuality filter(metrics[i]);
testFailed = TestMeshQualityFilter(input, expectedValues[i], metricName[i], filter);
if (testFailed)
{
numFailures++;
printf("\ttest \"%s\" failed\n", metricName[i].c_str());
}
else
printf("\t... passed\n");
}
if (numFailures > 0)
{
printf("Number of failed metrics is %d\n", numFailures);
bool see_previous_messages = false; // this variable name plays well with macro
VTKM_TEST_ASSERT(see_previous_messages, "Failure occurred during test");
}
return 0;
}

@ -24,6 +24,7 @@
#include "vtkm/exec/CellMeasure.h"
#include "vtkm/exec/cellmetrics/CellDiagonalRatioMetric.h"
#include "vtkm/exec/cellmetrics/CellEdgeRatioMetric.h"
#include "vtkm/exec/cellmetrics/CellJacobianMetric.h"
#include "vtkm/worklet/WorkletMapTopology.h"
namespace vtkm
@ -42,26 +43,22 @@ class MeshQuality : public vtkm::worklet::WorkletVisitCellsWithPoints
{
public:
using ControlSignature = void(CellSetIn cellset,
WholeArrayIn counts,
WholeArrayIn metrics,
FieldInPoint pointCoords,
FieldOutCell metricOut);
using ExecutionSignature = void(CellShape, PointCount, _2, _3, _4, _5);
using ExecutionSignature = void(CellShape, PointCount, _2, _3);
using InputDomain = _1;
template <typename CellShapeType,
typename PointCoordVecType,
typename CountsArrayType,
typename MetricsArrayType,
typename OutType>
void SetMetric(MetricTagType m) { metric = m; }
template <typename CellShapeType, typename PointCoordVecType, typename OutType>
VTKM_EXEC void operator()(CellShapeType shape,
const vtkm::IdComponent& numPoints,
const CountsArrayType& counts,
const MetricsArrayType& metrics,
//const CountsArrayType& counts,
//const MetricsArrayType& metrics,
//MetricTagType metric,
const PointCoordVecType& pts,
OutType& metricValue) const
{
printf("shape.Id: %u\n", shape.Id);
vtkm::UInt8 thisId = shape.Id;
if (shape.Id == vtkm::CELL_SHAPE_POLYGON)
{
@ -72,9 +69,8 @@ public:
}
switch (thisId)
{
vtkmGenericCellShapeMacro(
metricValue = this->ComputeMetric<OutType>(
numPoints, pts, counts.Get(shape.Id), CellShapeTag(), metrics.Get(CellShapeTag().Id)));
vtkmGenericCellShapeMacro(metricValue =
this->ComputeMetric<OutType>(numPoints, pts, CellShapeTag()));
default:
this->RaiseError("Asked for metric of unknown cell type.");
metricValue = OutType(0.0);
@ -82,17 +78,14 @@ public:
}
protected:
template <typename OutType,
typename PointCoordVecType,
typename CellShapeType,
typename CellMetricType>
// data member
MetricTagType metric;
template <typename OutType, typename PointCoordVecType, typename CellShapeType>
VTKM_EXEC OutType ComputeMetric(const vtkm::IdComponent& numPts,
const PointCoordVecType& pts,
const vtkm::Id& numShapes,
CellShapeType tag,
CellMetricType metric) const
CellShapeType tag) const
{
UNUSED(numShapes);
constexpr vtkm::IdComponent dims = vtkm::CellTraits<CellShapeType>::TOPOLOGICAL_DIMENSIONS;
//Only compute the metric for 2D and 3D shapes; return 0 otherwise
@ -105,10 +98,16 @@ protected:
metricValue =
vtkm::exec::cellmetrics::CellDiagonalRatioMetric<OutType>(numPts, pts, tag, *this);
break;
/* DEPRECATING
case MetricTagType::EDGE_RATIO:
metricValue =
vtkm::exec::cellmetrics::CellEdgeRatioMetric<OutType>(numPts, pts, tag, *this);
break;
*/
case MetricTagType::JACOBIAN:
metricValue =
vtkm::exec::cellmetrics::CellJacobianMetric<OutType>(numPts, pts, tag, *this);
break;
case MetricTagType::VOLUME:
metricValue = vtkm::exec::CellMeasure<OutType>(numPts, pts, tag, *this);
break;