//============================================================================ // 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 Sandia Corporation. // Copyright 2015 UT-Battelle, LLC. // Copyright 2015 Los Alamos National Security. // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // 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_cont_CellSetExplicit_h #define vtk_m_cont_CellSetExplicit_h #include #include #include #include #include namespace vtkm { namespace cont { namespace detail { template struct CellSetExplicitConnectivityChooser { typedef vtkm::cont::internal::ConnectivityExplicitInternals<> ConnectivityType; }; } // namespace detail template class CellSetExplicit : public CellSet { template struct ConnectivityChooser { typedef typename detail::CellSetExplicitConnectivityChooser< CellSetExplicit< ShapeStorageTag,NumIndicesStorageTag,ConnectivityStorageTag>, FromTopology, ToTopology>::ConnectivityType ConnectivityType; }; public: typedef vtkm::Id SchedulingRangeType; VTKM_CONT_EXPORT CellSetExplicit(const std::string &name = std::string(), vtkm::IdComponent dimensionality = 3) : CellSet(name, dimensionality), ConnectivityLength(-1), NumberOfCells(-1) { } VTKM_CONT_EXPORT CellSetExplicit(int dimensionality) : CellSet(std::string(), dimensionality), ConnectivityLength(-1), NumberOfCells(-1) { } virtual vtkm::Id GetNumberOfCells() const { return this->PointToCell.GetNumberOfElements(); } VTKM_CONT_EXPORT vtkm::Id GetSchedulingRange(vtkm::TopologyElementTagCell) const { return this->GetNumberOfCells(); } VTKM_CONT_EXPORT vtkm::Id GetNumberOfPointsInCell(vtkm::Id cellIndex) const { return this->PointToCell.NumIndices.GetPortalConstControl().Get(cellIndex); } VTKM_CONT_EXPORT vtkm::Id GetCellShape(vtkm::Id cellIndex) const { return this->PointToCell.Shapes.GetPortalConstControl().Get(cellIndex); } template VTKM_CONT_EXPORT void GetIndices(vtkm::Id index, vtkm::Vec &ids) const { this->PointToCell.BuildIndexOffsets(VTKM_DEFAULT_DEVICE_ADAPTER_TAG()); vtkm::Id numIndices = this->GetNumberOfIndices(index); vtkm::Id start = this->PointToCell.IndexOffset.GetPortalConstControl().Get(index); for (vtkm::IdComponent i=0; iConnectivity.GetPortalConstControl().Get(start+i); } /// First method to add cells -- one at a time. VTKM_CONT_EXPORT void PrepareToAddCells(vtkm::Id numShapes, vtkm::Id connectivityMaxLen) { this->PointToCell.Shapes.Allocate(numShapes); this->PointToCell.NumIndices.Allocate(numShapes); this->PointToCell.Connectivity.Allocate(connectivityMaxLen); this->PointToCell.IndexOffsets.Allocate(numShapes); this->NumberOfCells = 0; this->ConnectivityLength = 0; } template VTKM_CONT_EXPORT void AddCell(vtkm::IdComponent cellType, int numVertices, const vtkm::Vec &ids) { this->PointToCell.Shapes.GetPortalControl().Set(this->NumberOfCells, cellType); this->PointToCell.NumIndices.GetPortalControl().Set(this->NumberOfCells, numVertices); for (vtkm::IdComponent i=0; i < numVertices; ++i) { this->PointToCell.Connectivity.GetPortalControl().Set( this->ConnectivityLength+i,ids[i]); } this->PointToCell.IndexOffsets.GetPortalControl().Set( this->NumberOfCells, this->ConnectivityLength); this->NumberOfCells++; this->ConnectivityLength += numVertices; } VTKM_CONT_EXPORT void CompleteAddingCells() { this->PointToCell.Connectivity.Shrink(ConnectivityLength); this->PointToCell.ElementsValid = true; this->NumberOfCells = this->ConnectivityLength = -1; } /// Second method to add cells -- all at once. /// Copies the data from the vectors, so they can be released. VTKM_CONT_EXPORT void FillViaCopy(const std::vector &cellTypes, const std::vector &numIndices, const std::vector &connectivity) { this->PointToCell.Shapes.Allocate( static_cast(cellTypes.size()) ); std::copy(cellTypes.begin(), cellTypes.end(), vtkm::cont::ArrayPortalToIteratorBegin( this->PointToCell.Shapes.GetPortalControl())); this->PointToCell.NumIndices.Allocate( static_cast(numIndices.size()) ); std::copy(numIndices.begin(), numIndices.end(), vtkm::cont::ArrayPortalToIteratorBegin( this->PointToCell.NumIndices.GetPortalControl())); this->PointToCell.Connectivity.Allocate( static_cast(connectivity.size()) ); std::copy(connectivity.begin(), connectivity.end(), vtkm::cont::ArrayPortalToIteratorBegin( this->PointToCell.Connectivity.GetPortalControl())); this->PointToCell.ElementsValid = true; this->PointToCell.IndexOffsetsValid = false; } /// Second method to add cells -- all at once. /// Assigns the array handles to the explicit connectivity. This is /// the way you can fill the memory from another system without copying void Fill(const vtkm::cont::ArrayHandle &cellTypes, const vtkm::cont::ArrayHandle &numIndices, const vtkm::cont::ArrayHandle &connectivity) { this->PointToCell.Shapes = cellTypes; this->PointToCell.NumIndices = numIndices; this->PointToCell.Connectivity = connectivity; this->PointToCell.ElementsValid = true; this->PointToCell.IndexOffsetsValid = false; } template struct ExecutionTypes { VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapter); VTKM_IS_TOPOLOGY_ELEMENT_TAG(FromTopology); VTKM_IS_TOPOLOGY_ELEMENT_TAG(ToTopology); typedef typename ConnectivityChooser::ConnectivityType ContObjectType; typedef typename ContObjectType::ShapeArrayType::template ExecutionTypes::PortalConst ShapePortalType; typedef typename ContObjectType::NumIndicesArrayType::template ExecutionTypes::PortalConst IndicePortalType; typedef typename ContObjectType::ConnectivityArrayType::template ExecutionTypes::PortalConst ConnectivityPortalType; typedef typename ContObjectType::IndexOffsetArrayType::template ExecutionTypes::PortalConst IndexOffsetPortalType; typedef vtkm::exec::ConnectivityExplicit ExecObjectType; }; template typename ExecutionTypes::ExecObjectType PrepareForInput(Device, FromTopology, ToTopology) const { const typename ConnectivityChooser::ConnectivityType &connectivity = this->GetConnectivity(FromTopology(), ToTopology()); VTKM_ASSERT_CONT(connectivity.ElementsValid); connectivity.BuildIndexOffsets(Device()); typedef typename ExecutionTypes::ExecObjectType ExecObjType; return ExecObjType(connectivity.Shapes.PrepareForInput(Device()), connectivity.NumIndices.PrepareForInput(Device()), connectivity.Connectivity.PrepareForInput(Device()), connectivity.IndexOffsets.PrepareForInput(Device())); } virtual void PrintSummary(std::ostream &out) const { out << " ExplicitCellSet: " << this->Name << " dim= " << this->Dimensionality << std::endl; out << " PointToCell: " << std::endl; this->PointToCell.PrintSummary(out); out << " CellToPoint: " << std::endl; this->CellToPoint.PrintSummary(out); } VTKM_CONT_EXPORT const vtkm::cont::ArrayHandle & GetShapesArray() const { return this->PointToCell.Shapes; } VTKM_CONT_EXPORT const vtkm::cont::ArrayHandle & GetNumIndicesArray() const { return this->PointToCell.NumIndices; } VTKM_CONT_EXPORT const vtkm::cont::ArrayHandle & GetConnectivityArray() const { return this->PointToCell.Connectivity; } VTKM_CONT_EXPORT const vtkm::cont::ArrayHandle & GetIndexOffsetArray() const { return this->PointToCell.IndexOffsets; } private: typename ConnectivityChooser< vtkm::TopologyElementTagPoint,vtkm::TopologyElementTagCell>:: ConnectivityType PointToCell; // TODO: Actually implement CellToPoint and other connectivity. (That is, // derive the connectivity from PointToCell. typename ConnectivityChooser< vtkm::TopologyElementTagCell,vtkm::TopologyElementTagPoint>:: ConnectivityType CellToPoint; // A set of overloaded methods to get the connectivity from a pair of // topology element types. #define VTKM_GET_CONNECTIVITY_METHOD(FromTopology,ToTopology,Ivar) \ VTKM_CONT_EXPORT \ const typename ConnectivityChooser< \ FromTopology,ToTopology>::ConnectivityType & \ GetConnectivity(FromTopology, ToTopology) const \ { \ return this->Ivar; \ } \ VTKM_CONT_EXPORT \ typename ConnectivityChooser< \ FromTopology,ToTopology>::ConnectivityType & \ GetConnectivity(FromTopology, ToTopology) \ { \ return this->Ivar; \ } VTKM_GET_CONNECTIVITY_METHOD(vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell, PointToCell) VTKM_GET_CONNECTIVITY_METHOD(vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint, CellToPoint) #undef VTKM_GET_CONNECTIVITY_METHOD // These are used in the AddCell and related methods to incrementally add // cells. vtkm::Id ConnectivityLength; vtkm::Id NumberOfCells; }; namespace detail { template struct CellSetExplicitConnectivityChooser< vtkm::cont::CellSetExplicit, vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell> { typedef vtkm::cont::internal::ConnectivityExplicitInternals< Storage1,Storage2,Storage3> ConnectivityType; }; } // namespace detail } } // namespace vtkm::cont #endif //vtk_m_cont_CellSetExplicit_h