//============================================================================ // 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 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS). // Copyright 2017 UT-Battelle, LLC. // Copyright 2017 Los Alamos National Security. // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National // Laboratory (LANL), the U.S. Government retains certain rights in // this software. //============================================================================ #include #include namespace vtkm { namespace cont { template VTKM_CONT CellSetExplicit::CellSetExplicit(const std::string& name) : CellSet(name) , ConnectivityAdded(-1) , NumberOfCellsAdded(-1) , NumberOfPoints(0) { } template VTKM_CONT CellSetExplicit::CellSetExplicit(const Thisclass& src) : CellSet(src) , PointToCell(src.PointToCell) , CellToPoint(src.CellToPoint) , ConnectivityAdded(src.ConnectivityAdded) , NumberOfCellsAdded(src.NumberOfCellsAdded) , NumberOfPoints(src.NumberOfPoints) { } template VTKM_CONT auto CellSetExplicit:: operator=(const Thisclass& src) -> Thisclass& { this->CellSet::operator=(src); this->PointToCell = src.PointToCell; this->CellToPoint = src.CellToPoint; this->ConnectivityAdded = src.ConnectivityAdded; this->NumberOfCellsAdded = src.NumberOfCellsAdded; this->NumberOfPoints = src.NumberOfPoints; return *this; } template CellSetExplicit:: ~CellSetExplicit() // explicitly define instead of '=default' to workaround an intel compiler bug // (see #179) { } template void CellSetExplicit::PrintSummary(std::ostream& out) const { out << " ExplicitCellSet: " << this->Name << std::endl; out << " PointToCell: " << std::endl; this->PointToCell.PrintSummary(out); out << " CellToPoint: " << std::endl; this->CellToPoint.PrintSummary(out); } template void CellSetExplicit::ReleaseResourcesExecution() { this->PointToCell.ReleaseResourcesExecution(); this->CellToPoint.ReleaseResourcesExecution(); } //---------------------------------------------------------------------------- template vtkm::Id CellSetExplicit::GetNumberOfCells() const { return this->PointToCell.GetNumberOfElements(); } template vtkm::Id CellSetExplicit::GetNumberOfPoints() const { return this->NumberOfPoints; } template vtkm::Id CellSetExplicit::GetNumberOfFaces() const { return -1; } template vtkm::Id CellSetExplicit::GetNumberOfEdges() const { return -1; } //---------------------------------------------------------------------------- template VTKM_CONT vtkm::Id CellSetExplicit::GetSchedulingRange(vtkm::TopologyElementTagCell) const { return this->GetNumberOfCells(); } template VTKM_CONT vtkm::Id CellSetExplicit::GetSchedulingRange(vtkm::TopologyElementTagPoint) const { return this->GetNumberOfPoints(); } template VTKM_CONT vtkm::IdComponent CellSetExplicit:: GetNumberOfPointsInCell(vtkm::Id cellIndex) const { return this->PointToCell.NumIndices.GetPortalConstControl().Get(cellIndex); } template VTKM_CONT vtkm::UInt8 CellSetExplicit::GetCellShape(vtkm::Id cellIndex) const { return this->PointToCell.Shapes.GetPortalConstControl().Get(cellIndex); } template template VTKM_CONT void CellSetExplicit:: GetIndices(vtkm::Id index, vtkm::Vec& ids) const { this->PointToCell.BuildIndexOffsets(VTKM_DEFAULT_DEVICE_ADAPTER_TAG()); vtkm::IdComponent numIndices = this->GetNumberOfPointsInCell(index); vtkm::Id start = this->PointToCell.IndexOffsets.GetPortalConstControl().Get(index); for (vtkm::IdComponent i = 0; i < numIndices && i < ItemTupleLength; i++) { ids[i] = this->PointToCell.Connectivity.GetPortalConstControl().Get(start + i); } } template VTKM_CONT void CellSetExplicit:: GetIndices(vtkm::Id index, vtkm::cont::ArrayHandle& ids) const { this->PointToCell.BuildIndexOffsets(VTKM_DEFAULT_DEVICE_ADAPTER_TAG()); vtkm::IdComponent numIndices = this->GetNumberOfPointsInCell(index); ids.Allocate(numIndices); vtkm::Id start = this->PointToCell.IndexOffsets.GetPortalConstControl().Get(index); vtkm::cont::ArrayHandle::PortalControl idPortal = ids.GetPortalControl(); auto PtCellPortal = this->PointToCell.Connectivity.GetPortalConstControl(); for (vtkm::IdComponent i = 0; i < numIndices && i < numIndices; i++) idPortal.Set(i, PtCellPortal.Get(start + i)); } //---------------------------------------------------------------------------- template VTKM_CONT void CellSetExplicit::PrepareToAddCells(vtkm::Id numCells, vtkm::Id connectivityMaxLen) { this->PointToCell.Shapes.Allocate(numCells); this->PointToCell.NumIndices.Allocate(numCells); this->PointToCell.Connectivity.Allocate(connectivityMaxLen); this->PointToCell.IndexOffsets.Allocate(numCells); this->NumberOfCellsAdded = 0; this->ConnectivityAdded = 0; } template template VTKM_CONT void CellSetExplicit:: AddCell(vtkm::UInt8 cellType, vtkm::IdComponent numVertices, const IdVecType& ids) { using Traits = vtkm::VecTraits; VTKM_STATIC_ASSERT_MSG((std::is_same::value), "CellSetSingleType::AddCell requires vtkm::Id for indices."); if (Traits::GetNumberOfComponents(ids) < numVertices) { throw vtkm::cont::ErrorBadValue("Not enough indices given to CellSetSingleType::AddCell."); } if (this->NumberOfCellsAdded >= this->PointToCell.Shapes.GetNumberOfValues()) { throw vtkm::cont::ErrorBadValue("Added more cells then expected."); } if (this->ConnectivityAdded + numVertices > this->PointToCell.Connectivity.GetNumberOfValues()) { throw vtkm::cont::ErrorBadValue( "Connectivity increased passed estimated maximum connectivity."); } this->PointToCell.Shapes.GetPortalControl().Set(this->NumberOfCellsAdded, cellType); this->PointToCell.NumIndices.GetPortalControl().Set(this->NumberOfCellsAdded, numVertices); for (vtkm::IdComponent iVec = 0; iVec < numVertices; ++iVec) { this->PointToCell.Connectivity.GetPortalControl().Set(this->ConnectivityAdded + iVec, Traits::GetComponent(ids, iVec)); } this->PointToCell.IndexOffsets.GetPortalControl().Set(this->NumberOfCellsAdded, this->ConnectivityAdded); this->NumberOfCellsAdded++; this->ConnectivityAdded += numVertices; } template VTKM_CONT void CellSetExplicit::CompleteAddingCells(vtkm::Id numPoints) { this->NumberOfPoints = numPoints; this->PointToCell.Connectivity.Shrink(ConnectivityAdded); this->PointToCell.ElementsValid = true; this->PointToCell.IndexOffsetsValid = true; if (this->NumberOfCellsAdded != this->GetNumberOfCells()) { throw vtkm::cont::ErrorBadValue("Did not add as many cells as expected."); } this->NumberOfCellsAdded = -1; this->ConnectivityAdded = -1; } //---------------------------------------------------------------------------- template VTKM_CONT void CellSetExplicit:: Fill(vtkm::Id numPoints, const vtkm::cont::ArrayHandle& cellTypes, const vtkm::cont::ArrayHandle& numIndices, const vtkm::cont::ArrayHandle& connectivity, const vtkm::cont::ArrayHandle& offsets) { this->NumberOfPoints = numPoints; this->PointToCell.Shapes = cellTypes; this->PointToCell.NumIndices = numIndices; this->PointToCell.Connectivity = connectivity; this->PointToCell.ElementsValid = true; if (offsets.GetNumberOfValues() == cellTypes.GetNumberOfValues()) { this->PointToCell.IndexOffsets = offsets; this->PointToCell.IndexOffsetsValid = true; } else { this->PointToCell.IndexOffsetsValid = false; if (offsets.GetNumberOfValues() != 0) { throw vtkm::cont::ErrorBadValue("Explicit cell offsets array unexpected size. " "Use an empty array to automatically generate."); } } } //---------------------------------------------------------------------------- template template auto CellSetExplicit::PrepareForInput(Device, FromTopology, ToTopology) const -> typename ExecutionTypes::ExecObjectType { this->BuildConnectivity(FromTopology(), ToTopology()); const auto& connectivity = this->GetConnectivity(FromTopology(), ToTopology()); VTKM_ASSERT(connectivity.ElementsValid); using ExecObjType = typename ExecutionTypes::ExecObjectType; return ExecObjType(connectivity.Shapes.PrepareForInput(Device()), connectivity.NumIndices.PrepareForInput(Device()), connectivity.Connectivity.PrepareForInput(Device()), connectivity.IndexOffsets.PrepareForInput(Device())); } //---------------------------------------------------------------------------- template template VTKM_CONT auto CellSetExplicit::GetShapesArray(FromTopology, ToTopology) const -> const typename ConnectivityChooser::ShapeArrayType& { this->BuildConnectivity(FromTopology(), ToTopology()); return this->GetConnectivity(FromTopology(), ToTopology()).Shapes; } template template VTKM_CONT auto CellSetExplicit::GetNumIndicesArray(FromTopology, ToTopology) const -> const typename ConnectivityChooser::NumIndicesArrayType& { this->BuildConnectivity(FromTopology(), ToTopology()); return this->GetConnectivity(FromTopology(), ToTopology()).NumIndices; } template template VTKM_CONT auto CellSetExplicit::GetConnectivityArray(FromTopology, ToTopology) const -> const typename ConnectivityChooser::ConnectivityArrayType& { this->BuildConnectivity(FromTopology(), ToTopology()); return this->GetConnectivity(FromTopology(), ToTopology()).Connectivity; } template template VTKM_CONT auto CellSetExplicit::GetIndexOffsetArray(FromTopology, ToTopology) const -> const typename ConnectivityChooser::IndexOffsetArrayType& { this->BuildConnectivity(FromTopology(), ToTopology()); return this->GetConnectivity(FromTopology(), ToTopology()).IndexOffsets; } //---------------------------------------------------------------------------- namespace detail { template struct BuildPointToCellConnectivityFunctor { explicit BuildPointToCellConnectivityFunctor(PointToCellConnectivity& pointToCell) : PointToCell(&pointToCell) { } template bool operator()(Device) const { this->PointToCell->BuildIndexOffsets(Device()); return true; } PointToCellConnectivity* PointToCell; }; template struct BuildCellToPointConnectivityFunctor { BuildCellToPointConnectivityFunctor(PointToCellConnectivity& pointToCell, CellToPointConnectivity& cellToPoint, vtkm::Id numberOfPoints) : PointToCell(&pointToCell) , CellToPoint(&cellToPoint) , NumberOfPoints(numberOfPoints) { } template bool operator()(Device) const { this->PointToCell->BuildIndexOffsets(Device()); internal::ComputeCellToPointConnectivity( *this->CellToPoint, *this->PointToCell, this->NumberOfPoints, Device()); this->CellToPoint->BuildIndexOffsets(Device()); return true; } PointToCellConnectivity* PointToCell; CellToPointConnectivity* CellToPoint; vtkm::Id NumberOfPoints; }; } // detail template VTKM_CONT void CellSetExplicit:: BuildConnectivity(vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell, vtkm::cont::RuntimeDeviceTracker tracker) const { using PointToCellConnectivity = typename ConnectivityChooser::ConnectivityType; VTKM_ASSERT(this->PointToCell.ElementsValid); if (!this->PointToCell.IndexOffsetsValid) { auto self = const_cast(this); auto functor = detail::BuildPointToCellConnectivityFunctor(self->PointToCell); if (!vtkm::cont::TryExecute(functor, tracker)) { throw vtkm::cont::ErrorExecution("Failed to run BuildConnectivity on any device."); } } } template VTKM_CONT void CellSetExplicit:: BuildConnectivity(vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint, vtkm::cont::RuntimeDeviceTracker tracker) const { using PointToCellConnectivity = typename ConnectivityChooser::ConnectivityType; using CellToPointConnectivity = typename ConnectivityChooser::ConnectivityType; if (!this->CellToPoint.ElementsValid || !this->CellToPoint.IndexOffsetsValid) { auto self = const_cast(this); auto functor = detail::BuildCellToPointConnectivityFunctor( self->PointToCell, self->CellToPoint, this->NumberOfPoints); if (!vtkm::cont::TryExecute(functor, tracker)) { throw vtkm::cont::ErrorExecution("Failed to run BuildConnectivity on any device."); } } } } } // vtkm::cont