particleTracks.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 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  particleTracks
26 
27 Description
28  Generates a VTK file of particle tracks for cases that were computed using
29  a tracked-parcel-type cloud.
30 
31 \*---------------------------------------------------------------------------*/
32 
33 #include "argList.H"
34 #include "Cloud.H"
35 #include "IOdictionary.H"
36 #include "fvMesh.H"
37 #include "Time.H"
38 #include "timeSelector.H"
39 #include "OFstream.H"
40 #include "passiveParticleCloud.H"
41 #include "writer.H"
42 
43 using namespace Foam;
44 
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 
47 int main(int argc, char *argv[])
48 {
50  #include "addRegionOption.H"
51 
52  #include "setRootCase.H"
53 
54  #include "createTime.H"
56  #include "createNamedMesh.H"
57  #include "createFields.H"
58 
59  // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
60 
61  fileName vtkPath(runTime.path()/"VTK");
62  mkDir(vtkPath);
63 
64  Info<< "Scanning times to determine track data for cloud " << cloudName
65  << nl << endl;
66 
67  labelList maxIds(Pstream::nProcs(), -1);
68  forAll(timeDirs, timeI)
69  {
70  runTime.setTime(timeDirs[timeI], timeI);
71  Info<< "Time = " << runTime.timeName() << endl;
72 
73  Info<< " Reading particle positions" << endl;
75 
76  Info<< " Read " << returnReduce(myCloud.size(), sumOp<label>())
77  << " particles" << endl;
78 
80  {
81  label origId = iter().origId();
82  label origProc = iter().origProc();
83 
84  if (origProc >= maxIds.size())
85  {
86  maxIds.setSize(origProc+1, -1);
87  }
88 
89  maxIds[origProc] = max(maxIds[origProc], origId);
90  }
91  }
92 
93  label maxNProcs = returnReduce(maxIds.size(), maxOp<label>());
94 
95  Info<< "Detected particles originating from " << maxNProcs
96  << " processors." << nl << endl;
97 
98  maxIds.setSize(maxNProcs, -1);
99 
102 
103  labelList numIds = maxIds + 1;
104 
105  Info<< nl << "Particle statistics:" << endl;
106  forAll(maxIds, proci)
107  {
108  Info<< " Found " << numIds[proci] << " particles originating"
109  << " from processor " << proci << endl;
110  }
111  Info<< nl << endl;
112 
113 
114  // Calculate starting ids for particles on each processor
115  List<label> startIds(numIds.size(), 0);
116  for (label i = 0; i < numIds.size()-1; i++)
117  {
118  startIds[i+1] += startIds[i] + numIds[i];
119  }
120  label nParticle = startIds.last() + numIds[startIds.size()-1];
121 
122 
123  // Number of tracks to generate
124  label nTracks = nParticle/sampleFrequency;
125 
126  // Storage for all particle tracks
127  List<DynamicList<vector>> allTracks(nTracks);
128 
129  Info<< "\nGenerating " << nTracks << " particle tracks for cloud "
130  << cloudName << nl << endl;
131 
132  forAll(timeDirs, timeI)
133  {
134  runTime.setTime(timeDirs[timeI], timeI);
135  Info<< "Time = " << runTime.timeName() << endl;
136 
137  List<pointField> allPositions(Pstream::nProcs());
138  List<labelField> allOrigIds(Pstream::nProcs());
139  List<labelField> allOrigProcs(Pstream::nProcs());
140 
141  // Read particles. Will be size 0 if no particles.
142  Info<< " Reading particle positions" << endl;
144 
145  // Collect the track data on all processors that have positions
146  allPositions[Pstream::myProcNo()].setSize
147  (
148  myCloud.size(),
150  );
151  allOrigIds[Pstream::myProcNo()].setSize(myCloud.size(), 0);
152  allOrigProcs[Pstream::myProcNo()].setSize(myCloud.size(), 0);
153 
154  label i = 0;
155  forAllConstIter(passiveParticleCloud, myCloud, iter)
156  {
157  allPositions[Pstream::myProcNo()][i] = iter().position();
158  allOrigIds[Pstream::myProcNo()][i] = iter().origId();
159  allOrigProcs[Pstream::myProcNo()][i] = iter().origProc();
160  i++;
161  }
162 
163  // Collect the track data on the master processor
164  Pstream::gatherList(allPositions);
165  Pstream::gatherList(allOrigIds);
166  Pstream::gatherList(allOrigProcs);
167 
168  Info<< " Constructing tracks" << nl << endl;
169  if (Pstream::master())
170  {
171  forAll(allPositions, proci)
172  {
173  forAll(allPositions[proci], i)
174  {
175  label globalId =
176  startIds[allOrigProcs[proci][i]]
177  + allOrigIds[proci][i];
178 
179  if (globalId % sampleFrequency == 0)
180  {
181  label trackId = globalId/sampleFrequency;
182  if (allTracks[trackId].size() < maxPositions)
183  {
184  allTracks[trackId].append
185  (
186  allPositions[proci][i]
187  );
188  }
189  }
190  }
191  }
192  }
193  }
194 
195 
196  if (Pstream::master())
197  {
198  PtrList<coordSet> tracks(allTracks.size());
199  forAll(allTracks, trackI)
200  {
201  tracks.set
202  (
203  trackI,
204  new coordSet
205  (
206  "track" + Foam::name(trackI),
207  "distance"
208  )
209  );
210  tracks[trackI].transfer(allTracks[trackI]);
211  }
212 
213  autoPtr<writer<scalar>> scalarFormatterPtr = writer<scalar>::New
214  (
215  setFormat
216  );
217 
218  // OFstream vtkTracks(vtkPath/"particleTracks.vtk");
219  fileName vtkFile
220  (
221  scalarFormatterPtr().getFileName
222  (
223  tracks[0],
224  wordList(0)
225  )
226  );
227 
228  OFstream vtkTracks
229  (
230  vtkPath/("particleTracks." + vtkFile.ext())
231  );
232 
233  Info<< "\nWriting particle tracks in " << setFormat
234  << " format to " << vtkTracks.name()
235  << nl << endl;
236 
237  scalarFormatterPtr().write
238  (
239  true,
240  tracks,
241  wordList(0),
243  vtkTracks
244  );
245  }
246 
247  return 0;
248 }
249 
250 
251 // ************************************************************************* //
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
fileName path() const
Return path.
Definition: Time.H:266
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
A class for handling file names.
Definition: fileName.H:79
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Output to file stream.
Definition: OFstream.H:82
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:163
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:423
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:626
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
A Cloud of passive particles.
label maxPositions(readLabel(propsDict.lookup("maxPositions")))
dynamicFvMesh & mesh
Holds list of sampling positions.
Definition: coordSet.H:49
virtual void setTime(const Time &)
Reset the time and time-index to those of the given time.
Definition: Time.C:873
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
static autoPtr< writer > New(const word &writeFormat)
Return a reference to the selected writer.
Definition: writer.C:35
static const char nl
Definition: Ostream.H:265
static instantList select0(Time &runTime, const argList &args)
Return the set of times selected based on the argList options.
Definition: timeSelector.C:252
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:290
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
List< word > wordList
A List of words.
Definition: fileName.H:54
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:411
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:70
messageStream Info
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:52
const word cloudName(propsDict.lookup("cloudName"))
T & last()
Return the last element of the list.
Definition: UListI.H:128
Foam::argList args(argc, argv)
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
word setFormat(propsDict.lookupOrDefault< word >("setFormat", "vtk"))
static void addOptions(const bool constant=true, const bool withZero=false)
Add the options handled by timeSelector to argList::validOptions.
Definition: timeSelector.C:114
Namespace for OpenFOAM.
label sampleFrequency(readLabel(propsDict.lookup("sampleFrequency")))