mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-19 18:45:43 +00:00
e28309f09b
If a global static array is declared with VTKM_EXEC_CONSTANT and the code is compiled by nvcc (for multibackend code) then the array is only accesible on the GPU. If for some reason a worklet fails on the cuda backend and it is re-executed on any of the CPU backends, it will continue to fail. We couldn't find a simple way to declare the array once and have it available on both CPU and GPU. The approach we are using here is to declare the arrays as static inside some "Get" function which is marked as VTKM_EXEC_CONT.
805 lines
27 KiB
C++
805 lines
27 KiB
C++
//============================================================================
|
|
// 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_rendering_raytracing_MeshConnectivityStructures_h
|
|
#define vtk_m_rendering_raytracing_MeshConnectivityStructures_h
|
|
#include <sstream>
|
|
#include <vtkm/CellShape.h>
|
|
#include <vtkm/cont/ErrorBadValue.h>
|
|
#include <vtkm/rendering/raytracing/BoundingVolumeHierarchy.h>
|
|
#include <vtkm/rendering/raytracing/Logger.h>
|
|
#include <vtkm/rendering/raytracing/MeshConnectivityBuilder.h>
|
|
#include <vtkm/rendering/raytracing/Ray.h>
|
|
#include <vtkm/rendering/raytracing/TriangleIntersector.h>
|
|
namespace vtkm
|
|
{
|
|
namespace rendering
|
|
{
|
|
namespace raytracing
|
|
{
|
|
|
|
// MeshConnectivityStrucutures:
|
|
// Policy classes for different types of meshes. Each implemented class
|
|
// Must implement GetConnetingCell( indexOfCurrentCell, face) that returns
|
|
// the index of the cell that connects to the "face" of the current cell.
|
|
// Each policy should have a copy constructor to facilitate clean passing
|
|
// to worklets (i.e., initialize execution portals if needed).
|
|
|
|
//
|
|
// Primary template for MeshConnExec Object
|
|
//
|
|
|
|
template <typename MeshType, typename Device>
|
|
class MeshConnExec
|
|
{
|
|
};
|
|
|
|
|
|
class UnstructuredMeshConn
|
|
{
|
|
public:
|
|
typedef vtkm::cont::ArrayHandle<vtkm::Id> IdHandle;
|
|
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
|
typedef vtkm::cont::ArrayHandle<vtkm::UInt8> UCharHandle;
|
|
// Control Environment Handles
|
|
// FaceConn
|
|
IdHandle FaceConnectivity;
|
|
IdHandle FaceOffsets;
|
|
//Cell Set
|
|
IdHandle CellConn;
|
|
IdHandle CellOffsets;
|
|
UCharHandle Shapes;
|
|
// Mesh Boundry
|
|
Id4Handle ExternalTriangles;
|
|
LinearBVH Bvh;
|
|
|
|
// Restrict the coordinates to the types that be for unstructured meshes
|
|
DynamicArrayHandleExplicitCoordinateSystem Coordinates;
|
|
vtkm::Bounds CoordinateBounds;
|
|
vtkm::cont::CellSetExplicit<> Cellset;
|
|
vtkm::cont::CoordinateSystem Coords;
|
|
|
|
protected:
|
|
bool IsConstructed;
|
|
|
|
private:
|
|
VTKM_CONT
|
|
UnstructuredMeshConn(){};
|
|
|
|
public:
|
|
VTKM_CONT
|
|
UnstructuredMeshConn(const vtkm::cont::DynamicCellSet& cellset,
|
|
const vtkm::cont::CoordinateSystem& coords)
|
|
: IsConstructed(false)
|
|
{
|
|
Coords = coords;
|
|
vtkm::cont::DynamicArrayHandleCoordinateSystem dynamicCoordsHandle = coords.GetData();
|
|
|
|
//
|
|
// Reset the type lists to only contain the coordinate systemss of an
|
|
// unstructured cell set.
|
|
//
|
|
|
|
Coordinates = dynamicCoordsHandle.ResetTypeList(ExplicitCoordinatesType())
|
|
.ResetStorageList(StorageListTagExplicitCoordinateSystem());
|
|
|
|
if (!cellset.IsSameType(vtkm::cont::CellSetExplicit<>()))
|
|
{
|
|
throw vtkm::cont::ErrorBadValue(
|
|
"Unstructured Mesh Connecitity Error: not an explicit cell set!");
|
|
}
|
|
|
|
Cellset = cellset.Cast<vtkm::cont::CellSetExplicit<>>();
|
|
|
|
|
|
|
|
//
|
|
// Grab the cell arrays
|
|
//
|
|
CellConn =
|
|
Cellset.GetConnectivityArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
|
|
CellOffsets =
|
|
Cellset.GetIndexOffsetArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
|
|
Shapes =
|
|
Cellset.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <typename T>
|
|
VTKM_CONT UnstructuredMeshConn(const T& other)
|
|
: FaceConnectivity(other.FaceConnectivity)
|
|
, FaceOffsets(other.FaceOffsets)
|
|
, CellConn(other.CellConn)
|
|
, CellOffsets(other.CellOffsets)
|
|
, Shapes(other.Shapes)
|
|
, ExternalTriangles(other.ExternalTriangles)
|
|
, Bvh(other.Bvh)
|
|
, Coordinates(other.Coordinates)
|
|
, CoordinateBounds(other.CoordinateBounds)
|
|
, Cellset(other.Cellset)
|
|
, Coords(other.Coords)
|
|
, IsConstructed(other.IsConstructed)
|
|
{
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
template <typename Device>
|
|
VTKM_CONT void Construct(Device)
|
|
{
|
|
Logger* logger = Logger::GetInstance();
|
|
logger->OpenLogEntry("mesh_conn_construction");
|
|
vtkm::cont::Timer<Device> timer;
|
|
if (!IsConstructed)
|
|
{
|
|
|
|
CoordinateBounds = Coords.GetBounds();
|
|
MeshConnectivityBuilder<Device> connBuilder;
|
|
|
|
//
|
|
// Build the face-to-face connectivity
|
|
//
|
|
connBuilder.BuildConnectivity(Cellset, Coordinates, CoordinateBounds);
|
|
|
|
//
|
|
// Initialize all of the array handles
|
|
//
|
|
FaceConnectivity = connBuilder.GetFaceConnectivity();
|
|
FaceOffsets = connBuilder.GetFaceOffsets();
|
|
ExternalTriangles = connBuilder.GetExternalTriangles();
|
|
|
|
//
|
|
// Build BVH on external triangles
|
|
//
|
|
Bvh.SetData(Coords.GetData(), ExternalTriangles, Coords.GetBounds());
|
|
Bvh.ConstructOnDevice(Device());
|
|
IsConstructed = true;
|
|
}
|
|
|
|
vtkm::Float64 time = timer.GetElapsedTime();
|
|
logger->CloseLogEntry(time);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
template <typename T, typename Device>
|
|
VTKM_CONT void FindEntry(Ray<T>& rays, Device)
|
|
{
|
|
if (!IsConstructed)
|
|
{
|
|
throw vtkm::cont::ErrorBadValue(
|
|
"Unstructured Mesh Connecitity Error: FindEntry called before Construct");
|
|
}
|
|
TriangleIntersector<Device, TriLeafIntersector<WaterTight<T>>> intersector;
|
|
bool getCellIndex = true;
|
|
intersector.runHitOnly(rays, Bvh, Coordinates, getCellIndex);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
vtkm::Id GetNumberOfCells() { return this->Shapes.GetPortalConstControl().GetNumberOfValues(); }
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Control Environment Methods
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
Id4Handle GetExternalTriangles() { return ExternalTriangles; }
|
|
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
DynamicArrayHandleExplicitCoordinateSystem GetCoordinates() { return Coordinates; }
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <typename Device>
|
|
VTKM_CONT vtkm::Bounds GetCoordinateBounds(Device)
|
|
{
|
|
CoordinateBounds = Coords.GetBounds();
|
|
return CoordinateBounds;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
bool GetIsConstructed() { return IsConstructed; }
|
|
}; //Unstructure mesh conn
|
|
|
|
template <typename Device>
|
|
class MeshConnExec<UnstructuredMeshConn, Device>
|
|
{
|
|
protected:
|
|
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdHandle;
|
|
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
|
typedef typename vtkm::cont::ArrayHandle<vtkm::UInt8> UCharHandle;
|
|
typedef typename IdHandle::ExecutionTypes<Device>::PortalConst IdConstPortal;
|
|
typedef typename UCharHandle::ExecutionTypes<Device>::PortalConst UCharConstPortal;
|
|
|
|
// Constant Portals for the execution Environment
|
|
//FaceConn
|
|
IdConstPortal FaceConnPortal;
|
|
IdConstPortal FaceOffsetsPortal;
|
|
//Cell Set
|
|
IdConstPortal CellConnPortal;
|
|
IdConstPortal CellOffsetsPortal;
|
|
UCharConstPortal ShapesPortal;
|
|
|
|
private:
|
|
VTKM_CONT
|
|
MeshConnExec(){};
|
|
|
|
public:
|
|
VTKM_CONT
|
|
MeshConnExec(UnstructuredMeshConn& conn)
|
|
: FaceConnPortal(conn.FaceConnectivity.PrepareForInput(Device()))
|
|
, FaceOffsetsPortal(conn.FaceOffsets.PrepareForInput(Device()))
|
|
, CellConnPortal(conn.CellConn.PrepareForInput(Device()))
|
|
, CellOffsetsPortal(conn.CellOffsets.PrepareForInput(Device()))
|
|
, ShapesPortal(conn.Shapes.PrepareForInput(Device()))
|
|
{
|
|
if (!conn.GetIsConstructed())
|
|
{
|
|
throw vtkm::cont::ErrorBadValue(
|
|
"Unstructured Mesh Connecitity Error: GetExecObj called before Construct");
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <typename T>
|
|
VTKM_CONT MeshConnExec(const T& other)
|
|
: FaceConnPortal(other.FaceConnPortal)
|
|
, FaceOffsetsPortal(other.FaceConnPortal)
|
|
, CellConnPortal(other.CellConnPortal)
|
|
, CellOffsetsPortal(other.CellOffsetsPortal)
|
|
, ShapesPortal(other.ShapesPortal)
|
|
{
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
// Execution Environment Methods
|
|
//----------------------------------------------------------------------------
|
|
VTKM_EXEC
|
|
inline vtkm::Id GetConnectingCell(const vtkm::Id& cellId, const vtkm::Id& face) const
|
|
{
|
|
BOUNDS_CHECK(FaceOffsetsPortal, cellId);
|
|
vtkm::Id cellStartIndex = FaceOffsetsPortal.Get(cellId);
|
|
BOUNDS_CHECK(FaceConnPortal, cellStartIndex + face);
|
|
return FaceConnPortal.Get(cellStartIndex + face);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
VTKM_EXEC
|
|
inline vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8], const vtkm::Id& cellId) const
|
|
{
|
|
const vtkm::Int32 shapeId = static_cast<vtkm::Int32>(ShapesPortal.Get(cellId));
|
|
const vtkm::Int32 numIndices =
|
|
CellTables::Get().FaceLookUp[CellTables::Get().CellTypeLookUp[shapeId]][2];
|
|
BOUNDS_CHECK(CellOffsetsPortal, cellId);
|
|
const vtkm::Id cellOffset = CellOffsetsPortal.Get(cellId);
|
|
|
|
for (vtkm::Int32 i = 0; i < numIndices; ++i)
|
|
{
|
|
BOUNDS_CHECK(CellConnPortal, cellOffset + i);
|
|
cellIndices[i] = CellConnPortal.Get(cellOffset + i);
|
|
}
|
|
return numIndices;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
VTKM_EXEC
|
|
inline vtkm::UInt8 GetCellShape(const vtkm::Id& cellId) const
|
|
{
|
|
BOUNDS_CHECK(ShapesPortal, cellId)
|
|
return ShapesPortal.Get(cellId);
|
|
}
|
|
|
|
}; //Unstructure mesh conn exec
|
|
|
|
|
|
// Specialized version for unstructured meshes consisting of
|
|
// a single type of cell.
|
|
class UnstructuredMeshConnSingleType
|
|
{
|
|
public:
|
|
typedef vtkm::cont::ArrayHandle<vtkm::Id> IdHandle;
|
|
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
|
typedef vtkm::cont::ArrayHandleCounting<vtkm::Id> CountingHandle;
|
|
typedef vtkm::cont::ArrayHandleConstant<vtkm::UInt8> ShapesHandle;
|
|
typedef vtkm::cont::ArrayHandleConstant<vtkm::IdComponent> NumIndicesHandle;
|
|
// Control Environment Handles
|
|
IdHandle FaceConnectivity;
|
|
CountingHandle CellOffsets;
|
|
IdHandle CellConnectivity;
|
|
// Mesh Boundry
|
|
LinearBVH Bvh;
|
|
Id4Handle ExternalTriangles;
|
|
// Restrict the coordinates to the types that be for unstructured meshes
|
|
DynamicArrayHandleExplicitCoordinateSystem Coordinates;
|
|
vtkm::Bounds CoordinateBounds;
|
|
vtkm::cont::CoordinateSystem Coords;
|
|
vtkm::cont::CellSetSingleType<> Cellset;
|
|
|
|
vtkm::Int32 ShapeId;
|
|
vtkm::Int32 NumIndices;
|
|
vtkm::Int32 NumFaces;
|
|
|
|
protected:
|
|
bool IsConstructed;
|
|
|
|
private:
|
|
VTKM_CONT
|
|
UnstructuredMeshConnSingleType() {}
|
|
|
|
public:
|
|
VTKM_CONT
|
|
UnstructuredMeshConnSingleType(const vtkm::cont::DynamicCellSet& cellset,
|
|
const vtkm::cont::CoordinateSystem& coords)
|
|
: IsConstructed(false)
|
|
{
|
|
|
|
Coords = coords;
|
|
vtkm::cont::DynamicArrayHandleCoordinateSystem dynamicCoordsHandle = coords.GetData();
|
|
|
|
//
|
|
// Reset the type lists to only contain the coordinate systemss of an
|
|
// unstructured cell set.
|
|
//
|
|
|
|
Coordinates = dynamicCoordsHandle.ResetTypeList(ExplicitCoordinatesType())
|
|
.ResetStorageList(StorageListTagExplicitCoordinateSystem());
|
|
|
|
if (!cellset.IsSameType(vtkm::cont::CellSetSingleType<>()))
|
|
{
|
|
throw vtkm::cont::ErrorBadValue(
|
|
"Unstructured Mesh Connecitity Single type Error: not an single type cell set!");
|
|
}
|
|
|
|
Cellset = cellset.Cast<vtkm::cont::CellSetSingleType<>>();
|
|
|
|
CellConnectivity =
|
|
Cellset.GetConnectivityArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
|
|
vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapes =
|
|
Cellset.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
|
|
|
|
ShapeId = shapes.GetPortalConstControl().Get(0);
|
|
NumIndices = CellTables::Get().FaceLookUp[CellTables::Get().CellTypeLookUp[ShapeId]][2];
|
|
|
|
if (NumIndices == 0)
|
|
{
|
|
std::stringstream message;
|
|
message << "Unstructured Mesh Connecitity Single type Error: unsupported cell type: ";
|
|
message << ShapeId;
|
|
throw vtkm::cont::ErrorBadValue(message.str());
|
|
}
|
|
vtkm::Id start = 0;
|
|
NumFaces = CellTables::Get().FaceLookUp[CellTables::Get().CellTypeLookUp[ShapeId]][1];
|
|
vtkm::Id numCells = CellConnectivity.GetPortalConstControl().GetNumberOfValues();
|
|
CellOffsets = vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(start, NumIndices, numCells);
|
|
|
|
//
|
|
// Initialize all of the array portals
|
|
//
|
|
}
|
|
template <typename T>
|
|
VTKM_CONT UnstructuredMeshConnSingleType(const T& other)
|
|
: FaceConnectivity(other.FaceConnectivity)
|
|
, CellOffsets(other.CellOffsets)
|
|
, CellConnectivity(other.CellConnectivity)
|
|
, Bvh(other.Bvh)
|
|
, ExternalTriangles(other.ExternalTriangles)
|
|
, Coordinates(other.Coordinates)
|
|
, CoordinateBounds(other.CoordinateBounds)
|
|
, Coords(other.coords)
|
|
, Cellset(other.Cellset)
|
|
, ShapeId(other.ShapeId)
|
|
, NumIndices(other.NumIndices)
|
|
, NumFaces(other.NumFaces)
|
|
, IsConstructed(other.IsConstructed)
|
|
{
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
template <typename Device>
|
|
VTKM_CONT void Construct(Device)
|
|
{
|
|
Logger* logger = Logger::GetInstance();
|
|
logger->OpenLogEntry("mesh_conn_construction");
|
|
vtkm::cont::Timer<Device> timer;
|
|
|
|
if (!IsConstructed)
|
|
{
|
|
CoordinateBounds = Coords.GetBounds();
|
|
|
|
MeshConnectivityBuilder<Device> connBuilder;
|
|
|
|
//
|
|
// Build the face-to-face connectivity
|
|
//
|
|
connBuilder.BuildConnectivity(Cellset, Coordinates, CoordinateBounds);
|
|
//
|
|
// Initialize all of the array handles
|
|
//
|
|
FaceConnectivity = connBuilder.GetFaceConnectivity();
|
|
ExternalTriangles = connBuilder.GetExternalTriangles();
|
|
|
|
//
|
|
// Build BVH on external triangles
|
|
//
|
|
Bvh.SetData(Coords.GetData(), ExternalTriangles, Coords.GetBounds());
|
|
Bvh.ConstructOnDevice(Device());
|
|
|
|
IsConstructed = true;
|
|
}
|
|
|
|
vtkm::Float64 time = timer.GetElapsedTime();
|
|
logger->CloseLogEntry(time);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
|
|
template <typename T, typename Device>
|
|
VTKM_CONT void FindEntry(Ray<T>& rays, Device)
|
|
{
|
|
if (!IsConstructed)
|
|
{
|
|
throw vtkm::cont::ErrorBadValue(
|
|
"Unstructured Mesh Connecitity Single Error: FindEntry called before Construct");
|
|
}
|
|
TriangleIntersector<Device, TriLeafIntersector<WaterTight<T>>> intersector;
|
|
bool getCellIndex = true;
|
|
intersector.runHitOnly(rays, Bvh, Coordinates, getCellIndex);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
vtkm::Id GetNumberOfCells() { return this->Cellset.GetNumberOfCells(); }
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
Id4Handle GetExternalTriangles() { return ExternalTriangles; }
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
DynamicArrayHandleExplicitCoordinateSystem GetCoordinates() { return Coordinates; }
|
|
//----------------------------------------------------------------------------
|
|
template <typename Device>
|
|
VTKM_CONT vtkm::Bounds GetCoordinateBounds(Device)
|
|
{
|
|
CoordinateBounds = Coords.GetBounds();
|
|
return CoordinateBounds;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
bool GetIsConstructed() { return IsConstructed; }
|
|
}; //UnstructuredMeshConn Single Type
|
|
|
|
template <typename Device>
|
|
class MeshConnExec<UnstructuredMeshConnSingleType, Device>
|
|
{
|
|
protected:
|
|
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdHandle;
|
|
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
|
typedef typename vtkm::cont::ArrayHandleCounting<vtkm::Id> CountingHandle;
|
|
typedef typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8> ShapesHandle;
|
|
|
|
typedef typename IdHandle::ExecutionTypes<Device>::PortalConst IdConstPortal;
|
|
typedef typename CountingHandle::ExecutionTypes<Device>::PortalConst CountingPortal;
|
|
typedef typename vtkm::cont::ArrayHandleConstant<vtkm::IdComponent> NumIndicesHandle;
|
|
// Constant Portals for the execution Environment
|
|
IdConstPortal FaceConnPortal;
|
|
IdConstPortal CellConnectivityPortal;
|
|
CountingPortal CellOffsetsPortal;
|
|
|
|
vtkm::Int32 ShapeId;
|
|
vtkm::Int32 NumIndices;
|
|
vtkm::Int32 NumFaces;
|
|
|
|
private:
|
|
VTKM_CONT
|
|
MeshConnExec() {}
|
|
|
|
public:
|
|
VTKM_CONT
|
|
MeshConnExec(UnstructuredMeshConnSingleType& conn)
|
|
: FaceConnPortal(conn.FaceConnectivity.PrepareForInput(Device()))
|
|
, CellConnectivityPortal(conn.CellConnectivity.PrepareForInput(Device()))
|
|
, CellOffsetsPortal(conn.CellOffsets.PrepareForInput(Device()))
|
|
, ShapeId(conn.ShapeId)
|
|
, NumIndices(conn.NumIndices)
|
|
, NumFaces(conn.NumFaces)
|
|
{
|
|
if (!conn.GetIsConstructed())
|
|
{
|
|
throw vtkm::cont::ErrorBadValue(
|
|
"Unstructured Mesh Connecitity Single Error: GetExecObj called before Construct");
|
|
}
|
|
}
|
|
template <typename T>
|
|
VTKM_CONT MeshConnExec(const T& other)
|
|
: FaceConnPortal(other.FaceConnPortal)
|
|
, CellOffsetsPortal(other.CellOffsetsPortal)
|
|
, CellConnectivityPortal(other.CellConnectivityPortal)
|
|
, ShapeId(other.ShapeId)
|
|
, NumIndices(other.NumIndices)
|
|
, NumFaces(other.NumFaces)
|
|
{
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
// Execution Environment Methods
|
|
//----------------------------------------------------------------------------
|
|
VTKM_EXEC
|
|
inline vtkm::Id GetConnectingCell(const vtkm::Id& cellId, const vtkm::Id& face) const
|
|
{
|
|
BOUNDS_CHECK(CellOffsetsPortal, cellId);
|
|
vtkm::Id cellStartIndex = cellId * NumFaces;
|
|
BOUNDS_CHECK(FaceConnPortal, cellStartIndex + face);
|
|
return FaceConnPortal.Get(cellStartIndex + face);
|
|
}
|
|
|
|
VTKM_EXEC
|
|
inline vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8], const vtkm::Id& cellId) const
|
|
{
|
|
BOUNDS_CHECK(CellOffsetsPortal, cellId);
|
|
const vtkm::Id cellOffset = CellOffsetsPortal.Get(cellId);
|
|
|
|
for (vtkm::Int32 i = 0; i < NumIndices; ++i)
|
|
{
|
|
BOUNDS_CHECK(CellConnectivityPortal, cellOffset + i);
|
|
cellIndices[i] = CellConnectivityPortal.Get(cellOffset + i);
|
|
}
|
|
|
|
return NumIndices;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
VTKM_EXEC
|
|
inline vtkm::UInt8 GetCellShape(const vtkm::Id& vtkmNotUsed(cellId)) const
|
|
{
|
|
return vtkm::UInt8(ShapeId);
|
|
}
|
|
|
|
}; //MeshConn Single type specialization
|
|
|
|
class StructuredMeshConn
|
|
{
|
|
public:
|
|
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
|
vtkm::Id3 CellDims;
|
|
vtkm::Id3 PointDims;
|
|
DynamicArrayHandleStructuredCoordinateSystem Coordinates;
|
|
vtkm::Bounds CoordinateBounds;
|
|
vtkm::cont::CoordinateSystem Coords;
|
|
vtkm::cont::CellSetStructured<3> Cellset;
|
|
// Mesh Boundry
|
|
LinearBVH Bvh;
|
|
Id4Handle ExternalTriangles;
|
|
|
|
protected:
|
|
bool IsConstructed;
|
|
|
|
private:
|
|
VTKM_CONT
|
|
StructuredMeshConn() {}
|
|
|
|
public:
|
|
VTKM_CONT
|
|
StructuredMeshConn(const vtkm::cont::DynamicCellSet& cellset,
|
|
const vtkm::cont::CoordinateSystem& coords)
|
|
: IsConstructed(false)
|
|
{
|
|
Coords = coords;
|
|
vtkm::cont::DynamicArrayHandleCoordinateSystem dynamicCoordsHandle = coords.GetData();
|
|
|
|
//
|
|
// Reset the type lists to only contain the coordinate systemss of an
|
|
// unstructured cell set.
|
|
//
|
|
|
|
Coordinates = dynamicCoordsHandle.ResetTypeList(ExplicitCoordinatesType())
|
|
.ResetStorageList(StructuredStorage());
|
|
if (!cellset.IsSameType(vtkm::cont::CellSetStructured<3>()))
|
|
{
|
|
throw vtkm::cont::ErrorBadValue(
|
|
"Structured Mesh Connecitity Error: not a Structured<3> cell set!");
|
|
}
|
|
|
|
Cellset = cellset.Cast<vtkm::cont::CellSetStructured<3>>();
|
|
PointDims = Cellset.GetPointDimensions();
|
|
CellDims = Cellset.GetCellDimensions();
|
|
}
|
|
template <typename T>
|
|
VTKM_CONT StructuredMeshConn(const T& other)
|
|
: CellDims(other.CellDims)
|
|
, PointDims(other.PointDims)
|
|
, Coordinates(other.Coordinates)
|
|
, CoordinateBounds(other.CoordinateBounds)
|
|
, Coords(other.coords)
|
|
, Cellset(other.Cellset)
|
|
, Bvh(other.Bvh)
|
|
, ExternalTriangles(other.ExternalTriangles)
|
|
, IsConstructed(other.IsConstructed)
|
|
{
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
template <typename Device>
|
|
VTKM_CONT void Construct(Device)
|
|
{
|
|
Logger* logger = Logger::GetInstance();
|
|
logger->OpenLogEntry("mesh_conn_construction");
|
|
|
|
vtkm::cont::Timer<Device> timer;
|
|
|
|
if (!IsConstructed)
|
|
{
|
|
CoordinateBounds = Coords.GetBounds();
|
|
|
|
MeshConnectivityBuilder<Device> connBuilder;
|
|
ExternalTriangles = connBuilder.ExternalTrianglesStructured(Cellset);
|
|
|
|
//
|
|
// Build BVH on external triangles
|
|
//
|
|
Bvh.SetData(Coords.GetData(), ExternalTriangles, Coords.GetBounds());
|
|
Bvh.ConstructOnDevice(Device());
|
|
IsConstructed = true;
|
|
}
|
|
|
|
vtkm::Float64 time = timer.GetElapsedTime();
|
|
logger->CloseLogEntry(time);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
template <typename T, typename Device>
|
|
VTKM_CONT void FindEntry(Ray<T>& rays, Device)
|
|
{
|
|
if (!IsConstructed)
|
|
{
|
|
throw vtkm::cont::ErrorBadValue(
|
|
"Structured Mesh Connecitity Single Error: FindEntry called before Construct");
|
|
}
|
|
TriangleIntersector<Device, TriLeafIntersector<WaterTight<T>>> intersector;
|
|
bool getCellIndex = true;
|
|
intersector.runHitOnly(rays, Bvh, Coordinates, getCellIndex);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
vtkm::Id GetNumberOfCells() { return this->CellDims[0] * this->CellDims[1] * this->CellDims[2]; }
|
|
//----------------------------------------------------------------------------
|
|
// Control Environment Methods
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
Id4Handle GetExternalTriangles() { return ExternalTriangles; }
|
|
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
DynamicArrayHandleStructuredCoordinateSystem GetCoordinates() { return Coordinates; }
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <typename Device>
|
|
VTKM_CONT vtkm::Bounds GetCoordinateBounds(Device)
|
|
{
|
|
CoordinateBounds = Coords.GetBounds();
|
|
return CoordinateBounds;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
VTKM_CONT
|
|
bool GetIsConstructed() { return IsConstructed; }
|
|
}; //structure mesh conn
|
|
|
|
template <typename Device>
|
|
class MeshConnExec<StructuredMeshConn, Device>
|
|
{
|
|
protected:
|
|
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
|
vtkm::Id3 CellDims;
|
|
vtkm::Id3 PointDims;
|
|
vtkm::Bounds CoordinateBounds;
|
|
|
|
private:
|
|
VTKM_CONT
|
|
MeshConnExec() {}
|
|
|
|
public:
|
|
VTKM_CONT
|
|
MeshConnExec(const StructuredMeshConn& other)
|
|
: CellDims(other.CellDims)
|
|
, PointDims(other.PointDims)
|
|
, CoordinateBounds(other.CoordinateBounds)
|
|
{
|
|
}
|
|
template <typename T>
|
|
VTKM_CONT MeshConnExec(const T& other)
|
|
: CellDims(other.CellDims)
|
|
, PointDims(other.PointDims)
|
|
, CoordinateBounds(other.CoordinateBounds)
|
|
{
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
// Execution Environment Methods
|
|
//----------------------------------------------------------------------------
|
|
VTKM_EXEC_CONT
|
|
inline vtkm::Id GetConnectingCell(const vtkm::Id& cellId, const vtkm::Id& face) const
|
|
{
|
|
//TODO: there is probably a better way to do this.
|
|
vtkm::Id3 logicalCellId;
|
|
logicalCellId[0] = cellId % CellDims[0];
|
|
logicalCellId[1] = (cellId / CellDims[0]) % CellDims[1];
|
|
logicalCellId[2] = cellId / (CellDims[0] * CellDims[1]);
|
|
if (face == 0)
|
|
logicalCellId[1] -= 1;
|
|
if (face == 2)
|
|
logicalCellId[1] += 1;
|
|
if (face == 1)
|
|
logicalCellId[0] += 1;
|
|
if (face == 3)
|
|
logicalCellId[0] -= 1;
|
|
if (face == 4)
|
|
logicalCellId[2] -= 1;
|
|
if (face == 5)
|
|
logicalCellId[2] += 1;
|
|
vtkm::Id nextCell =
|
|
(logicalCellId[2] * CellDims[1] + logicalCellId[1]) * CellDims[0] + logicalCellId[0];
|
|
bool validCell = true;
|
|
if (logicalCellId[0] >= CellDims[0])
|
|
validCell = false;
|
|
if (logicalCellId[1] >= CellDims[1])
|
|
validCell = false;
|
|
if (logicalCellId[2] >= CellDims[2])
|
|
validCell = false;
|
|
vtkm::Id minId = vtkm::Min(logicalCellId[0], vtkm::Min(logicalCellId[1], logicalCellId[2]));
|
|
if (minId < 0)
|
|
validCell = false;
|
|
if (!validCell)
|
|
nextCell = -1;
|
|
return nextCell;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
VTKM_EXEC_CONT
|
|
inline vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8], const vtkm::Id& cellIndex) const
|
|
{
|
|
|
|
vtkm::Id3 cellId;
|
|
cellId[0] = cellIndex % CellDims[0];
|
|
cellId[1] = (cellIndex / CellDims[0]) % CellDims[1];
|
|
cellId[2] = cellIndex / (CellDims[0] * CellDims[1]);
|
|
cellIndices[0] = (cellId[2] * PointDims[1] + cellId[1]) * PointDims[0] + cellId[0];
|
|
cellIndices[1] = cellIndices[0] + 1;
|
|
cellIndices[2] = cellIndices[1] + PointDims[0];
|
|
cellIndices[3] = cellIndices[2] - 1;
|
|
cellIndices[4] = cellIndices[0] + PointDims[0] * PointDims[1];
|
|
cellIndices[5] = cellIndices[4] + 1;
|
|
cellIndices[6] = cellIndices[5] + PointDims[0];
|
|
cellIndices[7] = cellIndices[6] - 1;
|
|
return 8;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
VTKM_EXEC_CONT
|
|
inline vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8],
|
|
const vtkm::Vec<vtkm::Id, 3>& cellId) const
|
|
{
|
|
|
|
cellIndices[0] = (cellId[2] * PointDims[1] + cellId[1]) * PointDims[0] + cellId[0];
|
|
cellIndices[1] = cellIndices[0] + 1;
|
|
cellIndices[2] = cellIndices[1] + PointDims[0];
|
|
cellIndices[3] = cellIndices[2] - 1;
|
|
cellIndices[4] = cellIndices[0] + PointDims[0] * PointDims[1];
|
|
cellIndices[5] = cellIndices[4] + 1;
|
|
cellIndices[6] = cellIndices[5] + PointDims[0];
|
|
cellIndices[7] = cellIndices[6] - 1;
|
|
return 8;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
VTKM_EXEC
|
|
inline vtkm::UInt8 GetCellShape(const vtkm::Id& vtkmNotUsed(cellId)) const
|
|
{
|
|
return vtkm::UInt8(CELL_SHAPE_HEXAHEDRON);
|
|
}
|
|
}; //Unstructure mesh conn
|
|
}
|
|
}
|
|
} //namespace vtkm::rendering::raytracing
|
|
#endif
|