1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
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 "processorPolyPatch.H"
28 #include "globalMeshData.H"
29 #include "PstreamCombineReduceOps.H"
30 #include "mapPolyMesh.H"
33 #include "wallPolyPatch.H"
35 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
37 template<class ParticleType>
38 void Foam::Cloud<ParticleType>::calcCellWallFaces() const
40 cellWallFacesPtr_.reset(new PackedBoolList(pMesh().nCells(), false));
42 PackedBoolList& cellWallFaces = cellWallFacesPtr_();
44 const polyBoundaryMesh& patches = polyMesh_.boundaryMesh();
46 forAll(patches, patchI)
48 if (isA<wallPolyPatch>(patches[patchI]))
50 const polyPatch& patch = patches[patchI];
52 const labelList& pFaceCells = patch.faceCells();
54 forAll(pFaceCells, pFCI)
56 cellWallFaces[pFaceCells[pFCI]] = true;
63 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
65 template<class ParticleType>
66 Foam::Cloud<ParticleType>::Cloud
68 const polyMesh& pMesh,
69 const IDLList<ParticleType>& particles
73 IDLList<ParticleType>(),
79 // Ask for the tetBasePtIs to trigger all processors to build
80 // them, otherwise, if some processors have no particles then
81 // there is a comms mismatch.
82 polyMesh_.tetBasePtIs();
84 IDLList<ParticleType>::operator=(particles);
88 template<class ParticleType>
89 Foam::Cloud<ParticleType>::Cloud
91 const polyMesh& pMesh,
92 const word& cloudName,
93 const IDLList<ParticleType>& particles
96 cloud(pMesh, cloudName),
97 IDLList<ParticleType>(),
103 // Ask for the tetBasePtIs to trigger all processors to build
104 // them, otherwise, if some processors have no particles then
105 // there is a comms mismatch.
106 polyMesh_.tetBasePtIs();
108 IDLList<ParticleType>::operator=(particles);
112 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
114 template<class ParticleType>
115 const Foam::PackedBoolList& Foam::Cloud<ParticleType>::cellHasWallFaces()
118 if (!cellWallFacesPtr_.valid())
123 return cellWallFacesPtr_();
127 template<class ParticleType>
128 void Foam::Cloud<ParticleType>::addParticle(ParticleType* pPtr)
134 template<class ParticleType>
135 void Foam::Cloud<ParticleType>::deleteParticle(ParticleType& p)
137 delete(this->remove(&p));
141 template<class ParticleType>
142 void Foam::Cloud<ParticleType>::cloudReset(const Cloud<ParticleType>& c)
144 // Reset particle cound and particles only
145 // - not changing the cloud object registry or reference to the polyMesh
146 ParticleType::particleCount_ = 0;
147 IDLList<ParticleType>::operator=(c);
151 template<class ParticleType>
152 template<class TrackData>
153 void Foam::Cloud<ParticleType>::move(TrackData& td, const scalar trackTime)
155 const polyBoundaryMesh& pbm = pMesh().boundaryMesh();
156 const globalMeshData& pData = polyMesh_.globalData();
158 // Which patches are processor patches
159 const labelList& procPatches = pData.processorPatches();
161 // Indexing of patches into the procPatches list
162 const labelList& procPatchIndices = pData.processorPatchIndices();
164 // Indexing of equivalent patch on neighbour processor into the
165 // procPatches list on the neighbour
166 const labelList& procPatchNeighbours = pData.processorPatchNeighbours();
168 // Which processors this processor is connected to
169 const labelList& neighbourProcs = pData[Pstream::myProcNo()];
171 // Indexing from the processor number into the neighbourProcs list
172 labelList neighbourProcIndices(Pstream::nProcs(), -1);
174 forAll(neighbourProcs, i)
176 neighbourProcIndices[neighbourProcs[i]] = i;
179 // Initialise the stepFraction moved for the particles
180 forAllIter(typename Cloud<ParticleType>, *this, pIter)
182 pIter().stepFraction() = 0;
185 // Reset nTrackingRescues
186 nTrackingRescues_ = 0;
188 // While there are particles to transfer
191 // List of lists of particles to be transfered for all of the
192 // neighbour processors
193 List<IDLList<ParticleType> > particleTransferLists
195 neighbourProcs.size()
198 // List of destination processorPatches indices for all of the
199 // neighbour processors
200 List<DynamicList<label> > patchIndexTransferLists
202 neighbourProcs.size()
205 // Loop over all particles
206 forAllIter(typename Cloud<ParticleType>, *this, pIter)
208 ParticleType& p = pIter();
211 bool keepParticle = p.move(td, trackTime);
213 // If the particle is to be kept
214 // (i.e. it hasn't passed through an inlet or outlet)
217 // If we are running in parallel and the particle is on a
219 if (Pstream::parRun() && p.face() >= pMesh().nInternalFaces())
221 label patchI = pbm.whichPatch(p.face());
223 // ... and the face is on a processor patch
224 // prepare it for transfer
225 if (procPatchIndices[patchI] != -1)
227 label n = neighbourProcIndices
229 refCast<const processorPolyPatch>
235 p.prepareForParallelTransfer(patchI, td);
237 particleTransferLists[n].append(this->remove(&p));
239 patchIndexTransferLists[n].append
241 procPatchNeighbours[patchI]
252 if (!Pstream::parRun())
257 // Allocate transfer buffers
258 PstreamBuffers pBufs(Pstream::nonBlocking);
260 // Stream into send buffers
261 forAll(particleTransferLists, i)
263 if (particleTransferLists[i].size())
265 UOPstream particleStream
272 << patchIndexTransferLists[i]
273 << particleTransferLists[i];
277 // Set up transfers when in non-blocking mode. Returns sizes (in bytes)
278 // to be sent/received.
279 labelListList allNTrans(Pstream::nProcs());
281 pBufs.finishedSends(allNTrans);
283 bool transfered = false;
287 forAll(allNTrans[i], j)
302 // Retrieve from receive buffers
303 forAll(neighbourProcs, i)
305 label neighbProci = neighbourProcs[i];
307 label nRec = allNTrans[neighbProci][Pstream::myProcNo()];
311 UIPstream particleStream(neighbProci, pBufs);
313 labelList receivePatchIndex(particleStream);
315 IDLList<ParticleType> newParticles
318 typename ParticleType::iNew(polyMesh_)
323 forAllIter(typename Cloud<ParticleType>, newParticles, newpIter)
325 ParticleType& newp = newpIter();
327 label patchI = procPatches[receivePatchIndex[pI++]];
329 newp.correctAfterParallelTransfer(patchI, td);
331 addParticle(newParticles.remove(&newp));
339 reduce(nTrackingRescues_, sumOp<label>());
341 if (nTrackingRescues_ > 0)
343 Info<< nTrackingRescues_ << " tracking rescue corrections" << endl;
349 template<class ParticleType>
350 template<class TrackData>
351 void Foam::Cloud<ParticleType>::autoMap
354 const mapPolyMesh& mapper
359 Info<< "Cloud<ParticleType>::autoMap(TrackData&, const mapPolyMesh&) "
360 << "for lagrangian cloud " << cloud::name() << endl;
363 const labelList& reverseCellMap = mapper.reverseCellMap();
364 const labelList& reverseFaceMap = mapper.reverseFaceMap();
366 // Reset stored data that relies on the mesh
367 // polyMesh_.clearCellTree();
368 cellWallFacesPtr_.clear();
370 forAllIter(typename Cloud<ParticleType>, *this, pIter)
372 ParticleType& p = pIter();
374 if (reverseCellMap[p.cell()] >= 0)
376 p.cell() = reverseCellMap[p.cell()];
378 if (p.face() >= 0 && reverseFaceMap[p.face()] >= 0)
380 p.face() = reverseFaceMap[p.face()];
391 label trackStartCell = mapper.mergedCell(p.cell());
393 if (trackStartCell < 0)
398 vector pos = p.position();
400 const_cast<vector&>(p.position()) =
401 polyMesh_.cellCentres()[trackStartCell];
403 p.stepFraction() = 0;
413 template<class ParticleType>
414 void Foam::Cloud<ParticleType>::writePositions() const
418 this->db().time().path()/this->name() + "_positions.obj"
421 forAllConstIter(typename Cloud<ParticleType>, *this, pIter)
423 const ParticleType& p = pIter();
424 pObj<< "v " << p.position().x() << " " << p.position().y() << " "
425 << p.position().z() << nl;
432 // * * * * * * * * * * * * * * * * IOStream operators * * * * * * * * * * * //
436 // ************************************************************************* //