Loading...
Searching...
No Matches
Probes.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) 2011-2017 OpenFOAM Foundation
9 Copyright (C) 2015-2025 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "Probes.H"
30#include "IOmanip.H"
31#include "volFields.H"
32#include "surfaceFields.H"
33#include "SpanStream.H"
35
36// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37
38template<class ProbeType>
39void Foam::Probes<ProbeType>::createProbeFiles(const wordList& fieldNames)
40{
41 // Open new output streams
42
43 bool needsNewFiles = false;
44 for (const word& fieldName : fieldNames)
45 {
46 if (!probeFilePtrs_.found(fieldName))
47 {
48 needsNewFiles = true;
49 break;
50 }
51 }
52
53 if (needsNewFiles && Pstream::master())
54 {
56 << "Probing fields: " << fieldNames << nl
57 << "Probing locations: " << probeModel_.probeLocations() << nl
58 << endl;
59
60 // Put in undecomposed case
61 // (Note: gives problems for distributed data running)
62
63 fileName probeDir
64 (
65 mesh_.time().globalPath()
66 / functionObject::outputPrefix
67 / name()/mesh_.regionName()
68 // Use startTime as the instance for output files
69 / mesh_.time().timeName(mesh_.time().startTime().value())
70 );
71 probeDir.clean(); // Remove unneeded ".."
72
73 // Create directory if needed
74 Foam::mkDir(probeDir);
75
76 for (const word& fieldName : fieldNames)
77 {
78 if (probeFilePtrs_.found(fieldName))
79 {
80 // Safety
81 continue;
82 }
83
84 auto osPtr = autoPtr<OFstream>::New(probeDir/fieldName);
85 auto& os = *osPtr;
86
87 if (!os.good())
88 {
90 << "Cannot open probe output file: " << os.name() << nl
91 << exit(FatalError);
92 }
93
94 probeFilePtrs_.insert(fieldName, osPtr);
95
96 DebugInfo<< "open probe stream: " << os.name() << endl;
97
98 const unsigned int width(IOstream::defaultPrecision() + 7);
99 os.setf(std::ios_base::left);
100
101 const pointField& probeLocs = probeModel_.probeLocations();
102 const labelList& processors = probeModel_.processors();
103 const labelList& patchIDList = probeModel_.patchIDList();
104 const pointField& oldPoints = probeModel_.oldPoints();
105
106 forAll(probeLocs, probei)
107 {
108 os << "# Probe " << probei << ' ' << probeLocs[probei];
109
110 if (processors[probei] == -1)
111 {
112 os << " # Not Found";
113 }
114 else if (probei < patchIDList.size())
115 {
116 const label patchi = patchIDList[probei];
117 if (patchi != -1)
118 {
119 const polyBoundaryMesh& bm = mesh_.boundaryMesh();
120 if
121 (
122 patchi < bm.nNonProcessor()
123 || processors[probei] == Pstream::myProcNo()
124 )
125 {
126 os << " at patch " << bm[patchi].name();
127 }
128 os << " with a distance of "
129 << mag(probeLocs[probei]-oldPoints[probei])
130 << " m to the original point "
131 << oldPoints[probei];
132 }
133 }
134
135 os << nl;
136 }
137
138 os << setw(width) << "# Time";
139
140 forAll(probeLocs, probei)
141 {
142 if (probeModel_.includeOutOfBounds() || processors[probei] != -1)
143 {
144 os << ' ' << setw(width) << probei;
145 }
146 }
147 os << endl;
148 }
149 }
150}
151
152
153template<class ProbeType>
154template<class Type>
155void Foam::Probes<ProbeType>::writeValues
156(
157 const word& fieldName,
158 const Field<Type>& values,
159 const scalar timeValue
160)
161{
162 if (Pstream::master())
163 {
164 const unsigned int width(IOstream::defaultPrecision() + 7);
165 OFstream& os = *probeFilePtrs_[fieldName];
166
167 os << setw(width) << timeValue;
168
169 OCharStream buf;
170
171 const bool includeOutOfBounds = probeModel_.includeOutOfBounds();
172 const labelList& procs = probeModel_.processors();
173 forAll(values, probei)
174 {
175 if (includeOutOfBounds || procs[probei] != -1)
176 {
177 buf.rewind();
178 buf << values[probei];
179 os << ' ' << setw(width) << buf.str().data();
180 }
181 }
182 os << endl;
183 }
184}
185
186
187template<class ProbeType>
188template<class GeoField>
189void Foam::Probes<ProbeType>::performAction
190(
191 const fieldGroup<GeoField>& fieldNames,
192 unsigned request
193)
194{
195 for (const word& fieldName : fieldNames)
196 {
197 tmp<GeoField> tfield = getOrLoadField<GeoField>(fieldName);
198
199 if (tfield)
200 {
201 const auto& field = tfield();
202 const scalar timeValue = field.time().timeOutputValue();
203
204 Field<typename GeoField::value_type>
205 values(probeModel_.sample(field));
206
207 this->storeResults(fieldName, values);
208 if (request & ACTION_WRITE)
209 {
210 this->writeValues(fieldName, values, timeValue);
211 }
212 }
214}
215
216
217// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
218
219template<class ProbeType>
220Foam::label Foam::Probes<ProbeType>::prepare(unsigned request)
221{
222 // Prefilter on selection
223 HashTable<wordHashSet> selected =
224 (
225 loadFromFiles_
226 ? IOobjectList(mesh_, mesh_.time().timeName()).classes(fieldSelection_)
227 : mesh_.classes(fieldSelection_)
228 );
229
230 // Classify and count fields
231 label nFields = 0;
232 do
233 {
234 #undef doLocalCode
235 #define doLocalCode(InputType, Target) \
236 { \
237 Target.clear(); /* Remove old values */ \
238 const auto iter = selected.cfind(InputType::typeName); \
239 if (iter.good()) \
240 { \
241 /* Add new (current) values */ \
242 Target.append(iter.val().sortedToc()); \
243 nFields += Target.size(); \
244 } \
245 }
246
247 doLocalCode(volScalarField, scalarFields_);
248 doLocalCode(volVectorField, vectorFields_);
249 doLocalCode(volSphericalTensorField, sphericalTensorFields_);
250 doLocalCode(volSymmTensorField, symmTensorFields_);
251 doLocalCode(volTensorField, tensorFields_);
252
253 doLocalCode(surfaceScalarField, surfaceScalarFields_);
254 doLocalCode(surfaceVectorField, surfaceVectorFields_);
255 doLocalCode(surfaceSphericalTensorField, surfaceSphericalTensorFields_);
256 doLocalCode(surfaceSymmTensorField, surfaceSymmTensorFields_);
257 doLocalCode(surfaceTensorField, surfaceTensorFields_);
258 #undef doLocalCode
259 }
260 while (false);
261
262
263 // Adjust file streams
264 if (Pstream::master())
265 {
266 wordHashSet currentFields(2*nFields);
267 currentFields.insert(scalarFields_);
268 currentFields.insert(vectorFields_);
269 currentFields.insert(sphericalTensorFields_);
270 currentFields.insert(symmTensorFields_);
271 currentFields.insert(tensorFields_);
272
273 currentFields.insert(surfaceScalarFields_);
274 currentFields.insert(surfaceVectorFields_);
275 currentFields.insert(surfaceSphericalTensorFields_);
276 currentFields.insert(surfaceSymmTensorFields_);
277 currentFields.insert(surfaceTensorFields_);
278
280 << "Probing fields: " << currentFields << nl
281 << "Probing locations: " << probeModel_.probeLocations() << nl
282 << endl;
283
284 // Close streams for fields that no longer exist
285 forAllIters(probeFilePtrs_, iter)
286 {
287 if (!currentFields.erase(iter.key()))
288 {
289 DebugInfo<< "close probe stream: " << iter()->name() << endl;
290
291 probeFilePtrs_.remove(iter);
292 }
293 }
294
295 if ((request & ACTION_WRITE) && !currentFields.empty())
296 {
297 createProbeFiles(currentFields.sortedToc());
298 }
299 }
301 return nFields;
302}
303
304
305template<class ProbeType>
306template<class GeoField>
308(
309 const word& fieldName
310) const
311{
312 tmp<GeoField> tfield;
313
314 if (loadFromFiles_)
315 {
316 tfield.emplace
317 (
319 (
320 fieldName,
321 mesh_.time().timeName(),
322 mesh_.thisDb(),
326 ),
327 mesh_
328 );
329 }
330 else
331 {
332 tfield.cref(mesh_.cfindObject<GeoField>(fieldName));
333 }
335 return tfield;
336}
337
338
339template<class ProbeType>
340template<class Type>
342(
343 const word& fieldName,
344 const Field<Type>& values
345)
346{
347 const MinMax<Type> limits(values);
348 const Type avgVal = average(values);
349
350 this->setResult("average(" + fieldName + ")", avgVal);
351 this->setResult("min(" + fieldName + ")", limits.min());
352 this->setResult("max(" + fieldName + ")", limits.max());
353 this->setResult("size(" + fieldName + ")", values.size());
354
355 if (verbose_)
356 {
357 Info<< name() << " : " << fieldName << nl
358 << " avg: " << avgVal << nl
359 << " min: " << limits.min() << nl
360 << " max: " << limits.max() << nl << nl;
362}
363
364
365// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
366
367template<class ProbeType>
369(
370 const word& name,
371 const Time& runTime,
372 const dictionary& dict,
373 const bool loadFromFiles,
374 const bool readFields
375)
376:
377 functionObjects::fvMeshFunctionObject(name, runTime, dict),
378 probeModel_(mesh_, dict),
379 loadFromFiles_(loadFromFiles),
380 onExecute_(false),
381 fieldSelection_()
382{
383 if (readFields)
384 {
385 read(dict);
387}
388
389
390// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
391
392template<class ProbeType>
393bool Foam::Probes<ProbeType>::verbose(const bool on) noexcept
394{
395 bool old(verbose_);
396 verbose_ = on;
397 return old;
398}
399
400
401template<class ProbeType>
403{
404 dict.readEntry("fields", fieldSelection_);
405
406 verbose_ = dict.getOrDefault("verbose", false);
407 onExecute_ = dict.getOrDefault("sampleOnExecute", false);
408
409 // Close old (unused) streams
410 prepare(ACTION_NONE);
411
412 return true;
413}
414
415
416template<class ProbeType>
417bool Foam::Probes<ProbeType>::performAction(unsigned request)
418{
419 if (!probeModel_.empty() && request && prepare(request))
420 {
421 performAction(scalarFields_, request);
422 performAction(vectorFields_, request);
423 performAction(sphericalTensorFields_, request);
424 performAction(symmTensorFields_, request);
425 performAction(tensorFields_, request);
426
427 performAction(surfaceScalarFields_, request);
428 performAction(surfaceVectorFields_, request);
429 performAction(surfaceSphericalTensorFields_, request);
430 performAction(surfaceSymmTensorFields_, request);
431 performAction(surfaceTensorFields_, request);
432 }
433 return true;
434}
435
436
437template<class ProbeType>
439{
440 if (onExecute_)
441 {
442 return performAction(ACTION_ALL & ~ACTION_WRITE);
444
445 return true;
446}
447
448
449template<class ProbeType>
451{
452 return performAction(ACTION_ALL);
453}
454
455
456// ************************************************************************* //
Istream and Ostream manipulators taking arguments.
#define doLocalCode(InputType, Target)
Input/output streams with (internal or external) character storage.
Macros for easy insertion into run-time selection tables.
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition Field.H:172
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition HashSet.H:229
A HashTable similar to std::unordered_map.
Definition HashTable.H:124
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition HashTable.C:156
bool empty() const noexcept
True if the hash table is empty.
Definition HashTable.H:353
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Definition HashTable.C:489
List of IOobjects with searching and retrieving facilities. Implemented as a HashTable,...
HashTable< wordHashSet > classes() const
A summary hash of classes used and their associated object names.
@ NO_REGISTER
Do not request registration (bool: false).
@ MUST_READ
Reading required.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
A min/max value pair with additional methods. In addition to conveniently storing values,...
Definition MinMax.H:106
bool verbose(const bool on) noexcept
Enable/disable verbose output.
Definition Probes.C:386
HashPtrTable< OFstream > probeFilePtrs_
Current open files (non-empty on master only).
Definition Probes.H:146
ProbeType probeModel_
The specified point probeModel.
Definition Probes.H:69
fieldGroup< surfaceSphericalTensorField > surfaceSphericalTensorFields_
Definition Probes.H:139
void storeResults(const word &fieldName, const Field< Type > &values)
Store results: min/max/average/size.
Definition Probes.C:335
fieldGroup< volSphericalTensorField > sphericalTensorFields_
Definition Probes.H:130
label prepare(unsigned request)
Classify field types, close/open file streams.
Definition Probes.C:213
fieldGroup< volScalarField > scalarFields_
Categorized scalar/vector/tensor volume fields.
Definition Probes.H:128
fieldGroup< surfaceSymmTensorField > surfaceSymmTensorFields_
Definition Probes.H:140
Probes(const word &name, const Time &runTime, const dictionary &dict, const bool loadFromFiles=false, const bool readFields=true)
Construct from Time and dictionary.
Definition Probes.C:362
bool loadFromFiles_
Load fields from files (not from objectRegistry).
Definition Probes.H:100
fieldGroup< volVectorField > vectorFields_
Definition Probes.H:129
fieldGroup< volSymmTensorField > symmTensorFields_
Definition Probes.H:131
fieldGroup< surfaceScalarField > surfaceScalarFields_
Categorized scalar/vector/tensor surface fields.
Definition Probes.H:137
fieldGroup< surfaceTensorField > surfaceTensorFields_
Definition Probes.H:141
bool verbose_
Output verbosity.
Definition Probes.H:105
wordRes fieldSelection_
Requested names of fields to probe.
Definition Probes.H:115
fieldGroup< surfaceVectorField > surfaceVectorFields_
Definition Probes.H:138
tmp< GeoField > getOrLoadField(const word &fieldName) const
Get from registry or load from disk.
bool onExecute_
Perform sample actions on execute as well.
Definition Probes.H:110
virtual bool execute()
Sample and store result if the sampleOnExecute is enabled.
Definition Probes.C:431
virtual bool write()
Sample and write.
Definition Probes.C:443
fieldGroup< volTensorField > tensorFields_
Definition Probes.H:132
@ ACTION_WRITE
Definition Probes.H:89
@ ACTION_NONE
Definition Probes.H:88
virtual bool read(const dictionary &)
Read the settings from the dictionary.
Definition Probes.C:395
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition Time.H:75
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
const fvMesh & mesh_
Reference to the fvMesh.
fvMeshFunctionObject(const fvMeshFunctionObject &)=delete
No copy construct.
void setResult(const word &entryName, const Type &value)
Add result.
A class for managing temporary objects.
Definition tmp.H:75
T & emplace(Args &&... args)
Reset with emplace construction. Return reference to the new content.
Definition tmpI.H:357
const T & cref() const
Return const reference to the object or to the contents of a (non-null) managed pointer.
Definition tmpI.H:221
A class for handling words, derived from Foam::string.
Definition word.H:66
rDeltaTY field()
auto limits
Definition setRDeltaT.H:186
engineTime & runTime
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
auto & name
#define DebugInfo
Report an information message using Foam::Info.
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition HashOps.H:164
Function objects are OpenFOAM utilities to ease workflow configurations and enhance workflows.
GeometricField< vector, fvsPatchField, surfaceMesh > surfaceVectorField
GeometricField< vector, fvPatchField, volMesh > volVectorField
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition HashSet.H:80
void readFields(const typename GeoFieldType::Mesh &mesh, const IOobjectList &objects, const NameMatchPredicate &selectedFields, DynamicList< regIOobject * > &storedObjects)
Read the selected GeometricFields of the templated type and store on the objectRegistry.
List< label > labelList
A List of labels.
Definition List.H:62
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
GeometricField< scalar, fvPatchField, volMesh > volScalarField
messageStream Info
Information stream (stdout output on master, null elsewhere).
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
Omanip< int > setw(const int i)
Definition IOmanip.H:199
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
GeometricField< tensor, fvPatchField, volMesh > volTensorField
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
GeometricField< tensor, fvsPatchField, surfaceMesh > surfaceTensorField
GeometricField< sphericalTensor, fvPatchField, volMesh > volSphericalTensorField
GeometricField< sphericalTensor, fvsPatchField, surfaceMesh > surfaceSphericalTensorField
GeometricField< symmTensor, fvPatchField, volMesh > volSymmTensorField
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
dimensioned< Type > average(const DimensionedField< Type, GeoMesh > &f1, const label comm)
GeometricField< symmTensor, fvsPatchField, surfaceMesh > surfaceSymmTensorField
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition stdFoam.H:214
Foam::surfaceFields.