foamVtkOutputTemplates.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2016-2022 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "globalIndex.H"
29 #include "Pstream.H"
30 #include "ListOps.H"
31 
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33 
34 template<class Type>
35 inline void Foam::vtk::write
36 (
37  vtk::formatter& fmt,
38  const Type& val,
39  const label n
40 )
41 {
43 
44  for (label i=0; i < n; ++i)
45  {
46  for (direction cmpt=0; cmpt < nCmpt; ++cmpt)
47  {
48  fmt.write(component(val, cmpt));
49  }
50  }
51 }
52 
53 
54 template<class Type>
56 (
57  vtk::formatter& fmt,
58  const UList<Type>& values
59 )
60 {
61  for (const Type& val : values)
62  {
63  vtk::write(fmt, val);
64  }
65 }
66 
67 
68 template<class Type, unsigned N>
70 (
71  vtk::formatter& fmt,
72  const FixedList<Type, N>& values
73 )
74 {
75  for (const Type& val : values)
76  {
77  vtk::write(fmt, val);
78  }
79 }
80 
81 
82 template<class Type>
84 (
85  vtk::formatter& fmt,
86  const UList<Type>& values,
87  const labelUList& addressing
88 )
89 {
90  for (const label idx : addressing)
91  {
92  vtk::write(fmt, values[idx]);
93  }
94 }
95 
96 
97 template<class Type>
99 (
100  vtk::formatter& fmt,
101  const UList<Type>& values,
102  const bitSet& selected
103 )
104 {
105  for (const label idx : selected)
106  {
107  vtk::write(fmt, values[idx]);
108  }
109 }
110 
111 
112 template<class Type>
114 (
115  vtk::formatter& fmt,
116  const UList<Type>& values,
117  const UList<Type>& indirect,
118  const labelUList& addressing
119 )
120 {
122  vtk::writeList(fmt, indirect, addressing);
123 }
124 
125 
126 template<class Type>
128 (
129  vtk::formatter& fmt,
130  const Type& val,
131  const label count
132 )
133 {
135  {
136  // Non-contiguous data does not make sense
138  << "Contiguous data only" << endl
140  }
141 
142  // Gather [count, value] tuples, including from master
143  const List<label> counts(UPstream::listGatherValues(count));
144  const List<Type> values(UPstream::listGatherValues(val));
145 
146  if (Pstream::master())
147  {
148  forAll(counts, i)
149  {
150  // Write [count, value] tuple
151  vtk::write(fmt, counts[i], values[i]);
152  }
153  }
154 }
155 
156 
157 template<class Type>
159 (
160  vtk::formatter& fmt,
161  const UList<Type>& values
162 )
163 {
164  if (!is_contiguous<Type>::value)
165  {
166  // Non-contiguous data does not make sense
168  << "Contiguous data only" << endl
170  }
171 
172 
173  // Gather sizes (offsets irrelevant)
174  const globalIndex procAddr(globalIndex::gatherOnly{}, values.size());
175 
176 
177  if (Pstream::master())
178  {
179  // Write master data
180  vtk::writeList(fmt, values);
181 
182  // Receive and write
183  DynamicList<Type> recvData(procAddr.maxNonLocalSize());
184 
185  for (const label proci : procAddr.subProcs())
186  {
187  const label procSize = procAddr.localSize(proci);
188 
189  if (procSize)
190  {
191  recvData.resize_nocopy(procSize);
193  (
194  UPstream::commsTypes::scheduled,
195  proci,
196  recvData.data_bytes(),
197  recvData.size_bytes()
198  );
199  vtk::writeList(fmt, recvData);
200  }
201  }
202  }
203  else
204  {
205  if (values.size())
206  {
208  (
209  UPstream::commsTypes::scheduled,
210  UPstream::masterNo(),
211  values.cdata_bytes(),
212  values.size_bytes()
213  );
214  }
215  }
216 }
217 
218 
219 template<class Type>
221 (
222  vtk::formatter& fmt,
223  const UList<Type>& values,
224  const labelUList& addressing
225 )
226 {
227  if (!is_contiguous<Type>::value)
228  {
229  // Non-contiguous data does not make sense
231  << "Contiguous data only" << endl
233  }
234 
235 
236  List<Type> sendData;
237  if (!Pstream::master())
238  {
239  sendData = UIndirectList<Type>(values, addressing);
240  }
241 
242  // Gather sizes (offsets irrelevant)
243  const globalIndex procAddr(globalIndex::gatherOnly{}, sendData.size());
244 
245 
246  if (Pstream::master())
247  {
248  // Write master data
249  vtk::writeList(fmt, values, addressing);
250 
251  // Receive and write
252  DynamicList<Type> recvData(procAddr.maxNonLocalSize());
253 
254  for (const label proci : procAddr.subProcs())
255  {
256  const label procSize = procAddr.localSize(proci);
257 
258  if (procSize)
259  {
260  recvData.resize_nocopy(procSize);
262  (
263  UPstream::commsTypes::scheduled,
264  proci,
265  recvData.data_bytes(),
266  recvData.size_bytes()
267  );
268  vtk::writeList(fmt, recvData);
269  }
270  }
271  }
272  else
273  {
274  if (sendData.size())
275  {
277  (
278  UPstream::commsTypes::scheduled,
279  UPstream::masterNo(),
280  sendData.cdata_bytes(),
281  sendData.size_bytes()
282  );
283  }
284  }
285 }
286 
287 
288 template<class Type>
290 (
291  vtk::formatter& fmt,
292  const UList<Type>& values,
293  const bitSet& selected
294 )
295 {
296  if (!is_contiguous<Type>::value)
297  {
298  // Non-contiguous data does not make sense
300  << "Contiguous data only" << endl
302  }
303 
304 
305  List<Type> sendData;
306  if (!Pstream::master())
307  {
308  sendData = subset(selected, values);
309  }
310 
311  // Gather sizes (offsets irrelevant)
312  const globalIndex procAddr(globalIndex::gatherOnly{}, sendData.size());
313 
314 
315  if (Pstream::master())
316  {
317  // Write master data
318  vtk::writeList(fmt, values, selected);
319 
320  // Receive and write
321  DynamicList<Type> recvData(procAddr.maxNonLocalSize());
322 
323  for (const label proci : procAddr.subProcs())
324  {
325  const label procSize = procAddr.localSize(proci);
326 
327  if (procSize)
328  {
329  recvData.resize_nocopy(procSize);
330 
332  (
333  UPstream::commsTypes::scheduled,
334  proci,
335  recvData.data_bytes(),
336  recvData.size_bytes()
337  );
338  vtk::writeList(fmt, recvData);
339  }
340  }
341  }
342  else
343  {
344  if (sendData.size())
345  {
347  (
348  UPstream::commsTypes::scheduled,
349  UPstream::masterNo(),
350  sendData.cdata_bytes(),
351  sendData.size_bytes()
352  );
353  }
354  }
355 }
356 
357 
358 template<class Type>
360 (
361  vtk::formatter& fmt,
362  const UList<Type>& values1,
363  const UList<Type>& values2
364 )
365 {
366  if (!is_contiguous<Type>::value)
367  {
368  // Non-contiguous data does not make sense
370  << "Contiguous data only" << endl
372  }
373 
374 
375  // Gather sizes (offsets irrelevant)
376  const globalIndex procAddr1(globalIndex::gatherOnly{}, values1.size());
377  const globalIndex procAddr2(globalIndex::gatherOnly{}, values2.size());
378 
379 
380  if (Pstream::master())
381  {
382  // Write master data
383  vtk::writeList(fmt, values1);
384  vtk::writeList(fmt, values2);
385 
386  // Receive and write
387  DynamicList<Type> recvData
388  (
389  max(procAddr1.maxNonLocalSize(), procAddr2.maxNonLocalSize())
390  );
391 
392  for (const label proci : procAddr1.subProcs())
393  {
394  // values1
395  label procSize = procAddr1.localSize(proci);
396 
397  if (procSize)
398  {
399  recvData.resize_nocopy(procSize);
401  (
402  UPstream::commsTypes::scheduled,
403  proci,
404  recvData.data_bytes(),
405  recvData.size_bytes()
406  );
407  vtk::writeList(fmt, recvData);
408  }
409 
410  // values2
411  procSize = procAddr2.localSize(proci);
412 
413  if (procSize)
414  {
415  recvData.resize_nocopy(procSize);
417  (
418  UPstream::commsTypes::scheduled,
419  proci,
420  recvData.data_bytes(),
421  recvData.size_bytes()
422  );
423  vtk::writeList(fmt, recvData);
424  }
425  }
426  }
427  else
428  {
429  if (values1.size())
430  {
432  (
433  UPstream::commsTypes::scheduled,
434  UPstream::masterNo(),
435  values1.cdata_bytes(),
436  values1.size_bytes()
437  );
438  }
439 
440  if (values2.size())
441  {
443  (
444  UPstream::commsTypes::scheduled,
445  UPstream::masterNo(),
446  values2.cdata_bytes(),
447  values2.size_bytes()
448  );
449  }
450  }
451 }
452 
453 
454 template<class Type>
456 (
457  vtk::formatter& fmt,
458  const UList<Type>& values1,
459  const UList<Type>& values2,
460  const labelUList& addressing
461 )
462 {
463  if (!is_contiguous<Type>::value)
464  {
465  // Non-contiguous data does not make sense
467  << "Contiguous data only" << endl
469  }
470 
471 
472  List<Type> sendData2;
473  if (!Pstream::master())
474  {
475  sendData2 = UIndirectList<Type>(values2, addressing);
476  }
477 
478 
479  // Gather sizes (offsets irrelevant)
480  const globalIndex procAddr1(globalIndex::gatherOnly{}, values1.size());
481  const globalIndex procAddr2(globalIndex::gatherOnly{}, sendData2.size());
482 
483 
484  if (Pstream::master())
485  {
486  // Write master data
487 
488  vtk::writeList(fmt, values1);
489  vtk::writeList(fmt, values2, addressing);
490 
491  // Receive and write
492  DynamicList<Type> recvData
493  (
494  max(procAddr1.maxNonLocalSize(), procAddr2.maxNonLocalSize())
495  );
496 
497  for (const label proci : procAddr1.subProcs())
498  {
499  // values1
500  label procSize = procAddr1.localSize(proci);
501 
502  if (procSize)
503  {
504  recvData.resize_nocopy(procSize);
506  (
507  UPstream::commsTypes::scheduled,
508  proci,
509  recvData.data_bytes(),
510  recvData.size_bytes()
511  );
512  vtk::writeList(fmt, recvData);
513  }
514 
515  // values2
516  procSize = procAddr2.localSize(proci);
517 
518  if (procSize)
519  {
520  recvData.resize_nocopy(procSize);
522  (
523  UPstream::commsTypes::scheduled,
524  proci,
525  recvData.data_bytes(),
526  recvData.size_bytes()
527  );
528  vtk::writeList(fmt, recvData);
529  }
530  }
531  }
532  else
533  {
534  if (values1.size())
535  {
537  (
538  UPstream::commsTypes::scheduled,
539  UPstream::masterNo(),
540  values1.cdata_bytes(),
541  values1.size_bytes()
542  );
543  }
544 
545  if (sendData2.size())
546  {
548  (
549  UPstream::commsTypes::scheduled,
550  UPstream::masterNo(),
551  sendData2.cdata_bytes(),
552  sendData2.size_bytes()
553  );
554  }
555  }
556 }
557 
558 
559 // ************************************************************************* //
uint8_t direction
Definition: direction.H:46
void writeLists(vtk::formatter &fmt, const UList< Type > &values1, const UList< Type > &values2, const labelUList &addressing)
Write a list of values and a list of values via indirect addressing.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
Abstract class for a VTK output stream formatter.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
A traits class, which is primarily used for primitives and vector-space.
Definition: pTraits.H:75
void writeListsParallel(vtk::formatter &fmt, const UList< Type > &values1, const UList< Type > &values2)
Write a list of values and another list of values.
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:164
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
void writeList(vtk::formatter &fmt, const UList< uint8_t > &values)
Write a list of uint8_t values.
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
List< T > subset(const BoolListType &select, const UList< T > &input, const bool invert=false)
Extract elements of the input list when select is true.
globalIndex procAddr(aMesh.nFaces())
virtual void write(const uint8_t val)=0
A template class to specify that a data type can be considered as being contiguous in memory...
Definition: contiguous.H:70
label n
void writeListParallel(vtk::formatter &fmt, const UList< Type > &values)
Write a list of values.
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
void writeValueParallel(vtk::formatter &fmt, const Type &val, const label count=1)
Component-wise write of a value (N times) in parallel.