1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011-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 \*---------------------------------------------------------------------------*/
26 #include "CellZoneInjection.H"
27 #include "mathematicalConstants.H"
28 #include "polyMeshTetDecomposition.H"
29 #include "globalIndex.H"
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34 template<class CloudType>
35 void Foam::CellZoneInjection<CloudType>::setPositions
37 const labelList& cellZoneCells
40 const fvMesh& mesh = this->owner().mesh();
41 const scalarField& V = mesh.V();
42 const label nCells = cellZoneCells.size();
43 cachedRandom& rnd = this->owner().rndGen();
45 DynamicList<vector> positions(nCells); // initial size only
46 DynamicList<label> injectorCells(nCells); // initial size only
47 DynamicList<label> injectorTetFaces(nCells); // initial size only
48 DynamicList<label> injectorTetPts(nCells); // initial size only
50 scalar newParticlesTotal = 0.0;
51 label addParticlesTotal = 0;
53 forAll(cellZoneCells, i)
55 const label cellI = cellZoneCells[i];
57 // Calc number of particles to add
58 const scalar newParticles = V[cellI]*numberDensity_;
59 newParticlesTotal += newParticles;
60 label addParticles = floor(newParticles);
61 addParticlesTotal += addParticles;
63 const scalar diff = newParticlesTotal - addParticlesTotal;
66 label corr = floor(diff);
68 addParticlesTotal += corr;
71 // Construct cell tet indices
72 const List<tetIndices> cellTetIs =
73 polyMeshTetDecomposition::cellTetIndices(mesh, cellI);
75 // Construct cell tet volume fractions
76 scalarList cTetVFrac(cellTetIs.size(), 0.0);
77 for (label tetI = 1; tetI < cellTetIs.size() - 1; tetI++)
80 (cTetVFrac[tetI-1] + cellTetIs[tetI].tet(mesh).mag())/V[cellI];
82 cTetVFrac.last() = 1.0;
84 // Set new particle position and cellId
85 for (label pI = 0; pI < addParticles; pI++)
87 const scalar volFrac = rnd.sample01<scalar>();
89 forAll(cTetVFrac, vfI)
91 if (cTetVFrac[vfI] > volFrac)
97 positions.append(cellTetIs[tetI].tet(mesh).randomPoint(rnd));
99 injectorCells.append(cellI);
100 injectorTetFaces.append(cellTetIs[tetI].face());
101 injectorTetPts.append(cellTetIs[tetI].faceBasePt());
105 // Parallel operation manipulations
106 globalIndex globalPositions(positions.size());
107 List<vector> allPositions(globalPositions.size(), point::max);
108 List<label> allInjectorCells(globalPositions.size(), -1);
109 List<label> allInjectorTetFaces(globalPositions.size(), -1);
110 List<label> allInjectorTetPts(globalPositions.size(), -1);
112 // Gather all positions on to all processors
116 globalPositions.localSize(Pstream::myProcNo()),
117 globalPositions.offset(Pstream::myProcNo())
120 Pstream::listCombineGather(allPositions, minEqOp<point>());
121 Pstream::listCombineScatter(allPositions);
123 // Gather local cell tet and tet-point Ids, but leave non-local ids set -1
127 globalPositions.localSize(Pstream::myProcNo()),
128 globalPositions.offset(Pstream::myProcNo())
129 ).assign(injectorCells);
133 globalPositions.localSize(Pstream::myProcNo()),
134 globalPositions.offset(Pstream::myProcNo())
135 ).assign(injectorTetFaces);
139 globalPositions.localSize(Pstream::myProcNo()),
140 globalPositions.offset(Pstream::myProcNo())
141 ).assign(injectorTetPts);
144 positions_.transfer(allPositions);
145 injectorCells_.transfer(allInjectorCells);
146 injectorTetFaces_.transfer(allInjectorTetFaces);
147 injectorTetPts_.transfer(allInjectorTetPts);
152 OFstream points("points.obj");
153 forAll(positions_, i)
155 meshTools::writeOBJ(points, positions_[i]);
161 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
163 template<class CloudType>
164 Foam::CellZoneInjection<CloudType>::CellZoneInjection
166 const dictionary& dict,
170 InjectionModel<CloudType>(dict, owner, typeName),
171 cellZoneName_(this->coeffDict().lookup("cellZone")),
172 numberDensity_(readScalar(this->coeffDict().lookup("numberDensity"))),
178 U0_(this->coeffDict().lookup("U0")),
181 distributionModels::distributionModel::New
183 this->coeffDict().subDict("sizeDistribution"), owner.rndGen()
187 const fvMesh& mesh = owner.mesh();
188 const label zoneI = mesh.cellZones().findZoneID(cellZoneName_);
194 "Foam::CellZoneInjection<CloudType>::CellZoneInjection"
196 "const dictionary&, "
199 ) << "Unknown cell zone name: " << cellZoneName_
200 << ". Valid cell zones are: " << mesh.cellZones().names()
201 << nl << exit(FatalError);
204 const labelList& cellZoneCells = mesh.cellZones()[zoneI];
205 const label nCells = cellZoneCells.size();
206 const scalar nCellsTotal = returnReduce(nCells, sumOp<label>());
207 const scalar VCells = sum(scalarField(mesh.V(), cellZoneCells));
208 const scalar VCellsTotal = returnReduce(VCells, sumOp<scalar>());
209 Info<< " cell zone size = " << nCellsTotal << endl;
210 Info<< " cell zone volume = " << VCellsTotal << endl;
212 if ((nCells == 0) || (VCellsTotal*numberDensity_ < 1))
216 "Foam::CellZoneInjection<CloudType>::CellZoneInjection"
218 "const dictionary&, "
221 ) << "Number of particles to be added to cellZone " << cellZoneName_
222 << " is zero" << endl;
226 setPositions(cellZoneCells);
228 Info<< " number density = " << numberDensity_ << nl
229 << " number of particles = " << positions_.size() << endl;
231 // Construct parcel diameters
232 diameters_.setSize(positions_.size());
233 forAll(diameters_, i)
235 diameters_[i] = sizeDistribution_->sample();
239 // Determine volume of particles to inject
240 this->volumeTotal_ = sum(pow3(diameters_))*constant::mathematical::pi/6.0;
244 template<class CloudType>
245 Foam::CellZoneInjection<CloudType>::CellZoneInjection
247 const CellZoneInjection<CloudType>& im
250 InjectionModel<CloudType>(im),
251 cellZoneName_(im.cellZoneName_),
252 numberDensity_(im.numberDensity_),
253 positions_(im.positions_),
254 injectorCells_(im.injectorCells_),
255 injectorTetFaces_(im.injectorTetFaces_),
256 injectorTetPts_(im.injectorTetPts_),
257 diameters_(im.diameters_),
259 sizeDistribution_(im.sizeDistribution_().clone().ptr())
263 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
265 template<class CloudType>
266 Foam::CellZoneInjection<CloudType>::~CellZoneInjection()
270 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
272 template<class CloudType>
273 Foam::scalar Foam::CellZoneInjection<CloudType>::timeEnd() const
280 template<class CloudType>
281 Foam::label Foam::CellZoneInjection<CloudType>::parcelsToInject
287 if ((0.0 >= time0) && (0.0 < time1))
289 return positions_.size();
298 template<class CloudType>
299 Foam::scalar Foam::CellZoneInjection<CloudType>::volumeToInject
305 // All parcels introduced at SOI
306 if ((0.0 >= time0) && (0.0 < time1))
308 return this->volumeTotal_;
317 template<class CloudType>
318 void Foam::CellZoneInjection<CloudType>::setPositionAndCell
321 const label nParcels,
329 position = positions_[parcelI];
330 cellOwner = injectorCells_[parcelI];
331 tetFaceI = injectorTetFaces_[parcelI];
332 tetPtI = injectorTetPts_[parcelI];
336 template<class CloudType>
337 void Foam::CellZoneInjection<CloudType>::setProperties
342 typename CloudType::parcelType& parcel
345 // set particle velocity
348 // set particle diameter
349 parcel.d() = diameters_[parcelI];
353 template<class CloudType>
354 bool Foam::CellZoneInjection<CloudType>::fullyDescribed() const
360 template<class CloudType>
361 bool Foam::CellZoneInjection<CloudType>::validInjection(const label)
367 // ************************************************************************* //