Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
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 "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"
40// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42namespace Foam
43{
44namespace surfaceWriters
45{
49}
51
52
53// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
54
55template<class Type>
57Foam::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:
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
93 if (gatherv_) Info<< " <gatherv>";
95 Info<< " commsType=" << UPstream::commsTypeNames[commType_]
96 << " merge=" << Switch::name(enableMerge_)
97 << " write=" << Switch::name(enableWrite_) << endl;
98}
99
100
102(
103 const meshedSurf& surf,
104 const fileName& outputPath,
105 bool parallel,
106 const dictionary& options
107)
109 debugWriter(options)
110{
111 open(surf, outputPath, parallel);
112}
113
114
116(
117 const pointField& points,
118 const faceList& faces,
119 const fileName& outputPath,
120 bool parallel,
121 const dictionary& options
122)
123:
124 debugWriter(options)
125{
126 open(points, faces, outputPath, parallel);
127}
128
129
130// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
131
132void Foam::surfaceWriters::debugWriter::serialWriteGeometry
133(
134 const regIOobject& iopts,
135 const meshedSurf& surf
136)
137{
138 const pointField& points = surf.points();
139 const faceList& faces = surf.faces();
140
141 if (verbose_)
142 {
143 if (this->isPointData())
144 {
145 Info<< "Writing points: " << iopts.objectPath() << endl;
146 }
147 else
148 {
149 Info<< "Writing face centres: " << iopts.objectPath() << endl;
150 }
151 }
152
153 // Like regIOobject::writeObject without instance() adaptation
154 // since this would write to e.g. 0/ instead of postProcessing/
155
156 autoPtr<primitivePatch> ppPtr;
157
158 {
159 OFstream os(iopts.objectPath(), streamOpt_);
160
161 if (header_)
162 {
163 iopts.writeHeader(os);
164 }
165
166 if (this->isPointData())
167 {
168 // Just like writeData, but without copying beforehand
169 os << points;
170 }
171 else
172 {
173 ppPtr.reset(new primitivePatch(SubList<face>(faces), points));
174
175 // Just like writeData, but without copying beforehand
176 os << ppPtr().faceCentres();
177 }
178
179 if (header_)
182 }
183 }
184}
185
186
188{
189 checkOpen();
190
191 // Geometry: rootdir/surfaceName/"points"
192 // Field: rootdir/surfaceName/<TIME>/field
193
194 fileName surfaceDir = outputPath_;
195
196 if (parallel_ && !enableMerge_)
197 {
198 if (verbose_)
199 {
200 Info<< "Not merging or writing" << nl;
201 }
202
203 // Pretend to have succeeded
204 wroteGeom_ = true;
205 return surfaceDir;
206 }
207
208
209 const meshedSurf& surf = surface();
210 // const meshedSurfRef& surf = adjustSurface();
211
212 // Dummy Time to use as objectRegistry
213 autoPtr<Time> dummyTimePtr;
214
215 if (enableWrite_)
216 {
217 dummyTimePtr = Time::NewGlobalTime();
218 }
219 else if (verbose_)
220 {
221 Info<< "Not writing: " << surf.faces().size() << " faces" << nl;
222 }
223
224 if (enableWrite_ && (UPstream::master() || !parallel_))
225 {
226 if (!isDir(surfaceDir))
227 {
228 mkDir(surfaceDir);
229 }
230
231 // Write sample locations
232 pointIOField iopts
233 (
234 IOobject
235 (
236 surfaceDir/"points",
237 *dummyTimePtr,
241 )
242 );
243 iopts.note() = (this->isPointData() ? "point data" : "face data");
244
245 serialWriteGeometry(iopts, surf);
246 }
247
248 wroteGeom_ = true;
249 return surfaceDir;
250}
251
252
253// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
254
255template<class Type>
256Foam::fileName Foam::surfaceWriters::debugWriter::writeTemplate
257(
258 const word& fieldName,
259 const Field<Type>& localValues
260)
261{
262 checkOpen();
263
264 // Geometry: rootdir/surfaceName/"points"
265 // Field: rootdir/surfaceName/<TIME>/field
266
267 fileName surfaceDir = outputPath_;
268
269 const fileName outputFile(surfaceDir/timeName()/fieldName);
270
271 if (parallel_ && !enableMerge_)
272 {
273 if (verbose_)
274 {
275 Info<< "Not merging or writing" << nl;
276 }
277
278 // Pretend to have succeeded
279 wroteGeom_ = true;
280 return surfaceDir;
281 }
282
283
284 // Implicit geometry merge()
285 tmp<Field<Type>> tfield = mergeField(localValues);
286
287 // Dummy Time to use as objectRegistry
288 autoPtr<Time> dummyTimePtr;
289
290 if (enableWrite_)
291 {
292 dummyTimePtr = Time::NewGlobalTime();
293 }
294 else if (verbose_)
295 {
296 Info<< "Not writing: " << tfield().size()
297 << ' ' << pTraits<Type>::typeName
298 << " values" << nl;
299 }
300
301 const meshedSurf& surf = surface();
302 // const meshedSurfRef& surf = adjustSurface();
303
304 if (enableWrite_ && (UPstream::master() || !parallel_))
305 {
306 if (!isDir(outputFile.path()))
307 {
308 mkDir(outputFile.path());
309 }
310
311 // Write sample locations
312 {
313 pointIOField iopts
314 (
315 IOobject
316 (
317 surfaceDir/"points",
318 *dummyTimePtr,
322 )
323 );
324 iopts.note() = (this->isPointData() ? "point data" : "face data");
325
326 serialWriteGeometry(iopts, surf);
327 }
328
329 // Write field
330 {
331 IOField<Type> iofld
332 (
333 IOobject
334 (
335 outputFile,
336 *dummyTimePtr,
340 )
341 );
342 iofld.note() = (this->isPointData() ? "point data" : "face data");
343
344 OFstream os(iofld.objectPath(), streamOpt_);
345
346 if (header_)
347 {
348 iofld.writeHeader(os);
349 }
350
351 // Just like writeData, but without copying beforehand
352 os << tfield();
353
354 if (header_)
355 {
357 }
358 }
359 }
361 wroteGeom_ = true;
362 return surfaceDir;
363}
364
365
366// Field writing methods
367defineSurfaceWriterWriteFields(Foam::surfaceWriters::debugWriter);
368
369
370// ************************************************************************* //
Istream and Ostream manipulators taking arguments.
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
Info<< nl;Info<< "Write faMesh in vtk format:"<< nl;{ vtk::uindirectPatchWriter writer(aMesh.patch(), fileName(aMesh.time().globalPath()/vtkBaseFileName));writer.writeGeometry();globalIndex procAddr(aMesh.nFaces());labelList cellIDs;if(UPstream::master()) { cellIDs.resize(procAddr.totalSize());for(const labelRange &range :procAddr.ranges()) { auto slice=cellIDs.slice(range);slice=identity(range);} } writer.beginCellData(4);writer.writeProcIDs();writer.write("cellID", cellIDs);writer.write("area", aMesh.S().field());writer.write("normal", aMesh.faceAreaNormals());writer.beginPointData(1);writer.write("normal", aMesh.pointAreaNormals());Info<< " "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.time().globalPath()/(vtkBaseFileName+"-edges")));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition Field.H:172
A primitive field of type <T> with automated input and output.
Definition IOField.H:53
@ NO_REGISTER
Do not request registration (bool: false).
@ NO_READ
Nothing to be read.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
const string & note() const noexcept
Return the optional note.
Definition IOobjectI.H:235
fileName objectPath() const
The complete path + object name.
Definition IOobjectI.H:313
bool writeHeader(Ostream &os) const
Write header with current type().
A simple container for options an IOstream can normally have.
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
Definition OFstream.H:75
static const char * name(bool b) noexcept
A string representation of bool as "false" / "true".
static autoPtr< Time > NewGlobalTime()
Construct (dummy) global Time - no functionObjects or libraries, using the global path information st...
Definition TimeNew.C:78
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
static const Enum< commsTypes > commsTypeNames
Enumerated names for the communication types.
Definition UPstream.H:92
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
A class for handling file names.
Definition fileName.H:75
static std::string path(const std::string &str)
Return directory path name (part before last /).
Definition fileNameI.H:169
Abstract definition of a meshed surface defined by faces and points.
Definition meshedSurf.H:44
virtual const faceList & faces() const =0
The faces used for the surface.
virtual const pointField & points() const =0
The points used for the surface.
A traits class, which is primarily used for primitives and vector-space.
Definition pTraits.H:64
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition regIOobject.H:71
Base class for surface writers.
surfaceWriter()
Default construct.
virtual void open(const fileName &outputPath)
Open for output on specified path, using existing surface.
bool gatherv_
Prefer MPI gatherv intrinsic (for field merging) [experimental].
bool wroteGeom_
Track if geometry has been written since the last open.
const meshedSurf & surface() const
Merge surfaces (if not upToDate) and return merged (parallel) or regular surface (non-parallel).
bool isPointData() const noexcept
Are the field data to be treated as point data?
void checkOpen() const
Verify that the outputPath_ has been set or FatalError.
bool parallel_
Writing in parallel (via master).
UPstream::commsTypes commType_
Communication type (for field merging).
virtual bool merge() const
Merge surfaces if they are not already upToDate (parallel) or simply mark the surface as being up-to-...
bool verbose_
Additional output verbosity.
tmp< Field< label > > mergeField(const Field< label > &fld) const
fileName outputPath_
The full output directory and file (surface) name.
A surfaceWriter for special purpose debugging. Its definition and behaviour are subject to change at ...
virtual fileName write()
Write surface geometry to file.
A class for managing temporary objects.
Definition tmp.H:75
A class for handling words, derived from Foam::string.
Definition word.H:66
#define defineTypeName(Type)
Define the typeName.
Definition className.H:113
OBJstream os(runTime.globalPath()/outputName)
const pointField & points
word timeName
Definition getTimeIndex.H:3
const wordList surface
Standard surface field types (scalar, vector, tensor, etc).
Namespace for surface writers.
Namespace for OpenFOAM.
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:616
messageStream Info
Information stream (stdout output on master, null elsewhere).
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
List< face > faceList
List of faces.
Definition faceListFwd.H:41
vectorIOField pointIOField
pointIOField is a vectorIOField.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
vectorField pointField
pointField is a vectorField.
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition POSIX.C:862
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define addProfiling(Name,...)
Define profiling trigger with specified name and description string. The description is generated by ...
Convenience macros for instantiating surfaceWriter methods.
#define defineSurfaceWriterWriteFields(ThisClass)