1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //  This software is distributed WITHOUT ANY WARRANTY; without even
6 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
7 //  PURPOSE.  See the above copyright notice for more information.
8 //
9 //  Copyright 2015 Sandia Corporation.
10 //  Copyright 2015 UT-Battelle, LLC.
11 //  Copyright 2015 Los Alamos National Security.
12 //
13 //  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
14 //  the U.S. Government retains certain rights in this software.
15 //
16 //  Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
17 //  Laboratory (LANL), the U.S. Government retains certain rights in
18 //  this software.
19 //============================================================================
20 #include "vtkmlib/Storage.h"
21 #include "vtkmCellSetSingleType.h"
22 #include "vtkmConnectivityExec.h"
23 
24 #include <vtkm/cont/internal/ReverseConnectivityBuilder.h>
25 #include <vtkm/worklet/WorkletMapField.h>
26 #include <vtkm/worklet/DispatcherMapField.h>
27 
28 namespace
29 {
30 
31 // Converts [0, rconnSize) to [0, connSize), skipping cell length entries.
32 struct SingleTypeRConnToConn
33 {
34   vtkm::Id PointsPerCell;
35 
36   VTKM_EXEC
operator ()__anon3e3ba9110111::SingleTypeRConnToConn37   vtkm::Id operator()(vtkm::Id rconnIdx) const
38   {
39     return rconnIdx + 1 + (rconnIdx / this->PointsPerCell);
40   }
41 };
42 
43 // Converts a connectivity index to a cell id:
44 struct SingleTypeCellIdCalc
45 {
46   vtkm::Id EncodedCellSize;
47 
48   VTKM_EXEC
operator ()__anon3e3ba9110111::SingleTypeCellIdCalc49   vtkm::Id operator()(vtkm::Id connIdx) const
50   {
51     return connIdx / this->EncodedCellSize;
52   }
53 };
54 
55 } // end anon namespace
56 
57 namespace vtkm {
58 namespace cont {
59 
60 //------------------------------------------------------------------------------
DetermineNumberOfPoints() const61 vtkm::IdComponent vtkmCellSetSingleType::DetermineNumberOfPoints() const
62 {
63   vtkm::IdComponent numberOfPointsPerCell = -1;
64   switch (this->CellTypeAsId)
65   {
66     vtkmGenericCellShapeMacro(this->DetermineNumberOfPoints(
67         CellShapeTag(), vtkm::CellTraits<CellShapeTag>::IsSizeFixed(),
68         numberOfPointsPerCell));
69   default:
70     throw vtkm::cont::ErrorBadValue(
71         "CellSetSingleType unable to determine the cell type");
72   }
73   return numberOfPointsPerCell;
74 }
75 
76 //------------------------------------------------------------------------------
Fill(vtkm::Id numberOfPoints,const vtkm::cont::ArrayHandle<vtkm::Id,tovtkm::vtkCellArrayContainerTag> & connectivity)77 void vtkmCellSetSingleType::Fill(
78     vtkm::Id numberOfPoints,
79     const vtkm::cont::ArrayHandle<vtkm::Id, tovtkm::vtkCellArrayContainerTag>&
80         connectivity)
81 {
82   const vtkm::IdComponent numberOfPointsPerCell =
83       this->DetermineNumberOfPoints();
84   this->NumberOfCells =
85       connectivity.GetNumberOfValues() / (numberOfPointsPerCell + 1);
86   this->Connectivity = connectivity;
87   this->NumberOfPoints = numberOfPoints;
88 }
89 
90 //------------------------------------------------------------------------------
91 template <typename Device>
92 typename vtkm::exec::ConnectivityVTKSingleType<Device>
PrepareForInput(Device,vtkm::TopologyElementTagPoint,vtkm::TopologyElementTagCell) const93     vtkmCellSetSingleType::PrepareForInput(Device,
94                                            vtkm::TopologyElementTagPoint,
95                                            vtkm::TopologyElementTagCell) const
96 {
97   const vtkm::IdComponent numberOfPointsPerCell =
98       this->DetermineNumberOfPoints();
99   const vtkm::UInt8 shapeTypeValue =
100       static_cast<vtkm::UInt8>(this->CellTypeAsId);
101 
102   return vtkm::exec::ConnectivityVTKSingleType<Device>(
103       this->Connectivity.PrepareForInput(Device()), this->NumberOfCells,
104       numberOfPointsPerCell, shapeTypeValue);
105 }
106 
107 //------------------------------------------------------------------------------
108 template <typename Device>
109 typename vtkm::exec::ReverseConnectivityVTK<Device>
PrepareForInput(Device,vtkm::TopologyElementTagCell,vtkm::TopologyElementTagPoint) const110     vtkmCellSetSingleType::PrepareForInput(Device,
111                                            vtkm::TopologyElementTagCell,
112                                            vtkm::TopologyElementTagPoint) const
113 {
114   if(!this->ReverseConnectivityBuilt)
115   {
116     const vtkm::Id numberOfPoints = this->GetNumberOfPoints();
117     const vtkm::Id numberOfCells = this->GetNumberOfCells();
118     const vtkm::Id numberOfPointsPerCell = this->DetermineNumberOfPoints();
119     const vtkm::Id rconnSize = numberOfCells*numberOfPointsPerCell;
120 
121     const SingleTypeRConnToConn rconnToConnCalc{numberOfPointsPerCell};
122     const SingleTypeCellIdCalc cellIdCalc{numberOfPointsPerCell + 1}; // +1 for cell length entries
123 
124     vtkm::cont::internal::ReverseConnectivityBuilder builder;
125 
126     builder.Run(this->Connectivity,
127                 this->RConn,
128                 this->RNumIndices,
129                 this->RIndexOffsets,
130                 rconnToConnCalc,
131                 cellIdCalc,
132                 numberOfPoints,
133                 rconnSize,
134                 Device{});
135 
136     this->NumberOfPoints = this->RIndexOffsets.GetNumberOfValues();
137     this->ReverseConnectivityBuilt = true;
138   } // End if !RConnBuilt
139 
140   //no need to have a reverse shapes array, as everything has the shape type
141   //of vertex
142   return vtkm::exec::ReverseConnectivityVTK<Device>(
143       this->RConn.PrepareForInput(Device()),
144       this->RNumIndices.PrepareForInput(Device()),
145       this->RIndexOffsets.PrepareForInput(Device()));
146 }
147 
148 //------------------------------------------------------------------------------
PrintSummary(std::ostream & out) const149 void vtkmCellSetSingleType::PrintSummary(std::ostream& out) const
150 {
151   out << "   vtkmCellSetSingleType: " << this->Name << std::endl;
152   out << "   NumberOfCells: " << this->NumberOfCells << std::endl;
153   out << "   CellTypeAsId: " << this->CellTypeAsId << std::endl;
154   out << "   Connectivity: " << std::endl;
155   vtkm::cont::printSummary_ArrayHandle(this->Connectivity, out);
156 }
157 
158 // template methods we want to compile only once
159 template VTKACCELERATORSVTKM_EXPORT
160   vtkm::exec::ConnectivityVTKSingleType<vtkm::cont::DeviceAdapterTagSerial>
161     vtkmCellSetSingleType::PrepareForInput(vtkm::cont::DeviceAdapterTagSerial,
162       vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell) const;
163 
164 template VTKACCELERATORSVTKM_EXPORT
165   vtkm::exec::ReverseConnectivityVTK<vtkm::cont::DeviceAdapterTagSerial>
166     vtkmCellSetSingleType::PrepareForInput(vtkm::cont::DeviceAdapterTagSerial,
167       vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint) const;
168 
169 #ifdef VTKM_ENABLE_TBB
170 template VTKACCELERATORSVTKM_EXPORT
171   vtkm::exec::ConnectivityVTKSingleType<vtkm::cont::DeviceAdapterTagTBB>
172     vtkmCellSetSingleType::PrepareForInput(vtkm::cont::DeviceAdapterTagTBB,
173       vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell) const;
174 
175 template VTKACCELERATORSVTKM_EXPORT
176   vtkm::exec::ReverseConnectivityVTK<vtkm::cont::DeviceAdapterTagTBB>
177     vtkmCellSetSingleType::PrepareForInput(vtkm::cont::DeviceAdapterTagTBB,
178       vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint) const;
179 #endif
180 
181 #ifdef VTKM_ENABLE_OPENMP
182 template VTKACCELERATORSVTKM_EXPORT
183   vtkm::exec::ConnectivityVTKSingleType<vtkm::cont::DeviceAdapterTagOpenMP>
184     vtkmCellSetSingleType::PrepareForInput(vtkm::cont::DeviceAdapterTagOpenMP,
185       vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell) const;
186 
187 template VTKACCELERATORSVTKM_EXPORT
188   vtkm::exec::ReverseConnectivityVTK<vtkm::cont::DeviceAdapterTagOpenMP>
189     vtkmCellSetSingleType::PrepareForInput(vtkm::cont::DeviceAdapterTagOpenMP,
190       vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint) const;
191 #endif
192 }
193 }
194