First Extrude commit.

how did any of this work?

match other CellSet file layouts.

???

compile in CUDA.

unit tests.

also only serial.

make error message accurate

Well, this compiles and works now.

Did it ever?

use CellShapeTagGeneric

UnitTest matches previous changes.

whoops

Fix linking problems.

Need the same interface

as other ThreadIndices.

add filter test

okay, let's try duplicating CellSetStructure.

okay

inching...

change to wedge in CellSetListTag

Means changing these to support it.

switch back to wedge from generic

compiles and runs

remove ExtrudedType

need vtkm_worklet

vtkm_worklet needs to be included

fix segment count for wedge specialization

need to actually save the index

for the other constructor.

specialize on Explicit

clean up warning

angled brackets not quotes.

formatting
This commit is contained in:
Mark Kim 2019-06-06 14:43:53 -04:00
parent 0bf3c7ffcb
commit 6e1d3a84f0
37 changed files with 2592 additions and 61 deletions

@ -0,0 +1,81 @@
#ifndef vtk_m_cont_ArrayHandleExtrudeCoords_h
#define vtk_m_cont_ArrayHandleExtrudeCoords_h
#include <vtkm/cont/StorageExtrude.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayPortalExtrude.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/CoordinateSystem.hxx>
namespace vtkm
{
namespace cont
{
template <typename T>
class VTKM_ALWAYS_EXPORT ArrayHandleExtrudeCoords
: public vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, internal::StorageTagExtrude>
{
using StorageType = vtkm::cont::internal::Storage<vtkm::Vec<T, 3>, internal::StorageTagExtrude>;
public:
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleExtrudeCoords,
(ArrayHandleExtrudeCoords<T>),
(vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, internal::StorageTagExtrude>));
ArrayHandleExtrudeCoords(const StorageType& storage)
: Superclass(storage)
{
}
vtkm::Int32 GetNumberOfPointsPerPlane() const { return (this->GetStorage().Length / 2); }
vtkm::Int32 GetNumberOfPlanes() const { return this->GetStorage().NumberOfPlanes; }
};
template <typename T>
vtkm::cont::ArrayHandleExtrudeCoords<T> make_ArrayHandleExtrudeCoords(
const T* array,
vtkm::Id length,
vtkm::Int32 numberOfPlanes,
bool cylindrical,
vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
{
using StorageType = vtkm::cont::internal::Storage<vtkm::Vec<T, 3>, internal::StorageTagExtrude>;
if (copy == vtkm::CopyFlag::Off)
{
return ArrayHandleExtrudeCoords<T>(StorageType(array, length, numberOfPlanes, cylindrical));
}
else
{
auto storage = StorageType(
vtkm::cont::make_ArrayHandle(array, length, vtkm::CopyFlag::On), numberOfPlanes, cylindrical);
return ArrayHandleExtrudeCoords<T>(storage);
}
}
template <typename T>
vtkm::cont::ArrayHandleExtrudeCoords<T> make_ArrayHandleExtrudeCoords(
const std::vector<T>& array,
vtkm::Int32 numberOfPlanes,
bool cylindrical,
vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
{
if (!array.empty())
{
return make_ArrayHandleExtrudeCoords(
&array.front(), static_cast<vtkm::Id>(array.size()), numberOfPlanes, cylindrical, copy);
}
else
{
// Vector empty. Just return an empty array handle.
return ArrayHandleExtrudeCoords<T>();
}
}
}
}
#endif

@ -0,0 +1,73 @@
#ifndef vtk_m_cont_ArrayHandleExtrudeField_h
#define vtk_m_cont_ArrayHandleExtrudeField_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayPortalExtrude.h>
#include <vtkm/cont/StorageExtrude.h>
namespace vtkm
{
namespace cont
{
template <typename T>
class VTKM_ALWAYS_EXPORT ArrayHandleExtrudeField
: public vtkm::cont::ArrayHandle<T, internal::StorageTagExtrude>
{
using StorageType = vtkm::cont::internal::Storage<T, internal::StorageTagExtrude>;
public:
VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleExtrudeField,
(ArrayHandleExtrudeField<T>),
(vtkm::cont::ArrayHandle<T, internal::StorageTagExtrude>));
ArrayHandleExtrudeField(const StorageType& storage)
: Superclass(storage)
{
}
vtkm::Int32 GetNumberOfValuesPerPlane() const
{
return this->GetStorage().GetNumberOfValuesPerPlane();
}
vtkm::Int32 GetNumberOfPlanes() const { return this->GetStorage().GetNumberOfPlanes(); }
};
template <typename T>
vtkm::cont::ArrayHandleExtrudeField<T> make_ArrayHandleExtrudeField(
const T* array,
vtkm::Id length,
vtkm::Int32 numberOfPlanes,
bool cylindrical,
vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
{
using StorageType = vtkm::cont::internal::Storage<T, internal::StorageTagExtrude>;
auto storage =
StorageType(vtkm::cont::make_ArrayHandle(array, length, copy), numberOfPlanes, cylindrical);
return ArrayHandleExtrudeField<T>(storage);
}
template <typename T>
vtkm::cont::ArrayHandleExtrudeField<T> make_ArrayHandleExtrudeField(
const std::vector<T>& array,
vtkm::Int32 numberOfPlanes,
bool cylindrical,
vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
{
if (!array.empty())
{
return make_ArrayHandleExtrudeField(
array.data(), static_cast<vtkm::Id>(array.size()), numberOfPlanes, cylindrical, copy);
}
else
{
// Vector empty. Just return an empty array handle.
return ArrayHandleExtrudeField<T>();
}
}
}
} // vtkm::cont
#endif

@ -0,0 +1,145 @@
#ifndef vtk_m_internal_ArrayPortalExtrude_h
#define vtk_m_internal_ArrayPortalExtrude_h
#include <vtkm/internal/IndicesExtrude.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/ErrorInternal.h>
#include <vtkm/BaseComponent.h>
#include <vtkm/cont/StorageExtrude.h>
namespace vtkm
{
namespace exec
{
template <typename PortalType>
struct VTKM_ALWAYS_EXPORT ArrayPortalExtrude
{
using ValueType = vtkm::Vec<typename PortalType::ValueType, 3>;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ArrayPortalExtrude()
: Portal()
, NumberOfValues(0)
, NumberOfPlanes(0)
, UseCylindrical(false){};
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ArrayPortalExtrude(const PortalType& p,
vtkm::Int32 numOfValues,
vtkm::Int32 numOfPlanes,
bool cylindrical = false)
: Portal(p)
, NumberOfValues(numOfValues)
, NumberOfPlanes(numOfPlanes)
, UseCylindrical(cylindrical)
{
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
vtkm::Id GetNumberOfValues() const
{
return ((NumberOfValues / 2) * static_cast<vtkm::Id>(NumberOfPlanes));
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ValueType Get(vtkm::Id index) const;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ValueType Get(vtkm::Id2 index) const;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
vtkm::Vec<ValueType, 6> GetWedge(const IndicesExtrude& index) const;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
void Set(vtkm::Id vtkmNotUsed(index), const ValueType& vtkmNotUsed(value)) const {}
PortalType Portal;
vtkm::Int32 NumberOfValues;
vtkm::Int32 NumberOfPlanes;
bool UseCylindrical;
};
template <typename PortalType>
typename ArrayPortalExtrude<PortalType>::ValueType
ArrayPortalExtrude<PortalType>::ArrayPortalExtrude::Get(vtkm::Id index) const
{
using CompType = typename ValueType::ComponentType;
const vtkm::Id realIdx = (index * 2) % this->NumberOfValues;
const vtkm::Id whichPlane = (index * 2) / this->NumberOfValues;
const auto phi = static_cast<CompType>(whichPlane * (vtkm::TwoPi() / this->NumberOfPlanes));
auto r = this->Portal.Get(realIdx);
auto z = this->Portal.Get(realIdx + 1);
if (this->UseCylindrical)
{
return ValueType(r, phi, z);
}
else
{
return ValueType(r * vtkm::Cos(phi), r * vtkm::Sin(phi), z);
}
}
template <typename PortalType>
typename ArrayPortalExtrude<PortalType>::ValueType
ArrayPortalExtrude<PortalType>::ArrayPortalExtrude::Get(vtkm::Id2 index) const
{
using CompType = typename ValueType::ComponentType;
const vtkm::Id realIdx = (index[0] * 2);
const vtkm::Id whichPlane = index[1];
const auto phi = static_cast<CompType>(whichPlane * (vtkm::TwoPi() / this->NumberOfPlanes));
auto r = this->Portal.Get(realIdx);
auto z = this->Portal.Get(realIdx + 1);
if (this->UseCylindrical)
{
return ValueType(r, phi, z);
}
else
{
return ValueType(r * vtkm::Cos(phi), r * vtkm::Sin(phi), z);
}
}
template <typename PortalType>
vtkm::Vec<typename ArrayPortalExtrude<PortalType>::ValueType, 6>
ArrayPortalExtrude<PortalType>::ArrayPortalExtrude::GetWedge(const IndicesExtrude& index) const
{
using CompType = typename ValueType::ComponentType;
vtkm::Vec<ValueType, 6> result;
for (int j = 0; j < 2; ++j)
{
const auto phi =
static_cast<CompType>(index.Planes[j] * (vtkm::TwoPi() / this->NumberOfPlanes));
for (int i = 0; i < 3; ++i)
{
const vtkm::Id realIdx = index.PointIds[j][i] * 2;
auto r = this->Portal.Get(realIdx);
auto z = this->Portal.Get(realIdx + 1);
result[3 * j + i] = this->UseCylindrical
? ValueType(r, phi, z)
: ValueType(r * vtkm::Cos(phi), r * vtkm::Sin(phi), z);
}
}
return result;
}
}
}
#endif

@ -0,0 +1,215 @@
#ifndef vtk_m_internal_ArrayPortalExtrudePlane_h
#define vtk_m_internal_ArrayPortalExtrudePlane_h
#include <vtkm/internal/IndicesExtrude.h>
#include <vtkm/cont/ArrayHandle.h>
namespace vtkm
{
namespace exec
{
template <typename PortalType>
struct VTKM_ALWAYS_EXPORT ArrayPortalExtrudePlane
{
using ValueType = typename PortalType::ValueType;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ArrayPortalExtrudePlane()
: Portal()
, NumberOfPlanes(0){};
ArrayPortalExtrudePlane(const PortalType& p, vtkm::Int32 numOfPlanes)
: Portal(p)
, NumberOfPlanes(numOfPlanes)
{
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
vtkm::Id GetNumberOfValues() const
{
return this->Portal.GetNumberOfValues() * static_cast<vtkm::Id>(NumberOfPlanes);
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ValueType Get(vtkm::Id index) const { return this->Portal.Get(index % this->NumberOfPlanes); }
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ValueType Get(vtkm::Id2 index) const { return this->Portal.Get(index[0]); }
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
vtkm::Vec<ValueType, 6> GetWedge(const IndicesExtrude& index) const;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
void Set(vtkm::Id vtkmNotUsed(index), const ValueType& vtkmNotUsed(value)) const {}
PortalType Portal;
vtkm::Int32 NumberOfPlanes;
};
}
} // vtkm::exec
namespace vtkm
{
namespace cont
{
namespace internal
{
struct VTKM_ALWAYS_EXPORT StorageTagExtrudePlane
{
};
template <typename T>
class VTKM_ALWAYS_EXPORT Storage<T, internal::StorageTagExtrudePlane>
{
using HandleType = vtkm::cont::ArrayHandle<T>;
public:
using ValueType = T;
// This is meant to be invalid. Because point arrays are read only, you
// should only be able to use the const version.
struct PortalType
{
using ValueType = void*;
using IteratorType = void*;
};
using PortalConstType =
vtkm::exec::ArrayPortalExtrudePlane<typename HandleType::PortalConstControl>;
Storage()
: Array()
, NumberOfPlanes(0)
{
}
Storage(const HandleType& array, vtkm::Int32 numberOfPlanes)
: Array(array)
, NumberOfPlanes(numberOfPlanes)
{
}
PortalType GetPortal() { return PortalType{}; }
PortalConstType GetPortalConst() const
{
return PortalConstType(this->Array.GetPortalConstControl(), this->NumberOfPlanes);
}
vtkm::Id GetNumberOfValues() const
{
return this->Array.GetNumberOfValues() * static_cast<vtkm::Id>(this->NumberOfPlanes);
}
vtkm::Int32 GetNumberOfValuesPerPlane() const
{
return static_cast<vtkm::Int32>(this->Array->GetNumberOfValues());
}
vtkm::Int32 GetNumberOfPlanes() const { return this->NumberOfPlanes; }
void Allocate(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorBadType("ArrayPortalExtrudePlane is read only. It cannot be allocated.");
}
void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorBadType("ArrayPortalExtrudePlane is read only. It cannot shrink.");
}
void ReleaseResources()
{
// This request is ignored since we don't own the memory that was past
// to us
}
private:
vtkm::cont::ArrayHandle<T> Array;
vtkm::Int32 NumberOfPlanes;
};
template <typename T, typename Device>
class VTKM_ALWAYS_EXPORT ArrayTransfer<T, internal::StorageTagExtrudePlane, Device>
{
public:
using ValueType = T;
using StorageType = vtkm::cont::internal::Storage<T, internal::StorageTagExtrudePlane>;
using PortalControl = typename StorageType::PortalType;
using PortalConstControl = typename StorageType::PortalConstType;
//meant to be an invalid writeable execution portal
using PortalExecution = typename StorageType::PortalType;
using PortalConstExecution = vtkm::exec::ArrayPortalExtrudePlane<decltype(
vtkm::cont::ArrayHandle<T>{}.PrepareForInput(Device{}))>;
VTKM_CONT
ArrayTransfer(StorageType* storage)
: ControlData(storage)
{
}
vtkm::Id GetNumberOfValues() const { return this->ControlData->GetNumberOfValues(); }
VTKM_CONT
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
{
return PortalConstExecution(this->ControlData->Array.PrepareForInput(Device()),
this->ControlData->NumberOfPlanes);
}
VTKM_CONT
PortalExecution PrepareForInPlace(bool& vtkmNotUsed(updateData))
{
throw vtkm::cont::ErrorBadType("ArrayPortalExtrudePlane read only. "
"Cannot be used for in-place operations.");
}
VTKM_CONT
PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorBadType("ArrayPortalExtrudePlane read only. Cannot be used as output.");
}
VTKM_CONT
void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const
{
throw vtkm::cont::ErrorInternal(
"ArrayPortalExtrudePlane read only. "
"There should be no occurance of the ArrayHandle trying to pull "
"data from the execution environment.");
}
VTKM_CONT
void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorBadType("ArrayPortalExtrudePlane read only. Cannot shrink.");
}
VTKM_CONT
void ReleaseResources()
{
// This request is ignored since we don't own the memory that was past
// to us
}
private:
const StorageType* const ControlData;
};
}
}
} // vtkm::cont::internal
#endif

@ -0,0 +1,24 @@
#include <vtkm/cont/ArrayPortalExtrudePlane.h>
namespace vtkm
{
namespace exec
{
template <typename PortalType>
vtkm::Vec<typename ArrayPortalExtrudePlane<PortalType>::ValueType, 6> ArrayPortalExtrudePlane<
PortalType>::ArrayPortalExtrudePlane::GetWedge(const ToroidIndices& index) const
{
vtkm::Vec<ValueType, 6> result;
result[0] = this->Portal.Get(index.PointIds[0][0]);
result[1] = this->Portal.Get(index.PointIds[0][1]);
result[2] = this->Portal.Get(index.PointIds[0][2]);
result[3] = this->Portal.Get(index.PointIds[1][0]);
result[4] = this->Portal.Get(index.PointIds[1][1]);
result[5] = this->Portal.Get(index.PointIds[1][2]);
return result;
}
}
} // vtkm::exec

@ -21,6 +21,8 @@ set(headers
ArrayHandleCounting.h
ArrayHandleDiscard.h
ArrayHandleExtractComponent.h
ArrayHandleExtrudeCoords.h
ArrayHandleExtrudeField.h
ArrayHandleGroupVec.h
ArrayHandleGroupVecVariable.h
ArrayHandleImplicit.h
@ -37,6 +39,8 @@ set(headers
ArrayHandleZip.h
ArrayPortal.h
ArrayPortalToIterators.h
ArrayPortalExtrude.h
ArrayPortalExtrudePlane.h
ArrayRangeCompute.h
AssignerMultiBlock.h
AtomicArray.h
@ -52,6 +56,7 @@ set(headers
CellLocatorUniformGrid.h
CellSet.h
CellSetExplicit.h
CellSetExtrude.h
CellSetListTag.h
CellSetPermutation.h
CellSetSingleType.h
@ -94,6 +99,7 @@ set(headers
Serialization.h
Storage.h
StorageBasic.h
StorageExtrude.h
StorageImplicit.h
StorageListTag.h
StorageVirtual.h
@ -106,9 +112,11 @@ set(headers
set(template_sources
ArrayHandle.hxx
ArrayPortalExtrudePlane.hxx
ArrayHandleVirtual.hxx
ArrayRangeCompute.hxx
CellSetExplicit.hxx
CellSetExtrude.hxx
CellSetStructured.hxx
ColorTable.hxx
CoordinateSystem.hxx
@ -153,6 +161,7 @@ set(sources
CellLocatorUniformGrid.cxx
CellSet.cxx
CellSetExplicit.cxx
CellSetExtrude.cxx
CellSetStructured.cxx
ColorTable.cxx
CoordinateSystem.cxx

@ -0,0 +1,171 @@
#include <vtkm/cont/CellSetExtrude.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/CellShape.h>
namespace vtkm
{
namespace cont
{
VTKM_CONT CellSetExtrude::CellSetExtrude(const std::string& name)
: vtkm::cont::CellSet(name)
, IsPeriodic(false)
, NumberOfPointsPerPlane(0)
, NumberOfCellsPerPlane(0)
, NumberOfPlanes(0)
, ReverseConnectivityBuilt(false)
{
}
VTKM_CONT CellSetExtrude::CellSetExtrude(const vtkm::cont::ArrayHandle<vtkm::Int32>& conn,
vtkm::Int32 numberOfPointsPerPlane,
vtkm::Int32 numberOfPlanes,
const vtkm::cont::ArrayHandle<vtkm::Int32>& nextNode,
bool periodic,
const std::string& name)
: vtkm::cont::CellSet(name)
, IsPeriodic(periodic)
, NumberOfPointsPerPlane(numberOfPointsPerPlane)
, NumberOfCellsPerPlane(conn.GetNumberOfValues() / 3)
, NumberOfPlanes(numberOfPlanes)
, Connectivity(conn)
, NextNode(nextNode)
, ReverseConnectivityBuilt(false)
{
}
vtkm::Int32 CellSetExtrude::GetNumberOfPlanes() const
{
return this->NumberOfPlanes;
}
vtkm::Id CellSetExtrude::GetNumberOfCells() const
{
if (this->IsPeriodic)
{
return static_cast<vtkm::Id>(this->NumberOfPlanes) *
static_cast<vtkm::Id>(this->NumberOfCellsPerPlane);
}
else
{
return static_cast<vtkm::Id>(this->NumberOfPlanes - 1) *
static_cast<vtkm::Id>(this->NumberOfCellsPerPlane);
}
}
vtkm::Id CellSetExtrude::GetNumberOfPoints() const
{
return static_cast<vtkm::Id>(this->NumberOfPlanes) *
static_cast<vtkm::Id>(this->NumberOfPointsPerPlane);
}
vtkm::Id CellSetExtrude::GetNumberOfFaces() const
{
return -1;
}
vtkm::Id CellSetExtrude::GetNumberOfEdges() const
{
return -1;
}
vtkm::UInt8 CellSetExtrude::GetCellShape(vtkm::Id) const
{
return vtkm::CellShapeTagWedge::Id;
}
vtkm::IdComponent CellSetExtrude::GetNumberOfPointsInCell(vtkm::Id) const
{
return 6;
}
void CellSetExtrude::GetCellPointIds(vtkm::Id id, vtkm::Id* ptids) const
{
auto conn = this->PrepareForInput(vtkm::cont::DeviceAdapterTagSerial{},
vtkm::TopologyElementTagPoint{},
vtkm::TopologyElementTagCell{});
auto indices = conn.GetIndices(id);
for (int i = 0; i < 6; ++i)
{
ptids[i] = indices[i];
}
}
std::shared_ptr<CellSet> CellSetExtrude::NewInstance() const
{
return std::make_shared<CellSetExtrude>();
}
void CellSetExtrude::DeepCopy(const CellSet* src)
{
const auto* other = dynamic_cast<const CellSetExtrude*>(src);
if (!other)
{
throw vtkm::cont::ErrorBadType("CellSetExplicit::DeepCopy types don't match");
}
this->IsPeriodic = other->IsPeriodic;
this->NumberOfPointsPerPlane = other->NumberOfPointsPerPlane;
this->NumberOfCellsPerPlane = other->NumberOfCellsPerPlane;
this->NumberOfPlanes = other->NumberOfPlanes;
vtkm::cont::ArrayCopy(other->Connectivity, this->Connectivity);
vtkm::cont::ArrayCopy(other->NextNode, this->NextNode);
this->ReverseConnectivityBuilt = other->ReverseConnectivityBuilt;
if (this->ReverseConnectivityBuilt)
{
vtkm::cont::ArrayCopy(other->RConnectivity, this->RConnectivity);
vtkm::cont::ArrayCopy(other->ROffsets, this->ROffsets);
vtkm::cont::ArrayCopy(other->RCounts, this->RCounts);
vtkm::cont::ArrayCopy(other->PrevNode, this->PrevNode);
}
}
void CellSetExtrude::ReleaseResourcesExecution()
{
this->Connectivity.ReleaseResourcesExecution();
this->NextNode.ReleaseResourcesExecution();
this->RConnectivity.ReleaseResourcesExecution();
this->ROffsets.ReleaseResourcesExecution();
this->RCounts.ReleaseResourcesExecution();
this->PrevNode.ReleaseResourcesExecution();
}
VTKM_CONT vtkm::Id2 CellSetExtrude::GetSchedulingRange(vtkm::TopologyElementTagCell) const
{
if (this->IsPeriodic)
{
return vtkm::Id2(this->NumberOfCellsPerPlane, this->NumberOfPlanes);
}
else
{
return vtkm::Id2(this->NumberOfCellsPerPlane, this->NumberOfPlanes - 1);
}
}
VTKM_CONT vtkm::Id2 CellSetExtrude::GetSchedulingRange(vtkm::TopologyElementTagPoint) const
{
return vtkm::Id2(this->NumberOfPointsPerPlane, this->NumberOfPlanes);
}
void CellSetExtrude::PrintSummary(std::ostream& out) const
{
out << " vtkmCellSetSingleType: " << this->Name << std::endl;
out << " NumberOfCellsPerPlane: " << this->NumberOfCellsPerPlane << std::endl;
out << " NumberOfPointsPerPlane: " << this->NumberOfPointsPerPlane << std::endl;
out << " NumberOfPlanes: " << this->NumberOfPlanes << std::endl;
out << " Connectivity: " << std::endl;
vtkm::cont::printSummary_ArrayHandle(this->Connectivity, out);
out << " NextNode: " << std::endl;
vtkm::cont::printSummary_ArrayHandle(this->NextNode, out);
out << " ReverseConnectivityBuilt: " << this->NumberOfPlanes << std::endl;
}
}
} // vtkm::cont

136
vtkm/cont/CellSetExtrude.h Normal file

@ -0,0 +1,136 @@
#ifndef vtk_m_cont_CellSetExtrude_h
#define vtk_m_cont_CellSetExtrude_h
#include <vtkm/TopologyElementTag.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleExtrudeCoords.h>
#include <vtkm/cont/CellSet.h>
#include <vtkm/exec/ConnectivityExtrude.h>
#include <vtkm/exec/arg/ThreadIndicesExtrude.h>
#include <vtkm/worklet/Invoker.h>
#include <vtkm/worklet/WorkletMapField.h>
namespace vtkm
{
namespace cont
{
class VTKM_ALWAYS_EXPORT CellSetExtrude : public CellSet
{
public:
CellSetExtrude(const std::string& name = "extrude");
CellSetExtrude(const vtkm::cont::ArrayHandle<vtkm::Int32>& conn,
vtkm::Int32 numberOfPointsPerPlane,
vtkm::Int32 numberOfPlanes,
const vtkm::cont::ArrayHandle<vtkm::Int32>& nextNode,
bool periodic,
const std::string& name = "extrude");
vtkm::Int32 GetNumberOfPlanes() const;
vtkm::Id GetNumberOfCells() const override;
vtkm::Id GetNumberOfPoints() const override;
vtkm::Id GetNumberOfFaces() const override;
vtkm::Id GetNumberOfEdges() const override;
vtkm::Id2 GetSchedulingRange(vtkm::TopologyElementTagCell) const;
vtkm::Id2 GetSchedulingRange(vtkm::TopologyElementTagPoint) const;
vtkm::UInt8 GetCellShape(vtkm::Id id) const override;
vtkm::IdComponent GetNumberOfPointsInCell(vtkm::Id id) const override;
void GetCellPointIds(vtkm::Id id, vtkm::Id* ptids) const override;
std::shared_ptr<CellSet> NewInstance() const override;
void DeepCopy(const CellSet* src) override;
void PrintSummary(std::ostream& out) const override;
void ReleaseResourcesExecution() override;
template <typename DeviceAdapter>
using ConnectivityP2C = vtkm::exec::ConnectivityExtrude<DeviceAdapter>;
template <typename DeviceAdapter>
using ConnectivityC2P = vtkm::exec::ReverseConnectivityExtrude<DeviceAdapter>;
template <typename DeviceAdapter, typename FromTopology, typename ToTopology>
struct ExecutionTypes;
template <typename DeviceAdapter>
struct ExecutionTypes<DeviceAdapter, vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell>
{
using ExecObjectType = ConnectivityP2C<DeviceAdapter>;
};
template <typename DeviceAdapter>
struct ExecutionTypes<DeviceAdapter, vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint>
{
using ExecObjectType = ConnectivityC2P<DeviceAdapter>;
};
template <typename Device>
ConnectivityP2C<Device> PrepareForInput(Device,
vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell) const;
template <typename Device>
ConnectivityC2P<Device> PrepareForInput(Device,
vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagPoint) const;
private:
template <typename Device>
void BuildReverseConnectivity(Device);
bool IsPeriodic;
vtkm::Int32 NumberOfPointsPerPlane;
vtkm::Int32 NumberOfCellsPerPlane;
vtkm::Int32 NumberOfPlanes;
vtkm::cont::ArrayHandle<vtkm::Int32> Connectivity;
vtkm::cont::ArrayHandle<vtkm::Int32> NextNode;
bool ReverseConnectivityBuilt;
vtkm::cont::ArrayHandle<vtkm::Int32> RConnectivity;
vtkm::cont::ArrayHandle<vtkm::Int32> ROffsets;
vtkm::cont::ArrayHandle<vtkm::Int32> RCounts;
vtkm::cont::ArrayHandle<vtkm::Int32> PrevNode;
};
template <typename T>
CellSetExtrude make_CellSetExtrude(const vtkm::cont::ArrayHandle<vtkm::Int32>& conn,
const vtkm::cont::ArrayHandleExtrudeCoords<T>& coords,
const vtkm::cont::ArrayHandle<vtkm::Int32>& nextNode,
bool periodic = true,
const std::string name = "extrude")
{
return CellSetExtrude{
conn, coords.GetNumberOfPointsPerPlane(), coords.GetNumberOfPlanes(), nextNode, periodic, name
};
}
template <typename T>
CellSetExtrude make_CellSetExtrude(const std::vector<vtkm::Int32>& conn,
const vtkm::cont::ArrayHandleExtrudeCoords<T>& coords,
const std::vector<vtkm::Int32>& nextNode,
bool periodic = true,
const std::string name = "extrude")
{
return CellSetExtrude{ vtkm::cont::make_ArrayHandle(conn),
coords.GetNumberOfPointsPerPlane(),
coords.GetNumberOfPlanes(),
vtkm::cont::make_ArrayHandle(nextNode),
periodic,
name };
}
}
} // vtkm::cont
#include <vtkm/cont/CellSetExtrude.hxx>
#endif

@ -0,0 +1,119 @@
//============================================================================
// 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.
//============================================================================
namespace
{
struct ComputeReverseMapping : public vtkm::worklet::WorkletMapField
{
using ControlSignature = void(FieldIn cellIndex, WholeArrayOut cellIds);
using ExecutionSignature = void(_1, _2);
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename PortalType>
VTKM_EXEC void operator()(vtkm::Id cellId, PortalType&& pointIdValue) const
{
//3 as we are building the connectivity for triangles
const vtkm::Id offset = 3 * cellId;
pointIdValue.Set(offset, cellId);
pointIdValue.Set(offset + 1, cellId);
pointIdValue.Set(offset + 2, cellId);
}
};
struct ComputePrevNode : public vtkm::worklet::WorkletMapField
{
typedef void ControlSignature(FieldIn nextNode, WholeArrayOut prevNodeArray);
typedef void ExecutionSignature(InputIndex, _1, _2);
template <typename PortalType>
VTKM_EXEC void operator()(vtkm::Id idx, vtkm::Int32 next, PortalType& prevs) const
{
prevs.Set(static_cast<vtkm::Id>(next), static_cast<vtkm::Int32>(idx));
}
};
} // anonymous namespace
namespace vtkm
{
namespace cont
{
template <typename Device>
VTKM_CONT void CellSetExtrude::BuildReverseConnectivity(Device)
{
vtkm::worklet::Invoker invoke(Device{});
// create a mapping of where each key is the point id and the value
// is the cell id. We
const vtkm::Id numberOfPointsPerCell = 3;
const vtkm::Id rconnSize = this->NumberOfCellsPerPlane * numberOfPointsPerCell;
vtkm::cont::ArrayHandle<vtkm::Int32> pointIdKey;
vtkm::cont::DeviceAdapterAlgorithm<Device>::Copy(this->Connectivity, pointIdKey);
this->RConnectivity.Allocate(rconnSize);
invoke(ComputeReverseMapping{},
vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(0, 1, this->NumberOfCellsPerPlane),
this->RConnectivity);
vtkm::cont::DeviceAdapterAlgorithm<Device>::SortByKey(pointIdKey, this->RConnectivity);
// now we can compute the counts and offsets
vtkm::cont::ArrayHandle<vtkm::Int32> reducedKeys;
vtkm::cont::DeviceAdapterAlgorithm<Device>::ReduceByKey(
pointIdKey,
vtkm::cont::make_ArrayHandleConstant(vtkm::Int32(1), static_cast<vtkm::Int32>(rconnSize)),
reducedKeys,
this->RCounts,
vtkm::Add{});
vtkm::cont::DeviceAdapterAlgorithm<Device>::ScanExclusive(this->RCounts, this->ROffsets);
// compute PrevNode from NextNode
this->PrevNode.Allocate(this->NextNode.GetNumberOfValues());
invoke(ComputePrevNode{}, this->NextNode, this->PrevNode);
this->ReverseConnectivityBuilt = true;
}
template <typename Device>
CellSetExtrude::ConnectivityP2C<Device> CellSetExtrude::PrepareForInput(
Device,
vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell) const
{
return ConnectivityP2C<Device>(this->Connectivity.PrepareForInput(Device{}),
this->NextNode.PrepareForInput(Device{}),
this->NumberOfCellsPerPlane,
this->NumberOfPointsPerPlane,
this->NumberOfPlanes,
this->IsPeriodic);
}
template <typename Device>
VTKM_CONT CellSetExtrude::ConnectivityC2P<Device> CellSetExtrude::PrepareForInput(
Device,
vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagPoint) const
{
if (!this->ReverseConnectivityBuilt)
{
const_cast<CellSetExtrude*>(this)->BuildReverseConnectivity(Device{});
}
return ConnectivityC2P<Device>(this->RConnectivity.PrepareForInput(Device{}),
this->ROffsets.PrepareForInput(Device{}),
this->RCounts.PrepareForInput(Device{}),
this->PrevNode.PrepareForInput(Device{}),
this->NumberOfCellsPerPlane,
this->NumberOfPointsPerPlane,
this->NumberOfPlanes);
}
}
} // vtkm::cont

@ -17,6 +17,7 @@
#include <vtkm/ListTag.h>
#include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/CellSetExtrude.h>
#include <vtkm/cont/CellSetSingleType.h>
#include <vtkm/cont/CellSetStructured.h>
@ -40,6 +41,7 @@ struct VTKM_ALWAYS_EXPORT CellSetListTagStructured3D
{
};
template <typename ShapeStorageTag = VTKM_DEFAULT_SHAPE_STORAGE_TAG,
typename NumIndicesStorageTag = VTKM_DEFAULT_NUM_INDICES_STORAGE_TAG,
typename ConnectivityStorageTag = VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
@ -59,6 +61,7 @@ struct VTKM_ALWAYS_EXPORT CellSetListTagExplicitDefault : CellSetListTagExplicit
struct VTKM_ALWAYS_EXPORT CellSetListTagCommon : vtkm::ListTagBase<vtkm::cont::CellSetStructured<2>,
vtkm::cont::CellSetStructured<3>,
vtkm::cont::CellSetExplicit<>,
vtkm::cont::CellSetExtrude,
vtkm::cont::CellSetSingleType<>>
{
};

179
vtkm/cont/StorageExtrude.h Normal file

@ -0,0 +1,179 @@
#ifndef vtkm_internal_StorageExtrude_h
#define vtkm_internal_StorageExtrude_h
#include <vtkm/cont/ArrayPortalExtrude.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
#include <vtkm/cont/tbb/DeviceAdapterTBB.h>
namespace vtkm
{
namespace cont
{
namespace internal
{
struct VTKM_ALWAYS_EXPORT StorageTagExtrude
{
};
template <typename T>
class Storage<T, internal::StorageTagExtrude>
{
using BaseT = typename BaseComponent<T>::Type;
using HandleType = vtkm::cont::ArrayHandle<BaseT>;
using TPortalType = typename HandleType::PortalConstControl;
public:
using ValueType = T;
// This is meant to be invalid. Because point arrays are read only, you
// should only be able to use the const version.
struct PortalType
{
using ValueType = void*;
using IteratorType = void*;
};
using PortalConstType = exec::ArrayPortalExtrude<TPortalType>;
Storage()
: Array()
, Length(-1)
, NumberOfPlanes(0)
{
}
// Create with externally managed memory
Storage(const BaseT* array, vtkm::Id arrayLength, vtkm::Int32 numberOfPlanes, bool cylindrical)
: Array(vtkm::cont::make_ArrayHandle(array, arrayLength))
, Length(static_cast<vtkm::Int32>(arrayLength))
, NumberOfPlanes(numberOfPlanes)
, UseCylindrical(cylindrical)
{
VTKM_ASSERT(this->Length >= 0);
}
Storage(const HandleType& array, vtkm::Int32 numberOfPlanes, bool cylindrical)
: Array(array)
, Length(static_cast<vtkm::Int32>(array.GetNumberOfValues()))
, NumberOfPlanes(numberOfPlanes)
, UseCylindrical(cylindrical)
{
VTKM_ASSERT(this->Length >= 0);
}
PortalType GetPortal() { return PortalType{}; }
PortalConstType GetPortalConst() const
{
VTKM_ASSERT(this->Length >= 0);
return PortalConstType(this->Array.GetPortalConstControl(),
this->Length,
this->NumberOfPlanes,
this->UseCylindrical);
}
vtkm::Id GetNumberOfValues() const
{
VTKM_ASSERT(this->Length >= 0);
return (this->Length / 2) * static_cast<vtkm::Id>(this->NumberOfPlanes);
}
void Allocate(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorBadType("StorageTagExtrude is read only. It cannot be allocated.");
}
void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorBadType("StoraageTagExtrue is read only. It cannot shrink.");
}
void ReleaseResources()
{
// This request is ignored since we don't own the memory that was past
// to us
}
vtkm::cont::ArrayHandle<BaseT> Array;
vtkm::Int32 Length;
vtkm::Int32 NumberOfPlanes;
bool UseCylindrical;
};
template <typename T, typename Device>
class VTKM_ALWAYS_EXPORT ArrayTransfer<T, internal::StorageTagExtrude, Device>
{
using BaseT = typename BaseComponent<T>::Type;
using TPortalType = decltype(vtkm::cont::ArrayHandle<BaseT>{}.PrepareForInput(Device{}));
public:
using ValueType = T;
using StorageType = vtkm::cont::internal::Storage<T, internal::StorageTagExtrude>;
using PortalControl = typename StorageType::PortalType;
using PortalConstControl = typename StorageType::PortalConstType;
//meant to be an invalid writeable execution portal
using PortalExecution = typename StorageType::PortalType;
using PortalConstExecution = vtkm::exec::ArrayPortalExtrude<TPortalType>;
VTKM_CONT
ArrayTransfer(StorageType* storage)
: ControlData(storage)
{
}
vtkm::Id GetNumberOfValues() const { return this->ControlData->GetNumberOfValues(); }
VTKM_CONT
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
{
return PortalConstExecution(this->ControlData->Array.PrepareForInput(Device()),
this->ControlData->Length,
this->ControlData->NumberOfPlanes,
this->ControlData->UseCylindrical);
}
VTKM_CONT
PortalExecution PrepareForInPlace(bool& vtkmNotUsed(updateData))
{
throw vtkm::cont::ErrorBadType("StorageExtrude read only. "
"Cannot be used for in-place operations.");
}
VTKM_CONT
PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorBadType("StorageExtrude read only. Cannot be used as output.");
}
VTKM_CONT
void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const
{
throw vtkm::cont::ErrorInternal(
"ArrayHandleExrPointCoordinates read only. "
"There should be no occurance of the ArrayHandle trying to pull "
"data from the execution environment.");
}
VTKM_CONT
void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorBadType("StorageExtrude read only. Cannot shrink.");
}
VTKM_CONT
void ReleaseResources()
{
// This request is ignored since we don't own the memory that was past
// to us
}
private:
const StorageType* const ControlData;
};
}
}
}
#endif

@ -28,4 +28,4 @@ set(unit_tests
UnitTestCudaPointLocatorUniformGrid.cu
UnitTestCudaVirtualObjectHandle.cu
)
vtkm_unit_tests(SOURCES ${unit_tests})
vtkm_unit_tests(SOURCES ${unit_tests} LIBRARIES vtkm_worklet)

@ -25,7 +25,7 @@ set(unit_tests
UnitTestOpenMPPointLocatorUniformGrid.cxx
UnitTestOpenMPVirtualObjectHandle.cxx
)
vtkm_unit_tests(OpenMP SOURCES ${unit_tests} DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG)
vtkm_unit_tests(OpenMP SOURCES ${unit_tests} DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG LIBRARIES vtkm_worklet)
if (VTKm_ENABLE_TESTING)
#We need to have all OpenMP tests run serially as they

@ -26,4 +26,4 @@ set(unit_tests
UnitTestSerialPointLocatorUniformGrid.cxx
UnitTestSerialVirtualObjectHandle.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests} DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG)
vtkm_unit_tests(SOURCES ${unit_tests} DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG LIBRARIES vtkm_worklet)

@ -39,6 +39,7 @@ set(unit_tests
UnitTestArrayHandleCounting.cxx
UnitTestArrayHandleDiscard.cxx
UnitTestArrayHandleExtractComponent.cxx
UnitTestArrayHandleExtrude.cxx
UnitTestArrayHandleImplicit.cxx
UnitTestArrayHandleIndex.cxx
UnitTestArrayHandleReverse.cxx
@ -53,6 +54,7 @@ set(unit_tests
UnitTestCellLocatorGeneral.cxx
UnitTestCellSet.cxx
UnitTestCellSetExplicit.cxx
UnitTestCellSetExtrude.cxx
UnitTestCellSetPermutation.cxx
UnitTestContTesting.cxx
UnitTestDataSetBuilderExplicit.cxx

@ -0,0 +1,120 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/ArrayHandleExtrudeCoords.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
std::vector<float> points_rz = { 1.72485139f, 0.020562f, 1.73493571f,
0.02052826f, 1.73478011f, 0.02299051f }; //really a vec<float,2>
std::vector<float> correct_x_coords = {
1.72485139f, 1.73493571f, 1.73478011f, 1.21965411f, 1.22678481f, 1.22667478f,
1.05616686e-16f, 1.06234173e-16f, 1.06224646e-16f, -1.21965411f, -1.22678481f, -1.22667478f,
-1.72485139f, -1.73493571f, -1.73478011f, -1.21965411f, -1.22678481f, -1.22667478f,
-3.16850059e-16f, -3.18702520e-16f, -3.18673937e-16f, 1.21965411f, 1.22678481f, 1.22667478f
};
std::vector<float> correct_y_coords = { 0.0f,
0.0f,
0.0f,
1.21965411f,
1.22678481f,
1.22667478f,
1.72485139f,
1.73493571f,
1.73478011f,
1.21965411f,
1.22678481f,
1.22667478f,
2.11233373e-16f,
2.12468346e-16f,
2.12449291e-16f,
-1.21965411f,
-1.22678481f,
-1.22667478f,
-1.72485139f,
-1.73493571f,
-1.73478011f,
-1.21965411f,
-1.22678481f,
-1.22667478f };
std::vector<float> correct_z_coords = { 0.020562f, 0.02052826f, 0.02299051f, 0.020562f,
0.02052826f, 0.02299051f, 0.020562f, 0.02052826f,
0.02299051f, 0.020562f, 0.02052826f, 0.02299051f,
0.020562f, 0.02052826f, 0.02299051f, 0.020562f,
0.02052826f, 0.02299051f, 0.020562f, 0.02052826f,
0.02299051f, 0.020562f, 0.02052826f, 0.02299051f };
struct CopyValue : public vtkm::worklet::WorkletMapField
{
typedef void ControlSignature(FieldIn, FieldOut);
typedef _2 ExecutionSignature(_1);
template <typename T>
T&& operator()(T&& t) const
{
return std::forward<T>(t);
}
};
template <typename T, typename S>
void verify_results(vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, S> const& handle)
{
auto portal = handle.GetPortalConstControl();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == static_cast<vtkm::Id>(correct_x_coords.size()),
"coordinate portal size is incorrect");
for (vtkm::Id i = 0; i < handle.GetNumberOfValues(); ++i)
{
auto v = portal.Get(i);
auto e = vtkm::make_Vec(correct_x_coords[static_cast<std::size_t>(i)],
correct_y_coords[static_cast<std::size_t>(i)],
correct_z_coords[static_cast<std::size_t>(i)]);
// std::cout << std::setprecision(4) << "computed " << v << " expected " << e << std::endl;
VTKM_TEST_ASSERT(test_equal(v, e), "incorrect conversion to Cartesian space");
}
}
int TestArrayHandleExtrude()
{
const int numPlanes = 8;
auto coords = vtkm::cont::make_ArrayHandleExtrudeCoords(points_rz, numPlanes, false);
VTKM_TEST_ASSERT(coords.GetNumberOfValues() ==
static_cast<vtkm::Id>(((points_rz.size() / 2) * numPlanes)),
"coordinate size is incorrect");
// Verify first that control is correct
verify_results(coords);
// Verify 1d scheduling by doing a copy to a vtkm::ArrayHandle<Vec3>
vtkm::cont::ArrayHandle<vtkm::Vec<float, 3>> output1D;
vtkm::worklet::DispatcherMapField<CopyValue> dispatcher;
dispatcher.Invoke(coords, output1D);
verify_results(output1D);
return 0;
}
} // end namespace anonymous
int UnitTestArrayHandleExtrude(int argc, char* argv[])
{
vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(vtkm::cont::DeviceAdapterTagSerial{});
return vtkm::cont::testing::Testing::Run(TestArrayHandleExtrude, argc, argv);
}

@ -0,0 +1,161 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/WorkletMapTopology.h>
#include <vtkm/cont/ArrayHandleExtrudeCoords.h>
#include <vtkm/cont/CellSetExtrude.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/CellAverage.h>
#include <vtkm/filter/PointAverage.h>
#include <vtkm/filter/PolicyExtrude.h>
namespace
{
std::vector<float> points_rz = { 1.72485139f, 0.020562f, 1.73493571f,
0.02052826f, 1.73478011f, 0.02299051f }; //really a vec<float,2>
std::vector<int> topology = { 0, 2, 1 };
std::vector<int> nextNode = { 0, 1, 2 };
struct CopyTopo : public vtkm::worklet::WorkletMapPointToCell
{
typedef void ControlSignature(CellSetIn, FieldOutCell);
typedef _2 ExecutionSignature(CellShape, PointIndices);
template <typename T>
T&& operator()(vtkm::CellShapeTagWedge, T&& t) const
{
return std::forward<T>(t);
}
};
struct CopyReverseCellCount : public vtkm::worklet::WorkletMapCellToPoint
{
typedef void ControlSignature(CellSetIn, FieldOutPoint);
typedef _2 ExecutionSignature(CellShape, CellCount, CellIndices);
template <typename T>
vtkm::Int32 operator()(vtkm::CellShapeTagVertex shape, vtkm::IdComponent count, T&& t) const
{
if (shape.Id == vtkm::CELL_SHAPE_VERTEX)
{
bool valid = true;
for (vtkm::IdComponent i = 0; i < count; ++i)
{
valid = valid && t[i] > 0;
}
return (valid && count == t.GetNumberOfComponents()) ? count : -1;
}
return -1;
}
};
template <typename T, typename S>
void verify_topo(vtkm::cont::ArrayHandle<vtkm::Vec<T, 6>, S> const& handle, vtkm::Id expectedLen)
{
auto portal = handle.GetPortalConstControl();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == expectedLen, "topology portal size is incorrect");
for (vtkm::Id i = 0; i < expectedLen - 1; ++i)
{
auto v = portal.Get(i);
vtkm::Vec<int, 6> e;
e[0] = (topology[0] + (i * topology.size()));
e[1] = (topology[1] + (i * topology.size()));
e[2] = (topology[2] + (i * topology.size()));
e[3] = (topology[0] + ((i + 1) * topology.size()));
e[4] = (topology[1] + ((i + 1) * topology.size()));
e[5] = (topology[2] + ((i + 1) * topology.size()));
std::cout << "v, e: " << v << ", " << e << "\n";
VTKM_TEST_ASSERT(test_equal(v, e), "incorrect conversion of topology to Cartesian space");
}
auto v = portal.Get(expectedLen - 1);
vtkm::Vec<int, 6> e;
e[0] = (topology[0] + ((expectedLen - 1) * topology.size()));
e[1] = (topology[1] + ((expectedLen - 1) * topology.size()));
e[2] = (topology[2] + ((expectedLen - 1) * topology.size()));
e[3] = (topology[0]);
e[4] = (topology[1]);
e[5] = (topology[2]);
VTKM_TEST_ASSERT(test_equal(v, e), "incorrect conversion of topology to Cartesian space");
}
int TestCellSetExtrude()
{
const std::size_t numPlanes = 8;
auto coords = vtkm::cont::make_ArrayHandleExtrudeCoords(points_rz, numPlanes, false);
auto cells = vtkm::cont::make_CellSetExtrude(topology, coords, nextNode);
VTKM_TEST_ASSERT(cells.GetNumberOfPoints() == coords.GetNumberOfValues(),
"number of points don't match between cells and coordinates");
// Verify the topology by copying it into another array
{
vtkm::cont::ArrayHandle<vtkm::Vec<int, 6>> output;
vtkm::worklet::DispatcherMapTopology<CopyTopo> dispatcher;
dispatcher.Invoke(cells, output);
verify_topo(output, 8);
}
// Verify the reverse topology by copying the number of cells each point is
// used by it into another array
{
vtkm::cont::ArrayHandle<int> output;
vtkm::worklet::DispatcherMapTopology<CopyReverseCellCount> dispatcher;
dispatcher.Invoke(cells, output);
// verify_topo(output, 8);
}
//test a filter
vtkm::cont::DataSet dataset;
dataset.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coords", coords));
dataset.AddCellSet(cells);
// verify that a constant value point field can be accessed
std::vector<float> pvalues(coords.GetNumberOfValues(), 42.0f);
vtkm::cont::Field pfield(
"pfield", vtkm::cont::Field::Association::POINTS, vtkm::cont::make_ArrayHandle(pvalues));
dataset.AddField(pfield);
// verify that a constant cell value can be accessed
std::vector<float> cvalues(cells.GetNumberOfCells(), 42.0f);
vtkm::cont::Field cfield("cfield",
vtkm::cont::Field::Association::CELL_SET,
cells.GetName(),
vtkm::cont::make_ArrayHandle(cvalues));
dataset.AddField(cfield);
vtkm::filter::PointAverage avg;
try
{
avg.SetActiveField("cfield");
auto result = avg.Execute(dataset, PolicyExtrude{});
VTKM_TEST_ASSERT(result.HasField("cfield", vtkm::cont::Field::Association::POINTS),
"filter resulting dataset should be valid");
}
catch (const vtkm::cont::Error& err)
{
std::cout << err.GetMessage() << std::endl;
VTKM_TEST_ASSERT(false, "Filter execution threw an exception");
}
return 0;
}
}
int UnitTestCellSetExtrude(int argc, char* argv[])
{
vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(vtkm::cont::DeviceAdapterTagSerial{});
return vtkm::cont::testing::Testing::Run(TestCellSetExtrude, argc, argv);
}

@ -23,6 +23,7 @@ set(headers
CellMeasure.h
ColorTable.h
ConnectivityExplicit.h
ConnectivityExtrude.h
ConnectivityPermuted.h
ConnectivityStructured.h
ExecutionWholeArray.h

@ -0,0 +1,247 @@
#ifndef vtk_m_exec_ConnectivityExtrude_h
#define vtk_m_exec_ConnectivityExtrude_h
#include <vtkm/internal/IndicesExtrude.h>
#include <vtkm/CellShape.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/exec/arg/ThreadIndicesTopologyMap.h>
namespace vtkm
{
namespace exec
{
template <typename Device>
class VTKM_ALWAYS_EXPORT ConnectivityExtrude
{
private:
using Int32HandleType = vtkm::cont::ArrayHandle<vtkm::Int32>;
using Int32PortalType = typename Int32HandleType::template ExecutionTypes<Device>::PortalConst;
public:
using ConnectivityPortalType = Int32PortalType;
using NextNodePortalType = Int32PortalType;
using SchedulingRangeType = vtkm::Id2;
using CellShapeTag = vtkm::CellShapeTagWedge;
using IndicesType = IndicesExtrude;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ConnectivityExtrude() = default;
ConnectivityExtrude(const ConnectivityPortalType& conn,
const NextNodePortalType& nextnode,
vtkm::Int32 cellsPerPlane,
vtkm::Int32 pointsPerPlane,
vtkm::Int32 numPlanes,
bool periodic);
VTKM_EXEC
vtkm::Id GetNumberOfElements() const { return this->NumberOfCells; }
VTKM_EXEC
CellShapeTag GetCellShape(vtkm::Id) const { return vtkm::CellShapeTagWedge(); }
VTKM_EXEC
IndicesType GetIndices(vtkm::Id index) const
{
return this->GetIndices(this->FlatToLogicalToIndex(index));
}
VTKM_EXEC
IndicesType GetIndices(const vtkm::Id2& index) const;
template <typename IndexType>
VTKM_EXEC vtkm::IdComponent GetNumberOfIndices(const IndexType& vtkmNotUsed(index)) const
{
return 6;
}
VTKM_EXEC
vtkm::Id LogicalToFlatToIndex(const vtkm::Id2& index) const
{
return index[0] + (index[1] * this->NumberOfCellsPerPlane);
};
VTKM_EXEC
vtkm::Id2 FlatToLogicalToIndex(vtkm::Id index) const
{
const vtkm::Id cellId = index % this->NumberOfCellsPerPlane;
const vtkm::Id plane = index / this->NumberOfCellsPerPlane;
return vtkm::Id2(cellId, plane);
}
private:
ConnectivityPortalType Connectivity;
NextNodePortalType NextNode;
vtkm::Int32 NumberOfCellsPerPlane;
vtkm::Int32 NumberOfPointsPerPlane;
vtkm::Int32 NumberOfPlanes;
vtkm::Id NumberOfCells;
};
template <typename Device>
class VTKM_ALWAYS_EXPORT ReverseConnectivityExtrude
{
private:
using Int32HandleType = vtkm::cont::ArrayHandle<vtkm::Int32>;
using Int32PortalType = typename Int32HandleType::template ExecutionTypes<Device>::PortalConst;
public:
using ConnectivityPortalType = Int32PortalType;
using OffsetsPortalType = Int32PortalType;
using CountsPortalType = Int32PortalType;
using PrevNodePortalType = Int32PortalType;
using SchedulingRangeType = vtkm::Id2;
using CellShapeTag = vtkm::CellShapeTagVertex;
using IndicesType = ReverseIndicesExtrude<ConnectivityPortalType>;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ReverseConnectivityExtrude() = default;
ReverseConnectivityExtrude(const ConnectivityPortalType& conn,
const OffsetsPortalType& offsets,
const CountsPortalType& counts,
const PrevNodePortalType& prevNode,
vtkm::Int32 cellsPerPlane,
vtkm::Int32 pointsPerPlane,
vtkm::Int32 numPlanes);
VTKM_EXEC
vtkm::Id GetNumberOfElements() const
{
return this->NumberOfPointsPerPlane * this->NumberOfPlanes;
}
VTKM_EXEC
CellShapeTag GetCellShape(vtkm::Id) const { return vtkm::CellShapeTagVertex(); }
/// Returns a Vec-like object containing the indices for the given index.
/// The object returned is not an actual array, but rather an object that
/// loads the indices lazily out of the connectivity array. This prevents
/// us from having to know the number of indices at compile time.
///
VTKM_EXEC
IndicesType GetIndices(vtkm::Id index) const
{
return this->GetIndices(this->FlatToLogicalToIndex(index));
}
VTKM_EXEC
IndicesType GetIndices(const vtkm::Id2& index) const;
template <typename IndexType>
VTKM_EXEC vtkm::IdComponent GetNumberOfIndices(const IndexType& index) const
{
return 1;
}
VTKM_EXEC
vtkm::Id LogicalToFlatToIndex(const vtkm::Id2& index) const
{
return index[0] + (index[1] * this->NumberOfPointsPerPlane);
};
VTKM_EXEC
vtkm::Id2 FlatToLogicalToIndex(vtkm::Id index) const
{
const vtkm::Id vertId = index % this->NumberOfPointsPerPlane;
const vtkm::Id plane = index / this->NumberOfPointsPerPlane;
return vtkm::Id2(vertId, plane);
}
ConnectivityPortalType Connectivity;
OffsetsPortalType Offsets;
CountsPortalType Counts;
PrevNodePortalType PrevNode;
vtkm::Int32 NumberOfCellsPerPlane;
vtkm::Int32 NumberOfPointsPerPlane;
vtkm::Int32 NumberOfPlanes;
};
template <typename Device>
ConnectivityExtrude<Device>::ConnectivityExtrude(const ConnectivityPortalType& conn,
const ConnectivityPortalType& nextNode,
vtkm::Int32 cellsPerPlane,
vtkm::Int32 pointsPerPlane,
vtkm::Int32 numPlanes,
bool periodic)
: Connectivity(conn)
, NextNode(nextNode)
, NumberOfCellsPerPlane(cellsPerPlane)
, NumberOfPointsPerPlane(pointsPerPlane)
, NumberOfPlanes(numPlanes)
{
this->NumberOfCells = periodic ? (static_cast<vtkm::Id>(cellsPerPlane) * numPlanes)
: (static_cast<vtkm::Id>(cellsPerPlane) * (numPlanes - 1));
}
template <typename Device>
typename ConnectivityExtrude<Device>::IndicesType ConnectivityExtrude<Device>::GetIndices(
const vtkm::Id2& index) const
{
vtkm::Id tr = index[0];
vtkm::Id p0 = index[1];
vtkm::Id p1 = (p0 < (this->NumberOfPlanes - 1)) ? (p0 + 1) : 0;
vtkm::Vec<vtkm::Int32, 3> pointIds1, pointIds2;
for (int i = 0; i < 3; ++i)
{
pointIds1[i] = this->Connectivity.Get((tr * 3) + i);
pointIds2[i] = this->NextNode.Get(pointIds1[i]);
}
return IndicesType(pointIds1, p0, pointIds2, p1, this->NumberOfPointsPerPlane);
}
template <typename Device>
ReverseConnectivityExtrude<Device>::ReverseConnectivityExtrude(const ConnectivityPortalType& conn,
const OffsetsPortalType& offsets,
const CountsPortalType& counts,
const PrevNodePortalType& prevNode,
vtkm::Int32 cellsPerPlane,
vtkm::Int32 pointsPerPlane,
vtkm::Int32 numPlanes)
: Connectivity(conn)
, Offsets(offsets)
, Counts(counts)
, PrevNode(prevNode)
, NumberOfCellsPerPlane(cellsPerPlane)
, NumberOfPointsPerPlane(pointsPerPlane)
, NumberOfPlanes(numPlanes)
{
}
template <typename Device>
typename ReverseConnectivityExtrude<Device>::IndicesType
ReverseConnectivityExtrude<Device>::GetIndices(const vtkm::Id2& index) const
{
auto ptCur = index[0];
auto ptPre = this->PrevNode.Get(ptCur);
auto plCur = index[1];
auto plPre = (plCur == 0) ? (this->NumberOfPlanes - 1) : (plCur - 1);
return IndicesType(this->Connectivity,
this->Offsets.Get(ptPre),
this->Counts.Get(ptPre),
this->Offsets.Get(ptCur),
this->Counts.Get(ptCur),
plPre,
plCur,
this->NumberOfCellsPerPlane);
}
}
} // namespace vtkm::exec
#endif

@ -15,6 +15,7 @@ set(headers
CellShape.h
ExecutionSignatureTagBase.h
Fetch.h
FetchExtrude.h
FetchTagArrayDirectIn.h
FetchTagArrayDirectInOut.h
FetchTagArrayDirectOut.h
@ -30,6 +31,7 @@ set(headers
OutputIndex.h
ThreadIndices.h
ThreadIndicesBasic.h
ThreadIndicesExtrude.h
ThreadIndicesPointNeighborhood.h
ThreadIndicesReduceByKey.h
ThreadIndicesTopologyMap.h

@ -0,0 +1,187 @@
#ifndef vtk_m_exec_arg_FetchExtrude_h
#define vtk_m_exec_arg_FetchExtrude_h
#include <vtkm/cont/ArrayPortalExtrude.h>
#include <vtkm/cont/ArrayPortalExtrudePlane.h>
#include <vtkm/exec/ConnectivityExtrude.h>
#include <vtkm/exec/arg/FetchTagArrayDirectIn.h>
#include <vtkm/exec/arg/FetchTagArrayTopologyMapIn.h>
#include <vtkm/exec/arg/FromIndices.h>
//optimized fetches for ArrayPortalExtrude for
// - 3D Scheduling
// - WorkletNeighboorhood
namespace vtkm
{
namespace exec
{
namespace arg
{
//Optimized fetch for point ids when iterating the cells ConnectivityExtrude
template <typename FetchType, typename Device, typename ExecObjectType>
struct Fetch<FetchType,
vtkm::exec::arg::AspectTagFromIndices,
vtkm::exec::arg::ThreadIndicesTopologyMap<vtkm::exec::ConnectivityExtrude<Device>>,
ExecObjectType>
{
using ThreadIndicesType =
vtkm::exec::arg::ThreadIndicesTopologyMap<vtkm::exec::ConnectivityExtrude<Device>>;
using ValueType = vtkm::Vec<vtkm::Id, 6>;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
ValueType Load(const ThreadIndicesType& indices, const ExecObjectType&) const
{
// std::cout << "opimized fetch for point ids" << std::endl;
const auto& xgcidx = indices.GetIndicesFrom();
const vtkm::Id offset1 = (xgcidx.Planes[0] * xgcidx.NumberOfPointsPerPlane);
const vtkm::Id offset2 = (xgcidx.Planes[1] * xgcidx.NumberOfPointsPerPlane);
ValueType result;
result[0] = offset1 + xgcidx.PointIds[0][0];
result[1] = offset1 + xgcidx.PointIds[0][1];
result[2] = offset1 + xgcidx.PointIds[0][2];
result[3] = offset2 + xgcidx.PointIds[1][0];
result[4] = offset2 + xgcidx.PointIds[1][1];
result[5] = offset2 + xgcidx.PointIds[1][2];
return result;
}
VTKM_EXEC
void Store(const ThreadIndicesType&, const ExecObjectType&, const ValueType&) const
{
// Store is a no-op.
}
};
//Optimized fetch for point arrays when iterating the cells ConnectivityExtrude
template <typename Device, typename PortalType>
struct Fetch<vtkm::exec::arg::FetchTagArrayTopologyMapIn,
vtkm::exec::arg::AspectTagDefault,
vtkm::exec::arg::ThreadIndicesTopologyMap<vtkm::exec::ConnectivityExtrude<Device>>,
PortalType>
{
using ThreadIndicesType =
vtkm::exec::arg::ThreadIndicesTopologyMap<vtkm::exec::ConnectivityExtrude<Device>>;
using ValueType = vtkm::Vec<typename PortalType::ValueType, 6>;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
ValueType Load(const ThreadIndicesType& indices, const PortalType& portal)
{
// std::cout << "opimized fetch for point values" << std::endl;
const auto& xgcidx = indices.GetIndicesFrom();
const vtkm::Id offset1 = (xgcidx.Planes[0] * xgcidx.NumberOfPointsPerPlane);
const vtkm::Id offset2 = (xgcidx.Planes[1] * xgcidx.NumberOfPointsPerPlane);
ValueType result;
result[0] = portal.Get(offset1 + xgcidx.PointIds[0][0]);
result[1] = portal.Get(offset1 + xgcidx.PointIds[0][1]);
result[2] = portal.Get(offset1 + xgcidx.PointIds[0][2]);
result[3] = portal.Get(offset2 + xgcidx.PointIds[1][0]);
result[4] = portal.Get(offset2 + xgcidx.PointIds[1][1]);
result[5] = portal.Get(offset2 + xgcidx.PointIds[1][2]);
return result;
}
VTKM_EXEC
void Store(const ThreadIndicesType&, const PortalType&, const ValueType&) const
{
// Store is a no-op for this fetch.
}
};
//Optimized fetch for point coordinates when iterating the cells of ConnectivityExtrude
template <typename Device, typename T>
struct Fetch<vtkm::exec::arg::FetchTagArrayTopologyMapIn,
vtkm::exec::arg::AspectTagDefault,
vtkm::exec::arg::ThreadIndicesTopologyMap<vtkm::exec::ConnectivityExtrude<Device>>,
vtkm::exec::ArrayPortalExtrude<T>>
{
using ThreadIndicesType =
vtkm::exec::arg::ThreadIndicesTopologyMap<vtkm::exec::ConnectivityExtrude<Device>>;
using ValueType = vtkm::Vec<typename vtkm::exec::ArrayPortalExtrude<T>::ValueType, 6>;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
ValueType Load(const ThreadIndicesType& indices, const vtkm::exec::ArrayPortalExtrude<T>& points)
{
// std::cout << "opimized fetch for point coordinates" << std::endl;
return points.GetWedge(indices.GetIndicesFrom());
}
VTKM_EXEC
void Store(const ThreadIndicesType&,
const vtkm::exec::ArrayPortalExtrude<T>&,
const ValueType&) const
{
// Store is a no-op for this fetch.
}
};
//Optimized fetch for point coordinates when iterating the cells of ConnectivityExtrude
template <typename Device, typename T>
struct Fetch<vtkm::exec::arg::FetchTagArrayTopologyMapIn,
vtkm::exec::arg::AspectTagDefault,
vtkm::exec::arg::ThreadIndicesTopologyMap<vtkm::exec::ConnectivityExtrude<Device>>,
vtkm::exec::ArrayPortalExtrudePlane<T>>
{
using ThreadIndicesType =
vtkm::exec::arg::ThreadIndicesTopologyMap<vtkm::exec::ConnectivityExtrude<Device>>;
using ValueType = vtkm::Vec<typename vtkm::exec::ArrayPortalExtrudePlane<T>::ValueType, 6>;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
ValueType Load(const ThreadIndicesType& indices,
const vtkm::exec::ArrayPortalExtrudePlane<T>& portal)
{
// std::cout << "opimized fetch for point coordinates" << std::endl;
return portal.GetWedge(indices.GetIndicesFrom());
}
VTKM_EXEC
void Store(const ThreadIndicesType&,
const vtkm::exec::ArrayPortalExtrudePlane<T>&,
const ValueType&) const
{
// Store is a no-op for this fetch.
}
};
//Optimized fetch for point coordinates when iterating the points of ConnectivityExtrude
template <typename Device, typename T>
struct Fetch<
vtkm::exec::arg::FetchTagArrayDirectIn,
vtkm::exec::arg::AspectTagDefault,
vtkm::exec::arg::ThreadIndicesTopologyMap<vtkm::exec::ReverseConnectivityExtrude<Device>>,
vtkm::exec::ArrayPortalExtrude<T>>
{
using ThreadIndicesType =
vtkm::exec::arg::ThreadIndicesTopologyMap<vtkm::exec::ReverseConnectivityExtrude<Device>>;
using ValueType = typename vtkm::exec::ArrayPortalExtrude<T>::ValueType;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
ValueType Load(const ThreadIndicesType& indices, const vtkm::exec::ArrayPortalExtrude<T>& points)
{
// std::cout << "opimized fetch for point coordinates" << std::endl;
return points.Get(indices.GetIndexLogical());
}
VTKM_EXEC
void Store(const ThreadIndicesType&,
const vtkm::exec::ArrayPortalExtrude<T>&,
const ValueType&) const
{
// Store is a no-op for this fetch.
}
};
}
}
}
#endif

@ -0,0 +1,301 @@
#ifndef vtk_m_exec_arg_ThreadIndicesExtrude_h
#define vtk_m_exec_arg_ThreadIndicesExtrude_h
#include <vtkm/exec/ConnectivityExtrude.h>
#include <vtkm/exec/arg/ThreadIndicesTopologyMap.h>
namespace vtkm
{
namespace exec
{
namespace arg
{
// Specialization for extrude types.
template <typename Device>
class ThreadIndicesTopologyMap<vtkm::exec::ConnectivityExtrude<Device>>
{
using ConnectivityType = vtkm::exec::ConnectivityExtrude<Device>;
public:
using CellShapeTag = typename ConnectivityType::CellShapeTag;
using IndicesFromType = typename ConnectivityType::IndicesType;
using LogicalIndexType = typename ConnectivityType::SchedulingRangeType;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC ThreadIndicesTopologyMap(vtkm::Id threadIndex,
vtkm::Id vtkmNotUsed(inputIndex),
vtkm::IdComponent vtkmNotUsed(visitIndex),
vtkm::Id vtkmNotUsed(outputIndex),
const ConnectivityType& connectivity,
vtkm::Id globalThreadIndexOffset = 0)
{
const LogicalIndexType logicalIndex = detail::Deflate(threadIndex, LogicalIndexType());
const vtkm::Id index = connectivity.LogicalToFlatToIndex(logicalIndex);
this->ThreadIndex = index;
this->InputIndex = index;
this->OutputIndex = index;
this->VisitIndex = 0;
this->LogicalIndex = logicalIndex;
this->IndicesFrom = connectivity.GetIndices(logicalIndex);
//this->CellShape = connectivity.GetCellShape(index);
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
ThreadIndicesTopologyMap(const vtkm::Id3& threadIndex,
const ConnectivityType& connectivity,
vtkm::Id globalThreadIndexOffset = 0)
{
// We currently only support multidimensional indices on one-to-one input-
// to-output mappings. (We don't have a use case otherwise.)
// That is why we treat teh threadIndex as also the inputIndex and outputIndex
const LogicalIndexType logicalIndex = detail::Deflate(threadIndex, LogicalIndexType());
const vtkm::Id index = connectivity.LogicalToFlatToIndex(logicalIndex);
this->ThreadIndex = index;
this->InputIndex = index;
this->OutputIndex = index;
this->VisitIndex = 0;
this->LogicalIndex = logicalIndex;
this->IndicesFrom = connectivity.GetIndices(logicalIndex);
//this->CellShape = connectivity.GetCellShape(index);
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
/// \brief The logical index into the input domain.
///
/// This is similar to \c GetIndex3D except the Vec size matches the actual
/// dimensions of the data.
///
VTKM_EXEC
LogicalIndexType GetIndexLogical() const { return this->LogicalIndex; }
/// \brief The index into the input domain.
///
/// This index refers to the input element (array value, cell, etc.) that
/// this thread is being invoked for. This is the typical index used during
/// fetches.
///
VTKM_EXEC
vtkm::Id GetInputIndex() const { return this->InputIndex; }
/// \brief The 3D index into the input domain.
///
/// Overloads the implementation in the base class to return the 3D index
/// for the input.
///
VTKM_EXEC
vtkm::Id3 GetInputIndex3D() const { return detail::InflateTo3D(this->GetIndexLogical()); }
/// \brief The index into the output domain.
///
/// This index refers to the output element (array value, cell, etc.) that
/// this thread is creating. This is the typical index used during
/// Fetch::Store.
///
VTKM_EXEC
vtkm::Id GetOutputIndex() const { return this->OutputIndex; }
/// \brief The visit index.
///
/// When multiple output indices have the same input index, they are
/// distinguished using the visit index.
///
VTKM_EXEC
vtkm::IdComponent GetVisitIndex() const { return this->VisitIndex; }
VTKM_EXEC
vtkm::Id GetGlobalIndex() const { return (this->GlobalThreadIndexOffset + this->OutputIndex); }
/// \brief The input indices of the "from" elements.
///
/// A topology map has "from" and "to" elements (for example from points to
/// cells). For each worklet invocation, there is exactly one "to" element,
/// but can be several "from" element. This method returns a Vec-like object
/// containing the indices to the "from" elements.
///
VTKM_EXEC
const IndicesFromType& GetIndicesFrom() const { return this->IndicesFrom; }
/// \brief The input indices of the "from" elements in pointer form.
///
/// Returns the same object as GetIndicesFrom except that it returns a
/// pointer to the internally held object rather than a reference or copy.
/// Since the from indices can be a sizeable Vec (8 entries is common), it is
/// best not to have a bunch a copies. Thus, you can pass around a pointer
/// instead. However, care should be taken to make sure that this object does
/// not go out of scope, at which time the returned pointer becomes invalid.
///
VTKM_EXEC
const IndicesFromType* GetIndicesFromPointer() const { return &this->IndicesFrom; }
/// \brief The shape of the input cell.
///
/// In topology maps that map from points to something, the indices make up
/// the structure of a cell. Although the shape tag is not technically and
/// index, it defines the meaning of the indices, so we put it here. (That
/// and this class is the only convenient place to store it.)
///
VTKM_EXEC
CellShapeTag GetCellShape() const { return vtkm::CellShapeTagWedge{}; }
private:
vtkm::Id ThreadIndex;
vtkm::Id InputIndex;
vtkm::IdComponent VisitIndex;
vtkm::Id OutputIndex;
LogicalIndexType LogicalIndex;
IndicesFromType IndicesFrom;
//CellShapeTag CellShape;
vtkm::Id GlobalThreadIndexOffset;
};
// Specialization for extrude types.
template <typename Device>
class ThreadIndicesTopologyMap<vtkm::exec::ReverseConnectivityExtrude<Device>>
{
using ConnectivityType = vtkm::exec::ReverseConnectivityExtrude<Device>;
public:
using CellShapeTag = typename ConnectivityType::CellShapeTag;
using IndicesFromType = typename ConnectivityType::IndicesType;
using LogicalIndexType = typename ConnectivityType::SchedulingRangeType;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
ThreadIndicesTopologyMap(vtkm::Id& threadIndex,
vtkm::Id vtkmNotUsed(inputIndex),
vtkm::IdComponent vtkmNotUsed(visitIndex),
vtkm::Id vtkmNotUsed(outputIndex),
const ConnectivityType& connectivity,
vtkm::Id globalThreadIndexOffset = 0)
{
const LogicalIndexType logicalIndex = detail::Deflate(threadIndex, LogicalIndexType());
const vtkm::Id index = connectivity.LogicalToFlatToIndex(logicalIndex);
this->ThreadIndex = index;
this->InputIndex = index;
this->OutputIndex = index;
this->VisitIndex = 0;
this->LogicalIndex = logicalIndex;
this->IndicesFrom = connectivity.GetIndices(logicalIndex);
//this->CellShape = connectivity.GetCellShape(index);
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
ThreadIndicesTopologyMap(const vtkm::Id3& threadIndex,
const ConnectivityType& connectivity,
vtkm::Id globalThreadIndexOffset = 0)
{
const LogicalIndexType logicalIndex = detail::Deflate(threadIndex, LogicalIndexType());
const vtkm::Id index = connectivity.LogicalToFlatToIndex(logicalIndex);
this->ThreadIndex = index;
this->InputIndex = index;
this->OutputIndex = index;
this->VisitIndex = 0;
this->LogicalIndex = logicalIndex;
this->IndicesFrom = connectivity.GetIndices(logicalIndex);
//this->CellShape = connectivity.GetCellShape(index);
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
/// \brief The logical index into the input domain.
///
/// This is similar to \c GetIndex3D except the Vec size matches the actual
/// dimensions of the data.
///
VTKM_EXEC
LogicalIndexType GetIndexLogical() const { return this->LogicalIndex; }
/// \brief The index into the input domain.
///
/// This index refers to the input element (array value, cell, etc.) that
/// this thread is being invoked for. This is the typical index used during
/// fetches.
///
VTKM_EXEC
vtkm::Id GetInputIndex() const { return this->InputIndex; }
/// \brief The 3D index into the input domain.
///
/// Overloads the implementation in the base class to return the 3D index
/// for the input.
///
VTKM_EXEC
vtkm::Id3 GetInputIndex3D() const { return detail::InflateTo3D(this->GetIndexLogical()); }
/// \brief The index into the output domain.
///
/// This index refers to the output element (array value, cell, etc.) that
/// this thread is creating. This is the typical index used during
/// Fetch::Store.
///
VTKM_EXEC
vtkm::Id GetOutputIndex() const { return this->OutputIndex; }
/// \brief The visit index.
///
/// When multiple output indices have the same input index, they are
/// distinguished using the visit index.
///
VTKM_EXEC
vtkm::IdComponent GetVisitIndex() const { return this->VisitIndex; }
VTKM_EXEC
vtkm::Id GetGlobalIndex() const { return (this->GlobalThreadIndexOffset + this->OutputIndex); }
/// \brief The input indices of the "from" elements.
///
/// A topology map has "from" and "to" elements (for example from points to
/// cells). For each worklet invocation, there is exactly one "to" element,
/// but can be several "from" element. This method returns a Vec-like object
/// containing the indices to the "from" elements.
///
VTKM_EXEC
const IndicesFromType& GetIndicesFrom() const { return this->IndicesFrom; }
/// \brief The input indices of the "from" elements in pointer form.
///
/// Returns the same object as GetIndicesFrom except that it returns a
/// pointer to the internally held object rather than a reference or copy.
/// Since the from indices can be a sizeable Vec (8 entries is common), it is
/// best not to have a bunch a copies. Thus, you can pass around a pointer
/// instead. However, care should be taken to make sure that this object does
/// not go out of scope, at which time the returned pointer becomes invalid.
///
VTKM_EXEC
const IndicesFromType* GetIndicesFromPointer() const { return &this->IndicesFrom; }
/// \brief The shape of the input cell.
///
/// In topology maps that map from points to something, the indices make up
/// the structure of a cell. Although the shape tag is not technically and
/// index, it defines the meaning of the indices, so we put it here. (That
/// and this class is the only convenient place to store it.)
///
VTKM_EXEC
CellShapeTag GetCellShape() const { return vtkm::CellShapeTagVertex{}; }
private:
vtkm::Id ThreadIndex;
vtkm::Id InputIndex;
vtkm::IdComponent VisitIndex;
vtkm::Id OutputIndex;
LogicalIndexType LogicalIndex;
IndicesFromType IndicesFrom;
//CellShapeTag CellShape;
vtkm::Id GlobalThreadIndexOffset;
};
} //namespace arg
}
} // namespace vtkm::exec
#include <vtkm/exec/arg/FetchExtrude.h>
#endif

@ -52,6 +52,7 @@ set(headers
PointTransform.h
PolicyBase.h
PolicyDefault.h
PolicyExtrude.h
Probe.h
SplitSharpEdges.h
Streamline.h

@ -0,0 +1,45 @@
//=============================================================================
//
// 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 2012 Sandia Corporation.
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
//=============================================================================
#ifndef vtk_m_filter_PolicyExtrude_h
#define vtk_m_filter_PolicyExtrude_h
#include <vtkm/cont/ArrayHandleExtrudeCoords.h>
#include <vtkm/cont/CellSetExtrude.h>
#include <vtkm/ListTag.h>
#include <vtkm/filter/PolicyDefault.h>
struct VTKM_ALWAYS_EXPORT ExtrudeUnstructuredCellSets
: vtkm::ListTagBase<vtkm::cont::CellSetExtrude>
{
};
//Todo: add in Cylinder storage tag when it is written
struct VTKM_ALWAYS_EXPORT ExtrudeCoordinateStorage
: vtkm::ListTagBase<vtkm::cont::StorageTagBasic, vtkm::cont::internal::StorageTagExtrude>
{
};
struct VTKM_ALWAYS_EXPORT PolicyExtrude : vtkm::filter::PolicyBase<PolicyExtrude>
{
public:
using UnstructuredCellSetList = ExtrudeUnstructuredCellSets;
using AllCellSetList = ExtrudeUnstructuredCellSets;
using CoordinateStorageList = ExtrudeCoordinateStorage;
};
#endif

@ -26,11 +26,20 @@ public:
}
template <typename CellSetType>
void operator()(const CellSetType& cellset) const
void operator()(const CellSetType& vtkmNotUsed(cellset)) const
{
this->OutCellSet = Worklet.Run(cellset);
}
};
template <>
void DeduceCellSet::operator()(const vtkm::cont::CellSetExplicit<>& cellset) const
{
this->OutCellSet = Worklet.Run(cellset);
}
template <>
void DeduceCellSet::operator()(const vtkm::cont::CellSetStructured<3>& cellset) const
{
this->OutCellSet = Worklet.Run(cellset);
}
}
namespace vtkm

@ -60,6 +60,7 @@ set(headers
FunctionInterfaceDetailPost.h
FunctionInterfaceDetailPre.h
IndexTag.h
IndicesExtrude.h
Invocation.h
ListTagDetail.h
Unreachable.h

@ -0,0 +1,126 @@
#ifndef vtk_m_internal_IndicesExtrude_h
#define vtk_m_internal_IndicesExtrude_h
#include <vtkm/Math.h>
#include <vtkm/Types.h>
namespace vtkm
{
namespace exec
{
struct IndicesExtrude
{
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
IndicesExtrude() = default;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
IndicesExtrude(vtkm::Vec<vtkm::Int32, 3> pointIds1,
vtkm::Int32 plane1,
vtkm::Vec<vtkm::Int32, 3> pointIds2,
vtkm::Int32 plane2,
vtkm::Int32 numberOfPointsPerPlane)
: PointIds{ pointIds1, pointIds2 }
, Planes{ plane1, plane2 }
, NumberOfPointsPerPlane(numberOfPointsPerPlane)
{
}
VTKM_EXEC
vtkm::Id operator[](vtkm::IdComponent index) const
{
VTKM_ASSERT(index >= 0 && index < 6);
if (index < 3)
{
return (static_cast<vtkm::Id>(this->NumberOfPointsPerPlane) * this->Planes[0]) +
this->PointIds[0][index];
}
else
{
return (static_cast<vtkm::Id>(this->NumberOfPointsPerPlane) * this->Planes[1]) +
this->PointIds[1][index - 3];
}
}
VTKM_EXEC
constexpr vtkm::IdComponent GetNumberOfComponents() const { return 6; }
template <typename T, vtkm::IdComponent DestSize>
VTKM_EXEC void CopyInto(vtkm::Vec<T, DestSize>& dest) const
{
for (vtkm::IdComponent i = 0; i < vtkm::Min(6, DestSize); ++i)
{
dest[i] = (*this)[i];
}
}
vtkm::Vec<vtkm::Int32, 3> PointIds[2];
vtkm::Int32 Planes[2];
vtkm::Int32 NumberOfPointsPerPlane;
};
template <typename ConnectivityPortalType>
struct ReverseIndicesExtrude
{
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ReverseIndicesExtrude() = default;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ReverseIndicesExtrude(const ConnectivityPortalType conn,
vtkm::Id offset1,
vtkm::IdComponent length1,
vtkm::Id offset2,
vtkm::IdComponent length2,
vtkm::IdComponent plane1,
vtkm::IdComponent plane2,
vtkm::Int32 numberOfCellsPerPlane)
: Connectivity(conn)
, Offset1(offset1)
, Offset2(offset2)
, Length1(length1)
, NumberOfComponents(length1 + length2)
, CellOffset1(plane1 * numberOfCellsPerPlane)
, CellOffset2(plane2 * numberOfCellsPerPlane)
{
}
VTKM_EXEC
vtkm::Id operator[](vtkm::IdComponent index) const
{
VTKM_ASSERT(index >= 0 && index < (this->NumberOfComponents));
if (index < this->Length1)
{
return this->Connectivity.Get(this->Offset1 + index) + this->CellOffset1;
}
else
{
return this->Connectivity.Get(this->Offset2 + index - this->Length1) + this->CellOffset2;
}
}
VTKM_EXEC
vtkm::IdComponent GetNumberOfComponents() const { return this->NumberOfComponents; }
template <typename T, vtkm::IdComponent DestSize>
VTKM_EXEC void CopyInto(vtkm::Vec<T, DestSize>& dest) const
{
for (vtkm::IdComponent i = 0; i < vtkm::Min(this->NumberOfComponents, DestSize); ++i)
{
dest[i] = (*this)[i];
}
}
ConnectivityPortalType Connectivity;
vtkm::Id Offset1, Offset2;
vtkm::IdComponent Length1;
vtkm::IdComponent NumberOfComponents;
vtkm::Id CellOffset1, CellOffset2;
};
}
}
#endif //vtkm_m_internal_IndicesExtrude_h

@ -68,12 +68,14 @@ public:
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagQuad shapeType, vtkm::Id& segments) const
void operator()(vtkm::CellShapeTagQuad vtkmNotUsed(shapeType), vtkm::Id& segments) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
segments = 4;
else
segments = 0;
segments = 4;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), vtkm::Id& segments) const
{
segments = 24;
}
}; //class CountSegments
@ -279,7 +281,24 @@ public:
tri2seg(offset, cellIndices, cellId, 4, 5, 6, outputIndices);
tri2seg(offset, cellIndices, cellId, 4, 6, 7, outputIndices);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagWedge vtkmNotUsed(shapeType),
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
vtkm::Id offset = pointOffset;
tri2seg(offset, cellIndices, cellId, 0, 1, 2, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 5, 4, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 0, 2, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 2, 5, outputIndices);
tri2seg(offset, cellIndices, cellId, 1, 4, 5, outputIndices);
tri2seg(offset, cellIndices, cellId, 1, 5, 2, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 3, 4, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 4, 1, outputIndices);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagGeneric shapeType,

@ -69,6 +69,11 @@ public:
else
quads = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), vtkm::Id& quads) const
{
quads = 3;
}
}; //class CountQuads
template <int DIM>
@ -191,7 +196,19 @@ public:
outputIndices.Set(offset++, quad);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagWedge vtkmNotUsed(shapeType),
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
vtkm::Id offset = pointOffset;
cell2quad(offset, cellIndices, cellId, 3, 0, 2, 5, outputIndices);
cell2quad(offset, cellIndices, cellId, 1, 4, 5, 2, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 3, 4, 1, outputIndices);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& offset,
vtkm::CellShapeTagQuad shapeType,

@ -71,6 +71,11 @@ public:
{
triangles = 2;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), vtkm::Id& triangles) const
{
triangles = 8;
}
}; //class CountTriangles
template <int DIM>
@ -271,6 +276,56 @@ public:
using ControlSignature = void(CellSetIn cellset, FieldInCell, WholeArrayOut);
using ExecutionSignature = void(_2, CellShape, PointIndices, WorkIndex, _3);
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& triangleOffset,
vtkm::CellShapeTagWedge vtkmNotUsed(shapeType),
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
vtkm::Vec<vtkm::Id, 4> triangle;
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[1];
triangle[3] = cellIndices[2];
triangle[0] = cellId;
outputIndices.Set(triangleOffset, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[5];
triangle[3] = cellIndices[4];
outputIndices.Set(triangleOffset + 1, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[0];
triangle[3] = cellIndices[2];
outputIndices.Set(triangleOffset + 2, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[5];
outputIndices.Set(triangleOffset + 3, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[4];
triangle[3] = cellIndices[5];
outputIndices.Set(triangleOffset + 4, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[5];
triangle[3] = cellIndices[2];
outputIndices.Set(triangleOffset + 5, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[3];
triangle[3] = cellIndices[4];
outputIndices.Set(triangleOffset + 6, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[4];
triangle[3] = cellIndices[1];
outputIndices.Set(triangleOffset + 7, triangle);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& triangleOffset,
vtkm::CellShapeTagQuad vtkmNotUsed(shapeType),

@ -58,6 +58,11 @@ public:
{
points = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), vtkm::Id& points) const
{
points = 0;
}
}; // ClassCountSegments
@ -79,6 +84,15 @@ public:
{
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset),
vtkm::CellShapeTagWedge vtkmNotUsed(shapeType),
const VecType& vtkmNotUsed(cellIndices),
const vtkm::Id& vtkmNotUsed(cellId),
OutputPortal& vtkmNotUsed(outputIndices)) const
{
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset),
vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType),

@ -54,6 +54,11 @@ public:
{
points = 1;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), vtkm::Id& points) const
{
points = 0;
}
}; // ClassCountquads
@ -94,6 +99,15 @@ public:
{
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset),
vtkm::CellShapeTagWedge vtkmNotUsed(shapeType),
const VecType& vtkmNotUsed(cellIndices),
const vtkm::Id& vtkmNotUsed(cellId),
OutputPortal& vtkmNotUsed(outputIndices)) const
{
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType),

@ -53,6 +53,11 @@ public:
{
points = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), vtkm::Id& points) const
{
points = 0;
}
}; // ClassCountPoints
@ -73,6 +78,14 @@ public:
OutputPortal& vtkmNotUsed(outputIndices)) const
{
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset),
vtkm::CellShapeTagWedge vtkmNotUsed(shapeType),
const VecType& vtkmNotUsed(cellIndices),
const vtkm::Id& vtkmNotUsed(cellId),
OutputPortal& vtkmNotUsed(outputIndices)) const
{
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset),

@ -142,6 +142,15 @@ public:
{
}
template <typename IsoValuesType, typename FieldInType, typename NumTrianglesTablePortalType>
VTKM_EXEC void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shape),
const IsoValuesType& vtkmNotUsed(isovalues),
const FieldInType& vtkmNotUsed(fieldIn),
vtkm::IdComponent& vtkmNotUsed(numTriangles),
const NumTrianglesTablePortalType& vtkmNotUsed(numTrianglesTable)) const
{
}
template <typename IsoValuesType, typename FieldInType, typename NumTrianglesTablePortalType>
VTKM_EXEC void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shape),
const IsoValuesType& isovalues,
@ -330,6 +339,21 @@ public:
{ //covers when we have quads coming from 2d structured data
}
template <typename IsoValuesType,
typename FieldInType, // Vec-like, one per input point
typename IndicesVecType,
typename DeviceAdapter>
VTKM_EXEC void operator()(
CellShapeTagWedge vtkmNotUsed(shape),
const IsoValuesType& vtkmNotUsed(isovalues),
const FieldInType& vtkmNotUsed(fieldIn), // Input point field defining the contour
EdgeWeightGenerateMetaData::ExecObject<DeviceAdapter>& vtkmNotUsed(metaData),
vtkm::Id vtkmNotUsed(inputCellId),
vtkm::Id vtkmNotUsed(outputCellId),
vtkm::IdComponent vtkmNotUsed(visitIndex),
const IndicesVecType& vtkmNotUsed(indices)) const
{ //covers when we have quads coming from 2d structured data
}
template <typename IsoValuesType,
typename FieldInType, // Vec-like, one per input point
typename IndicesVecType,

@ -20,6 +20,7 @@
#include <vtkm/worklet/connectivities/InnerJoin.h>
#include <vtkm/worklet/connectivities/UnionFind.h>
namespace vtkm
{
namespace worklet

@ -102,37 +102,47 @@ public:
};
template <typename CellSetType>
vtkm::cont::CellSetSingleType<> Run(const CellSetType& cellSet,
vtkm::cont::ArrayHandle<vtkm::IdComponent>& outCellsPerCell)
vtkm::cont::CellSetSingleType<> Run(
const CellSetType& cellSet,
vtkm::cont::ArrayHandle<vtkm::IdComponent>& vtkmNotUsed(outCellsPerCell))
{
vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName());
// Input topology
auto inShapes =
cellSet.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
auto inNumIndices =
cellSet.GetNumIndicesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
// Output topology
vtkm::cont::ArrayHandle<vtkm::Id> outConnectivity;
vtkm::worklet::internal::TetrahedralizeTables tables;
// Determine the number of output cells each input cell will generate
vtkm::worklet::DispatcherMapField<TetrahedraPerCell> tetPerCellDispatcher;
tetPerCellDispatcher.Invoke(inShapes, tables.PrepareForInput(), outCellsPerCell);
// Build new cells
vtkm::worklet::DispatcherMapTopology<TetrahedralizeCell> tetrahedralizeDispatcher(
TetrahedralizeCell::MakeScatter(outCellsPerCell));
tetrahedralizeDispatcher.Invoke(
cellSet, tables.PrepareForInput(), vtkm::cont::make_ArrayHandleGroupVec<4>(outConnectivity));
// Add cells to output cellset
outCellSet.Fill(cellSet.GetNumberOfPoints(), vtkm::CellShapeTagTetra::Id, 4, outConnectivity);
return outCellSet;
}
};
template <>
vtkm::cont::CellSetSingleType<> TetrahedralizeExplicit::Run(
const vtkm::cont::CellSetExplicit<>& cellSet,
vtkm::cont::ArrayHandle<vtkm::IdComponent>& outCellsPerCell)
{
vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName());
// Input topology
auto inShapes =
cellSet.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
auto inNumIndices =
cellSet.GetNumIndicesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
// Output topology
vtkm::cont::ArrayHandle<vtkm::Id> outConnectivity;
vtkm::worklet::internal::TetrahedralizeTables tables;
// Determine the number of output cells each input cell will generate
vtkm::worklet::DispatcherMapField<TetrahedraPerCell> tetPerCellDispatcher;
tetPerCellDispatcher.Invoke(inShapes, tables.PrepareForInput(), outCellsPerCell);
// Build new cells
vtkm::worklet::DispatcherMapTopology<TetrahedralizeCell> tetrahedralizeDispatcher(
TetrahedralizeCell::MakeScatter(outCellsPerCell));
tetrahedralizeDispatcher.Invoke(
cellSet, tables.PrepareForInput(), vtkm::cont::make_ArrayHandleGroupVec<4>(outConnectivity));
// Add cells to output cellset
outCellSet.Fill(cellSet.GetNumberOfPoints(), vtkm::CellShapeTagTetra::Id, 4, outConnectivity);
return outCellSet;
}
}
} // namespace vtkm::worklet

@ -101,40 +101,46 @@ public:
connectivityOut[2] = connectivityIn[triIndices[2]];
}
};
template <typename CellSetType>
vtkm::cont::CellSetSingleType<> Run(const CellSetType& cellSet,
vtkm::cont::ArrayHandle<vtkm::IdComponent>& outCellsPerCell)
{
vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName());
// Input topology
auto inShapes =
cellSet.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
auto inNumIndices =
cellSet.GetNumIndicesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
// Output topology
vtkm::cont::ArrayHandle<vtkm::Id> outConnectivity;
vtkm::worklet::internal::TriangulateTables tables;
// Determine the number of output cells each input cell will generate
vtkm::worklet::DispatcherMapField<TrianglesPerCell> triPerCellDispatcher;
triPerCellDispatcher.Invoke(inShapes, inNumIndices, tables.PrepareForInput(), outCellsPerCell);
// Build new cells
vtkm::worklet::DispatcherMapTopology<TriangulateCell> triangulateDispatcher(
TriangulateCell::MakeScatter(outCellsPerCell));
triangulateDispatcher.Invoke(
cellSet, tables.PrepareForInput(), vtkm::cont::make_ArrayHandleGroupVec<3>(outConnectivity));
// Add cells to output cellset
outCellSet.Fill(
cellSet.GetNumberOfPoints(), vtkm::CellShapeTagTriangle::Id, 3, outConnectivity);
return outCellSet;
}
};
template <>
vtkm::cont::CellSetSingleType<> TriangulateExplicit::Run(
const vtkm::cont::CellSetExplicit<>& cellSet,
vtkm::cont::ArrayHandle<vtkm::IdComponent>& outCellsPerCell)
{
vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName());
// Input topology
auto inShapes =
cellSet.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
auto inNumIndices =
cellSet.GetNumIndicesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
// Output topology
vtkm::cont::ArrayHandle<vtkm::Id> outConnectivity;
vtkm::worklet::internal::TriangulateTables tables;
// Determine the number of output cells each input cell will generate
vtkm::worklet::DispatcherMapField<TrianglesPerCell> triPerCellDispatcher;
triPerCellDispatcher.Invoke(inShapes, inNumIndices, tables.PrepareForInput(), outCellsPerCell);
// Build new cells
vtkm::worklet::DispatcherMapTopology<TriangulateCell> triangulateDispatcher(
TriangulateCell::MakeScatter(outCellsPerCell));
triangulateDispatcher.Invoke(
cellSet, tables.PrepareForInput(), vtkm::cont::make_ArrayHandleGroupVec<3>(outConnectivity));
// Add cells to output cellset
outCellSet.Fill(cellSet.GetNumberOfPoints(), vtkm::CellShapeTagTriangle::Id, 3, outConnectivity);
return outCellSet;
}
}
} // namespace vtkm::worklet