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-2022 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
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
34template<class LabelListListType>
36(
38 const LabelListListType& listOfLists,
39 const label pointOffset
40)
41{
42 const label off = (pointOffset + 1); // 1-based for Ensight
43
44 forAll(listOfLists, listi)
45 {
46 for (const label pointi : listOfLists[listi])
47 {
48 os.write(pointi + off);
49 }
50 os.newline(); // One list (cell/faces) per line (ASCII)
51 }
52}
53
54
55template<template<typename> class FieldContainer, class Type>
57(
58 List<scalar>& cmptBuffer,
59 const FieldContainer<Type>& input,
60 const direction cmpt
61)
62{
63 if (cmptBuffer.size() < input.size())
64 {
66 << "Component buffer too small: "
67 << cmptBuffer.size() << " < " << input.size() << nl
68 << exit(FatalError);
69 }
70
71 auto iter = cmptBuffer.begin();
72
73 for (const Type& val : input)
74 {
75 *iter = component(val, cmpt);
76 ++iter;
77 }
78}
79
80
81template<template<typename> class FieldContainer, class Type>
83(
85 const FieldContainer<Type>& fld,
86 bool parallel
87)
88{
89 // already checked prior to calling, but extra safety
90 parallel = parallel && Pstream::parRun();
91
92 // Gather sizes (offsets irrelevant)
94 (
95 parallel
98 );
99
100
101 if (Pstream::master())
102 {
103 DynamicList<scalar> cmptBuffer(procAddr.maxSize());
104
105 for (direction d=0; d < pTraits<Type>::nComponents; ++d)
106 {
108
109 // Write master data
110 cmptBuffer.resize_nocopy(procAddr.localSize(0));
111 copyComponent(cmptBuffer, fld, cmpt);
112 os.writeList(cmptBuffer);
113
114 // Receive and write
115 for (const label proci : procAddr.subProcs())
116 {
117 cmptBuffer.resize_nocopy(procAddr.localSize(proci));
118 UIPstream::read
119 (
120 UPstream::commsTypes::scheduled,
121 proci,
122 cmptBuffer.data_bytes(),
123 cmptBuffer.size_bytes()
124 );
125 os.writeList(cmptBuffer);
126 }
127 }
128 }
129 else if (parallel)
130 {
131 // Send
132 List<scalar> cmptBuffer(fld.size());
133
134 for (direction d=0; d < pTraits<Type>::nComponents; ++d)
135 {
137
138 copyComponent(cmptBuffer, fld, cmpt);
139 UOPstream::write
140 (
141 UPstream::commsTypes::scheduled,
142 UPstream::masterNo(),
143 cmptBuffer.cdata_bytes(),
144 cmptBuffer.size_bytes()
145 );
146 }
147 }
148}
149
150
151template<template<typename> class FieldContainer>
153(
155 const label partId,
156 const word& partName,
157 const label nPoints,
158 const FieldContainer<Foam::point>& fld,
159 bool parallel
160)
161{
162 parallel = parallel && Pstream::parRun();
163
164 if (Pstream::master())
165 {
166 os.beginPart(partId, partName);
167 os.beginCoordinates(nPoints);
168 }
169
170 ensightOutput::Detail::writeFieldContent(os, fld, parallel);
171
172 return true;
173}
174
175
176template<template<typename> class FieldContainer, class Type>
178(
180 const char* key,
181 const FieldContainer<Type>& fld,
182 bool parallel
183)
184{
185 parallel = parallel && Pstream::parRun();
186
187 // Preliminary checks
188 {
189 bool hasField = !fld.empty();
190
191 if (parallel)
192 {
193 reduce(hasField, orOp<bool>());
194 }
195
196 // No field
197 if (!hasField) return false;
198 }
199
200
201 if (Pstream::master())
202 {
203 os.writeKeyword(key);
204 }
205
206 ensightOutput::Detail::writeFieldContent(os, fld, parallel);
207
208 return true;
209}
210
211
212template<class Type>
214(
216 const Field<Type>& fld,
217 const ensightFaces& part,
218 bool parallel
219)
220{
221 parallel = parallel && Pstream::parRun();
222
223 // Preliminary checks: total() contains pre-reduced information
224 {
225 // No geometry
226 if (parallel ? !part.total() : !part.size()) return false;
227
228 bool hasField = !fld.empty();
229
230 if (parallel)
231 {
232 reduce(hasField, orOp<bool>());
233 }
234
235 // No field
236 if (!hasField) return false;
237 }
238
239
240 if (Pstream::master())
241 {
242 os.beginPart(part.index());
243 }
244
245 for (int typei=0; typei < ensightFaces::nTypes; ++typei)
246 {
247 const auto etype = ensightFaces::elemType(typei);
248
249 ensightOutput::Detail::writeFieldComponents
250 (
251 os,
252 ensightFaces::key(etype),
253 SubField<Type>(fld, part.range(etype)),
254 parallel
255 );
256 }
257
258 return true;
259}
260
261
262template<class Type>
264(
266 const Field<Type>& fld,
267 const ensightFaces& part,
268 bool parallel
269)
270{
271 parallel = parallel && Pstream::parRun();
272
273 // Preliminary checks: total() contains pre-reduced information
274 {
275 // No geometry
276 if (parallel ? !part.total() : !part.size()) return false;
277
278 bool hasField = !fld.empty();
279
280 if (parallel)
281 {
282 reduce(hasField, orOp<bool>());
283 }
284
285 // No field
286 if (!hasField) return false;
287 }
288
289 bool validAddressing = (part.size() == part.faceOrder().size());
290
291 if (parallel)
292 {
293 reduce(validAddressing, orOp<bool>());
294 }
295
296 if (!validAddressing)
297 {
299 << "Called without faceOrder having been set" << nl
300 << exit(FatalError);
301 }
302
303
304 if (Pstream::master())
305 {
306 os.beginPart(part.index());
307 }
308
309 for (int typei=0; typei < ensightFaces::nTypes; ++typei)
310 {
311 const auto etype = ensightFaces::elemType(typei);
312
313 ensightOutput::Detail::writeFieldComponents
314 (
315 os,
316 ensightFaces::key(etype),
317 UIndirectList<Type>(fld, part.faceOrder(etype)),
318 parallel
319 );
320 }
321
322 return true;
323}
324
325
326// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
327
328template<class Type>
330(
332 const Field<Type>& fld,
333 const ensightCells& part,
334 bool parallel
335)
336{
337 parallel = parallel && Pstream::parRun();
338
339 // Preliminary checks: total() contains pre-reduced information
340 {
341 // No geometry
342 if (parallel ? !part.total() : !part.size()) return false;
343
344 bool hasField = !fld.empty();
345
346 if (parallel)
347 {
348 reduce(hasField, orOp<bool>());
349 }
350
351 // No field
352 if (!hasField) return false;
353 }
354
355
356 if (Pstream::master())
357 {
358 os.beginPart(part.index());
359 }
360
361 for (int typei=0; typei < ensightCells::nTypes; ++typei)
362 {
363 const auto etype = ensightCells::elemType(typei);
364
365 ensightOutput::Detail::writeFieldComponents
366 (
367 os,
368 ensightCells::key(etype),
369 UIndirectList<Type>(fld, part.cellIds(etype)),
370 parallel
371 );
372 }
373
374 return true;
375}
376
377
378template<class Type>
380(
382 const Field<Type>& fld,
383 const ensightFaces& part,
384 bool parallel
385)
386{
387 parallel = parallel && Pstream::parRun();
388
389 // Preliminary checks: total() contains pre-reduced information
390 {
391 // No geometry
392 if (parallel ? !part.total() : !part.size()) return false;
393
394 bool hasField = !fld.empty();
395
396 if (parallel)
397 {
398 reduce(hasField, orOp<bool>());
399 }
400
401 // No field
402 if (!hasField) return false;
403 }
404
405
406 if (Pstream::master())
407 {
408 os.beginPart(part.index());
409 }
410
411 for (int typei=0; typei < ensightFaces::nTypes; ++typei)
412 {
413 const auto etype = ensightFaces::elemType(typei);
414
415 ensightOutput::Detail::writeFieldComponents
416 (
417 os,
418 ensightFaces::key(etype),
419 UIndirectList<Type>(fld, part.faceIds(etype)),
420 parallel
421 );
422 }
423
424 return true;
425}
426
427
428// ************************************************************************* //
Info<< nl<< "Wrote faMesh in vtk format: "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.mesh().time().globalPath()/"finiteArea-edges"));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
globalIndex procAddr(aMesh.nFaces())
reduce(hasMovingMesh, orOp< bool >())
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
void resize_nocopy(const label len)
Definition: DynamicListI.H:363
Generic templated field type.
Definition: Field.H:82
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
SubField is a Field obtained as a section of another Field, without its own allocation....
Definition: SubField.H:62
A List with indirect addressing. Like IndirectList but does not store addressing.
Definition: IndirectList.H:79
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:329
char * data_bytes() noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:251
const char * cdata_bytes() const noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:244
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
std::streamsize size_bytes() const noexcept
Number of contiguous bytes for the List data.
Definition: UListI.H:258
Sorting/classification of cells (3D) into corresponding ensight element types.
Definition: ensightCells.H:58
label size(const elemType etype) const
Processor-local size of the specified element type.
Definition: ensightCellsI.H:67
elemType
Supported ensight 'Cell' element types.
Definition: ensightCells.H:66
label total() const
The global size of all element types.
Definition: ensightCells.C:111
const labelList & cellIds() const
Processor-local cell ids of all elements.
Definition: ensightCellsI.H:79
Sorting/classification of faces (2D) into corresponding ensight types.
Definition: ensightFaces.H:75
labelRange range(const elemType etype) const
Processor-local offset/size of element type.
Definition: ensightFacesI.H:73
const labelList & faceIds() const noexcept
Processor-local face ids of all elements.
Definition: ensightFacesI.H:79
const labelList & faceOrder() const noexcept
label size(const elemType etype) const
Processor-local size of the specified element type.
Definition: ensightFacesI.H:67
elemType
Supported ensight 'Face' element types.
Definition: ensightFaces.H:83
label total() const
The global size of all element types.
Definition: ensightFaces.C:136
Ensight output with specialized write() for strings, integers and floats. Correctly handles binary wr...
Definition: ensightFile.H:55
Specialized Ensight output with extra geometry file header.
label index() const noexcept
The index in a list (0-based)
Definition: ensightPart.H:124
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
OBJstream os(runTime.globalPath()/outputName)
label nPoints
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.
bool writeFaceSubField(ensightFile &os, const Field< Type > &fld, const ensightFaces &part, bool parallel)
bool writeFieldComponents(ensightFile &os, const char *key, const FieldContainer< Type > &fld, bool parallel)
Write field content (component-wise) for the given ensight element type.
void copyComponent(List< scalar > &cmptBuffer, const FieldContainer< Type > &input, const direction cmpt)
void writeFieldContent(ensightFile &os, const FieldContainer< Type > &fld, bool parallel)
Write field content (component-wise)
void writeLabelListList(ensightGeoFile &os, const labelUList &offsets, const labelUList &values, const label pointOffset)
Write CompactListList<label> by components.
bool writeFaceLocalField(ensightFile &os, const Field< Type > &fld, const ensightFaces &part, bool parallel)
bool writeField(ensightFile &os, const Field< Type > &fld, const ensightCells &part, bool parallel)
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
uint8_t direction
Definition: direction.H:56
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
Ensight names and component order for base types.