1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //
6 //  This software is distributed WITHOUT ANY WARRANTY; without even
7 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 //  PURPOSE.  See the above copyright notice for more information.
9 //============================================================================
10 #ifndef vtk_m_cont_DataSet_h
11 #define vtk_m_cont_DataSet_h
12 
13 #include <vtkm/cont/vtkm_cont_export.h>
14 
15 #include <vtkm/cont/ArrayHandle.h>
16 #include <vtkm/cont/CoordinateSystem.h>
17 #include <vtkm/cont/DeviceAdapterAlgorithm.h>
18 #include <vtkm/cont/DynamicCellSet.h>
19 #include <vtkm/cont/ErrorBadValue.h>
20 #include <vtkm/cont/Field.h>
21 #include <vtkm/cont/UnknownArrayHandle.h>
22 
23 namespace vtkm
24 {
25 namespace cont
26 {
27 
28 class VTKM_CONT_EXPORT DataSet
29 {
30 public:
31   VTKM_CONT void Clear();
32 
33   /// Get the number of cells contained in this DataSet
34   VTKM_CONT vtkm::Id GetNumberOfCells() const;
35 
36   /// Get the number of points contained in this DataSet
37   ///
38   /// Note: All coordinate systems for a DataSet are expected
39   /// to have the same number of points.
40   VTKM_CONT vtkm::Id GetNumberOfPoints() const;
41 
42   VTKM_CONT void AddField(const Field& field);
43 
44   VTKM_CONT
45   const vtkm::cont::Field& GetField(vtkm::Id index) const;
46 
47   VTKM_CONT
48   vtkm::cont::Field& GetField(vtkm::Id index);
49 
50   VTKM_CONT
51   bool HasField(const std::string& name,
52                 vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::ANY) const
53   {
54     bool found = false;
55     this->FindFieldIndex(name, assoc, found);
56     return found;
57   }
58 
59   VTKM_CONT
HasCellField(const std::string & name)60   bool HasCellField(const std::string& name) const
61   {
62     bool found = false;
63     this->FindFieldIndex(name, vtkm::cont::Field::Association::CELL_SET, found);
64     return found;
65   }
66 
67   VTKM_CONT
HasPointField(const std::string & name)68   bool HasPointField(const std::string& name) const
69   {
70     bool found = false;
71     this->FindFieldIndex(name, vtkm::cont::Field::Association::POINTS, found);
72     return found;
73   }
74 
75 
76   /// Returns the field that matches the provided name and association
77   /// Will return -1 if no match is found
78   VTKM_CONT
79   vtkm::Id GetFieldIndex(
80     const std::string& name,
81     vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::ANY) const;
82 
83   /// Returns the field that matches the provided name and association
84   /// Will throw an exception if no match is found
85   //@{
86   VTKM_CONT
87   const vtkm::cont::Field& GetField(
88     const std::string& name,
89     vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::ANY) const
90   {
91     return this->GetField(this->GetFieldIndex(name, assoc));
92   }
93 
94   VTKM_CONT
95   vtkm::cont::Field& GetField(
96     const std::string& name,
97     vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::ANY)
98   {
99     return this->GetField(this->GetFieldIndex(name, assoc));
100   }
101   //@}
102 
103   /// Returns the first cell field that matches the provided name.
104   /// Will throw an exception if no match is found
105   //@{
106   VTKM_CONT
GetCellField(const std::string & name)107   const vtkm::cont::Field& GetCellField(const std::string& name) const
108   {
109     return this->GetField(name, vtkm::cont::Field::Association::CELL_SET);
110   }
111 
112   VTKM_CONT
GetCellField(const std::string & name)113   vtkm::cont::Field& GetCellField(const std::string& name)
114   {
115     return this->GetField(name, vtkm::cont::Field::Association::CELL_SET);
116   }
117   //@}
118 
119   /// Returns the first point field that matches the provided name.
120   /// Will throw an exception if no match is found
121   //@{
122   VTKM_CONT
GetPointField(const std::string & name)123   const vtkm::cont::Field& GetPointField(const std::string& name) const
124   {
125     return this->GetField(name, vtkm::cont::Field::Association::POINTS);
126   }
127 
128   VTKM_CONT
GetPointField(const std::string & name)129   vtkm::cont::Field& GetPointField(const std::string& name)
130   {
131     return this->GetField(name, vtkm::cont::Field::Association::POINTS);
132   }
133   //@}
134 
135   VTKM_CONT
AddPointField(const std::string & fieldName,const vtkm::cont::UnknownArrayHandle & field)136   void AddPointField(const std::string& fieldName, const vtkm::cont::UnknownArrayHandle& field)
137   {
138     this->AddField(make_FieldPoint(fieldName, field));
139   }
140 
141   template <typename T, typename Storage>
AddPointField(const std::string & fieldName,const vtkm::cont::ArrayHandle<T,Storage> & field)142   VTKM_CONT void AddPointField(const std::string& fieldName,
143                                const vtkm::cont::ArrayHandle<T, Storage>& field)
144   {
145     this->AddField(make_FieldPoint(fieldName, field));
146   }
147 
148   template <typename T>
AddPointField(const std::string & fieldName,const std::vector<T> & field)149   VTKM_CONT void AddPointField(const std::string& fieldName, const std::vector<T>& field)
150   {
151     this->AddField(
152       make_Field(fieldName, vtkm::cont::Field::Association::POINTS, field, vtkm::CopyFlag::On));
153   }
154 
155   template <typename T>
AddPointField(const std::string & fieldName,const T * field,const vtkm::Id & n)156   VTKM_CONT void AddPointField(const std::string& fieldName, const T* field, const vtkm::Id& n)
157   {
158     this->AddField(
159       make_Field(fieldName, vtkm::cont::Field::Association::POINTS, field, n, vtkm::CopyFlag::On));
160   }
161 
162   //Cell centered field
163   VTKM_CONT
AddCellField(const std::string & fieldName,const vtkm::cont::UnknownArrayHandle & field)164   void AddCellField(const std::string& fieldName, const vtkm::cont::UnknownArrayHandle& field)
165   {
166     this->AddField(make_FieldCell(fieldName, field));
167   }
168 
169   template <typename T, typename Storage>
AddCellField(const std::string & fieldName,const vtkm::cont::ArrayHandle<T,Storage> & field)170   VTKM_CONT void AddCellField(const std::string& fieldName,
171                               const vtkm::cont::ArrayHandle<T, Storage>& field)
172   {
173     this->AddField(make_FieldCell(fieldName, field));
174   }
175 
176   template <typename T>
AddCellField(const std::string & fieldName,const std::vector<T> & field)177   VTKM_CONT void AddCellField(const std::string& fieldName, const std::vector<T>& field)
178   {
179     this->AddField(
180       make_Field(fieldName, vtkm::cont::Field::Association::CELL_SET, field, vtkm::CopyFlag::On));
181   }
182 
183   template <typename T>
AddCellField(const std::string & fieldName,const T * field,const vtkm::Id & n)184   VTKM_CONT void AddCellField(const std::string& fieldName, const T* field, const vtkm::Id& n)
185   {
186     this->AddField(make_Field(
187       fieldName, vtkm::cont::Field::Association::CELL_SET, field, n, vtkm::CopyFlag::On));
188   }
189 
190 
191   VTKM_CONT
AddCoordinateSystem(const vtkm::cont::CoordinateSystem & cs)192   void AddCoordinateSystem(const vtkm::cont::CoordinateSystem& cs)
193   {
194     this->CoordSystems.push_back(cs);
195   }
196 
197   VTKM_CONT
HasCoordinateSystem(const std::string & name)198   bool HasCoordinateSystem(const std::string& name) const
199   {
200     return this->GetCoordinateSystemIndex(name) >= 0;
201   }
202 
203   VTKM_CONT
204   const vtkm::cont::CoordinateSystem& GetCoordinateSystem(vtkm::Id index = 0) const;
205 
206   VTKM_CONT
207   vtkm::cont::CoordinateSystem& GetCoordinateSystem(vtkm::Id index = 0);
208 
209   /// Returns the index for the first CoordinateSystem whose
210   /// name matches the provided string.
211   /// Will return -1 if no match is found
212   VTKM_CONT
213   vtkm::Id GetCoordinateSystemIndex(const std::string& name) const;
214 
215   /// Returns the first CoordinateSystem that matches the provided name.
216   /// Will throw an exception if no match is found
217   //@{
218   VTKM_CONT
219   const vtkm::cont::CoordinateSystem& GetCoordinateSystem(const std::string& name) const;
220 
221   VTKM_CONT
222   vtkm::cont::CoordinateSystem& GetCoordinateSystem(const std::string& name);
223   //@}
224 
225   VTKM_CONT
SetCellSet(const vtkm::cont::DynamicCellSet & cellSet)226   void SetCellSet(const vtkm::cont::DynamicCellSet& cellSet) { this->CellSet = cellSet; }
227 
228   template <typename CellSetType>
SetCellSet(const CellSetType & cellSet)229   VTKM_CONT void SetCellSet(const CellSetType& cellSet)
230   {
231     VTKM_IS_CELL_SET(CellSetType);
232     this->CellSet = vtkm::cont::DynamicCellSet(cellSet);
233   }
234 
235   VTKM_CONT
GetCellSet()236   const vtkm::cont::DynamicCellSet& GetCellSet() const { return this->CellSet; }
237 
238   VTKM_CONT
GetCellSet()239   vtkm::cont::DynamicCellSet& GetCellSet() { return this->CellSet; }
240 
241   VTKM_CONT
GetNumberOfFields()242   vtkm::IdComponent GetNumberOfFields() const
243   {
244     return static_cast<vtkm::IdComponent>(this->Fields.size());
245   }
246 
247   VTKM_CONT
GetNumberOfCoordinateSystems()248   vtkm::IdComponent GetNumberOfCoordinateSystems() const
249   {
250     return static_cast<vtkm::IdComponent>(this->CoordSystems.size());
251   }
252 
253   /// Copies the structure i.e. coordinates systems and cellset from the source
254   /// dataset. The fields are left unchanged.
255   VTKM_CONT
256   void CopyStructure(const vtkm::cont::DataSet& source);
257 
258   VTKM_CONT
259   void PrintSummary(std::ostream& out) const;
260 
261 private:
262   struct FieldCompare
263   {
264     using Key = std::pair<std::string, vtkm::cont::Field::Association>;
265 
266     template <typename T>
operatorFieldCompare267     bool operator()(const T& a, const T& b) const
268     {
269       if (a.first == b.first)
270         return a.second < b.second && a.second != vtkm::cont::Field::Association::ANY &&
271           b.second != vtkm::cont::Field::Association::ANY;
272 
273       return a.first < b.first;
274     }
275   };
276 
277   std::vector<vtkm::cont::CoordinateSystem> CoordSystems;
278   std::map<FieldCompare::Key, vtkm::cont::Field, FieldCompare> Fields;
279   vtkm::cont::DynamicCellSet CellSet;
280 
281   VTKM_CONT
282   vtkm::Id FindFieldIndex(const std::string& name,
283                           vtkm::cont::Field::Association association,
284                           bool& found) const;
285 };
286 
287 } // namespace cont
288 } // namespace vtkm
289 
290 //=============================================================================
291 // Specializations of serialization related classes
292 /// @cond SERIALIZATION
293 namespace vtkm
294 {
295 namespace cont
296 {
297 
298 template <typename FieldTypeList = VTKM_DEFAULT_TYPE_LIST,
299           typename CellSetTypesList = VTKM_DEFAULT_CELL_SET_LIST>
300 struct SerializableDataSet
301 {
302   SerializableDataSet() = default;
303 
SerializableDataSetSerializableDataSet304   explicit SerializableDataSet(const vtkm::cont::DataSet& dataset)
305     : DataSet(dataset)
306   {
307   }
308 
309   vtkm::cont::DataSet DataSet;
310 };
311 }
312 } // vtkm::cont
313 
314 namespace mangled_diy_namespace
315 {
316 
317 template <typename FieldTypeList, typename CellSetTypesList>
318 struct Serialization<vtkm::cont::SerializableDataSet<FieldTypeList, CellSetTypesList>>
319 {
320 private:
321   using Type = vtkm::cont::SerializableDataSet<FieldTypeList, CellSetTypesList>;
322 
323 public:
324   static VTKM_CONT void save(BinaryBuffer& bb, const Type& serializable)
325   {
326     const auto& dataset = serializable.DataSet;
327 
328     vtkm::IdComponent numberOfCoordinateSystems = dataset.GetNumberOfCoordinateSystems();
329     vtkmdiy::save(bb, numberOfCoordinateSystems);
330     for (vtkm::IdComponent i = 0; i < numberOfCoordinateSystems; ++i)
331     {
332       vtkmdiy::save(bb, dataset.GetCoordinateSystem(i));
333     }
334 
335     vtkmdiy::save(bb, dataset.GetCellSet().ResetCellSetList(CellSetTypesList{}));
336 
337     vtkm::IdComponent numberOfFields = dataset.GetNumberOfFields();
338     vtkmdiy::save(bb, numberOfFields);
339     for (vtkm::IdComponent i = 0; i < numberOfFields; ++i)
340     {
341       vtkmdiy::save(bb, dataset.GetField(i));
342     }
343   }
344 
345   static VTKM_CONT void load(BinaryBuffer& bb, Type& serializable)
346   {
347     auto& dataset = serializable.DataSet;
348     dataset = {}; // clear
349 
350     vtkm::IdComponent numberOfCoordinateSystems = 0;
351     vtkmdiy::load(bb, numberOfCoordinateSystems);
352     for (vtkm::IdComponent i = 0; i < numberOfCoordinateSystems; ++i)
353     {
354       vtkm::cont::CoordinateSystem coords;
355       vtkmdiy::load(bb, coords);
356       dataset.AddCoordinateSystem(coords);
357     }
358 
359     vtkm::cont::DynamicCellSetBase<CellSetTypesList> cells;
360     vtkmdiy::load(bb, cells);
361     dataset.SetCellSet(vtkm::cont::DynamicCellSet(cells));
362 
363     vtkm::IdComponent numberOfFields = 0;
364     vtkmdiy::load(bb, numberOfFields);
365     for (vtkm::IdComponent i = 0; i < numberOfFields; ++i)
366     {
367       vtkm::cont::Field field;
368       vtkmdiy::load(bb, field);
369       dataset.AddField(field);
370     }
371   }
372 };
373 
374 } // diy
375 /// @endcond SERIALIZATION
376 
377 #endif //vtk_m_cont_DataSet_h
378