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 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10 // Copyright 2014 UT-Battelle, LLC.
11 // Copyright 2014 Los Alamos National Security.
12 //
13 // Under the terms of Contract DE-NA0003525 with NTESS,
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 #ifndef vtk_m_cont_Field_h
21 #define vtk_m_cont_Field_h
22
23 #include <vtkm/cont/vtkm_cont_export.h>
24
25 #include <vtkm/Range.h>
26 #include <vtkm/Types.h>
27
28 #include <vtkm/cont/ArrayHandle.h>
29 #include <vtkm/cont/ArrayPortalToIterators.h>
30 #include <vtkm/cont/ArrayRangeCompute.h>
31 #include <vtkm/cont/DynamicArrayHandle.h>
32
33 namespace vtkm
34 {
35 namespace cont
36 {
37
38 namespace internal
39 {
40
41 class ComputeRange
42 {
43 public:
ComputeRange(ArrayHandle<vtkm::Range> & range)44 ComputeRange(ArrayHandle<vtkm::Range>& range)
45 : Range(&range)
46 {
47 }
48
49 template <typename ArrayHandleType>
operator()50 void operator()(const ArrayHandleType& input) const
51 {
52 *this->Range = vtkm::cont::ArrayRangeCompute(input);
53 }
54
55 private:
56 vtkm::cont::ArrayHandle<vtkm::Range>* Range;
57 };
58
59 } // namespace internal
60
61 /// A \c Field encapsulates an array on some piece of the mesh, such as
62 /// the points, a cell set, a point logical dimension, or the whole mesh.
63 ///
64 class VTKM_CONT_EXPORT Field
65 {
66 public:
67 enum struct Association
68 {
69 ANY,
70 WHOLE_MESH,
71 POINTS,
72 CELL_SET,
73 LOGICAL_DIM
74 };
75
76 /// constructors for points / whole mesh
77 VTKM_CONT
Field(std::string name,Association association,const vtkm::cont::DynamicArrayHandle & data)78 Field(std::string name, Association association, const vtkm::cont::DynamicArrayHandle& data)
79 : Name(name)
80 , FieldAssociation(association)
81 , AssocCellSetName()
82 , AssocLogicalDim(-1)
83 , Data(data)
84 , Range()
85 , ModifiedFlag(true)
86 {
87 VTKM_ASSERT(this->FieldAssociation == Association::WHOLE_MESH ||
88 this->FieldAssociation == Association::POINTS);
89 }
90
91 template <typename T, typename Storage>
Field(std::string name,Association association,const ArrayHandle<T,Storage> & data)92 VTKM_CONT Field(std::string name, Association association, const ArrayHandle<T, Storage>& data)
93 : Name(name)
94 , FieldAssociation(association)
95 , AssocCellSetName()
96 , AssocLogicalDim(-1)
97 , Data(data)
98 , Range()
99 , ModifiedFlag(true)
100 {
101 VTKM_ASSERT((this->FieldAssociation == Association::WHOLE_MESH) ||
102 (this->FieldAssociation == Association::POINTS));
103 }
104
105 /// constructors for cell set associations
106 VTKM_CONT
Field(std::string name,Association association,const std::string & cellSetName,const vtkm::cont::DynamicArrayHandle & data)107 Field(std::string name,
108 Association association,
109 const std::string& cellSetName,
110 const vtkm::cont::DynamicArrayHandle& data)
111 : Name(name)
112 , FieldAssociation(association)
113 , AssocCellSetName(cellSetName)
114 , AssocLogicalDim(-1)
115 , Data(data)
116 , Range()
117 , ModifiedFlag(true)
118 {
119 VTKM_ASSERT(this->FieldAssociation == Association::CELL_SET);
120 }
121
122 template <typename T, typename Storage>
Field(std::string name,Association association,const std::string & cellSetName,const vtkm::cont::ArrayHandle<T,Storage> & data)123 VTKM_CONT Field(std::string name,
124 Association association,
125 const std::string& cellSetName,
126 const vtkm::cont::ArrayHandle<T, Storage>& data)
127 : Name(name)
128 , FieldAssociation(association)
129 , AssocCellSetName(cellSetName)
130 , AssocLogicalDim(-1)
131 , Data(data)
132 , Range()
133 , ModifiedFlag(true)
134 {
135 VTKM_ASSERT(this->FieldAssociation == Association::CELL_SET);
136 }
137
138 /// constructors for logical dimension associations
139 VTKM_CONT
Field(std::string name,Association association,vtkm::IdComponent logicalDim,const vtkm::cont::DynamicArrayHandle & data)140 Field(std::string name,
141 Association association,
142 vtkm::IdComponent logicalDim,
143 const vtkm::cont::DynamicArrayHandle& data)
144 : Name(name)
145 , FieldAssociation(association)
146 , AssocCellSetName()
147 , AssocLogicalDim(logicalDim)
148 , Data(data)
149 , Range()
150 , ModifiedFlag(true)
151 {
152 VTKM_ASSERT(this->FieldAssociation == Association::LOGICAL_DIM);
153 }
154
155 template <typename T, typename Storage>
Field(std::string name,Association association,vtkm::IdComponent logicalDim,const vtkm::cont::ArrayHandle<T,Storage> & data)156 VTKM_CONT Field(std::string name,
157 Association association,
158 vtkm::IdComponent logicalDim,
159 const vtkm::cont::ArrayHandle<T, Storage>& data)
160 : Name(name)
161 , FieldAssociation(association)
162 , AssocLogicalDim(logicalDim)
163 , Data(data)
164 , Range()
165 , ModifiedFlag(true)
166 {
167 VTKM_ASSERT(this->FieldAssociation == Association::LOGICAL_DIM);
168 }
169
170 VTKM_CONT
Field()171 Field()
172 : Name()
173 , FieldAssociation(Association::ANY)
174 , AssocCellSetName()
175 , AssocLogicalDim()
176 , Data()
177 , Range()
178 , ModifiedFlag(true)
179 {
180 //Generate an empty field
181 }
182
183 VTKM_CONT
184 virtual ~Field();
185
186 VTKM_CONT
187 Field& operator=(const vtkm::cont::Field& src) = default;
188
189 VTKM_CONT
GetName()190 const std::string& GetName() const { return this->Name; }
191
192 VTKM_CONT
GetAssociation()193 Association GetAssociation() const { return this->FieldAssociation; }
194
195 VTKM_CONT
GetAssocCellSet()196 std::string GetAssocCellSet() const { return this->AssocCellSetName; }
197
198 VTKM_CONT
GetAssocLogicalDim()199 vtkm::IdComponent GetAssocLogicalDim() const { return this->AssocLogicalDim; }
200
201 template <typename TypeList, typename StorageList>
GetRange(TypeList,StorageList)202 VTKM_CONT const vtkm::cont::ArrayHandle<vtkm::Range>& GetRange(TypeList, StorageList) const
203 {
204 VTKM_IS_LIST_TAG(TypeList);
205 VTKM_IS_LIST_TAG(StorageList);
206
207 return this->GetRangeImpl(TypeList(), StorageList());
208 }
209
210 VTKM_CONT
211 const vtkm::cont::ArrayHandle<vtkm::Range>& GetRange(VTKM_DEFAULT_TYPE_LIST_TAG,
212 VTKM_DEFAULT_STORAGE_LIST_TAG) const;
213
214 template <typename TypeList, typename StorageList>
GetRange(vtkm::Range * range,TypeList,StorageList)215 VTKM_CONT void GetRange(vtkm::Range* range, TypeList, StorageList) const
216 {
217 VTKM_IS_LIST_TAG(TypeList);
218 VTKM_IS_LIST_TAG(StorageList);
219
220 this->GetRange(TypeList(), StorageList());
221
222 vtkm::Id length = this->Range.GetNumberOfValues();
223 for (vtkm::Id i = 0; i < length; ++i)
224 {
225 range[i] = this->Range.GetPortalConstControl().Get(i);
226 }
227 }
228
229 template <typename TypeList>
GetRange(TypeList)230 VTKM_CONT const vtkm::cont::ArrayHandle<vtkm::Range>& GetRange(TypeList) const
231 {
232 VTKM_IS_LIST_TAG(TypeList);
233
234 return this->GetRange(TypeList(), VTKM_DEFAULT_STORAGE_LIST_TAG());
235 }
236
237 template <typename TypeList>
GetRange(vtkm::Range * range,TypeList)238 VTKM_CONT void GetRange(vtkm::Range* range, TypeList) const
239 {
240 VTKM_IS_LIST_TAG(TypeList);
241
242 this->GetRange(range, TypeList(), VTKM_DEFAULT_STORAGE_LIST_TAG());
243 }
244
245 VTKM_CONT
246 const vtkm::cont::ArrayHandle<vtkm::Range>& GetRange() const;
247
248 VTKM_CONT
249 void GetRange(vtkm::Range* range) const;
250
251 const vtkm::cont::DynamicArrayHandle& GetData() const;
252
253 vtkm::cont::DynamicArrayHandle& GetData();
254
255 template <typename T, typename StorageTag>
SetData(const vtkm::cont::ArrayHandle<T,StorageTag> & newdata)256 VTKM_CONT void SetData(const vtkm::cont::ArrayHandle<T, StorageTag>& newdata)
257 {
258 this->Data = newdata;
259 this->ModifiedFlag = true;
260 }
261
262 VTKM_CONT
SetData(const vtkm::cont::DynamicArrayHandle & newdata)263 void SetData(const vtkm::cont::DynamicArrayHandle& newdata)
264 {
265 this->Data = newdata;
266 this->ModifiedFlag = true;
267 }
268
269 template <typename T>
CopyData(const T * ptr,vtkm::Id nvals)270 VTKM_CONT void CopyData(const T* ptr, vtkm::Id nvals)
271 {
272 this->Data = vtkm::cont::make_ArrayHandle(ptr, nvals, true);
273 this->ModifiedFlag = true;
274 }
275
276 VTKM_CONT
277 virtual void PrintSummary(std::ostream& out) const;
278
279 VTKM_CONT
ReleaseResourcesExecution()280 virtual void ReleaseResourcesExecution()
281 {
282 // TODO: Call ReleaseResourcesExecution on the data when
283 // the DynamicArrayHandle class is able to do so.
284 this->Range.ReleaseResourcesExecution();
285 }
286
287 private:
288 std::string Name; ///< name of field
289
290 Association FieldAssociation;
291 std::string AssocCellSetName; ///< only populate if assoc is cells
292 vtkm::IdComponent AssocLogicalDim; ///< only populate if assoc is logical dim
293
294 vtkm::cont::DynamicArrayHandle Data;
295 mutable vtkm::cont::ArrayHandle<vtkm::Range> Range;
296 mutable bool ModifiedFlag;
297
298 template <typename TypeList, typename StorageList>
GetRangeImpl(TypeList,StorageList)299 VTKM_CONT const vtkm::cont::ArrayHandle<vtkm::Range>& GetRangeImpl(TypeList, StorageList) const
300 {
301 VTKM_IS_LIST_TAG(TypeList);
302 VTKM_IS_LIST_TAG(StorageList);
303
304 if (this->ModifiedFlag)
305 {
306 internal::ComputeRange computeRange(this->Range);
307 this->Data.ResetTypeAndStorageLists(TypeList(), StorageList()).CastAndCall(computeRange);
308 this->ModifiedFlag = false;
309 }
310
311 return this->Range;
312 }
313 };
314
315 template <typename Functor, typename... Args>
CastAndCall(const vtkm::cont::Field & field,Functor && f,Args &&...args)316 void CastAndCall(const vtkm::cont::Field& field, Functor&& f, Args&&... args)
317 {
318 field.GetData().CastAndCall(std::forward<Functor>(f), std::forward<Args>(args)...);
319 }
320
321 //@{
322 /// Convenience functions to build fields from C style arrays and std::vector
323 template <typename T>
324 vtkm::cont::Field make_Field(std::string name,
325 Field::Association association,
326 const T* data,
327 vtkm::Id size,
328 vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
329 {
330 return vtkm::cont::Field(name, association, vtkm::cont::make_ArrayHandle(data, size, copy));
331 }
332
333 template <typename T>
334 vtkm::cont::Field make_Field(std::string name,
335 Field::Association association,
336 const std::vector<T>& data,
337 vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
338 {
339 return vtkm::cont::Field(name, association, vtkm::cont::make_ArrayHandle(data, copy));
340 }
341
342 template <typename T>
343 vtkm::cont::Field make_Field(std::string name,
344 Field::Association association,
345 const std::string& cellSetName,
346 const T* data,
347 vtkm::Id size,
348 vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
349 {
350 return vtkm::cont::Field(
351 name, association, cellSetName, vtkm::cont::make_ArrayHandle(data, size, copy));
352 }
353
354 template <typename T>
355 vtkm::cont::Field make_Field(std::string name,
356 Field::Association association,
357 const std::string& cellSetName,
358 const std::vector<T>& data,
359 vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
360 {
361 return vtkm::cont::Field(
362 name, association, cellSetName, vtkm::cont::make_ArrayHandle(data, copy));
363 }
364
365 template <typename T>
366 vtkm::cont::Field make_Field(std::string name,
367 Field::Association association,
368 vtkm::IdComponent logicalDim,
369 const T* data,
370 vtkm::Id size,
371 vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
372 {
373 return vtkm::cont::Field(
374 name, association, logicalDim, vtkm::cont::make_ArrayHandle(data, size, copy));
375 }
376
377 template <typename T>
378 vtkm::cont::Field make_Field(std::string name,
379 Field::Association association,
380 vtkm::IdComponent logicalDim,
381 const std::vector<T>& data,
382 vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
383 {
384 return vtkm::cont::Field(name, association, logicalDim, vtkm::cont::make_ArrayHandle(data, copy));
385 }
386 //@}
387
388 namespace internal
389 {
390
391 template <>
392 struct DynamicTransformTraits<vtkm::cont::Field>
393 {
394 using DynamicTag = vtkm::cont::internal::DynamicTransformTagCastAndCall;
395 };
396
397 } // namespace internal
398 } // namespace cont
399 } // namespace vtkm
400
401 //=============================================================================
402 // Specializations of serialization related classes
403 namespace vtkm
404 {
405 namespace cont
406 {
407
408 template <typename TypeList = VTKM_DEFAULT_TYPE_LIST_TAG,
409 typename StorageList = VTKM_DEFAULT_STORAGE_LIST_TAG>
410 struct SerializableField
411 {
412 SerializableField() = default;
413
414 explicit SerializableField(const vtkm::cont::Field& field)
415 : Field(field)
416 {
417 }
418
419 vtkm::cont::Field Field;
420 };
421 }
422 } // vtkm::cont
423
424 namespace diy
425 {
426
427 template <typename TypeList, typename StorageList>
428 struct Serialization<vtkm::cont::SerializableField<TypeList, StorageList>>
429 {
430 private:
431 using Type = vtkm::cont::SerializableField<TypeList, StorageList>;
432
433 public:
434 static VTKM_CONT void save(BinaryBuffer& bb, const Type& serializable)
435 {
436 const auto& field = serializable.Field;
437
438 diy::save(bb, field.GetName());
439 diy::save(bb, static_cast<int>(field.GetAssociation()));
440 if (field.GetAssociation() == vtkm::cont::Field::Association::CELL_SET)
441 {
442 diy::save(bb, field.GetAssocCellSet());
443 }
444 else if (field.GetAssociation() == vtkm::cont::Field::Association::LOGICAL_DIM)
445 {
446 diy::save(bb, field.GetAssocLogicalDim());
447 }
448 diy::save(bb, field.GetData().ResetTypeAndStorageLists(TypeList{}, StorageList{}));
449 }
450
451 static VTKM_CONT void load(BinaryBuffer& bb, Type& serializable)
452 {
453 auto& field = serializable.Field;
454
455 std::string name;
456 diy::load(bb, name);
457 int assocVal = 0;
458 diy::load(bb, assocVal);
459
460 auto assoc = static_cast<vtkm::cont::Field::Association>(assocVal);
461 vtkm::cont::DynamicArrayHandleBase<TypeList, StorageList> data;
462 if (assoc == vtkm::cont::Field::Association::CELL_SET)
463 {
464 std::string assocCellSetName;
465 diy::load(bb, assocCellSetName);
466 diy::load(bb, data);
467 field =
468 vtkm::cont::Field(name, assoc, assocCellSetName, vtkm::cont::DynamicArrayHandle(data));
469 }
470 else if (assoc == vtkm::cont::Field::Association::LOGICAL_DIM)
471 {
472 vtkm::IdComponent assocLogicalDim;
473 diy::load(bb, assocLogicalDim);
474 diy::load(bb, data);
475 field = vtkm::cont::Field(name, assoc, assocLogicalDim, vtkm::cont::DynamicArrayHandle(data));
476 }
477 else
478 {
479 diy::load(bb, data);
480 field = vtkm::cont::Field(name, assoc, vtkm::cont::DynamicArrayHandle(data));
481 }
482 }
483 };
484
485 } // diy
486
487 #endif //vtk_m_cont_Field_h
488