steadyParticleTracks.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-2014 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 Application
25  steadyParticleTracks
26 
27 Description
28  Generates a VTK file of particle tracks for cases that were computed using
29  a steady-state cloud
30 
31  Note:
32  - Case must be re-constructed (if running in parallel) before use
33 
34 \*---------------------------------------------------------------------------*/
35 
36 #include "argList.H"
37 #include "Cloud.H"
38 #include "IOdictionary.H"
39 #include "fvMesh.H"
40 #include "Time.H"
41 #include "timeSelector.H"
42 #include "OFstream.H"
43 #include "passiveParticleCloud.H"
44 
45 #include "SortableList.H"
46 #include "IOobjectList.H"
47 #include "PtrList.H"
48 #include "Field.H"
50 
51 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
52 
53 using namespace Foam;
54 
55 namespace Foam
56 {
57 
58 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
59 
60 label validateFields
61 (
62  const List<word>& userFields,
63  const IOobjectList& cloudObjs
64 )
65 {
66  List<bool> ok(userFields.size(), false);
67 
68  forAll(userFields, i)
69  {
70  ok[i] = ok[i] || fieldOk<label>(cloudObjs, userFields[i]);
71  ok[i] = ok[i] || fieldOk<scalar>(cloudObjs, userFields[i]);
72  ok[i] = ok[i] || fieldOk<vector>(cloudObjs, userFields[i]);
73  ok[i] = ok[i] || fieldOk<sphericalTensor>(cloudObjs, userFields[i]);
74  ok[i] = ok[i] || fieldOk<symmTensor>(cloudObjs, userFields[i]);
75  ok[i] = ok[i] || fieldOk<tensor>(cloudObjs, userFields[i]);
76  }
77 
78  label nOk = 0;
79  forAll(ok, i)
80  {
81  if (ok[i])
82  {
83  nOk++;
84  }
85  else
86  {
87  Info << "\n*** Warning: user specified field '" << userFields[i]
88  << "' unavailable" << endl;
89  }
90  }
91 
92  return nOk;
93 }
94 
95 
96 template<>
97 void writeVTK(OFstream& os, const label& value)
98 {
99  os << value;
100 }
101 
102 
103 template<>
104 void writeVTK(OFstream& os, const scalar& value)
105 {
106  os << value;
107 }
108 
109 }
110 
111 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
112 
113 int main(int argc, char *argv[])
114 {
117  #include "addRegionOption.H"
118  #include "addDictOption.H"
119 
120  #include "setRootCase.H"
121 
122  #include "createTime.H"
124  #include "createNamedMesh.H"
125  #include "createFields.H"
126 
127  // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
128 
129  fileName vtkPath(runTime.path()/"VTK");
130  mkDir(vtkPath);
131 
132  typedef HashTable<label, labelPair, labelPair::Hash<> > trackTableType;
133 
134  forAll(timeDirs, timeI)
135  {
136  runTime.setTime(timeDirs[timeI], timeI);
137  Info<< "Time = " << runTime.timeName() << endl;
138 
139  fileName vtkTimePath(runTime.path()/"VTK"/runTime.timeName());
140  mkDir(vtkTimePath);
141 
142  Info<< " Reading particle positions" << endl;
143 
144  PtrList<passiveParticle> particles(0);
145 
146  // transfer particles to (more convenient) list
147  {
149  Info<< "\n Read " << returnReduce(ppc.size(), sumOp<label>())
150  << " particles" << endl;
151 
152  particles.setSize(ppc.size());
153 
154  label i = 0;
155  forAllIter(passiveParticleCloud, ppc, iter)
156  {
157  particles.set(i++, ppc.remove(&iter()));
158  }
159 
160  // myCloud should now be empty
161  }
162 
163  List<label> particleToTrack(particles.size());
164  label nTracks = 0;
165 
166  {
167  trackTableType trackTable;
168  forAll(particles, i)
169  {
170  const label origProc = particles[i].origProc();
171  const label origId = particles[i].origId();
172 
173  const trackTableType::const_iterator& iter =
174  trackTable.find(labelPair(origProc, origId));
175 
176  if (iter == trackTable.end())
177  {
178  particleToTrack[i] = nTracks;
179  trackTable.insert(labelPair(origProc, origId), nTracks);
180  nTracks++;
181  }
182  else
183  {
184  particleToTrack[i] = iter();
185  }
186  }
187  }
188 
189 
190  if (nTracks == 0)
191  {
192  Info<< "\n No track data" << endl;
193  }
194  else
195  {
196  Info<< "\n Generating " << nTracks << " tracks" << endl;
197 
198  // determine length of each track
199  labelList trackLengths(nTracks, 0);
200  forAll(particleToTrack, i)
201  {
202  const label trackI = particleToTrack[i];
203  trackLengths[trackI]++;
204  }
205 
206  // particle "age" property used to sort the tracks
207  List<SortableList<scalar> > agePerTrack(nTracks);
208  List<List<label> > particleMap(nTracks);
209 
210  forAll(trackLengths, i)
211  {
212  const label length = trackLengths[i];
213  agePerTrack[i].setSize(length);
214  particleMap[i].setSize(length);
215  }
216 
217  // store the particle age per track
218  IOobjectList cloudObjs
219  (
220  mesh,
221  runTime.timeName(),
223  );
224 
225  // TODO: gather age across all procs
226  {
227  tmp<scalarField> tage =
228  readParticleField<scalar>("age", cloudObjs);
229  const scalarField& age = tage();
230  List<label> trackSamples(nTracks, 0);
231  forAll(particleToTrack, i)
232  {
233  const label trackI = particleToTrack[i];
234  const label sampleI = trackSamples[trackI];
235  agePerTrack[trackI][sampleI] = age[i];
236  particleMap[trackI][sampleI] = i;
237  trackSamples[trackI]++;
238  }
239  tage.clear();
240  }
241 
242 
243  if (Pstream::master())
244  {
245  OFstream os(vtkTimePath/"particleTracks.vtk");
246 
247  Info<< "\n Writing particle tracks to " << os.name() << endl;
248 
249  label nPoints = sum(trackLengths);
250 
251  os << "# vtk DataFile Version 2.0" << nl
252  << "particleTracks" << nl
253  << "ASCII" << nl
254  << "DATASET POLYDATA" << nl
255  << "POINTS " << nPoints << " float" << nl;
256 
257  Info<< "\n Writing points" << endl;
258 
259  {
260  forAll(agePerTrack, i)
261  {
262  agePerTrack[i].sort();
263 
264  const labelList& ids = agePerTrack[i].indices();
265  labelList& particleIds = particleMap[i];
266 
267  {
268  // update addressing
269  List<label> sortedIds(ids);
270  forAll(sortedIds, j)
271  {
272  sortedIds[j] = particleIds[ids[j]];
273  }
274  particleIds = sortedIds;
275  }
276 
277  forAll(ids, j)
278  {
279  const label localId = particleIds[j];
280  const vector& pos = particles[localId].position();
281  os << pos.x() << ' ' << pos.y() << ' ' << pos.z()
282  << nl;
283  }
284  }
285  }
286 
287 
288  // write track (line) connectivity to file
289 
290  Info<< "\n Writing track lines" << endl;
291  os << "\nLINES " << nTracks << ' ' << nPoints + nTracks << nl;
292 
293  // Write ids of track points to file
294  {
295  label globalPtI = 0;
296  forAll(particleMap, i)
297  {
298  os << particleMap[i].size() << nl;
299 
300  forAll(particleMap[i], j)
301  {
302  os << ' ' << globalPtI++;
303 
304  if (((j + 1) % 10 == 0) && (j != 0))
305  {
306  os << nl;
307  }
308  }
309 
310  os << nl;
311  }
312  }
313 
314 
315  const label nFields = validateFields(userFields, cloudObjs);
316 
317  os << "POINT_DATA " << nPoints << nl
318  << "FIELD attributes " << nFields << nl;
319 
320  Info<< "\n Processing fields" << nl << endl;
321 
322  processFields<label>(os, particleMap, userFields, cloudObjs);
323  processFields<scalar>(os, particleMap, userFields, cloudObjs);
324  processFields<vector>(os, particleMap, userFields, cloudObjs);
325  processFields<sphericalTensor>
326  (os, particleMap, userFields, cloudObjs);
327  processFields<symmTensor>
328  (os, particleMap, userFields, cloudObjs);
329  processFields<tensor>(os, particleMap, userFields, cloudObjs);
330 
331  }
332  }
333  Info<< endl;
334  }
335 
336  Info<< "End" << nl << endl;
337 
338  return 0;
339 }
340 
341 
342 // ************************************************************************* //
forAllIter
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:431
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:118
Cloud.H
IOobjectList.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::writeVTK
void writeVTK(OFstream &os, const Type &value)
OFstream.H
addDictOption.H
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
SortableList.H
steadyParticleTracksTemplates.H
Foam::label
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
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
argList.H
Field.H
addRegionOption.H
main
int main(int argc, char *argv[])
Definition: postCalc.C:54
Foam::PtrList
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:61
Foam::passiveParticleCloud
A Cloud of passive particles.
Definition: passiveParticleCloud.H:49
createNamedMesh.H
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::IOobjectList
List of IOobjects with searching and retrieving facilities.
Definition: IOobjectList.H:50
Foam::OFstream
Output to file stream.
Definition: OFstream.H:81
userFields
List< word > userFields(propsDict.lookup("fields"))
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:399
Foam::HashTable
An STL-conforming hash table.
Definition: HashTable.H:61
Foam::cloud::prefix
static const word prefix
The prefix to local: lagrangian.
Definition: cloud.H:71
IOdictionary.H
setRootCase.H
timeDirs
static instantList timeDirs
Definition: globalFoam.H:44
Foam::sumOp
Definition: ops.H:162
Foam::timeSelector::addOptions
static void addOptions(const bool constant=true, const bool withZero=false)
Add the options handled by timeSelector to argList::validOptions.
Definition: timeSelector.C:114
passiveParticleCloud.H
Foam::Vector< scalar >
Foam::List< word >
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:333
timeSelector.H
createTime.H
cloudName
const word cloudName(propsDict.lookup("cloudName"))
PtrList.H
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::argList::noParallel
static void noParallel()
Remove the parallel options.
Definition: argList.C:161
Foam::timeSelector::select0
static instantList select0(Time &runTime, const argList &args)
Return the set of times selected based on the argList options.
Definition: timeSelector.C:253
args
Foam::argList args(argc, argv)
Foam::mkDir
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:419
Foam::tmp::clear
void clear() const
If object pointer points to valid object:
Definition: tmpI.H:172
Foam::labelPair
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:190