1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "InjectionModel.H"
28 #include "mathematicalConstants.H"
29 #include "meshTools.H"
31 // * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * //
33 template<class CloudType>
34 void Foam::InjectionModel<CloudType>::readProps()
36 IOobject propsDictHeader
38 "injectionProperties",
39 owner_.db().time().timeName(),
40 "uniform"/cloud::prefix/owner_.name(),
47 if (propsDictHeader.headerOk())
49 const IOdictionary propsDict(propsDictHeader);
51 propsDict.readIfPresent("massInjected", massInjected_);
52 propsDict.readIfPresent("nInjections", nInjections_);
53 propsDict.readIfPresent("parcelsAddedTotal", parcelsAddedTotal_);
54 propsDict.readIfPresent("timeStep0", timeStep0_);
59 template<class CloudType>
60 void Foam::InjectionModel<CloudType>::writeProps()
62 if (owner_.db().time().outputTime())
64 IOdictionary propsDict
68 "injectionProperties",
69 owner_.db().time().timeName(),
70 "uniform"/cloud::prefix/owner_.name(),
78 propsDict.add("massInjected", massInjected_);
79 propsDict.add("nInjections", nInjections_);
80 propsDict.add("parcelsAddedTotal", parcelsAddedTotal_);
81 propsDict.add("timeStep0", timeStep0_);
83 propsDict.regIOobject::write();
88 template<class CloudType>
89 void Foam::InjectionModel<CloudType>::prepareForNextTimeStep
100 // Return if not started injection event
107 // Make times relative to SOI
108 scalar t0 = timeStep0_ - SOI_;
109 scalar t1 = time - SOI_;
111 // Number of parcels to inject
112 newParcels = parcelsToInject(t0, t1);
114 // Volume of parcels to inject
115 newVolume = volumeToInject(t0, t1);
117 // Hold previous time if no parcels, but non-zero volume fraction
118 if ((newParcels == 0) && (newVolume > 0.0))
120 // hold value of timeStep0_
124 // advance value of timeStep0_
130 template<class CloudType>
131 void Foam::InjectionModel<CloudType>::findCellAtPosition
137 const vector p0 = position;
139 bool foundCell = false;
141 cellI = owner_.mesh().findCell(position);
145 const vector& C = owner_.mesh().C()[cellI];
146 position += SMALL*(C - position);
148 foundCell = owner_.mesh().pointInCell(position, cellI);
150 reduce(foundCell, orOp<bool>());
152 // Last chance - find nearest cell and try that one
153 // - the point is probably on an edge
156 cellI = owner_.mesh().findNearestCell(position);
160 const vector& C = owner_.mesh().C()[cellI];
161 position += SMALL*(C - position);
163 foundCell = owner_.mesh().pointInCell(position, cellI);
165 reduce(foundCell, orOp<bool>());
172 "Foam::InjectionModel<CloudType>::findCellAtPosition"
177 )<< "Cannot find parcel injection cell. "
178 << "Parcel position = " << p0 << nl
179 << abort(FatalError);
184 template<class CloudType>
185 Foam::scalar Foam::InjectionModel<CloudType>::setNumberOfParticles
189 const scalar diameter,
194 switch (parcelBasis_)
198 nP = volume/volumeTotal_
200 /(parcels*mathematicalConstant::pi/6.0*pow3(diameter));
205 nP = massTotal_/(rho*volumeTotal_*parcels);
214 "Foam::InjectionModel<CloudType>::setNumberOfParticles"
222 )<< "Unknown parcelBasis type" << nl
231 template<class CloudType>
232 void Foam::InjectionModel<CloudType>::postInjectCheck(const label parcelsAdded)
234 if (parcelsAdded > 0)
237 << "--> Cloud: " << owner_.name() << nl
238 << " Added " << parcelsAdded
239 << " new parcels" << nl << endl;
242 // Increment total number of parcels added
243 parcelsAddedTotal_ += parcelsAdded;
245 // Update time for start of next injection
246 time0_ = owner_.db().time().value();
248 // Increment number of injections
251 // Write current state to properties file
256 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
258 template<class CloudType>
259 Foam::InjectionModel<CloudType>::InjectionModel(CloudType& owner)
261 dict_(dictionary::null),
263 coeffDict_(dictionary::null),
269 parcelsAddedTotal_(0),
270 parcelBasis_(pbNumber),
278 template<class CloudType>
279 Foam::InjectionModel<CloudType>::InjectionModel
281 const dictionary& dict,
288 coeffDict_(dict.subDict(type + "Coeffs")),
289 SOI_(readScalar(coeffDict_.lookup("SOI"))),
291 massTotal_(dimensionedScalar(coeffDict_.lookup("massTotal")).value()),
294 parcelsAddedTotal_(0),
295 parcelBasis_(pbNumber),
296 time0_(owner.db().time().value()),
300 // - also serves to initialise mesh dimensions - needed for parallel runs
301 // due to lazy evaluation of valid mesh dimensions
302 Info<< " Constructing " << owner.mesh().nGeometricD() << "-D injection"
305 word parcelBasisType = coeffDict_.lookup("parcelBasisType");
306 if (parcelBasisType == "mass")
308 parcelBasis_ = pbMass;
310 else if (parcelBasisType == "number")
312 parcelBasis_ = pbNumber;
318 "Foam::InjectionModel<CloudType>::InjectionModel"
320 "const dictionary&, "
324 )<< "parcelBasisType must be either 'number' or 'mass'" << nl
332 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
334 template<class CloudType>
335 Foam::InjectionModel<CloudType>::~InjectionModel()
339 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
341 template<class CloudType>
342 template<class TrackData>
343 void Foam::InjectionModel<CloudType>::inject(TrackData& td)
350 const scalar time = owner_.db().time().value();
351 const scalar carrierDt = owner_.db().time().deltaT().value();
352 const polyMesh& mesh = owner_.mesh();
354 // Prepare for next time step
355 label newParcels = 0;
356 scalar newVolume = 0.0;
357 prepareForNextTimeStep(time, newParcels, newVolume);
359 // Return if no parcels are required
366 // Duration of injection period during this timestep
367 const scalar deltaT =
368 max(0.0, min(carrierDt, min(time - SOI_, timeEnd() - time0_)));
370 // Pad injection time if injection starts during this timestep
371 const scalar padTime = max(0.0, SOI_ - time0_);
373 // Introduce new parcels linearly across carrier phase timestep
374 label parcelsAdded = 0;
375 for (label parcelI=0; parcelI<newParcels; parcelI++)
377 if (validInjection(parcelI))
379 // Calculate the pseudo time of injection for parcel 'parcelI'
380 scalar timeInj = time0_ + padTime + deltaT*parcelI/newParcels;
382 // Determine the injection position and owner cell
384 vector pos = vector::zero;
385 setPositionAndCell(parcelI, newParcels, timeInj, pos, cellI);
389 // Lagrangian timestep
390 scalar dt = time - timeInj;
392 // Apply corrections to position for 2-D cases
393 meshTools::constrainToMeshCentre(mesh, pos);
395 // Create a new parcel
396 parcelType* pPtr = new parcelType(td.cloud(), pos, cellI);
398 // Assign new parcel properties in injection model
399 setProperties(parcelI, newParcels, timeInj, *pPtr);
401 // Check new parcel properties
402 td.cloud().checkParcelProperties(*pPtr, dt, fullyDescribed());
404 // Apply correction to velocity for 2-D cases
405 meshTools::constrainDirection
412 // Number of particles per parcel
422 // Add the new parcel
423 td.cloud().addParticle(pPtr);
425 massInjected_ += pPtr->nParticle()*pPtr->mass();
431 postInjectCheck(parcelsAdded);
435 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
437 #include "NewInjectionModel.C"
439 // ************************************************************************* //