debugSurfaceWriter.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) 2022-2023 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 "debugSurfaceWriter.H"
29 #include "globalIndex.H"
30 #include "OFstream.H"
31 #include "OSspecific.H"
32 #include "IOmanip.H"
33 #include "Time.H"
34 #include "pointIOField.H"
35 #include "primitivePatch.H"
36 #include "profiling.H"
37 #include "surfaceWriterMethods.H"
39 
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44 namespace surfaceWriters
45 {
46  defineTypeName(debugWriter);
47  addToRunTimeSelectionTable(surfaceWriter, debugWriter, word);
48  addToRunTimeSelectionTable(surfaceWriter, debugWriter, wordDict);
49 }
50 }
51 
52 
53 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
54 
55 template<class Type>
57 Foam::surfaceWriters::debugWriter::mergeField
58 (
59  const Field<Type>& fld
60 ) const
61 {
62  addProfiling(merge, "debugWriter::merge-field");
64 }
65 
66 
67 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
68 
70 :
71  surfaceWriter(),
72  enableMerge_(true),
73  enableWrite_(false),
74  header_(true),
75  streamOpt_(IOstreamOption::BINARY)
76 {}
77 
78 
80 (
81  const dictionary& options
82 )
83 :
84  surfaceWriter(options),
85  enableMerge_(options.getOrDefault("merge", true)),
86  enableWrite_(options.getOrDefault("write", false)),
87  header_(true),
88  streamOpt_(IOstreamOption::BINARY)
89 {
90  Info<< "Using debug surface writer ("
91  << (this->isPointData() ? "point" : "face") << " data):"
92  << " commsType=" << UPstream::commsTypeNames[commType_]
93  << " merge=" << Switch::name(enableMerge_)
94  << " write=" << Switch::name(enableWrite_) << endl;
95 }
96 
97 
99 (
100  const meshedSurf& surf,
101  const fileName& outputPath,
102  bool parallel,
103  const dictionary& options
104 )
105 :
106  debugWriter(options)
107 {
108  open(surf, outputPath, parallel);
109 }
110 
111 
113 (
114  const pointField& points,
115  const faceList& faces,
116  const fileName& outputPath,
117  bool parallel,
118  const dictionary& options
119 )
120 :
121  debugWriter(options)
122 {
123  open(points, faces, outputPath, parallel);
124 }
125 
126 
127 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
128 
129 void Foam::surfaceWriters::debugWriter::serialWriteGeometry
130 (
131  const regIOobject& iopts,
132  const meshedSurf& surf
133 )
134 {
135  const pointField& points = surf.points();
136  const faceList& faces = surf.faces();
137 
138  if (verbose_)
139  {
140  if (this->isPointData())
141  {
142  Info<< "Writing points: " << iopts.objectPath() << endl;
143  }
144  else
145  {
146  Info<< "Writing face centres: " << iopts.objectPath() << endl;
147  }
148  }
149 
150  // Like regIOobject::writeObject without instance() adaptation
151  // since this would write to e.g. 0/ instead of postProcessing/
152 
153  autoPtr<primitivePatch> ppPtr;
154 
155  {
156  OFstream os(iopts.objectPath(), streamOpt_);
157 
158  if (header_)
159  {
160  iopts.writeHeader(os);
161  }
162 
163  if (this->isPointData())
164  {
165  // Just like writeData, but without copying beforehand
166  os << points;
167  }
168  else
169  {
170  ppPtr.reset(new primitivePatch(SubList<face>(faces), points));
171 
172  // Just like writeData, but without copying beforehand
173  os << ppPtr().faceCentres();
174  }
175 
176  if (header_)
177  {
179  }
180  }
181 }
182 
183 
185 {
186  checkOpen();
187 
188  // Geometry: rootdir/surfaceName/"points"
189  // Field: rootdir/surfaceName/<TIME>/field
190 
191  fileName surfaceDir = outputPath_;
192 
193  if (parallel_ && !enableMerge_)
194  {
195  if (verbose_)
196  {
197  Info<< "Not merging or writing" << nl;
198  }
199 
200  // Pretend to have succeeded
201  wroteGeom_ = true;
202  return surfaceDir;
203  }
204 
205 
206  const meshedSurf& surf = surface();
207  // const meshedSurfRef& surf = adjustSurface();
208 
209  // Dummy Time to use as objectRegistry
210  autoPtr<Time> dummyTimePtr;
211 
212  if (enableWrite_)
213  {
214  dummyTimePtr = Time::NewGlobalTime();
215  }
216  else if (verbose_)
217  {
218  Info<< "Not writing: " << surf.faces().size() << " faces" << nl;
219  }
220 
221  if (enableWrite_ && (UPstream::master() || !parallel_))
222  {
223  if (!isDir(surfaceDir))
224  {
225  mkDir(surfaceDir);
226  }
227 
228  // Write sample locations
229  pointIOField iopts
230  (
231  IOobject
232  (
233  surfaceDir/"points",
234  *dummyTimePtr,
238  )
239  );
240  iopts.note() = (this->isPointData() ? "point data" : "face data");
241 
242  serialWriteGeometry(iopts, surf);
243  }
244 
245  wroteGeom_ = true;
246  return surfaceDir;
247 }
248 
249 
250 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
251 
252 template<class Type>
253 Foam::fileName Foam::surfaceWriters::debugWriter::writeTemplate
254 (
255  const word& fieldName,
256  const Field<Type>& localValues
257 )
258 {
259  checkOpen();
260 
261  // Geometry: rootdir/surfaceName/"points"
262  // Field: rootdir/surfaceName/<TIME>/field
263 
264  fileName surfaceDir = outputPath_;
265 
266  const fileName outputFile(surfaceDir/timeName()/fieldName);
267 
268  if (parallel_ && !enableMerge_)
269  {
270  if (verbose_)
271  {
272  Info<< "Not merging or writing" << nl;
273  }
274 
275  // Pretend to have succeeded
276  wroteGeom_ = true;
277  return surfaceDir;
278  }
279 
280 
281  // Implicit geometry merge()
282  tmp<Field<Type>> tfield = mergeField(localValues);
283 
284  // Dummy Time to use as objectRegistry
285  autoPtr<Time> dummyTimePtr;
286 
287  if (enableWrite_)
288  {
289  dummyTimePtr = Time::NewGlobalTime();
290  }
291  else if (verbose_)
292  {
293  Info<< "Not writing: " << tfield().size()
294  << ' ' << pTraits<Type>::typeName
295  << " values" << nl;
296  }
297 
298  const meshedSurf& surf = surface();
299  // const meshedSurfRef& surf = adjustSurface();
300 
301  if (enableWrite_ && (UPstream::master() || !parallel_))
302  {
303  if (!isDir(outputFile.path()))
304  {
305  mkDir(outputFile.path());
306  }
307 
308  // Write sample locations
309  {
310  pointIOField iopts
311  (
312  IOobject
313  (
314  surfaceDir/"points",
315  *dummyTimePtr,
319  )
320  );
321  iopts.note() = (this->isPointData() ? "point data" : "face data");
322 
323  serialWriteGeometry(iopts, surf);
324  }
325 
326  // Write field
327  {
328  IOField<Type> iofld
329  (
330  IOobject
331  (
332  outputFile,
333  *dummyTimePtr,
337  )
338  );
339  iofld.note() = (this->isPointData() ? "point data" : "face data");
340 
341  OFstream os(iofld.objectPath(), streamOpt_);
342 
343  if (header_)
344  {
345  iofld.writeHeader(os);
346  }
347 
348  // Just like writeData, but without copying beforehand
349  os << tfield();
350 
351  if (header_)
352  {
354  }
355  }
356  }
357 
358  wroteGeom_ = true;
359  return surfaceDir;
360 }
361 
362 
363 // Field writing methods
365 
366 
367 // ************************************************************************* //
A class for handling file names.
Definition: fileName.H:72
static const Enum< commsTypes > commsTypeNames
Enumerated names for the communication types.
Definition: UPstream.H:82
static autoPtr< Time > NewGlobalTime()
Construct (dummy) global Time - no functionObjects or libraries, using the global path information st...
Definition: TimeNew.C:78
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
vectorIOField pointIOField
pointIOField is a vectorIOField.
Definition: pointIOField.H:38
virtual void open(const fileName &outputPath)
Open for output on specified path, using existing surface.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
const string & note() const noexcept
Return the optional note.
Definition: IOobjectI.H:225
A simple container for options an IOstream can normally have.
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:169
Ignore writing from objectRegistry::writeObject()
bool writeHeader(Ostream &os) const
Write header with current type()
UPstream::commsTypes commType_
Communication type (for field merging)
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:284
Macros for easy insertion into run-time selection tables.
defineSurfaceWriterWriteFields(Foam::surfaceWriters::debugWriter)
Abstract definition of a meshed surface defined by faces and points.
Definition: meshedSurf.H:43
bool isPointData() const noexcept
Are the field data to be treated as point data?
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:860
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
word timeName
Definition: getTimeIndex.H:3
static const char * name(const bool b) noexcept
A string representation of bool as "false" / "true".
Definition: Switch.C:141
#define addProfiling(Name, Descr)
Define profiling trigger with specified name and description string.
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:614
const pointField & points
Generic templated field type.
Definition: Field.H:62
A class for handling words, derived from Foam::string.
Definition: word.H:63
virtual fileName write()
Write surface geometry to file.
virtual const faceList & faces() const =0
The faces used for the surface.
const wordList surface
Standard surface field types (scalar, vector, tensor, etc)
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
Istream and Ostream manipulators taking arguments.
tmp< Field< label > > mergeField(const Field< label > &fld) const
OBJstream os(runTime.globalPath()/outputName)
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field...
Convenience macros for instantiating surfaceWriter methods.
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))
defineTypeName(abaqusWriter)
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
Nothing to be read.
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:66
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual bool merge() const
Merge surfaces if they are not already upToDate (parallel) or simply mark the surface as being up-to-...
Base class for surface writers.
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
A surfaceWriter for special purpose debugging. Its definition and behaviour are subject to change at ...
A class for managing temporary objects.
Definition: HashPtrTable.H:50
addToRunTimeSelectionTable(surfaceWriter, abaqusWriter, word)
Do not request registration (bool: false)
virtual const pointField & points() const =0
The points used for the surface.
Namespace for OpenFOAM.