ensightOutputCloud.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 "ensightOutputCloud.H"
29 #include "fvMesh.H"
30 #include "Cloud.H"
31 #include "passiveParticle.H"
32 #include "globalIndex.H"
33 
34 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38 
39 //- Binary output
40 static inline void writeMeasured_binary
41 (
42  ensightFile& os,
44 )
45 {
46  for (const floatVector& p : points)
47  {
48  os.write(p.x());
49  os.write(p.y());
50  os.write(p.z());
51  }
52 }
53 
54 //- ASCII output. Id + position together
55 static inline label writeMeasured_ascii
56 (
57  ensightFile& os,
58  label pointId,
60 )
61 {
62  for (const floatVector& p : points)
63  {
64  os.write(++pointId, 8); // 1-index and an unusual width
65  os.write(p.x());
66  os.write(p.y());
67  os.write(p.z());
68  os.newline();
69  }
70 
71  return pointId;
72 }
73 
74 } // End namespace Foam
75 
76 
77 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
78 
80 (
81  ensightFile& os,
82  const fvMesh& mesh,
83  const word& cloudName,
84  bool exists
85 )
86 {
87  label nLocalParcels(0);
89 
90  if (exists)
91  {
92  parcelsPtr.reset(new Cloud<passiveParticle>(mesh, cloudName, false));
93  nLocalParcels = parcelsPtr().size();
94  }
95 
96  // Total number of parcels on all processes
97  const label nTotParcels = returnReduce(nLocalParcels, sumOp<label>());
98 
99  if (UPstream::master())
100  {
101  os.beginParticleCoordinates(nTotParcels);
102  }
103 
104  if (!nTotParcels)
105  {
106  return false; // DONE
107  }
108 
109 
110  // Gather sizes (offsets irrelevant)
111  const globalIndex procAddr(globalIndex::gatherOnly{}, nLocalParcels);
112 
113 
114  DynamicList<floatVector> positions;
115  positions.reserve(UPstream::master() ? procAddr.maxSize() : nLocalParcels);
116 
117  // Extract positions from parcel.
118  // Store as floatVector, since that is what Ensight will write anyhow
119 
120  if (parcelsPtr)
121  {
122  const auto& parcels = *parcelsPtr;
123 
124  positions.resize_nocopy(parcels.size()); // same as nLocalParcels
125 
126  auto outIter = positions.begin();
127 
128  if (std::is_same<float, vector::cmptType>::value)
129  {
130  for (const passiveParticle& p : parcels)
131  {
132  *outIter = p.position();
133  ++outIter;
134  }
135  }
136  else
137  {
138  for (const passiveParticle& p : parcels)
139  {
140  vector pos(p.position());
141 
142  (*outIter).x() = narrowFloat(pos.x());
143  (*outIter).y() = narrowFloat(pos.y());
144  (*outIter).z() = narrowFloat(pos.z());
145 
146  ++outIter;
147  }
148  }
149 
150  parcelsPtr.reset(nullptr);
151  }
152 
153  if (UPstream::master())
154  {
155  const bool isBinaryOutput = (os.format() == IOstreamOption::BINARY);
156 
157  label parcelId = 0;
158 
159  if (isBinaryOutput)
160  {
161  // NB: binary write is Ensight6 - first ids, then positions
162 
163  // 1-index
164  for (label id = 1; id <= nTotParcels; ++id)
165  {
166  os.write(id);
167  }
168 
169  // Write master data
170  writeMeasured_binary(os, positions);
171  }
172  else
173  {
174  // NB: ascii write is (id + position) together
175 
176  // Write master data
177  parcelId = writeMeasured_ascii(os, parcelId, positions);
178  }
179 
180 
181  // Receive and write
182  for (const label proci : procAddr.subProcs())
183  {
184  const label procSize = procAddr.localSize(proci);
185 
186  if (procSize)
187  {
188  positions.resize_nocopy(procSize);
190  (
191  UPstream::commsTypes::scheduled,
192  proci,
193  positions.data_bytes(),
194  positions.size_bytes()
195  );
196 
197  if (isBinaryOutput)
198  {
199  writeMeasured_binary(os, positions);
200  }
201  else
202  {
203  parcelId = writeMeasured_ascii(os, parcelId, positions);
204  }
205  }
206  }
207  }
208  else
209  {
210  if (positions.size())
211  {
213  (
214  UPstream::commsTypes::scheduled,
215  UPstream::masterNo(),
216  positions.cdata_bytes(),
217  positions.size_bytes()
218  );
219  }
220  }
221 
222  return true;
223 }
224 
225 
226 // ************************************************************************* //
Ensight output with specialized write() for strings, integers and floats. Correctly handles binary wr...
Definition: ensightFile.H:46
float narrowFloat(const double val)
Type narrowing from double to float.
Definition: scalar.H:240
virtual Ostream & write(const char c) override
Write character.
Definition: OBJstream.C:69
static void writeMeasured_binary(ensightFile &os, const UList< floatVector > &points)
Binary output.
Dispatch tag: Construct &#39;one-sided&#39; from local sizes, using gather but no broadcast.
Definition: globalIndex.H:110
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
A collection of functions for writing clouds as ensight file content.
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:37
dimensionedScalar pos(const dimensionedScalar &ds)
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:61
dynamicFvMesh & mesh
const pointField & points
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
const word cloudName(propsDict.get< word >("cloud"))
A class for handling words, derived from Foam::string.
Definition: word.H:63
bool exists(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist (as DIRECTORY or FILE) in the file system?
Definition: POSIX.C:835
bool writeCloudPositions(ensightFile &os, const fvMesh &mesh, const word &cloudName, bool exists)
Write cloud positions.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
void reserve(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
Definition: DynamicListI.H:333
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
OBJstream os(runTime.globalPath()/outputName)
static label writeMeasured_ascii(ensightFile &os, label pointId, const UList< floatVector > &points)
ASCII output. Id + position together.
globalIndex procAddr(aMesh.nFaces())
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
A Vector of values with float precision.
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
volScalarField & p
Copy of base particle.
Namespace for OpenFOAM.