diff --git a/vtkm/VecVariable.h b/vtkm/VecVariable.h index 0e2db0b50..7c9a28529 100644 --- a/vtkm/VecVariable.h +++ b/vtkm/VecVariable.h @@ -48,8 +48,8 @@ public: { } - template - VTKM_EXEC_CONT VecVariable(const vtkm::VecVariable& src) + template + VTKM_EXEC_CONT VecVariable(const SrcVecType& src) : NumComponents(src.GetNumberOfComponents()) { VTKM_ASSERT(this->NumComponents <= MaxSize); @@ -59,17 +59,6 @@ public: } } - template - VTKM_EXEC_CONT VecVariable(const vtkm::Vec& src) - : NumComponents(SrcSize) - { - VTKM_ASSERT(this->NumComponents <= MaxSize); - for (vtkm::IdComponent index = 0; index < this->NumComponents; index++) - { - this->Data[index] = src[index]; - } - } - VTKM_EXEC_CONT vtkm::IdComponent GetNumberOfComponents() const { return this->NumComponents; } diff --git a/vtkm/exec/ParametricCoordinates.h b/vtkm/exec/ParametricCoordinates.h index 7946faa47..e1e683e26 100644 --- a/vtkm/exec/ParametricCoordinates.h +++ b/vtkm/exec/ParametricCoordinates.h @@ -28,6 +28,7 @@ #include #include #include +#include #include namespace vtkm @@ -586,7 +587,77 @@ ParametricCoordinatesToWorldCoordinates(const WorldCoordVector& pointWCoords, } //----------------------------------------------------------------------------- +template +static inline VTKM_EXEC typename WorldCoordVector::ComponentType +WorldCoordinatesToParametricCoordinates(const WorldCoordVector&, + const typename WorldCoordVector::ComponentType&, + vtkm::CellShapeTagEmpty, + bool& success, + const vtkm::exec::FunctorBase& worklet) +{ + worklet.RaiseError("Attempted to find point coordinates in empty cell."); + success = false; + return typename WorldCoordVector::ComponentType(); +} +template +static inline VTKM_EXEC typename WorldCoordVector::ComponentType +WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, + const typename WorldCoordVector::ComponentType&, + vtkm::CellShapeTagVertex, + bool& success, + const vtkm::exec::FunctorBase& vtkmNotUsed(worklet)) +{ + (void)pointWCoords; // Silence compiler warnings. + VTKM_ASSERT(pointWCoords.GetNumberOfComponents() == 1); + success = true; + return typename WorldCoordVector::ComponentType(0, 0, 0); +} + +template +static inline VTKM_EXEC typename WorldCoordVector::ComponentType +WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, + const typename WorldCoordVector::ComponentType& wcoords, + vtkm::CellShapeTagLine, + bool& success, + const vtkm::exec::FunctorBase& vtkmNotUsed(worklet)) +{ + VTKM_ASSERT(pointWCoords.GetNumberOfComponents() == 2); + success = true; + + // Because this is a line, there is only one valid parametric coordinate. Let + // vec be the vector from the first point to the second point + // (pointWCoords[1] - pointWCoords[0]), which is the direction of the line. + // dot(vec,wcoords-pointWCoords[0])/mag(vec) is the orthoginal projection of + // wcoords on the line and represents the distance between the orthoginal + // projection and pointWCoords[0]. The parametric coordinate is the fraction + // of this over the length of the segment, which is mag(vec). Thus, the + // parametric coordinate is dot(vec,wcoords-pointWCoords[0])/mag(vec)^2. + + using Vector3 = typename WorldCoordVector::ComponentType; + using T = typename Vector3::ComponentType; + + Vector3 vec = pointWCoords[1] - pointWCoords[0]; + T numerator = vtkm::dot(vec, wcoords - pointWCoords[0]); + T denominator = vtkm::MagnitudeSquared(vec); + + return Vector3(numerator / denominator, 0, 0); +} + +template +static inline VTKM_EXEC typename WorldCoordVector::ComponentType +WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, + const typename WorldCoordVector::ComponentType& wcoords, + vtkm::CellShapeTagTriangle, + bool& success, + const vtkm::exec::FunctorBase&) +{ + success = true; + vtkm::exec::internal::FastVec local(pointWCoords); + return vtkm::exec::internal::ReverseInterpolateTriangle(local.Get(), wcoords); +} + +//----------------------------------------------------------------------------- namespace detail { @@ -655,160 +726,37 @@ public: } }; -template -class JacobianFunctor3DCell -{ - using T = typename WorldCoordVector::ComponentType::ComponentType; - using Vector3 = vtkm::Vec; - using Matrix3x3 = vtkm::Matrix; - - const WorldCoordVector* PointWCoords; - -public: - VTKM_EXEC - JacobianFunctor3DCell(const WorldCoordVector* pointWCoords) - : PointWCoords(pointWCoords) - { - } - - VTKM_EXEC - Matrix3x3 operator()(const Vector3& pcoords) const - { - Matrix3x3 jacobian; - vtkm::exec::JacobianFor3DCell(*this->PointWCoords, pcoords, jacobian, CellShapeTag()); - return jacobian; - } -}; - -template -class CoordinatesFunctor3DCell -{ - using T = typename WorldCoordVector::ComponentType::ComponentType; - using Vector3 = vtkm::Vec; - - const WorldCoordVector* PointWCoords; - const vtkm::exec::FunctorBase* Worklet; - -public: - VTKM_EXEC - CoordinatesFunctor3DCell(const WorldCoordVector* pointWCoords, - const vtkm::exec::FunctorBase* worklet) - : PointWCoords(pointWCoords) - , Worklet(worklet) - { - } - - VTKM_EXEC - Vector3 operator()(Vector3 pcoords) const - { - return vtkm::exec::ParametricCoordinatesToWorldCoordinates( - *this->PointWCoords, pcoords, CellShapeTag(), *this->Worklet); - } -}; - -template +template static inline VTKM_EXEC typename WorldCoordVector::ComponentType -WorldCoordinatesToParametricCoordinates3D(const WorldCoordVector& pointWCoords, - const typename WorldCoordVector::ComponentType& wcoords, - CellShapeTag, - bool& success, - const vtkm::exec::FunctorBase& worklet) +WorldCoordinatesToParametricCoordinatesQuad(const WorldCoordVector& pointWCoords, + const typename WorldCoordVector::ComponentType& wcoords, + bool& success, + const vtkm::exec::FunctorBase& worklet) { - auto result = vtkm::NewtonsMethod( - JacobianFunctor3DCell(&pointWCoords), - CoordinatesFunctor3DCell(&pointWCoords, &worklet), - wcoords, - typename WorldCoordVector::ComponentType(0.5f, 0.5f, 0.5f)); - success = result.Valid; - return result.Solution; -} + using T = typename WorldCoordVector::ComponentType::ComponentType; + using Vector2 = vtkm::Vec; + using Vector3 = vtkm::Vec; + // We have an underdetermined system in 3D, so create a 2D space in the + // plane that the polygon sits. + vtkm::exec::internal::Space2D space(pointWCoords[0], pointWCoords[1], pointWCoords[3]); + + auto result = vtkm::NewtonsMethod( + JacobianFunctorQuad(&pointWCoords, &space), + CoordinatesFunctorQuad( + &pointWCoords, &space, &worklet), + space.ConvertCoordToSpace(wcoords), + Vector2(0.5f, 0.5f)); + + success = result.Valid; + return Vector3(result.Solution[0], result.Solution[1], 0); +} } // namespace detail -//----------------------------------------------------------------------------- -template -static inline VTKM_EXEC typename WorldCoordVector::ComponentType -WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, - const typename WorldCoordVector::ComponentType& wcoords, - vtkm::CellShapeTagGeneric shape, - bool& success, - const vtkm::exec::FunctorBase& worklet) -{ - typename WorldCoordVector::ComponentType result; - switch (shape.Id) - { - vtkmGenericCellShapeMacro(result = WorldCoordinatesToParametricCoordinates( - pointWCoords, wcoords, CellShapeTag(), success, worklet)); - default: - success = false; - worklet.RaiseError("Unknown cell shape sent to world 2 parametric."); - return typename WorldCoordVector::ComponentType(); - } - - return result; -} - -template -static inline VTKM_EXEC typename WorldCoordVector::ComponentType -WorldCoordinatesToParametricCoordinates(const WorldCoordVector&, - const typename WorldCoordVector::ComponentType&, - vtkm::CellShapeTagEmpty, - bool& success, - const vtkm::exec::FunctorBase& worklet) -{ - worklet.RaiseError("Attempted to find point coordinates in empty cell."); - success = false; - return typename WorldCoordVector::ComponentType(); -} - -template -static inline VTKM_EXEC typename WorldCoordVector::ComponentType -WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, - const typename WorldCoordVector::ComponentType&, - vtkm::CellShapeTagVertex, - bool& success, - const vtkm::exec::FunctorBase& vtkmNotUsed(worklet)) -{ - (void)pointWCoords; // Silence compiler warnings. - VTKM_ASSERT(pointWCoords.GetNumberOfComponents() == 1); - success = true; - return typename WorldCoordVector::ComponentType(0, 0, 0); -} - -template -static inline VTKM_EXEC typename WorldCoordVector::ComponentType -WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, - const typename WorldCoordVector::ComponentType& wcoords, - vtkm::CellShapeTagLine, - bool& success, - const vtkm::exec::FunctorBase& vtkmNotUsed(worklet)) -{ - VTKM_ASSERT(pointWCoords.GetNumberOfComponents() == 2); - success = true; - - // Because this is a line, there is only one valid parametric coordinate. Let - // vec be the vector from the first point to the second point - // (pointWCoords[1] - pointWCoords[0]), which is the direction of the line. - // dot(vec,wcoords-pointWCoords[0])/mag(vec) is the orthoginal projection of - // wcoords on the line and represents the distance between the orthoginal - // projection and pointWCoords[0]. The parametric coordinate is the fraction - // of this over the length of the segment, which is mag(vec). Thus, the - // parametric coordinate is dot(vec,wcoords-pointWCoords[0])/mag(vec)^2. - - using Vector3 = typename WorldCoordVector::ComponentType; - using T = typename Vector3::ComponentType; - - Vector3 vec = pointWCoords[1] - pointWCoords[0]; - T numerator = vtkm::dot(vec, wcoords - pointWCoords[0]); - T denominator = vtkm::MagnitudeSquared(vec); - - return Vector3(numerator / denominator, 0, 0); -} - static inline VTKM_EXEC vtkm::Vec WorldCoordinatesToParametricCoordinates( - const vtkm::VecAxisAlignedPointCoordinates<1>& pointWCoords, + const vtkm::VecAxisAlignedPointCoordinates<2>& pointWCoords, const vtkm::Vec& wcoords, - vtkm::CellShapeTagLine, + vtkm::CellShapeTagQuad, bool& success, const FunctorBase&) { @@ -820,14 +768,16 @@ template static inline VTKM_EXEC typename WorldCoordVector::ComponentType WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, const typename WorldCoordVector::ComponentType& wcoords, - vtkm::CellShapeTagTriangle, + vtkm::CellShapeTagQuad, bool& success, - const vtkm::exec::FunctorBase& vtkmNotUsed(worklet)) + const vtkm::exec::FunctorBase& worklet) { - success = true; - return vtkm::exec::internal::ReverseInterpolateTriangle(pointWCoords, wcoords); + vtkm::exec::internal::FastVec local(pointWCoords); + return detail::WorldCoordinatesToParametricCoordinatesQuad( + local.Get(), wcoords, success, worklet); } +//----------------------------------------------------------------------------- template static inline VTKM_EXEC typename WorldCoordVector::ComponentType WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, @@ -951,57 +901,16 @@ WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, triangleWCoords, trianglePCoords, vtkm::CellShapeTagTriangle(), worklet); } -template -static inline VTKM_EXEC typename WorldCoordVector::ComponentType -WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, - const typename WorldCoordVector::ComponentType& wcoords, - vtkm::CellShapeTagQuad, - bool& success, - const vtkm::exec::FunctorBase& worklet) +//----------------------------------------------------------------------------- +namespace detail { - VTKM_ASSERT(pointWCoords.GetNumberOfComponents() == 4); - - using T = typename WorldCoordVector::ComponentType::ComponentType; - using Vector2 = vtkm::Vec; - using Vector3 = vtkm::Vec; - - // We have an underdetermined system in 3D, so create a 2D space in the - // plane that the polygon sits. - vtkm::exec::internal::Space2D space(pointWCoords[0], pointWCoords[1], pointWCoords[3]); - - auto result = vtkm::NewtonsMethod( - detail::JacobianFunctorQuad(&pointWCoords, &space), - detail::CoordinatesFunctorQuad( - &pointWCoords, &space, &worklet), - space.ConvertCoordToSpace(wcoords), - Vector2(0.5f, 0.5f)); - - success = result.Valid; - return Vector3(result.Solution[0], result.Solution[1], 0); -} - -static inline VTKM_EXEC vtkm::Vec WorldCoordinatesToParametricCoordinates( - const vtkm::VecAxisAlignedPointCoordinates<2>& pointWCoords, - const vtkm::Vec& wcoords, - vtkm::CellShapeTagQuad, - bool& success, - const FunctorBase&) -{ - success = true; - return (wcoords - pointWCoords.GetOrigin()) / pointWCoords.GetSpacing(); -} template static inline VTKM_EXEC typename WorldCoordVector::ComponentType -WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, - const typename WorldCoordVector::ComponentType& wcoords, - vtkm::CellShapeTagTetra, - bool& success, - const vtkm::exec::FunctorBase& vtkmNotUsed(worklet)) +WorldCoordinatesToParametricCoordinatesTetra( + const WorldCoordVector& pointWCoords, + const typename WorldCoordVector::ComponentType& wcoords) { - VTKM_ASSERT(pointWCoords.GetNumberOfComponents() == 4); - success = true; - // We solve the world to parametric coordinates problem for tetrahedra // similarly to that for triangles. Before understanding this code, you // should understand the triangle code (in ReverseInterpolateTriangle in @@ -1025,16 +934,13 @@ WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, // d = dot((wcoords - p0), planeNormal)/dot((p1-p0), planeNormal) // - using Vector3 = typename WorldCoordVector::ComponentType; + const auto vec0 = pointWCoords[1] - pointWCoords[0]; + const auto vec1 = pointWCoords[2] - pointWCoords[0]; + const auto vec2 = pointWCoords[3] - pointWCoords[0]; + const auto coordVec = wcoords - pointWCoords[0]; - Vector3 pcoords; - - const Vector3 vec0 = pointWCoords[1] - pointWCoords[0]; - const Vector3 vec1 = pointWCoords[2] - pointWCoords[0]; - const Vector3 vec2 = pointWCoords[3] - pointWCoords[0]; - const Vector3 coordVec = wcoords - pointWCoords[0]; - - Vector3 planeNormal = vtkm::Cross(vec1, vec2); + typename WorldCoordVector::ComponentType pcoords; + auto planeNormal = vtkm::Cross(vec1, vec2); pcoords[0] = vtkm::dot(coordVec, planeNormal) / vtkm::dot(vec0, planeNormal); planeNormal = vtkm::Cross(vec0, vec2); @@ -1045,21 +951,94 @@ WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, return pcoords; } +} // detail template static inline VTKM_EXEC typename WorldCoordVector::ComponentType WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, const typename WorldCoordVector::ComponentType& wcoords, - vtkm::CellShapeTagHexahedron, + vtkm::CellShapeTagTetra, bool& success, - const vtkm::exec::FunctorBase& worklet) + const vtkm::exec::FunctorBase&) { - VTKM_ASSERT(pointWCoords.GetNumberOfComponents() == 8); - - return detail::WorldCoordinatesToParametricCoordinates3D( - pointWCoords, wcoords, vtkm::CellShapeTagHexahedron(), success, worklet); + success = true; + vtkm::exec::internal::FastVec local(pointWCoords); + return detail::WorldCoordinatesToParametricCoordinatesTetra(local.Get(), wcoords); } +//----------------------------------------------------------------------------- +namespace detail +{ + +template +class JacobianFunctor3DCell +{ + using T = typename WorldCoordVector::ComponentType::ComponentType; + using Vector3 = vtkm::Vec; + using Matrix3x3 = vtkm::Matrix; + + const WorldCoordVector* PointWCoords; + +public: + VTKM_EXEC + JacobianFunctor3DCell(const WorldCoordVector* pointWCoords) + : PointWCoords(pointWCoords) + { + } + + VTKM_EXEC + Matrix3x3 operator()(const Vector3& pcoords) const + { + Matrix3x3 jacobian; + vtkm::exec::JacobianFor3DCell(*this->PointWCoords, pcoords, jacobian, CellShapeTag()); + return jacobian; + } +}; + +template +class CoordinatesFunctor3DCell +{ + using T = typename WorldCoordVector::ComponentType::ComponentType; + using Vector3 = vtkm::Vec; + + const WorldCoordVector* PointWCoords; + const vtkm::exec::FunctorBase* Worklet; + +public: + VTKM_EXEC + CoordinatesFunctor3DCell(const WorldCoordVector* pointWCoords, + const vtkm::exec::FunctorBase* worklet) + : PointWCoords(pointWCoords) + , Worklet(worklet) + { + } + + VTKM_EXEC + Vector3 operator()(Vector3 pcoords) const + { + return vtkm::exec::ParametricCoordinatesToWorldCoordinates( + *this->PointWCoords, pcoords, CellShapeTag(), *this->Worklet); + } +}; + +template +static inline VTKM_EXEC typename WorldCoordVector::ComponentType +WorldCoordinatesToParametricCoordinates3D(const WorldCoordVector& pointWCoords, + const typename WorldCoordVector::ComponentType& wcoords, + CellShapeTag, + bool& success, + const vtkm::exec::FunctorBase& worklet) +{ + auto result = vtkm::NewtonsMethod( + JacobianFunctor3DCell(&pointWCoords), + CoordinatesFunctor3DCell(&pointWCoords, &worklet), + wcoords, + typename WorldCoordVector::ComponentType(0.5f, 0.5f, 0.5f)); + success = result.Valid; + return result.Solution; +} +} // detail + static inline VTKM_EXEC vtkm::Vec WorldCoordinatesToParametricCoordinates( const vtkm::VecAxisAlignedPointCoordinates<3>& pointWCoords, const vtkm::Vec& wcoords, @@ -1071,6 +1050,19 @@ static inline VTKM_EXEC vtkm::Vec WorldCoordinatesToParam return (wcoords - pointWCoords.GetOrigin()) / pointWCoords.GetSpacing(); } +template +static inline VTKM_EXEC typename WorldCoordVector::ComponentType +WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, + const typename WorldCoordVector::ComponentType& wcoords, + vtkm::CellShapeTagHexahedron, + bool& success, + const vtkm::exec::FunctorBase& worklet) +{ + vtkm::exec::internal::FastVec local(pointWCoords); + return detail::WorldCoordinatesToParametricCoordinates3D( + local.Get(), wcoords, vtkm::CellShapeTagHexahedron(), success, worklet); +} + template static inline VTKM_EXEC typename WorldCoordVector::ComponentType WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, @@ -1079,10 +1071,9 @@ WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, bool& success, const vtkm::exec::FunctorBase& worklet) { - VTKM_ASSERT(pointWCoords.GetNumberOfComponents() == 6); - + vtkm::exec::internal::FastVec local(pointWCoords); return detail::WorldCoordinatesToParametricCoordinates3D( - pointWCoords, wcoords, vtkm::CellShapeTagWedge(), success, worklet); + local.Get(), wcoords, vtkm::CellShapeTagWedge(), success, worklet); } template @@ -1093,10 +1084,32 @@ WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, bool& success, const vtkm::exec::FunctorBase& worklet) { - VTKM_ASSERT(pointWCoords.GetNumberOfComponents() == 5); - + vtkm::exec::internal::FastVec local(pointWCoords); return detail::WorldCoordinatesToParametricCoordinates3D( - pointWCoords, wcoords, vtkm::CellShapeTagPyramid(), success, worklet); + local.Get(), wcoords, vtkm::CellShapeTagPyramid(), success, worklet); +} + +//----------------------------------------------------------------------------- +template +static inline VTKM_EXEC typename WorldCoordVector::ComponentType +WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords, + const typename WorldCoordVector::ComponentType& wcoords, + vtkm::CellShapeTagGeneric shape, + bool& success, + const vtkm::exec::FunctorBase& worklet) +{ + typename WorldCoordVector::ComponentType result; + switch (shape.Id) + { + vtkmGenericCellShapeMacro(result = WorldCoordinatesToParametricCoordinates( + pointWCoords, wcoords, CellShapeTag(), success, worklet)); + default: + success = false; + worklet.RaiseError("Unknown cell shape sent to world 2 parametric."); + return typename WorldCoordVector::ComponentType(); + } + + return result; } } } // namespace vtkm::exec diff --git a/vtkm/exec/internal/CMakeLists.txt b/vtkm/exec/internal/CMakeLists.txt index 31eacb3cf..05cac31ef 100644 --- a/vtkm/exec/internal/CMakeLists.txt +++ b/vtkm/exec/internal/CMakeLists.txt @@ -20,6 +20,7 @@ set(headers ErrorMessageBuffer.h + FastVec.h ReduceByKeyLookup.h TaskSingular.h WorkletInvokeFunctorDetail.h diff --git a/vtkm/exec/internal/FastVec.h b/vtkm/exec/internal/FastVec.h new file mode 100644 index 000000000..7519ab78c --- /dev/null +++ b/vtkm/exec/internal/FastVec.h @@ -0,0 +1,96 @@ +//============================================================================ +// 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 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2015 UT-Battelle, LLC. +// Copyright 2015 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_internal_FastVec_h +#define vtk_m_exec_internal_FastVec_h + +#include +#include + +namespace vtkm +{ +namespace exec +{ +namespace internal +{ + +/// Use this class to convert Vecs of any type to an efficient stack based Vec +/// type. The template parameters are the input Vec type and the maximum +/// number of components it may have. Specializations exist to optimize +/// the copy and stack usage away for already efficient types. +/// This class is useful when several accesses will be performed on +/// potentially inefficient Vec types such as VecFromPortalPermute. +/// +template +class FastVec +{ +public: + using Type = vtkm::VecVariable; + + explicit VTKM_EXEC FastVec(const VecType& vec) + : Vec(vec) + { + } + + VTKM_EXEC const Type& Get() const { return this->Vec; } + +private: + Type Vec; +}; + +template +class FastVec, MaxSize> +{ +public: + using Type = vtkm::Vec; + + explicit VTKM_EXEC FastVec(const Type& vec) + : Vec(vec) + { + VTKM_ASSERT(vec.GetNumberOfComponents() <= MaxSize); + } + + VTKM_EXEC const Type& Get() const { return this->Vec; } + +private: + const Type& Vec; +}; + +template +class FastVec, MaxSize2> +{ +public: + using Type = vtkm::VecVariable; + + explicit VTKM_EXEC FastVec(const Type& vec) + : Vec(vec) + { + VTKM_ASSERT(vec.GetNumberOfComponents() <= MaxSize2); + } + + VTKM_EXEC const Type& Get() const { return this->Vec; } + +private: + const Type& Vec; +}; +} +} +} // vtkm::exec::internal + +#endif // vtk_m_exec_internal_FastVec_h