BUG: UListIO: byteSize overflowing on really big faceLists
[OpenFOAM-2.0.x.git] / src / lagrangian / intermediate / submodels / Kinematic / CollisionModel / PairCollision / PairCollision.C
blob435d9525aee5f6e0c6252cc75f4ee71e98d95172
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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 "PairCollision.H"
27 #include "PairModel.H"
28 #include "WallModel.H"
30 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 template<class CloudType>
33 Foam::scalar Foam::PairCollision<CloudType>::cosPhiMinFlatWall = 1 - SMALL;
35 template<class CloudType>
36 Foam::scalar Foam::PairCollision<CloudType>::flatWallDuplicateExclusion =
37     sqrt(3*SMALL);
40 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
42 template<class CloudType>
43 void Foam::PairCollision<CloudType>::preInteraction()
45     // Set accumulated quantities to zero
46     forAllIter(typename CloudType, this->owner(), iter)
47     {
48         typename CloudType::parcelType& p = iter();
50         p.f() = vector::zero;
52         p.torque() = vector::zero;
53     }
57 template<class CloudType>
58 void Foam::PairCollision<CloudType>::parcelInteraction()
60     PstreamBuffers pBufs(Pstream::nonBlocking);
62     il_.sendReferredData(this->owner().cellOccupancy(), pBufs);
64     realRealInteraction();
66     il_.receiveReferredData(pBufs);
68     realReferredInteraction();
72 template<class CloudType>
73 void Foam::PairCollision<CloudType>::realRealInteraction()
75     // Direct interaction list (dil)
76     const labelListList& dil = il_.dil();
78     typename CloudType::parcelType* pA_ptr = NULL;
79     typename CloudType::parcelType* pB_ptr = NULL;
81     List<DynamicList<typename CloudType::parcelType*> >& cellOccupancy =
82         this->owner().cellOccupancy();
84     forAll(dil, realCellI)
85     {
86         // Loop over all Parcels in cell A (a)
87         forAll(cellOccupancy[realCellI], a)
88         {
89             pA_ptr = cellOccupancy[realCellI][a];
91             forAll(dil[realCellI], interactingCells)
92             {
93                 List<typename CloudType::parcelType*> cellBParcels =
94                     cellOccupancy[dil[realCellI][interactingCells]];
96                 // Loop over all Parcels in cell B (b)
97                 forAll(cellBParcels, b)
98                 {
99                     pB_ptr = cellBParcels[b];
101                     evaluatePair(*pA_ptr, *pB_ptr);
102                 }
103             }
105             // Loop over the other Parcels in cell A (aO)
106             forAll(cellOccupancy[realCellI], aO)
107             {
108                 pB_ptr = cellOccupancy[realCellI][aO];
110                 // Do not double-evaluate, compare pointers, arbitrary
111                 // order
112                 if (pB_ptr > pA_ptr)
113                 {
114                     evaluatePair(*pA_ptr, *pB_ptr);
115                 }
116             }
117         }
118     }
122 template<class CloudType>
123 void Foam::PairCollision<CloudType>::realReferredInteraction()
125     // Referred interaction list (ril)
126     const labelListList& ril = il_.ril();
128     List<IDLList<typename CloudType::parcelType> >& referredParticles =
129     il_.referredParticles();
131     List<DynamicList<typename CloudType::parcelType*> >& cellOccupancy =
132         this->owner().cellOccupancy();
134     // Loop over all referred cells
135     forAll(ril, refCellI)
136     {
137         IDLList<typename CloudType::parcelType>& refCellRefParticles =
138             referredParticles[refCellI];
140         const labelList& realCells = ril[refCellI];
142         // Loop over all referred parcels in the referred cell
144         forAllIter
145         (
146             typename IDLList<typename CloudType::parcelType>,
147             refCellRefParticles,
148             referredParcel
149         )
150         {
151             // Loop over all real cells in that the referred cell is
152             // to supply interactions to
154             forAll(realCells, realCellI)
155             {
156                 List<typename CloudType::parcelType*> realCellParcels =
157                     cellOccupancy[realCells[realCellI]];
159                 forAll(realCellParcels, realParcelI)
160                 {
161                     evaluatePair
162                     (
163                         *realCellParcels[realParcelI],
164                         referredParcel()
165                     );
166                 }
167             }
168         }
169     }
173 template<class CloudType>
174 void Foam::PairCollision<CloudType>::wallInteraction()
176     const polyMesh& mesh = this->owner().mesh();
178     const labelListList& dil = il_.dil();
180     const labelListList directWallFaces = il_.dwfil();
182     const labelList& patchID = mesh.boundaryMesh().patchID();
184     const volVectorField& U = mesh.lookupObject<volVectorField>(il_.UName());
186     List<DynamicList<typename CloudType::parcelType*> >& cellOccupancy =
187         this->owner().cellOccupancy();
189     // Storage for the wall interaction sites
190     DynamicList<point> flatSitePoints;
191     DynamicList<scalar> flatSiteExclusionDistancesSqr;
192     DynamicList<WallSiteData<vector> > flatSiteData;
193     DynamicList<point> otherSitePoints;
194     DynamicList<scalar> otherSiteDistances;
195     DynamicList<WallSiteData<vector> > otherSiteData;
196     DynamicList<point> sharpSitePoints;
197     DynamicList<scalar> sharpSiteExclusionDistancesSqr;
198     DynamicList<WallSiteData<vector> > sharpSiteData;
200     forAll(dil, realCellI)
201     {
202         // The real wall faces in range of this real cell
203         const labelList& realWallFaces = directWallFaces[realCellI];
205         // Loop over all Parcels in cell
206         forAll(cellOccupancy[realCellI], cellParticleI)
207         {
208             flatSitePoints.clear();
209             flatSiteExclusionDistancesSqr.clear();
210             flatSiteData.clear();
211             otherSitePoints.clear();
212             otherSiteDistances.clear();
213             otherSiteData.clear();
214             sharpSitePoints.clear();
215             sharpSiteExclusionDistancesSqr.clear();
216             sharpSiteData.clear();
218             typename CloudType::parcelType& p =
219                 *cellOccupancy[realCellI][cellParticleI];
221             const point& pos = p.position();
223             scalar r = wallModel_->pREff(p);
225             // real wallFace interactions
227             forAll(realWallFaces, realWallFaceI)
228             {
229                 label realFaceI = realWallFaces[realWallFaceI];
231                 pointHit nearest = mesh.faces()[realFaceI].nearestPoint
232                 (
233                     pos,
234                     mesh.points()
235                 );
237                 if (nearest.distance() < r)
238                 {
239                     vector normal = mesh.faceAreas()[realFaceI];
241                     normal /= mag(normal);
243                     const vector& nearPt = nearest.rawPoint();
245                     vector pW = nearPt - pos;
247                     scalar normalAlignment = normal & pW/mag(pW);
249                     // Find the patchIndex and wallData for WallSiteData object
250                     label patchI = patchID[realFaceI - mesh.nInternalFaces()];
252                     label patchFaceI =
253                         realFaceI - mesh.boundaryMesh()[patchI].start();
255                     WallSiteData<vector> wSD
256                     (
257                         patchI,
258                         U.boundaryField()[patchI][patchFaceI]
259                     );
261                     bool particleHit = false;
262                     if (normalAlignment > cosPhiMinFlatWall)
263                     {
264                         // Guard against a flat interaction being
265                         // present on the boundary of two or more
266                         // faces, which would create duplicate contact
267                         // points. Duplicates are discarded.
268                         if
269                         (
270                             !duplicatePointInList
271                             (
272                                 flatSitePoints,
273                                 nearPt,
274                                 sqr(r*flatWallDuplicateExclusion)
275                             )
276                         )
277                         {
278                             flatSitePoints.append(nearPt);
280                             flatSiteExclusionDistancesSqr.append
281                             (
282                                 sqr(r) - sqr(nearest.distance())
283                             );
285                             flatSiteData.append(wSD);
287                             particleHit = true;
288                         }
289                     }
290                     else
291                     {
292                         otherSitePoints.append(nearPt);
294                         otherSiteDistances.append(nearest.distance());
296                         otherSiteData.append(wSD);
298                         particleHit = true;
299                     }
301                     if (particleHit)
302                     {
303                         this->owner().functions().postFace(p, realFaceI);
304                         this->owner().functions().postPatch
305                         (
306                             p,
307                             patchI,
308                             patchFaceI
309                         );
310                     }
311                 }
312             }
314             // referred wallFace interactions
316             // The labels of referred wall faces in range of this real cell
317             const labelList& cellRefWallFaces = il_.rwfilInverse()[realCellI];
319             
321             forAll(cellRefWallFaces, rWFI)
322             {
323                 label refWallFaceI = cellRefWallFaces[rWFI];
325                 const referredWallFace& rwf =
326                     il_.referredWallFaces()[refWallFaceI];
328                 const pointField& pts = rwf.points();
330                 pointHit nearest = rwf.nearestPoint(pos, pts);
332                 if (nearest.distance() < r)
333                 {
334                     vector normal = rwf.normal(pts);
336                     normal /= mag(normal);
338                     const vector& nearPt = nearest.rawPoint();
340                     vector pW = nearPt - pos;
342                     scalar normalAlignment = normal & pW/mag(pW);
344                     // Find the patchIndex and wallData for WallSiteData object
346                     WallSiteData<vector> wSD
347                     (
348                         rwf.patchIndex(),
349                         il_.referredWallData()[refWallFaceI]
350                     );
352                     bool particleHit = false;
353                     if (normalAlignment > cosPhiMinFlatWall)
354                     {
355                         // Guard against a flat interaction being
356                         // present on the boundary of two or more
357                         // faces, which would create duplicate contact
358                         // points. Duplicates are discarded.
359                         if
360                         (
361                             !duplicatePointInList
362                             (
363                                 flatSitePoints,
364                                 nearPt,
365                                 sqr(r*flatWallDuplicateExclusion)
366                             )
367                         )
368                         {
369                             flatSitePoints.append(nearPt);
371                             flatSiteExclusionDistancesSqr.append
372                             (
373                                 sqr(r) - sqr(nearest.distance())
374                             );
376                             flatSiteData.append(wSD);
378                             particleHit = true;
379                         }
380                     }
381                     else
382                     {
383                         otherSitePoints.append(nearPt);
385                         otherSiteDistances.append(nearest.distance());
387                         otherSiteData.append(wSD);
389                         particleHit = true;
390                     }
392                     if (particleHit)
393                     {
394                         // TODO: call cloud function objects for referred
395                         //       wall particle interactions
396                     }
397                 }
398             }
400             // All flat interaction sites found, now classify the
401             // other sites as being in range of a flat interaction, or
402             // a sharp interaction, being aware of not duplicating the
403             // sharp interaction sites.
405             // The "other" sites need to evaluated in order of
406             // ascending distance to their nearest point so that
407             // grouping occurs around the closest in any group
409             labelList sortedOtherSiteIndices;
411             sortedOrder(otherSiteDistances, sortedOtherSiteIndices);
413             forAll(sortedOtherSiteIndices, siteI)
414             {
415                 label orderedIndex = sortedOtherSiteIndices[siteI];
417                 const point& otherPt = otherSitePoints[orderedIndex];
419                 if
420                 (
421                     !duplicatePointInList
422                     (
423                         flatSitePoints,
424                         otherPt,
425                         flatSiteExclusionDistancesSqr
426                     )
427                 )
428                 {
429                     // Not in range of a flat interaction, must be a
430                     // sharp interaction.
432                     if
433                     (
434                         !duplicatePointInList
435                         (
436                             sharpSitePoints,
437                             otherPt,
438                             sharpSiteExclusionDistancesSqr
439                         )
440                     )
441                     {
442                         sharpSitePoints.append(otherPt);
444                         sharpSiteExclusionDistancesSqr.append
445                         (
446                             sqr(r) - sqr(otherSiteDistances[orderedIndex])
447                         );
449                         sharpSiteData.append(otherSiteData[orderedIndex]);
450                     }
451                 }
452             }
454             evaluateWall
455             (
456                 p,
457                 flatSitePoints,
458                 flatSiteData,
459                 sharpSitePoints,
460                 sharpSiteData
461             );
462         }
463     }
467 template<class CloudType>
468 bool Foam::PairCollision<CloudType>::duplicatePointInList
470     const DynamicList<point>& existingPoints,
471     const point& pointToTest,
472     scalar duplicateRangeSqr
473 ) const
475     forAll(existingPoints, i)
476     {
477         if (magSqr(existingPoints[i] - pointToTest) < duplicateRangeSqr)
478         {
479             return true;
480         }
481     }
483     return false;
487 template<class CloudType>
488 bool Foam::PairCollision<CloudType>::duplicatePointInList
490     const DynamicList<point>& existingPoints,
491     const point& pointToTest,
492     const scalarList& duplicateRangeSqr
493 ) const
495     forAll(existingPoints, i)
496     {
497         if (magSqr(existingPoints[i] - pointToTest) < duplicateRangeSqr[i])
498         {
499             return true;
500         }
501     }
503     return false;
507 template<class CloudType>
508 void Foam::PairCollision<CloudType>::postInteraction()
510     // Delete any collision records where no collision occurred this step
512     forAllIter(typename CloudType, this->owner(), iter)
513     {
514         typename CloudType::parcelType& p = iter();
516         p.collisionRecords().update();
517     }
521 template<class CloudType>
522 void Foam::PairCollision<CloudType>::evaluatePair
524     typename CloudType::parcelType& pA,
525     typename CloudType::parcelType& pB
526 ) const
528     pairModel_->evaluatePair(pA, pB);
532 template<class CloudType>
533 void Foam::PairCollision<CloudType>::evaluateWall
535     typename CloudType::parcelType& p,
536     const List<point>& flatSitePoints,
537     const List<WallSiteData<vector> >& flatSiteData,
538     const List<point>& sharpSitePoints,
539     const List<WallSiteData<vector> >& sharpSiteData
540 ) const
542     wallModel_->evaluateWall
543     (
544         p,
545         flatSitePoints,
546         flatSiteData,
547         sharpSitePoints,
548         sharpSiteData
549     );
553 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
555 template<class CloudType>
556 Foam::PairCollision<CloudType>::PairCollision
558     const dictionary& dict,
559     CloudType& owner
562     CollisionModel<CloudType>(dict, owner, typeName),
563     pairModel_
564     (
565         PairModel<CloudType>::New
566         (
567             this->coeffDict(),
568             this->owner()
569         )
570     ),
571     wallModel_
572     (
573         WallModel<CloudType>::New
574         (
575             this->coeffDict(),
576             this->owner()
577         )
578     ),
579     il_
580     (
581         owner.mesh(),
582         readScalar(this->coeffDict().lookup("maxInteractionDistance")),
583         Switch
584         (
585             this->coeffDict().lookupOrDefault
586             (
587                 "writeReferredParticleCloud",
588                 false
589             )
590         ),
591         this->coeffDict().lookupOrDefault("UName", word("U"))
592     )
596 template<class CloudType>
597 Foam::PairCollision<CloudType>::PairCollision(PairCollision<CloudType>& cm)
599     CollisionModel<CloudType>(cm),
600     pairModel_(NULL),
601     wallModel_(NULL),
602     il_(cm.owner().mesh())
604     notImplemented
605     (
606         "Foam::PairCollision<CloudType>::PairCollision"
607         "("
608             "PairCollision<CloudType>& cm"
609         ")"
610     );
614 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
616 template<class CloudType>
617 Foam::PairCollision<CloudType>::~PairCollision()
621 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
623 template<class CloudType>
624 Foam::label Foam::PairCollision<CloudType>::nSubCycles() const
626     label nSubCycles = 1;
628     if (pairModel_->controlsTimestep())
629     {
630         label nPairSubCycles = returnReduce
631         (
632             pairModel_->nSubCycles(), maxOp<label>()
633         );
635         nSubCycles = max(nSubCycles, nPairSubCycles);
636     }
638     if (wallModel_->controlsTimestep())
639     {
640         label nWallSubCycles = returnReduce
641         (
642             wallModel_->nSubCycles(), maxOp<label>()
643         );
645         nSubCycles = max(nSubCycles, nWallSubCycles);
646     }
648     return nSubCycles;
652 template<class CloudType>
653 bool Foam::PairCollision<CloudType>::controlsWallInteraction() const
655     return true;
659 template<class CloudType>
660 void Foam::PairCollision<CloudType>::collide()
662     preInteraction();
664     parcelInteraction();
666     wallInteraction();
668     postInteraction();
672 // ************************************************************************* //