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 \*---------------------------------------------------------------------------*/
26 #include "KinematicCloud.H"
27 #include "IntegrationScheme.H"
28 #include "interpolation.H"
29 #include "subCycleTime.H"
31 #include "DispersionModel.H"
32 #include "InjectionModel.H"
33 #include "PatchInteractionModel.H"
34 #include "SurfaceFilmModel.H"
36 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
38 template<class CloudType>
39 void Foam::KinematicCloud<CloudType>::setModels()
41 dispersionModel_.reset
43 DispersionModel<KinematicCloud<CloudType> >::New
52 InjectionModel<KinematicCloud<CloudType> >::New
59 patchInteractionModel_.reset
61 PatchInteractionModel<KinematicCloud<CloudType> >::New
68 surfaceFilmModel_.reset
70 SurfaceFilmModel<KinematicCloud<CloudType> >::New
80 vectorIntegrationScheme::New
83 solution_.integrationSchemes()
89 template<class CloudType>
90 template<class TrackData>
91 void Foam::KinematicCloud<CloudType>::solve(TrackData& td)
93 if (solution_.steadyState())
95 td.cloud().storeState();
97 td.cloud().preEvolve();
101 if (solution_.coupled())
103 td.cloud().relaxSources(td.cloud().cloudCopy());
108 td.cloud().preEvolve();
112 if (solution_.coupled())
114 td.cloud().scaleSources();
120 td.cloud().postEvolve();
122 if (solution_.steadyState())
124 td.cloud().restoreState();
129 template<class CloudType>
130 void Foam::KinematicCloud<CloudType>::buildCellOccupancy()
132 if (cellOccupancyPtr_.empty())
134 cellOccupancyPtr_.reset
136 new List<DynamicList<parcelType*> >(mesh_.nCells())
139 else if (cellOccupancyPtr_().size() != mesh_.nCells())
141 // If the size of the mesh has changed, reset the
142 // cellOccupancy size
144 cellOccupancyPtr_().setSize(mesh_.nCells());
147 List<DynamicList<parcelType*> >& cellOccupancy = cellOccupancyPtr_();
149 forAll(cellOccupancy, cO)
151 cellOccupancy[cO].clear();
154 forAllIter(typename KinematicCloud<CloudType>, *this, iter)
156 cellOccupancy[iter().cell()].append(&iter());
161 template<class CloudType>
162 void Foam::KinematicCloud<CloudType>::updateCellOccupancy()
164 // Only build the cellOccupancy if the pointer is set, i.e. it has
165 // been requested before.
167 if (cellOccupancyPtr_.valid())
169 buildCellOccupancy();
174 template<class CloudType>
175 template<class TrackData>
176 void Foam::KinematicCloud<CloudType>::evolveCloud(TrackData& td)
178 if (solution_.coupled())
180 td.cloud().resetSourceTerms();
183 if (solution_.transient())
185 label preInjectionSize = this->size();
187 this->surfaceFilm().inject(td);
189 // Update the cellOccupancy if the size of the cloud has changed
190 // during the injection.
191 if (preInjectionSize != this->size())
193 updateCellOccupancy();
195 preInjectionSize = this->size();
197 this->injection().inject(td);
200 // Assume that motion will update the cellOccupancy as necessary
201 // before it is required.
202 td.cloud().motion(td);
206 // this->surfaceFilm().injectSteadyState(td);
208 this->injection().injectSteadyState(td, solution_.trackTime());
210 td.part() = TrackData::tpLinearTrack;
211 CloudType::move(td, solution_.trackTime());
216 template<class CloudType>
217 void Foam::KinematicCloud<CloudType>::postEvolve()
223 this->writePositions();
226 this->dispersion().cacheFields(false);
228 forces_.cacheFields(false);
229 functions_.postEvolve();
231 solution_.nextIter();
235 template<class CloudType>
236 void Foam::KinematicCloud<CloudType>::cloudReset(KinematicCloud<CloudType>& c)
238 CloudType::cloudReset(c);
242 forces_.transfer(c.forces_);
244 functions_.transfer(c.functions_);
246 dispersionModel_.reset(c.dispersionModel_.ptr());
247 injectionModel_.reset(c.injectionModel_.ptr());
248 patchInteractionModel_.reset(c.patchInteractionModel_.ptr());
249 surfaceFilmModel_.reset(c.surfaceFilmModel_.ptr());
251 UIntegrator_.reset(c.UIntegrator_.ptr());
255 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
257 template<class CloudType>
258 Foam::KinematicCloud<CloudType>::KinematicCloud
260 const word& cloudName,
261 const volScalarField& rho,
262 const volVectorField& U,
263 const volScalarField& mu,
264 const dimensionedVector& g,
268 CloudType(rho.mesh(), cloudName, false),
276 cloudName + "Properties",
277 rho.mesh().time().constant(),
279 IOobject::MUST_READ_IF_MODIFIED,
283 solution_(mesh_, particleProperties_.subDict("solution")),
284 constProps_(particleProperties_, solution_.active()),
287 particleProperties_.subOrEmptyDict("subModels", solution_.active())
292 solution_.steadyState() ?
293 particleProperties_.lookupOrDefault<label>("randomSampleSize", 100000)
306 subModelProperties_.subOrEmptyDict
316 particleProperties_.subOrEmptyDict("cloudFunctions"),
319 dispersionModel_(NULL),
320 injectionModel_(NULL),
321 patchInteractionModel_(NULL),
322 surfaceFilmModel_(NULL),
326 new DimensionedField<vector, volMesh>
330 this->name() + "UTrans",
331 this->db().time().timeName(),
333 IOobject::READ_IF_PRESENT,
337 dimensionedVector("zero", dimMass*dimVelocity, vector::zero)
342 new DimensionedField<scalar, volMesh>
346 this->name() + "UCoeff",
347 this->db().time().timeName(),
349 IOobject::READ_IF_PRESENT,
353 dimensionedScalar("zero", dimMass, 0.0)
357 if (solution_.active())
363 parcelType::readFields(*this);
367 if (solution_.resetSourcesOnStartup())
374 template<class CloudType>
375 Foam::KinematicCloud<CloudType>::KinematicCloud
377 KinematicCloud<CloudType>& c,
381 CloudType(c.mesh_, name, c),
385 particleProperties_(c.particleProperties_),
386 solution_(c.solution_),
387 constProps_(c.constProps_),
388 subModelProperties_(c.subModelProperties_),
389 rndGen_(c.rndGen_, true),
390 cellOccupancyPtr_(NULL),
395 pAmbient_(c.pAmbient_),
397 functions_(c.functions_),
398 dispersionModel_(c.dispersionModel_->clone()),
399 injectionModel_(c.injectionModel_->clone()),
400 patchInteractionModel_(c.patchInteractionModel_->clone()),
401 surfaceFilmModel_(c.surfaceFilmModel_->clone()),
402 UIntegrator_(c.UIntegrator_->clone()),
405 new DimensionedField<vector, volMesh>
409 this->name() + "UTrans",
410 this->db().time().timeName(),
421 new DimensionedField<scalar, volMesh>
426 this->db().time().timeName(),
438 template<class CloudType>
439 Foam::KinematicCloud<CloudType>::KinematicCloud
443 const KinematicCloud<CloudType>& c
446 CloudType(mesh, name, IDLList<parcelType>()),
455 mesh.time().constant(),
464 subModelProperties_(dictionary::null),
466 cellOccupancyPtr_(NULL),
471 pAmbient_(c.pAmbient_),
472 forces_(*this, mesh),
474 dispersionModel_(NULL),
475 injectionModel_(NULL),
476 patchInteractionModel_(NULL),
477 surfaceFilmModel_(NULL),
484 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
486 template<class CloudType>
487 Foam::KinematicCloud<CloudType>::~KinematicCloud()
491 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
493 template<class CloudType>
494 bool Foam::KinematicCloud<CloudType>::hasWallImpactDistance() const
500 template<class CloudType>
501 void Foam::KinematicCloud<CloudType>::setParcelThermoProperties
504 const scalar lagrangianDt
507 parcel.rho() = constProps_.rho0();
511 template<class CloudType>
512 void Foam::KinematicCloud<CloudType>::checkParcelProperties
515 const scalar lagrangianDt,
516 const bool fullyDescribed
519 const scalar carrierDt = mesh_.time().deltaTValue();
520 parcel.stepFraction() = (carrierDt - lagrangianDt)/carrierDt;
521 parcel.typeId() = constProps_.parcelTypeId();
525 template<class CloudType>
526 void Foam::KinematicCloud<CloudType>::storeState()
530 static_cast<KinematicCloud<CloudType>*>
532 clone(this->name() + "Copy").ptr()
538 template<class CloudType>
539 void Foam::KinematicCloud<CloudType>::restoreState()
541 cloudReset(cloudCopyPtr_());
542 cloudCopyPtr_.clear();
546 template<class CloudType>
547 void Foam::KinematicCloud<CloudType>::resetSourceTerms()
549 UTrans().field() = vector::zero;
550 UCoeff().field() = 0.0;
554 template<class CloudType>
556 void Foam::KinematicCloud<CloudType>::relax
558 DimensionedField<Type, volMesh>& field,
559 const DimensionedField<Type, volMesh>& field0,
563 const scalar coeff = solution_.relaxCoeff(name);
564 field = field0 + coeff*(field - field0);
568 template<class CloudType>
570 void Foam::KinematicCloud<CloudType>::scale
572 DimensionedField<Type, volMesh>& field,
576 const scalar coeff = solution_.relaxCoeff(name);
581 template<class CloudType>
582 void Foam::KinematicCloud<CloudType>::relaxSources
584 const KinematicCloud<CloudType>& cloudOldTime
587 this->relax(UTrans_(), cloudOldTime.UTrans(), "U");
588 this->relax(UCoeff_(), cloudOldTime.UCoeff(), "U");
592 template<class CloudType>
593 void Foam::KinematicCloud<CloudType>::scaleSources()
595 this->scale(UTrans_(), "U");
596 this->scale(UCoeff_(), "U");
600 template<class CloudType>
601 void Foam::KinematicCloud<CloudType>::preEvolve()
603 Info<< "\nSolving cloud " << this->name() << endl;
605 this->dispersion().cacheFields(true);
606 forces_.cacheFields(true);
607 updateCellOccupancy();
609 pAmbient_ = constProps_.dict().template
610 lookupOrDefault<scalar>("pAmbient", pAmbient_);
612 functions_.preEvolve();
616 template<class CloudType>
617 void Foam::KinematicCloud<CloudType>::evolve()
619 if (solution_.canEvolve())
621 typename parcelType::template
622 TrackingData<KinematicCloud<CloudType> > td(*this);
629 template<class CloudType>
630 template<class TrackData>
631 void Foam::KinematicCloud<CloudType>::motion(TrackData& td)
633 td.part() = TrackData::tpLinearTrack;
634 CloudType::move(td, solution_.trackTime());
636 updateCellOccupancy();
640 template<class CloudType>
641 void Foam::KinematicCloud<CloudType>::info() const
643 vector linearMomentum = linearMomentumOfSystem();
644 reduce(linearMomentum, sumOp<vector>());
646 scalar linearKineticEnergy = linearKineticEnergyOfSystem();
647 reduce(linearKineticEnergy, sumOp<scalar>());
649 scalar rotationalKineticEnergy = rotationalKineticEnergyOfSystem();
650 reduce(rotationalKineticEnergy, sumOp<scalar>());
652 Info<< "Cloud: " << this->name() << nl
653 << " Current number of parcels = "
654 << returnReduce(this->size(), sumOp<label>()) << nl
655 << " Current mass in system = "
656 << returnReduce(massInSystem(), sumOp<scalar>()) << nl
657 << " Linear momentum = "
658 << linearMomentum << nl
659 << " |Linear momentum| = "
660 << mag(linearMomentum) << nl
661 << " Linear kinetic energy = "
662 << linearKineticEnergy << nl
663 << " Rotational kinetic energy = "
664 << rotationalKineticEnergy << nl;
666 this->injection().info(Info);
667 this->surfaceFilm().info(Info);
668 this->patchInteraction().info(Info);
672 // ************************************************************************* //