1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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.
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
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/>.
24 \*---------------------------------------------------------------------------*/
27 #include "functionObjectList.H"
28 #include "streamLine.H"
30 #include "streamLineParticleCloud.H"
31 #include "ReadFields.H"
32 #include "meshSearch.H"
33 #include "sampledSet.H"
34 #include "globalIndex.H"
35 #include "mapDistribute.H"
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 defineTypeNameAndDebug(Foam::streamLine, 0);
41 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 void Foam::streamLine::track()
45 const Time& runTime = obr_.time();
46 const fvMesh& mesh = dynamic_cast<const fvMesh&>(obr_);
48 IDLList<streamLineParticle> initialParticles;
49 streamLineParticleCloud particles
56 const sampledSet& seedPoints = sampledSetPtr_();
62 new streamLineParticle
66 seedPoints.cells()[i],
72 label nSeeds = returnReduce(particles.size(), sumOp<label>());
74 Info<< "Seeded " << nSeeds << " particles." << endl;
76 // Read or lookup fields
77 PtrList<volScalarField> vsFlds;
78 PtrList<interpolationCellPoint<scalar> > vsInterp;
79 PtrList<volVectorField> vvFlds;
80 PtrList<interpolationCellPoint<vector> > vvInterp;
86 IOobjectList allObjects(mesh, runTime.timeName());
88 IOobjectList objects(2*fields_.size());
91 objects.add(*allObjects[fields_[i]]);
94 ReadFields(mesh, objects, vsFlds);
95 vsInterp.setSize(vsFlds.size());
98 vsInterp.set(i, new interpolationCellPoint<scalar>(vsFlds[i]));
100 ReadFields(mesh, objects, vvFlds);
101 vvInterp.setSize(vvFlds.size());
104 vvInterp.set(i, new interpolationCellPoint<vector>(vvFlds[i]));
114 if (mesh.foundObject<volScalarField>(fields_[i]))
118 else if (mesh.foundObject<volVectorField>(fields_[i]))
124 FatalErrorIn("streamLine::execute()")
125 << "Cannot find field " << fields_[i] << endl
126 << "Valid scalar fields are:"
127 << mesh.names(volScalarField::typeName) << endl
128 << "Valid vector fields are:"
129 << mesh.names(volVectorField::typeName)
133 vsInterp.setSize(nScalar);
135 vvInterp.setSize(nVector);
140 if (mesh.foundObject<volScalarField>(fields_[i]))
142 const volScalarField& f = mesh.lookupObject<volScalarField>
149 new interpolationCellPoint<scalar>(f)
152 else if (mesh.foundObject<volVectorField>(fields_[i]))
154 const volVectorField& f = mesh.lookupObject<volVectorField>
159 if (f.name() == UName_)
167 new interpolationCellPoint<vector>(f)
174 scalarNames_.setSize(vsInterp.size());
177 scalarNames_[i] = vsInterp[i].psi().name();
179 vectorNames_.setSize(vvInterp.size());
182 vectorNames_[i] = vvInterp[i].psi().name();
185 // Check that we know the index of U in the interpolators.
189 FatalErrorIn("streamLine::execute()")
190 << "Cannot find field to move particles with : " << UName_
192 << "This field has to be present in the sampled fields "
194 << " and in the objectRegistry." << endl
201 // Size to maximum expected sizes.
203 allTracks_.setCapacity(nSeeds);
204 allScalars_.setSize(vsInterp.size());
205 forAll(allScalars_, i)
207 allScalars_[i].clear();
208 allScalars_[i].setCapacity(nSeeds);
210 allVectors_.setSize(vvInterp.size());
211 forAll(allVectors_, i)
213 allVectors_[i].clear();
214 allVectors_[i].setCapacity(nSeeds);
217 // additional particle info
218 streamLineParticle::trackingData td
223 UIndex, // index of U in vvInterp
224 trackForward_, // track in +u direction
225 nSubCycle_, // step through cells in steps?
232 // Set very large dt. Note: cannot use GREAT since 1/GREAT is SMALL
233 // which is a trigger value for the tracking...
234 const scalar trackTime = Foam::sqrt(GREAT);
237 particles.move(td, trackTime);
241 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
243 Foam::streamLine::streamLine
246 const objectRegistry& obr,
247 const dictionary& dict,
248 const bool loadFromFiles
254 loadFromFiles_(loadFromFiles),
257 // Only active if a fvMesh is available
258 if (isA<fvMesh>(obr_))
267 "streamLine::streamLine\n"
270 "const objectRegistry&,\n"
271 "const dictionary&,\n"
274 ) << "No fvMesh available, deactivating."
280 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
282 Foam::streamLine::~streamLine()
286 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
288 void Foam::streamLine::read(const dictionary& dict)
293 dict.lookup("fields") >> fields_;
294 if (dict.found("UName"))
296 dict.lookup("UName") >> UName_;
300 UName_ = dict.lookupOrDefault<word>("U", "U");
302 dict.lookup("trackForward") >> trackForward_;
303 dict.lookup("lifeTime") >> lifeTime_;
306 FatalErrorIn(":streamLine::read(const dictionary&)")
307 << "Illegal value " << lifeTime_ << " for lifeTime"
311 dict.lookup("nSubCycle") >> nSubCycle_;
317 cloudName_ = dict.lookupOrDefault<word>("cloudName", "streamLine");
318 dict.lookup("seedSampleSet") >> seedSet_;
320 const fvMesh& mesh = dynamic_cast<const fvMesh&>(obr_);
322 meshSearchPtr_.reset(new meshSearch(mesh, false));
324 const dictionary& coeffsDict = dict.subDict(seedSet_ + "Coeffs");
325 sampledSetPtr_ = sampledSet::New
332 coeffsDict.lookup("axis") >> sampledSetAxis_;
334 scalarFormatterPtr_ = writer<scalar>::New(dict.lookup("setFormat"));
335 vectorFormatterPtr_ = writer<vector>::New(dict.lookup("setFormat"));
340 void Foam::streamLine::execute()
342 // const Time& runTime = obr_.time();
343 // Pout<< "**streamLine::execute : time:" << runTime.timeName() << endl;
345 // bool isOutputTime = false;
347 // const functionObjectList& fobs = runTime.functionObjects();
351 // if (isA<streamLineFunctionObject>(fobs[i]))
353 // const streamLineFunctionObject& fo =
354 // dynamic_cast<const streamLineFunctionObject&>(fobs[i]);
356 // if (fo.name() == name_)
358 // Pout<< "found me:" << i << endl;
359 // if (fo.outputControl().output())
361 // isOutputTime = true;
369 // if (active_ && isOutputTime)
376 void Foam::streamLine::end()
380 void Foam::streamLine::write()
384 const Time& runTime = obr_.time();
385 const fvMesh& mesh = dynamic_cast<const fvMesh&>(obr_);
388 // Do all injection and tracking
392 if (Pstream::parRun())
394 // Append slave tracks to master ones
395 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
397 globalIndex globalTrackIDs(allTracks_.size());
399 // Construct a distribution map to pull all to the master.
400 labelListList sendMap(Pstream::nProcs());
401 labelListList recvMap(Pstream::nProcs());
403 if (Pstream::master())
405 // Master: receive all. My own first, then consecutive
409 forAll(recvMap, procI)
411 labelList& fromProc = recvMap[procI];
412 fromProc.setSize(globalTrackIDs.localSize(procI));
415 fromProc[i] = trackI++;
420 labelList& toMaster = sendMap[0];
421 toMaster.setSize(globalTrackIDs.localSize());
427 const mapDistribute distMap
429 globalTrackIDs.size(),
435 // Distribute the track positions. Note: use scheduled comms
436 // to prevent buffering.
437 mapDistribute::distribute
441 distMap.constructSize(),
443 distMap.constructMap(),
447 // Distribute the scalars
448 forAll(allScalars_, scalarI)
450 mapDistribute::distribute
454 distMap.constructSize(),
456 distMap.constructMap(),
460 // Distribute the vectors
461 forAll(allVectors_, vectorI)
463 mapDistribute::distribute
467 distMap.constructSize(),
469 distMap.constructMap(),
477 forAll(allTracks_, trackI)
479 n += allTracks_[trackI].size();
482 Info<< "Tracks:" << allTracks_.size()
483 << " total samples:" << n << endl;
486 // Massage into form suitable for writers
487 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
489 if (Pstream::master() && allTracks_.size())
491 // Make output directory
496 ? runTime.path()/".."/"sets"/name()
497 : runTime.path()/"sets"/name()
499 if (mesh.name() != fvMesh::defaultRegion)
501 vtkPath = vtkPath/mesh.name();
503 vtkPath = vtkPath/mesh.time().timeName();
507 // Convert track positions
509 PtrList<coordSet> tracks(allTracks_.size());
510 forAll(allTracks_, trackI)
517 "track" + Foam::name(trackI),
518 sampledSetAxis_ //"xyz"
521 tracks[trackI].transfer(allTracks_[trackI]);
524 // Convert scalar values
526 if (allScalars_.size() > 0)
528 List<List<scalarField> > scalarValues(allScalars_.size());
530 forAll(allScalars_, scalarI)
532 DynamicList<scalarList>& allTrackVals =
533 allScalars_[scalarI];
534 scalarValues[scalarI].setSize(allTrackVals.size());
536 forAll(allTrackVals, trackI)
538 scalarList& trackVals = allTrackVals[trackI];
539 scalarValues[scalarI][trackI].transfer(trackVals);
546 / scalarFormatterPtr_().getFileName
553 Info<< "Writing data to " << vtkFile.path() << endl;
555 scalarFormatterPtr_().write
565 // Convert vector values
567 if (allVectors_.size() > 0)
569 List<List<vectorField> > vectorValues(allVectors_.size());
571 forAll(allVectors_, vectorI)
573 DynamicList<vectorList>& allTrackVals =
574 allVectors_[vectorI];
575 vectorValues[vectorI].setSize(allTrackVals.size());
577 forAll(allTrackVals, trackI)
579 vectorList& trackVals = allTrackVals[trackI];
580 vectorValues[vectorI][trackI].transfer(trackVals);
587 / vectorFormatterPtr_().getFileName
594 //Info<< "Writing vector data to " << vtkFile << endl;
596 vectorFormatterPtr_().write
610 void Foam::streamLine::updateMesh(const mapPolyMesh&)
616 void Foam::streamLine::movePoints(const pointField&)
618 // Moving mesh affects the search tree
623 //void Foam::streamLine::readUpdate(const polyMesh::readUpdateState state)
625 // if (state != UNCHANGED)
632 // ************************************************************************* //