//============================================================================ // 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. //============================================================================ #ifndef vtk_m_cont_CellSetExtrude_hxx #define vtk_m_cont_CellSetExtrude_hxx namespace { struct ComputeReverseMapping : public vtkm::worklet::WorkletMapField { using ControlSignature = void(FieldIn cellIndex, WholeArrayOut cellIds); using ExecutionSignature = void(_1, _2); VTKM_SUPPRESS_EXEC_WARNINGS template 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, static_cast(cellId)); pointIdValue.Set(offset + 1, static_cast(cellId)); pointIdValue.Set(offset + 2, static_cast(cellId)); } }; struct ComputePrevNode : public vtkm::worklet::WorkletMapField { typedef void ControlSignature(FieldIn nextNode, WholeArrayOut prevNodeArray); typedef void ExecutionSignature(InputIndex, _1, _2); template VTKM_EXEC void operator()(vtkm::Id idx, vtkm::Int32 next, PortalType& prevs) const { prevs.Set(static_cast(next), static_cast(idx)); } }; } // anonymous namespace namespace vtkm { namespace cont { template VTKM_CONT void CellSetExtrude::BuildReverseConnectivity(Device) { vtkm::cont::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 pointIdKey; vtkm::cont::DeviceAdapterAlgorithm::Copy(this->Connectivity, pointIdKey); this->RConnectivity.Allocate(rconnSize); invoke(ComputeReverseMapping{}, vtkm::cont::make_ArrayHandleCounting(0, 1, this->NumberOfCellsPerPlane), this->RConnectivity); vtkm::cont::DeviceAdapterAlgorithm::SortByKey(pointIdKey, this->RConnectivity); // now we can compute the counts and offsets vtkm::cont::ArrayHandle reducedKeys; vtkm::cont::DeviceAdapterAlgorithm::ReduceByKey( pointIdKey, vtkm::cont::make_ArrayHandleConstant(vtkm::Int32(1), static_cast(rconnSize)), reducedKeys, this->RCounts, vtkm::Add{}); vtkm::cont::DeviceAdapterAlgorithm::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 CellSetExtrude::ConnectivityP2C CellSetExtrude::PrepareForInput( Device, vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint) const { return ConnectivityP2C(this->Connectivity.PrepareForInput(Device{}), this->NextNode.PrepareForInput(Device{}), this->NumberOfCellsPerPlane, this->NumberOfPointsPerPlane, this->NumberOfPlanes, this->IsPeriodic); } template VTKM_CONT CellSetExtrude::ConnectivityC2P CellSetExtrude::PrepareForInput( Device, vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell) const { if (!this->ReverseConnectivityBuilt) { const_cast(this)->BuildReverseConnectivity(Device{}); } return ConnectivityC2P(this->RConnectivity.PrepareForInput(Device{}), this->ROffsets.PrepareForInput(Device{}), this->RCounts.PrepareForInput(Device{}), this->PrevNode.PrepareForInput(Device{}), this->NumberOfCellsPerPlane, this->NumberOfPointsPerPlane, this->NumberOfPlanes); } } } // vtkm::cont #endif