ensightOutputTemplates.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) 2019-2021 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 "ensightOutput.H"
29 #include "ensightPTraits.H"
30 #include "globalIndex.H"
31 
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33 
34 template<template<typename> class FieldContainer, class Type>
36 (
37  List<scalar>& cmptBuffer,
38  const FieldContainer<Type>& input,
39  const direction cmpt
40 )
41 {
42  if (cmptBuffer.size() < input.size())
43  {
45  << "Component buffer too small: "
46  << cmptBuffer.size() << " < " << input.size() << nl
47  << exit(FatalError);
48  }
49 
50  auto iter = cmptBuffer.begin();
51 
52  for (const Type& val : input)
53  {
54  *iter = component(val, cmpt);
55  ++iter;
56  }
57 }
58 
59 
60 template<template<typename> class FieldContainer, class Type>
62 (
63  ensightFile& os,
64  const FieldContainer<Type>& fld,
65  bool parallel
66 )
67 {
68  // already checked prior to calling, but extra safety
69  parallel = parallel && Pstream::parRun();
70 
71  // Size information (offsets are irrelevant)
72  globalIndex procAddr;
73  if (parallel)
74  {
75  procAddr.reset(UPstream::listGatherValues<label>(fld.size()));
76  }
77  else
78  {
79  // Master size
80  procAddr.reset(labelList(Foam::one{}, fld.size()));
81  }
82 
83 
84  if (Pstream::master())
85  {
86  DynamicList<scalar> cmptBuffer(procAddr.maxSize());
87 
88  for (direction d=0; d < pTraits<Type>::nComponents; ++d)
89  {
91 
92  // Write master data
93  cmptBuffer.resize_nocopy(procAddr.localSize(0));
94  copyComponent(cmptBuffer, fld, cmpt);
95  os.writeList(cmptBuffer);
96 
97  // Receive and write
98  for (const label proci : procAddr.subProcs())
99  {
100  cmptBuffer.resize_nocopy(procAddr.localSize(proci));
102  (
103  UPstream::commsTypes::scheduled,
104  proci,
105  cmptBuffer.data_bytes(),
106  cmptBuffer.size_bytes()
107  );
108  os.writeList(cmptBuffer);
109  }
110  }
111  }
112  else if (parallel)
113  {
114  // Send
115  List<scalar> cmptBuffer(fld.size());
116 
117  for (direction d=0; d < pTraits<Type>::nComponents; ++d)
118  {
120 
121  copyComponent(cmptBuffer, fld, cmpt);
123  (
124  UPstream::commsTypes::scheduled,
125  Pstream::masterNo(),
126  cmptBuffer.cdata_bytes(),
127  cmptBuffer.size_bytes()
128  );
129  }
130  }
131 }
132 
133 
134 template<template<typename> class FieldContainer>
136 (
138  const label partId,
139  const word& partName,
140  const label nPoints,
141  const FieldContainer<Foam::point>& fld,
142  bool parallel
143 )
144 {
145  parallel = parallel && Pstream::parRun();
146 
147  if (Pstream::master())
148  {
149  os.beginPart(partId, partName);
150  os.beginCoordinates(nPoints);
151  }
152 
154 
155  return true;
156 }
157 
158 
159 template<template<typename> class FieldContainer, class Type>
161 (
162  ensightFile& os,
163  const char* key,
164  const FieldContainer<Type>& fld,
165  bool parallel
166 )
167 {
168  parallel = parallel && Pstream::parRun();
169 
170  // Preliminary checks
171  {
172  bool hasField = !fld.empty();
173 
174  if (parallel)
175  {
176  reduce(hasField, orOp<bool>());
177  }
178 
179  // No field
180  if (!hasField) return false;
181  }
182 
183 
184  if (Pstream::master())
185  {
186  os.writeKeyword(key);
187  }
188 
190 
191  return true;
192 }
193 
194 
195 template<class Type>
197 (
198  ensightFile& os,
199  const Field<Type>& fld,
200  const ensightFaces& part,
201  bool parallel
202 )
203 {
204  parallel = parallel && Pstream::parRun();
205 
206  // Preliminary checks: total() contains pre-reduced information
207  {
208  // No geometry
209  if (parallel ? !part.total() : !part.size()) return false;
210 
211  bool hasField = !fld.empty();
212 
213  if (parallel)
214  {
215  reduce(hasField, orOp<bool>());
216  }
217 
218  // No field
219  if (!hasField) return false;
220  }
221 
222 
223  if (Pstream::master())
224  {
225  os.beginPart(part.index());
226  }
227 
228  for (int typei=0; typei < ensightFaces::nTypes; ++typei)
229  {
230  const auto etype = ensightFaces::elemType(typei);
231 
233  (
234  os,
235  ensightFaces::key(etype),
236  SubField<Type>(fld, part.range(etype)),
237  parallel
238  );
239  }
240 
241  return true;
242 }
243 
244 
245 template<class Type>
247 (
248  ensightFile& os,
249  const Field<Type>& fld,
250  const ensightFaces& part,
251  bool parallel
252 )
253 {
254  parallel = parallel && Pstream::parRun();
255 
256  // Preliminary checks: total() contains pre-reduced information
257  {
258  // No geometry
259  if (parallel ? !part.total() : !part.size()) return false;
260 
261  bool hasField = !fld.empty();
262 
263  if (parallel)
264  {
265  reduce(hasField, orOp<bool>());
266  }
267 
268  // No field
269  if (!hasField) return false;
270  }
271 
272  bool validAddressing = (part.size() == part.faceOrder().size());
273 
274  if (parallel)
275  {
276  reduce(validAddressing, orOp<bool>());
277  }
278 
279  if (!validAddressing)
280  {
282  << "Called without faceOrder having been set" << nl
283  << exit(FatalError);
284  }
285 
286 
287  if (Pstream::master())
288  {
289  os.beginPart(part.index());
290  }
291 
292  for (int typei=0; typei < ensightFaces::nTypes; ++typei)
293  {
294  const auto etype = ensightFaces::elemType(typei);
295 
297  (
298  os,
299  ensightFaces::key(etype),
300  UIndirectList<Type>(fld, part.faceOrder(etype)),
301  parallel
302  );
303  }
304 
305  return true;
306 }
307 
308 
309 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
310 
311 template<class Type>
313 (
314  ensightFile& os,
315  const Field<Type>& fld,
316  const ensightCells& part,
317  bool parallel
318 )
319 {
320  parallel = parallel && Pstream::parRun();
321 
322  // Preliminary checks: total() contains pre-reduced information
323  {
324  // No geometry
325  if (parallel ? !part.total() : !part.size()) return false;
326 
327  bool hasField = !fld.empty();
328 
329  if (parallel)
330  {
331  reduce(hasField, orOp<bool>());
332  }
333 
334  // No field
335  if (!hasField) return false;
336  }
337 
338 
339  if (Pstream::master())
340  {
341  os.beginPart(part.index());
342  }
343 
344  for (int typei=0; typei < ensightCells::nTypes; ++typei)
345  {
346  const auto etype = ensightCells::elemType(typei);
347 
349  (
350  os,
351  ensightCells::key(etype),
352  UIndirectList<Type>(fld, part.cellIds(etype)),
353  parallel
354  );
355  }
356 
357  return true;
358 }
359 
360 
361 template<class Type>
363 (
364  ensightFile& os,
365  const Field<Type>& fld,
366  const ensightFaces& part,
367  bool parallel
368 )
369 {
370  parallel = parallel && Pstream::parRun();
371 
372  // Preliminary checks: total() contains pre-reduced information
373  {
374  // No geometry
375  if (parallel ? !part.total() : !part.size()) return false;
376 
377  bool hasField = !fld.empty();
378 
379  if (parallel)
380  {
381  reduce(hasField, orOp<bool>());
382  }
383 
384  // No field
385  if (!hasField) return false;
386  }
387 
388 
389  if (Pstream::master())
390  {
391  os.beginPart(part.index());
392  }
393 
394  for (int typei=0; typei < ensightFaces::nTypes; ++typei)
395  {
396  const auto etype = ensightFaces::elemType(typei);
397 
399  (
400  os,
401  ensightFaces::key(etype),
402  UIndirectList<Type>(fld, part.faceIds(etype)),
403  parallel
404  );
405  }
406 
407  return true;
408 }
409 
410 
411 // ************************************************************************* //
Foam::ensightFaces::faceIds
const labelList & faceIds() const noexcept
Processor-local face ids of all elements.
Definition: ensightFacesI.H:79
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::component
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
Definition: FieldFieldFunctions.C:44
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::ensightPart::index
label index() const noexcept
The index in a list (0-based)
Definition: ensightPart.H:124
Foam::DynamicList< scalar >
Foam::ensightPTraits
Ensight names and component order for base types.
Definition: ensightPTraits.H:53
globalIndex.H
Foam::glTF::key
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:108
Foam::one
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition: one.H:61
Foam::globalIndex::localSize
label localSize() const
My local size.
Definition: globalIndexI.H:187
Foam::ensightOutput::Detail::writeFieldComponents
bool writeFieldComponents(ensightFile &os, const char *key, const FieldContainer< Type > &fld, bool parallel)
Write field content (component-wise) for the given ensight element type.
Definition: ensightOutputTemplates.C:161
Foam::List::resize_nocopy
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:146
Foam::ensightFaces
Sorting/classification of faces (2D) into corresponding ensight types.
Definition: ensightFaces.H:71
Foam::ensightFaces::range
labelRange range(const elemType etype) const
Processor-local offset/size of element type.
Definition: ensightFacesI.H:73
Foam::globalIndex::maxSize
label maxSize() const
Global max of localSizes.
Definition: globalIndexI.H:193
Foam::ensightFaces::total
label total() const
The global size of all element types.
Definition: ensightFaces.C:136
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::SubField
SubField is a Field obtained as a section of another Field, without its own allocation....
Definition: Field.H:64
Foam::blockMeshTools::read
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:57
Foam::ensightOutput::Detail::writeFaceLocalField
bool writeFaceLocalField(ensightFile &os, const Field< Type > &fld, const ensightFaces &part, bool parallel)
Definition: ensightOutputTemplates.C:247
Foam::ensightGeoFile
Specialized Ensight output with extra geometry file header.
Definition: ensightGeoFile.H:48
ensightOutput.H
Foam::Field
Generic templated field type.
Definition: Field.H:63
ensightPTraits.H
Foam::ensightCells::total
label total() const
The global size of all element types.
Definition: ensightCells.C:109
Foam::ensightCells::cellIds
const labelList & cellIds() const
Processor-local cell ids of all elements.
Definition: ensightCellsI.H:73
Foam::ensightCells
Sorting/classification of cells (3D) into corresponding ensight element types.
Definition: ensightCells.H:54
fld
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputLagrangian.H:23
Foam::FatalError
error FatalError
Foam::ensightOutput::Detail::writeFaceSubField
bool writeFaceSubField(ensightFile &os, const Field< Type > &fld, const ensightFaces &part, bool parallel)
Definition: ensightOutputTemplates.C:197
reduce
reduce(hasMovingMesh, orOp< bool >())
os
OBJstream os(runTime.globalPath()/outputName)
Foam::ensightFaces::faceOrder
const labelList & faceOrder() const noexcept
Definition: ensightFacesI.H:105
Foam::ensightFile
Ensight output with specialized write() for strings, integers and floats. Correctly handles binary wr...
Definition: ensightFile.H:52
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
Foam::globalIndex::reset
void reset(const label localSize)
Reset from local size.
Definition: globalIndexI.H:157
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::globalIndex::subProcs
labelRange subProcs() const noexcept
Range of process indices for addressed sub-offsets (processes)
Definition: globalIndexI.H:121
Foam::ensightCells::size
label size(const elemType etype) const
Processor-local size of the specified element type.
Definition: ensightCellsI.H:61
Foam::ensightCells::elemType
elemType
Supported ensight 'Cell' element types.
Definition: ensightCells.H:64
Foam::ensightFaces::elemType
elemType
Supported ensight 'Face' element types.
Definition: ensightFaces.H:81
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::ensightOutput::writeField
bool writeField(ensightFile &os, const Field< Type > &fld, const ensightCells &part, bool parallel)
Definition: ensightOutputTemplates.C:313
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::List< scalar >
Foam::direction
uint8_t direction
Definition: direction.H:52
Foam::input
static Istream & input(Istream &is, IntRange< T > &range)
Definition: IntRanges.C:55
Foam::vtk::write
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
Definition: foamVtkOutputTemplates.C:36
Foam::UIndirectList
A List with indirect addressing.
Definition: faMatrix.H:60
Foam::orOp
Definition: ops.H:234
Foam::ensightOutput::Detail::writeFieldContent
void writeFieldContent(ensightFile &os, const FieldContainer< Type > &fld, bool parallel)
Write field content (component-wise)
Definition: ensightOutputTemplates.C:62
Foam::ensightOutput::Detail::copyComponent
void copyComponent(List< scalar > &cmptBuffer, const FieldContainer< Type > &input, const direction cmpt)
Definition: ensightOutputTemplates.C:36
Foam::ensightOutput::Detail::writeCoordinates
bool writeCoordinates(ensightGeoFile &os, const label partId, const word &partName, const label nPoints, const FieldContainer< Foam::point > &fld, bool parallel)
Write coordinates (component-wise) for the given part.
Definition: ensightOutputTemplates.C:136
Foam::ensightFaces::size
label size(const elemType etype) const
Processor-local size of the specified element type.
Definition: ensightFacesI.H:67