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 | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "probes.H"
27 #include "volFields.H"
28 #include "dictionary.H"
29 #include "Time.H"
30 #include "IOmanip.H"
31 #include "mapPolyMesh.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37  defineTypeNameAndDebug(probes, 0);
38 }
39 
40 
41 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
42 
44 {
45  if (debug)
46  {
47  Info<< "probes: resetting sample locations" << endl;
48  }
49 
50  elementList_.clear();
51  elementList_.setSize(size());
52 
53  faceList_.clear();
54  faceList_.setSize(size());
55 
56  forAll(*this, probeI)
57  {
58  const vector& location = operator[](probeI);
59 
60  const label cellI = mesh.findCell(location);
61 
62  elementList_[probeI] = cellI;
63 
64  if (cellI != -1)
65  {
66  const labelList& cellFaces = mesh.cells()[cellI];
67  const vector& cellCentre = mesh.cellCentres()[cellI];
68  scalar minDistance = GREAT;
69  label minFaceID = -1;
70  forAll (cellFaces, i)
71  {
72  label faceI = cellFaces[i];
73  vector dist = mesh.faceCentres()[faceI] - cellCentre;
74  if (mag(dist) < minDistance)
75  {
76  minDistance = mag(dist);
77  minFaceID = faceI;
78  }
79  }
80  faceList_[probeI] = minFaceID;
81  }
82  else
83  {
84  faceList_[probeI] = -1;
85  }
86 
87  if (debug && (elementList_[probeI] != -1 || faceList_[probeI] != -1))
88  {
89  Pout<< "probes : found point " << location
90  << " in cell " << elementList_[probeI]
91  << " and face " << faceList_[probeI] << endl;
92  }
93  }
94 
95 
96  // Check if all probes have been found.
97  forAll(elementList_, probeI)
98  {
99  const vector& location = operator[](probeI);
100  label cellI = elementList_[probeI];
101  label faceI = faceList_[probeI];
102 
103  // Check at least one processor with cell.
104  reduce(cellI, maxOp<label>());
105  reduce(faceI, maxOp<label>());
106 
107  if (cellI == -1)
108  {
109  if (Pstream::master())
110  {
111  WarningIn("findElements::findElements(const fvMesh&)")
112  << "Did not find location " << location
113  << " in any cell. Skipping location." << endl;
114  }
115  }
116  else if (faceI == -1)
117  {
118  if (Pstream::master())
119  {
120  WarningIn("probes::findElements(const fvMesh&)")
121  << "Did not find location " << location
122  << " in any face. Skipping location." << endl;
123  }
124  }
125  else
126  {
127  // Make sure location not on two domains.
128  if (elementList_[probeI] != -1 && elementList_[probeI] != cellI)
129  {
130  WarningIn("probes::findElements(const fvMesh&)")
131  << "Location " << location
132  << " seems to be on multiple domains:"
133  << " cell " << elementList_[probeI]
134  << " on my domain " << Pstream::myProcNo()
135  << " and cell " << cellI << " on some other domain."
136  << endl
137  << "This might happen if the probe location is on"
138  << " a processor patch. Change the location slightly"
139  << " to prevent this." << endl;
140  }
141 
142  if (faceList_[probeI] != -1 && faceList_[probeI] != faceI)
143  {
144  WarningIn("probes::findElements(const fvMesh&)")
145  << "Location " << location
146  << " seems to be on multiple domains:"
147  << " cell " << faceList_[probeI]
148  << " on my domain " << Pstream::myProcNo()
149  << " and face " << faceI << " on some other domain."
150  << endl
151  << "This might happen if the probe location is on"
152  << " a processor patch. Change the location slightly"
153  << " to prevent this." << endl;
154  }
155  }
156  }
157 }
158 
159 
161 {
162  const label nFields = classifyFields();
163 
164  // adjust file streams
165  if (Pstream::master())
166  {
167  wordHashSet currentFields;
168 
169  currentFields.insert(scalarFields_);
170  currentFields.insert(vectorFields_);
171  currentFields.insert(sphericalTensorFields_);
172  currentFields.insert(symmTensorFields_);
173  currentFields.insert(tensorFields_);
174 
175  currentFields.insert(surfaceScalarFields_);
176  currentFields.insert(surfaceVectorFields_);
177  currentFields.insert(surfaceSphericalTensorFields_);
178  currentFields.insert(surfaceSymmTensorFields_);
179  currentFields.insert(surfaceTensorFields_);
180 
181  if (debug)
182  {
183  Info<< "Probing fields: " << currentFields << nl
184  << "Probing locations: " << *this << nl
185  << endl;
186  }
187 
188 
189  fileName probeDir;
190  fileName probeSubDir = name_;
191 
192  if (mesh_.name() != polyMesh::defaultRegion)
193  {
194  probeSubDir = probeSubDir/mesh_.name();
195  }
196  probeSubDir = "postProcessing"/probeSubDir/mesh_.time().timeName();
197 
198  if (Pstream::parRun())
199  {
200  // Put in undecomposed case
201  // (Note: gives problems for distributed data running)
202  probeDir = mesh_.time().path()/".."/probeSubDir;
203  }
204  else
205  {
206  probeDir = mesh_.time().path()/probeSubDir;
207  }
208 
209  // ignore known fields, close streams for fields that no longer exist
210  forAllIter(HashPtrTable<OFstream>, probeFilePtrs_, iter)
211  {
212  if (!currentFields.erase(iter.key()))
213  {
214  if (debug)
215  {
216  Info<< "close probe stream: " << iter()->name() << endl;
217  }
218 
219  delete probeFilePtrs_.remove(iter);
220  }
221  }
222 
223  // currentFields now just has the new fields - open streams for them
224  forAllConstIter(wordHashSet, currentFields, iter)
225  {
226  const word& fieldName = iter.key();
227 
228  // Create directory if does not exist.
229  mkDir(probeDir);
230 
231  OFstream* fPtr = new OFstream(probeDir/fieldName);
232 
233  OFstream& fout = *fPtr;
234 
235  if (debug)
236  {
237  Info<< "open probe stream: " << fout.name() << endl;
238  }
239 
240  probeFilePtrs_.insert(fieldName, fPtr);
241 
242  unsigned int w = IOstream::defaultPrecision() + 7;
243 
244  forAll(*this, probeI)
245  {
246  fout<< "# Probe " << probeI << ' ' << operator[](probeI)
247  << endl;
248  }
249 
250  fout<< '#' << setw(IOstream::defaultPrecision() + 6)
251  << "Probe";
252 
253  forAll(*this, probeI)
254  {
255  fout<< ' ' << setw(w) << probeI;
256  }
257  fout<< endl;
258 
259  fout<< '#' << setw(IOstream::defaultPrecision() + 6)
260  << "Time" << endl;
261  }
262  }
263 
264  return nFields;
265 }
266 
267 
268 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
269 
270 Foam::probes::probes
271 (
272  const word& name,
273  const objectRegistry& obr,
274  const dictionary& dict,
275  const bool loadFromFiles
276 )
277 :
278  pointField(0),
279  name_(name),
280  mesh_(refCast<const fvMesh>(obr)),
281  loadFromFiles_(loadFromFiles),
282  fieldSelection_(),
283  fixedLocations_(true),
284  interpolationScheme_("cell")
285 {
286  read(dict);
287 }
288 
289 
290 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
291 
293 {}
294 
295 
296 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
297 
299 {
300  // Do nothing - only valid on write
301 }
302 
303 
305 {
306  // Do nothing - only valid on write
307 }
308 
309 
311 {
312  // Do nothing - only valid on write
313 }
314 
315 
317 {
318  if (size() && prepare())
319  {
320  sampleAndWrite(scalarFields_);
321  sampleAndWrite(vectorFields_);
322  sampleAndWrite(sphericalTensorFields_);
323  sampleAndWrite(symmTensorFields_);
324  sampleAndWrite(tensorFields_);
325 
326  sampleAndWriteSurfaceFields(surfaceScalarFields_);
327  sampleAndWriteSurfaceFields(surfaceVectorFields_);
328  sampleAndWriteSurfaceFields(surfaceSphericalTensorFields_);
329  sampleAndWriteSurfaceFields(surfaceSymmTensorFields_);
330  sampleAndWriteSurfaceFields(surfaceTensorFields_);
331  }
332 }
333 
334 
336 {
337  dict.lookup("probeLocations") >> *this;
338  dict.lookup("fields") >> fieldSelection_;
339 
340  dict.readIfPresent("fixedLocations", fixedLocations_);
341  if (dict.readIfPresent("interpolationScheme", interpolationScheme_))
342  {
343  if (!fixedLocations_ && interpolationScheme_ != "cell")
344  {
345  WarningIn("void Foam::probes::read(const dictionary&)")
346  << "Only cell interpolation can be applied when "
347  << "not using fixedLocations. InterpolationScheme "
348  << "entry will be ignored";
349  }
350  }
351 
352  // Initialise cells to sample from supplied locations
353  findElements(mesh_);
354 
355  prepare();
356 }
357 
358 
360 {
361  if (debug)
362  {
363  Info<< "probes: updateMesh" << endl;
364  }
365 
366  if (fixedLocations_)
367  {
368  findElements(mesh_);
369  }
370  else
371  {
372  if (debug)
373  {
374  Info<< "probes: remapping sample locations" << endl;
375  }
376 
377  // 1. Update cells
378  {
379  DynamicList<label> elems(elementList_.size());
380 
381  const labelList& reverseMap = mpm.reverseCellMap();
382  forAll(elementList_, i)
383  {
384  label cellI = elementList_[i];
385  label newCellI = reverseMap[cellI];
386  if (newCellI == -1)
387  {
388  // cell removed
389  }
390  else if (newCellI < -1)
391  {
392  // cell merged
393  elems.append(-newCellI - 2);
394  }
395  else
396  {
397  // valid new cell
398  elems.append(newCellI);
399  }
400  }
401 
402  elementList_.transfer(elems);
403  }
404 
405  // 2. Update faces
406  {
407  DynamicList<label> elems(faceList_.size());
408 
409  const labelList& reverseMap = mpm.reverseFaceMap();
410  forAll(faceList_, i)
411  {
412  label faceI = faceList_[i];
413  label newFaceI = reverseMap[faceI];
414  if (newFaceI == -1)
415  {
416  // face removed
417  }
418  else if (newFaceI < -1)
419  {
420  // face merged
421  elems.append(-newFaceI - 2);
422  }
423  else
424  {
425  // valid new face
426  elems.append(newFaceI);
427  }
428  }
429 
430  faceList_.transfer(elems);
431  }
432  }
433 }
434 
435 
437 {
438  if (debug)
439  {
440  Info<< "probes: movePoints" << endl;
441  }
442 
443  if (fixedLocations_)
444  {
445  findElements(mesh_);
446  }
447 }
448 
449 
450 // ************************************************************************* //
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Output to file stream.
Definition: OFstream.H:81
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:380
word name() const
Return file name (part beyond last /)
Definition: fileName.C:206
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
virtual void timeSet()
Called when time was set at the end of the Time::operator++.
Definition: probes.C:310
const labelList & reverseFaceMap() const
Reverse face map.
Definition: mapPolyMesh.H:497
virtual void movePoints(const polyMesh &)
Update for changes of mesh.
Definition: probes.C:436
bool erase(const iterator &)
Erase a hashedEntry specified by given iterator.
Definition: HashTable.C:379
dimensioned< scalar > mag(const dimensioned< Type > &)
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:158
#define forAllIter(Container, container, iter)
Definition: UList.H:440
A class for handling words, derived from string.
Definition: word.H:59
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:310
const cellList & cells() const
label prepare()
Classify field type and Open/close file streams,.
Definition: probes.C:160
const vectorField & cellCentres() const
messageStream Info
virtual void end()
Execute at the final time-loop, currently does nothing.
Definition: probes.C:304
fileName path() const
Return directory path name (part before last /)
Definition: fileName.C:287
dynamicFvMesh & mesh
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
virtual void write()
Sample and write.
Definition: probes.C:316
virtual void findElements(const fvMesh &)
Find cells and faces containing probes.
Definition: probes.C:43
virtual void read(const dictionary &)
Read the probes.
Definition: probes.C:335
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
Namespace for OpenFOAM.
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
static const char nl
Definition: Ostream.H:260
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
#define WarningIn(functionName)
Report a warning using Foam::Warning.
const fileName & name() const
Return the name of the stream.
Definition: OFstream.H:118
#define forAll(list, i)
Definition: UList.H:421
virtual ~probes()
Destructor.
Definition: probes.C:292
label findCell(const point &p, const cellDecomposition=CELL_TETS) const
Find cell enclosing this location and return index.
Definition: polyMesh.C:1476
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:404
Istream and Ostream manipulators taking arguments.
virtual void updateMesh(const mapPolyMesh &)
Update for changes of mesh.
Definition: probes.C:359
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:306
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:452
Registry of regIOobjects.
A class for handling file names.
Definition: fileName.H:69
A HashTable with keys but without contents.
Definition: HashSet.H:59
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
const labelList & reverseCellMap() const
Reverse cell map.
Definition: mapPolyMesh.H:528
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:398
bool read(const char *, int32_t &)
Definition: int32IO.C:87
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:420
static unsigned int defaultPrecision()
Return the default precision.
Definition: IOstream.H:461
virtual void execute()
Execute, currently does nothing.
Definition: probes.C:298
defineTypeNameAndDebug(combustionModel, 0)
prefixOSstream Pout(cout,"Pout")
Definition: IOstreams.H:53
const vectorField & faceCentres() const
A HashTable specialization for hashing pointers.
Definition: HashPtrTable.H:50
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:116