particleTracks.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-2016 OpenFOAM Foundation
9 -------------------------------------------------------------------------------
10 License
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 Application
27  particleTracks
28 
29 Group
30  grpPostProcessingUtilities
31 
32 Description
33  Generate a legacy VTK file of particle tracks for cases that were
34  computed using a tracked-parcel-type cloud.
35 
36 \*---------------------------------------------------------------------------*/
37 
38 #include "argList.H"
39 #include "Cloud.H"
40 #include "IOdictionary.H"
41 #include "fvMesh.H"
42 #include "Time.H"
43 #include "timeSelector.H"
44 #include "OFstream.H"
45 #include "passiveParticleCloud.H"
46 #include "writer.H"
47 
48 using namespace Foam;
49 
50 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51 
52 int main(int argc, char *argv[])
53 {
55  (
56  "Generate a legacy VTK file of particle tracks for cases that were"
57  " computed using a tracked-parcel-type cloud"
58  );
59 
61  #include "addRegionOption.H"
62 
63  #include "setRootCase.H"
64 
65  #include "createTime.H"
67  #include "createNamedMesh.H"
68  #include "createFields.H"
69 
70  // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
71 
72  const fileName vtkPath(runTime.rootPath()/runTime.globalCaseName()/"VTK");
73  mkDir(vtkPath);
74 
75  Info<< "Scanning times to determine track data for cloud " << cloudName
76  << nl << endl;
77 
78  labelList maxIds(Pstream::nProcs(), -1);
79  forAll(timeDirs, timeI)
80  {
81  runTime.setTime(timeDirs[timeI], timeI);
82  Info<< "Time = " << runTime.timeName() << endl;
83 
84  Info<< " Reading particle positions" << endl;
86 
87  Info<< " Read " << returnReduce(myCloud.size(), sumOp<label>())
88  << " particles" << endl;
89 
90  for (const passiveParticle& p : myCloud)
91  {
92  const label origId = p.origId();
93  const label origProc = p.origProc();
94 
95  if (origProc >= maxIds.size())
96  {
97  maxIds.setSize(origProc+1, -1);
98  }
99 
100  maxIds[origProc] = max(maxIds[origProc], origId);
101  }
102  }
103 
104  label maxNProcs = returnReduce(maxIds.size(), maxOp<label>());
105 
106  Info<< "Detected particles originating from " << maxNProcs
107  << " processors." << nl << endl;
108 
109  maxIds.setSize(maxNProcs, -1);
110 
113 
114  labelList numIds = maxIds + 1;
115 
116  Info<< nl << "Particle statistics:" << endl;
117  forAll(maxIds, proci)
118  {
119  Info<< " Found " << numIds[proci] << " particles originating"
120  << " from processor " << proci << endl;
121  }
122  Info<< nl << endl;
123 
124 
125  // Calculate starting ids for particles on each processor
126  labelList startIds(numIds.size(), Zero);
127  for (label i = 0; i < numIds.size()-1; i++)
128  {
129  startIds[i+1] += startIds[i] + numIds[i];
130  }
131  label nParticle = startIds.last() + numIds[startIds.size()-1];
132 
133 
134  // Number of tracks to generate
135  label nTracks = nParticle/sampleFrequency;
136 
137  // Storage for all particle tracks
138  List<DynamicList<vector>> allTracks(nTracks);
139 
140  Info<< "\nGenerating " << nTracks << " particle tracks for cloud "
141  << cloudName << nl << endl;
142 
143  forAll(timeDirs, timeI)
144  {
145  runTime.setTime(timeDirs[timeI], timeI);
146  Info<< "Time = " << runTime.timeName() << endl;
147 
148  List<pointField> allPositions(Pstream::nProcs());
149  List<labelField> allOrigIds(Pstream::nProcs());
150  List<labelField> allOrigProcs(Pstream::nProcs());
151 
152  // Read particles. Will be size 0 if no particles.
153  Info<< " Reading particle positions" << endl;
155 
156  // Collect the track data on all processors that have positions
157  allPositions[Pstream::myProcNo()].setSize
158  (
159  myCloud.size(),
161  );
162  allOrigIds[Pstream::myProcNo()].setSize(myCloud.size(), Zero);
163  allOrigProcs[Pstream::myProcNo()].setSize(myCloud.size(), Zero);
164 
165  label i = 0;
166  for (const passiveParticle& p : myCloud)
167  {
168  allPositions[Pstream::myProcNo()][i] = p.position();
169  allOrigIds[Pstream::myProcNo()][i] = p.origId();
170  allOrigProcs[Pstream::myProcNo()][i] = p.origProc();
171  ++i;
172  }
173 
174  // Collect the track data on the master processor
175  Pstream::gatherList(allPositions);
176  Pstream::gatherList(allOrigIds);
177  Pstream::gatherList(allOrigProcs);
178 
179  Info<< " Constructing tracks" << nl << endl;
180  if (Pstream::master())
181  {
182  forAll(allPositions, proci)
183  {
184  forAll(allPositions[proci], i)
185  {
186  label globalId =
187  startIds[allOrigProcs[proci][i]]
188  + allOrigIds[proci][i];
189 
190  if (globalId % sampleFrequency == 0)
191  {
192  label trackId = globalId/sampleFrequency;
193  if (allTracks[trackId].size() < maxPositions)
194  {
195  allTracks[trackId].append
196  (
197  allPositions[proci][i]
198  );
199  }
200  }
201  }
202  }
203  }
204  }
205 
206 
207  if (Pstream::master())
208  {
209  PtrList<coordSet> tracks(allTracks.size());
210  forAll(allTracks, trackI)
211  {
212  tracks.set
213  (
214  trackI,
215  new coordSet
216  (
217  "track" + Foam::name(trackI),
218  "distance"
219  )
220  );
221  tracks[trackI].transfer(allTracks[trackI]);
222  }
223 
224  autoPtr<writer<scalar>> scalarFormatterPtr = writer<scalar>::New
225  (
226  setFormat
227  );
228 
229  //OFstream vtkTracks(vtkPath/"particleTracks.vtk");
230  fileName vtkFile
231  (
232  scalarFormatterPtr().getFileName
233  (
234  tracks[0],
235  wordList(0)
236  )
237  );
238 
239  OFstream vtkTracks
240  (
241  vtkPath/("particleTracks." + vtkFile.ext())
242  );
243 
244  Info<< "\nWriting particle tracks in " << setFormat
245  << " format to " << vtkTracks.name()
246  << nl << endl;
247 
248  scalarFormatterPtr().write
249  (
250  true,
251  tracks,
252  wordList(0),
254  vtkTracks
255  );
256  }
257 
258  Info<< "End\n" << endl;
259 
260  return 0;
261 }
262 
263 
264 // ************************************************************************* //
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::TimePaths::globalCaseName
const fileName & globalCaseName() const
Return global case name.
Definition: TimePathsI.H:48
Foam::maxOp
Definition: ops.H:223
sampleFrequency
const label sampleFrequency(propsDict.get< label >("sampleFrequency"))
p
volScalarField & p
Definition: createFieldRefs.H:8
cloudName
const word cloudName(propsDict.get< word >("cloud"))
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:94
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
setFormat
const word setFormat(propsDict.getOrDefault< word >("setFormat", "vtk"))
Foam::UPstream::nProcs
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:427
Foam::Time::timeName
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:785
Foam::passiveParticle
Copy of base particle.
Definition: passiveParticle.H:53
Cloud.H
Foam::argList::addNote
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:413
maxPositions
const label maxPositions(propsDict.get< label >("maxPositions"))
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
OFstream.H
Foam::wordList
List< word > wordList
A List of words.
Definition: fileName.H:59
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
argList.H
addRegionOption.H
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:62
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::passiveParticleCloud
A Cloud of passive particles.
Definition: passiveParticleCloud.H:52
createNamedMesh.H
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::coordSet
Holds list of sampling positions.
Definition: coordSet.H:53
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::maxEqOp
Definition: ops.H:80
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:87
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:445
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:439
Foam::Pstream::listCombineGather
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:290
IOdictionary.H
Time.H
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
setRootCase.H
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Definition: gatherScatterList.C:52
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::timeSelector::addOptions
static void addOptions(const bool constant=true, const bool withZero=false)
Add timeSelector options to argList::validOptions.
Definition: timeSelector.C:108
passiveParticleCloud.H
Foam::Time::rootPath
const fileName & rootPath() const
Return root path.
Definition: TimePathsI.H:42
Foam::List< instant >
Foam::Time::setTime
virtual void setTime(const Time &t)
Reset the time and time-index to those of the given time.
Definition: Time.C:1006
timeSelector.H
createTime.H
Foam::VectorSpace< Vector< Cmpt >, Cmpt, 3 >::zero
static const Vector< Cmpt > zero
Definition: VectorSpace.H:115
Foam::Pstream::listCombineScatter
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Definition: combineGatherScatter.C:432
writer.H
Foam::timeSelector::select0
static instantList select0(Time &runTime, const argList &args)
Definition: timeSelector.C:241
args
Foam::argList args(argc, argv)
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
Foam::writer::New
static autoPtr< writer > New(const word &writeFormat)
Return a reference to the selected writer.
Definition: writer.C:38