InteractionLists.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "InteractionLists.H"
28 #include "indexedOctree.H"
29 #include "treeDataFace.H"
30 #include "treeDataCell.H"
31 #include "volFields.H"
32 #include "meshTools.H"
33 
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35 
36 template<class ParticleType>
38 {
39  Info<< "Building InteractionLists with interaction distance "
40  << maxDistance_ << endl;
41 
42  Random rndGen(419715);
43 
44  const vector interactionVec = maxDistance_*vector::one;
45 
46  treeBoundBox procBb(treeBoundBox(mesh_.points()));
47 
48  treeBoundBox extendedProcBb
49  (
50  procBb.min() - interactionVec,
51  procBb.max() + interactionVec
52  );
53 
54  treeBoundBoxList allExtendedProcBbs(Pstream::nProcs());
55 
56  allExtendedProcBbs[Pstream::myProcNo()] = extendedProcBb;
57 
58  Pstream::gatherList(allExtendedProcBbs);
59 
60  Pstream::scatterList(allExtendedProcBbs);
61 
62  List<treeBoundBox> extendedProcBbsInRange;
63  List<label> extendedProcBbsTransformIndex;
64  List<label> extendedProcBbsOrigProc;
65 
66  findExtendedProcBbsInRange
67  (
68  procBb,
69  allExtendedProcBbs,
70  mesh_.globalData().globalTransforms(),
71  extendedProcBbsInRange,
72  extendedProcBbsTransformIndex,
73  extendedProcBbsOrigProc
74  );
75 
76  treeBoundBoxList cellBbs(mesh_.nCells());
77 
78  forAll(cellBbs, cellI)
79  {
80  cellBbs[cellI] = treeBoundBox
81  (
82  mesh_.cells()[cellI].points
83  (
84  mesh_.faces(),
85  mesh_.points()
86  )
87  );
88  }
89 
90  const globalIndexAndTransform& globalTransforms =
91  mesh_.globalData().globalTransforms();
92 
93  // Recording which cells are in range of an extended boundBox, as
94  // only these cells will need to be tested to determine which
95  // referred cells that they interact with.
96  PackedBoolList cellInRangeOfCoupledPatch(mesh_.nCells(), false);
97 
98  // IAndT: index (=local cell index) and transform (from
99  // globalIndexAndTransform)
100  DynamicList<labelPair> cellIAndTToExchange;
101 
102  DynamicList<treeBoundBox> cellBbsToExchange;
103 
104  DynamicList<label> procToDistributeCellTo;
105 
106  forAll(extendedProcBbsInRange, ePBIRI)
107  {
108  const treeBoundBox& otherExtendedProcBb =
109  extendedProcBbsInRange[ePBIRI];
110 
111  label transformIndex = extendedProcBbsTransformIndex[ePBIRI];
112 
113  label origProc = extendedProcBbsOrigProc[ePBIRI];
114 
115  forAll(cellBbs, cellI)
116  {
117  const treeBoundBox& cellBb = cellBbs[cellI];
118 
119  if (cellBb.overlaps(otherExtendedProcBb))
120  {
121  // This cell is in range of the Bb of the other
122  // processor Bb, and so needs to be referred to it
123 
124  cellInRangeOfCoupledPatch[cellI] = true;
125 
126  cellIAndTToExchange.append
127  (
128  globalTransforms.encode(cellI, transformIndex)
129  );
130 
131  cellBbsToExchange.append(cellBb);
132 
133  procToDistributeCellTo.append(origProc);
134  }
135  }
136  }
137 
138  buildMap(cellMapPtr_, procToDistributeCellTo);
139 
140  // Needed for reverseDistribute
141  label preDistributionCellMapSize = procToDistributeCellTo.size();
142 
143  cellMap().distribute(cellBbsToExchange);
144 
145  cellMap().distribute(cellIAndTToExchange);
146 
147  // Determine labelList specifying only cells that are in range of
148  // a coupled boundary to build an octree limited to these cells.
149  DynamicList<label> coupledPatchRangeCells;
150 
151  forAll(cellInRangeOfCoupledPatch, cellI)
152  {
153  if (cellInRangeOfCoupledPatch[cellI])
154  {
155  coupledPatchRangeCells.append(cellI);
156  }
157  }
158 
159  treeBoundBox procBbRndExt
160  (
161  treeBoundBox(mesh_.points()).extend(rndGen, 1e-4)
162  );
163 
164  indexedOctree<treeDataCell> coupledPatchRangeTree
165  (
167  (
168  true, // Cache cell bb
169  mesh_,
170  coupledPatchRangeCells, // Subset of mesh
171  polyMesh::CELL_TETS // Consistent with tracking
172  ),
173  procBbRndExt,
174  8, // maxLevel,
175  10, // leafSize,
176  100.0 // duplicity
177  );
178 
179  ril_.setSize(cellBbsToExchange.size());
180 
181  // This needs to be a boolList, not PackedBoolList if
182  // reverseDistribute is called.
183  boolList cellBbRequiredByAnyCell(cellBbsToExchange.size(), false);
184 
185  Info<< " Building referred interaction lists" << endl;
186 
187  forAll(cellBbsToExchange, bbI)
188  {
189  const labelPair& ciat = cellIAndTToExchange[bbI];
190 
191  const vectorTensorTransform& transform = globalTransforms.transform
192  (
193  globalTransforms.transformIndex(ciat)
194  );
195 
196  treeBoundBox tempTransformedBb
197  (
198  transform.invTransformPosition(cellBbsToExchange[bbI].points())
199  );
200 
201  treeBoundBox extendedBb
202  (
203  tempTransformedBb.min() - interactionVec,
204  tempTransformedBb.max() + interactionVec
205  );
206 
207  // Find all elements intersecting box.
208  labelList interactingElems
209  (
210  coupledPatchRangeTree.findBox(extendedBb)
211  );
212 
213  if (!interactingElems.empty())
214  {
215  cellBbRequiredByAnyCell[bbI] = true;
216  }
217 
218  ril_[bbI].setSize(interactingElems.size(), -1);
219 
220  forAll(interactingElems, i)
221  {
222  label elemI = interactingElems[i];
223 
224  // Here, a more detailed geometric test could be applied,
225  // i.e. a more accurate bounding volume like a OBB or
226  // convex hull or an exact geometrical test.
227 
228  label c = coupledPatchRangeTree.shapes().cellLabels()[elemI];
229 
230  ril_[bbI][i] = c;
231  }
232  }
233 
234  // Perform subset of ril_, to remove any referred cells that do
235  // not interact. They will not be sent from originating
236  // processors. This assumes that the disappearance of the cell
237  // from the sending list of the source processor, simply removes
238  // the referred cell from the ril_, all of the subsequent indices
239  // shuffle down one, but the order and structure is preserved,
240  // i.e. it, is as if the cell had never been referred in the first
241  // place.
242 
243  inplaceSubset(cellBbRequiredByAnyCell, ril_);
244 
245  // Send information about which cells are actually required back
246  // to originating processors.
247 
248  // At this point, cellBbsToExchange does not need to be maintained
249  // or distributed as it is not longer needed.
250 
251  cellBbsToExchange.setSize(0);
252 
253  cellMap().reverseDistribute
254  (
255  preDistributionCellMapSize,
256  cellBbRequiredByAnyCell
257  );
258 
259  cellMap().reverseDistribute
260  (
261  preDistributionCellMapSize,
262  cellIAndTToExchange
263  );
264 
265  // Perform ordering of cells to send, this invalidates the
266  // previous value of preDistributionCellMapSize.
267 
268  preDistributionCellMapSize = -1;
269 
270  // Move all of the used cells to refer to the start of the list
271  // and truncate it
272 
273  inplaceSubset(cellBbRequiredByAnyCell, cellIAndTToExchange);
274 
275  inplaceSubset(cellBbRequiredByAnyCell, procToDistributeCellTo);
276 
277  preDistributionCellMapSize = procToDistributeCellTo.size();
278 
279  // Rebuild mapDistribute with only required referred cells
280  buildMap(cellMapPtr_, procToDistributeCellTo);
281 
282  // Store cellIndexAndTransformToDistribute
283  cellIndexAndTransformToDistribute_.transfer(cellIAndTToExchange);
284 
285  // Determine inverse addressing for referred cells
286 
287  rilInverse_.setSize(mesh_.nCells());
288 
289  // Temporary Dynamic lists for accumulation
290  List<DynamicList<label> > rilInverseTemp(rilInverse_.size());
291 
292  // Loop over all referred cells
293  forAll(ril_, refCellI)
294  {
295  const labelList& realCells = ril_[refCellI];
296 
297  // Loop over all real cells in that the referred cell is to
298  // supply interactions to and record the index of this
299  // referred cell in the real cells entry in rilInverse
300 
301  forAll(realCells, realCellI)
302  {
303  rilInverseTemp[realCells[realCellI]].append(refCellI);
304  }
305  }
306 
307  forAll(rilInverse_, cellI)
308  {
309  rilInverse_[cellI].transfer(rilInverseTemp[cellI]);
310  }
311 
312  // Determine which wall faces to refer
313 
314  // The referring of wall patch data relies on patches having the same
315  // index on each processor.
316  mesh_.boundaryMesh().checkParallelSync(true);
317 
318  // Determine the index of all of the wall faces on this processor
319  DynamicList<label> localWallFaces;
320 
321  forAll(mesh_.boundaryMesh(), patchI)
322  {
323  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
324 
325  if (isA<wallPolyPatch>(patch))
326  {
327  localWallFaces.append(identity(patch.size()) + patch.start());
328  }
329  }
330 
331  treeBoundBoxList wallFaceBbs(localWallFaces.size());
332 
333  forAll(wallFaceBbs, i)
334  {
335  wallFaceBbs[i] = treeBoundBox
336  (
337  mesh_.faces()[localWallFaces[i]].points(mesh_.points())
338  );
339  }
340 
341  // IAndT: index and transform
342  DynamicList<labelPair> wallFaceIAndTToExchange;
343 
344  DynamicList<treeBoundBox> wallFaceBbsToExchange;
345 
346  DynamicList<label> procToDistributeWallFaceTo;
347 
348  forAll(extendedProcBbsInRange, ePBIRI)
349  {
350  const treeBoundBox& otherExtendedProcBb =
351  extendedProcBbsInRange[ePBIRI];
352 
353  label transformIndex = extendedProcBbsTransformIndex[ePBIRI];
354 
355  label origProc = extendedProcBbsOrigProc[ePBIRI];
356 
357  forAll(wallFaceBbs, i)
358  {
359  const treeBoundBox& wallFaceBb = wallFaceBbs[i];
360 
361  if (wallFaceBb.overlaps(otherExtendedProcBb))
362  {
363  // This wall face is in range of the Bb of the other
364  // processor Bb, and so needs to be referred to it
365 
366  label wallFaceI = localWallFaces[i];
367 
368  wallFaceIAndTToExchange.append
369  (
370  globalTransforms.encode(wallFaceI, transformIndex)
371  );
372 
373  wallFaceBbsToExchange.append(wallFaceBb);
374 
375  procToDistributeWallFaceTo.append(origProc);
376  }
377  }
378  }
379 
380  buildMap(wallFaceMapPtr_, procToDistributeWallFaceTo);
381 
382  // Needed for reverseDistribute
383  label preDistributionWallFaceMapSize = procToDistributeWallFaceTo.size();
384 
385  wallFaceMap().distribute(wallFaceBbsToExchange);
386 
387  wallFaceMap().distribute(wallFaceIAndTToExchange);
388 
389  indexedOctree<treeDataCell> allCellsTree
390  (
391  treeDataCell(true, mesh_, polyMesh::CELL_TETS),
392  procBbRndExt,
393  8, // maxLevel,
394  10, // leafSize,
395  100.0 // duplicity
396  );
397 
398  rwfil_.setSize(wallFaceBbsToExchange.size());
399 
400  // This needs to be a boolList, not PackedBoolList if
401  // reverseDistribute is called.
402  boolList wallFaceBbRequiredByAnyCell(wallFaceBbsToExchange.size(), false);
403 
404  forAll(wallFaceBbsToExchange, bbI)
405  {
406  const labelPair& wfiat = wallFaceIAndTToExchange[bbI];
407 
408  const vectorTensorTransform& transform = globalTransforms.transform
409  (
410  globalTransforms.transformIndex(wfiat)
411  );
412 
413  treeBoundBox tempTransformedBb
414  (
415  transform.invTransformPosition(wallFaceBbsToExchange[bbI].points())
416  );
417 
418  treeBoundBox extendedBb
419  (
420  tempTransformedBb.min() - interactionVec,
421  tempTransformedBb.max() + interactionVec
422  );
423 
424  // Find all elements intersecting box.
425  labelList interactingElems
426  (
427  coupledPatchRangeTree.findBox(extendedBb)
428  );
429 
430  if (!interactingElems.empty())
431  {
432  wallFaceBbRequiredByAnyCell[bbI] = true;
433  }
434 
435  rwfil_[bbI].setSize(interactingElems.size(), -1);
436 
437  forAll(interactingElems, i)
438  {
439  label elemI = interactingElems[i];
440 
441  // Here, a more detailed geometric test could be applied,
442  // i.e. a more accurate bounding volume like a OBB or
443  // convex hull or an exact geometrical test.
444 
445  label c = coupledPatchRangeTree.shapes().cellLabels()[elemI];
446 
447  rwfil_[bbI][i] = c;
448  }
449  }
450 
451  // Perform subset of rwfil_, to remove any referred wallFaces that do
452  // not interact. They will not be sent from originating
453  // processors. This assumes that the disappearance of the wallFace
454  // from the sending list of the source processor, simply removes
455  // the referred wallFace from the rwfil_, all of the subsequent indices
456  // shuffle down one, but the order and structure is preserved,
457  // i.e. it, is as if the wallFace had never been referred in the first
458  // place.
459 
460  inplaceSubset(wallFaceBbRequiredByAnyCell, rwfil_);
461 
462  // Send information about which wallFaces are actually required
463  // back to originating processors.
464 
465  // At this point, wallFaceBbsToExchange does not need to be
466  // maintained or distributed as it is not longer needed.
467 
468  wallFaceBbsToExchange.setSize(0);
469 
470  wallFaceMap().reverseDistribute
471  (
472  preDistributionWallFaceMapSize,
473  wallFaceBbRequiredByAnyCell
474  );
475 
476  wallFaceMap().reverseDistribute
477  (
478  preDistributionWallFaceMapSize,
479  wallFaceIAndTToExchange
480  );
481 
482  // Perform ordering of wallFaces to send, this invalidates the
483  // previous value of preDistributionWallFaceMapSize.
484 
485  preDistributionWallFaceMapSize = -1;
486 
487  // Move all of the used wallFaces to refer to the start of the
488  // list and truncate it
489 
490  inplaceSubset(wallFaceBbRequiredByAnyCell, wallFaceIAndTToExchange);
491 
492  inplaceSubset(wallFaceBbRequiredByAnyCell, procToDistributeWallFaceTo);
493 
494  preDistributionWallFaceMapSize = procToDistributeWallFaceTo.size();
495 
496  // Rebuild mapDistribute with only required referred wallFaces
497  buildMap(wallFaceMapPtr_, procToDistributeWallFaceTo);
498 
499  // Store wallFaceIndexAndTransformToDistribute
500  wallFaceIndexAndTransformToDistribute_.transfer(wallFaceIAndTToExchange);
501 
502  // Determine inverse addressing for referred wallFaces
503 
504  rwfilInverse_.setSize(mesh_.nCells());
505 
506  // Temporary Dynamic lists for accumulation
507  List<DynamicList<label> > rwfilInverseTemp(rwfilInverse_.size());
508 
509  // Loop over all referred wall faces
510  forAll(rwfil_, refWallFaceI)
511  {
512  const labelList& realCells = rwfil_[refWallFaceI];
513 
514  // Loop over all real cells in that the referred wall face is
515  // to supply interactions to and record the index of this
516  // referred wall face in the real cells entry in rwfilInverse
517 
518  forAll(realCells, realCellI)
519  {
520  rwfilInverseTemp[realCells[realCellI]].append(refWallFaceI);
521  }
522  }
523 
524  forAll(rwfilInverse_, cellI)
525  {
526  rwfilInverse_[cellI].transfer(rwfilInverseTemp[cellI]);
527  }
528 
529  // Refer wall faces to the appropriate processor
530  referredWallFaces_.setSize(wallFaceIndexAndTransformToDistribute_.size());
531 
532  forAll(referredWallFaces_, rWFI)
533  {
534  const labelPair& wfiat = wallFaceIndexAndTransformToDistribute_[rWFI];
535 
536  label wallFaceIndex = globalTransforms.index(wfiat);
537 
538  const vectorTensorTransform& transform = globalTransforms.transform
539  (
540  globalTransforms.transformIndex(wfiat)
541  );
542 
543  const face& f = mesh_.faces()[wallFaceIndex];
544 
545  label patchI = mesh_.boundaryMesh().patchID()
546  [
547  wallFaceIndex - mesh_.nInternalFaces()
548  ];
549 
550  referredWallFaces_[rWFI] = referredWallFace
551  (
552  face(identity(f.size())),
553  transform.invTransformPosition(f.points(mesh_.points())),
554  patchI
555  );
556  }
557 
558  wallFaceMap().distribute(referredWallFaces_);
559 
560  if (writeCloud_)
561  {
562  writeReferredWallFaces();
563  }
564 
565  // Direct interaction list and direct wall faces
566 
567  Info<< " Building direct interaction lists" << endl;
568 
569  indexedOctree<treeDataFace> wallFacesTree
570  (
571  treeDataFace(true, mesh_, localWallFaces),
572  procBbRndExt,
573  8, // maxLevel,
574  10, // leafSize,
575  100.0
576  );
577 
578  dil_.setSize(mesh_.nCells());
579 
580  dwfil_.setSize(mesh_.nCells());
581 
582  forAll(cellBbs, cellI)
583  {
584  const treeBoundBox& cellBb = cellBbs[cellI];
585 
586  treeBoundBox extendedBb
587  (
588  cellBb.min() - interactionVec,
589  cellBb.max() + interactionVec
590  );
591 
592  // Find all cells intersecting extendedBb
593  labelList interactingElems(allCellsTree.findBox(extendedBb));
594 
595  // Reserve space to avoid multiple resizing
596  DynamicList<label> cellDIL(interactingElems.size());
597 
598  forAll(interactingElems, i)
599  {
600  label elemI = interactingElems[i];
601 
602  label c = allCellsTree.shapes().cellLabels()[elemI];
603 
604  // Here, a more detailed geometric test could be applied,
605  // i.e. a more accurate bounding volume like a OBB or
606  // convex hull, or an exact geometrical test.
607 
608  // The higher index cell is added to the lower index
609  // cell's DIL. A cell is not added to its own DIL.
610  if (c > cellI)
611  {
612  cellDIL.append(c);
613  }
614  }
615 
616  dil_[cellI].transfer(cellDIL);
617 
618  // Find all wall faces intersecting extendedBb
619  interactingElems = wallFacesTree.findBox(extendedBb);
620 
621  dwfil_[cellI].setSize(interactingElems.size(), -1);
622 
623  forAll(interactingElems, i)
624  {
625  label elemI = interactingElems[i];
626 
627  label f = wallFacesTree.shapes().faceLabels()[elemI];
628 
629  dwfil_[cellI][i] = f;
630  }
631  }
632 }
633 
634 
635 template<class ParticleType>
637 (
638  const treeBoundBox& procBb,
639  const List<treeBoundBox>& allExtendedProcBbs,
640  const globalIndexAndTransform& globalTransforms,
641  List<treeBoundBox>& extendedProcBbsInRange,
642  List<label>& extendedProcBbsTransformIndex,
643  List<label>& extendedProcBbsOrigProc
644 )
645 {
646  extendedProcBbsInRange.setSize(0);
647  extendedProcBbsTransformIndex.setSize(0);
648  extendedProcBbsOrigProc.setSize(0);
649 
650  DynamicList<treeBoundBox> tmpExtendedProcBbsInRange;
651  DynamicList<label> tmpExtendedProcBbsTransformIndex;
652  DynamicList<label> tmpExtendedProcBbsOrigProc;
653 
654  label nTrans = globalTransforms.nIndependentTransforms();
655 
656  forAll(allExtendedProcBbs, procI)
657  {
658  List<label> permutationIndices(nTrans, 0);
659 
660  if (nTrans == 0 && procI != Pstream::myProcNo())
661  {
662  treeBoundBox extendedReferredProcBb = allExtendedProcBbs[procI];
663 
664  if (procBb.overlaps(extendedReferredProcBb))
665  {
666  tmpExtendedProcBbsInRange.append(extendedReferredProcBb);
667 
668  // Dummy index, there are no transforms, so there will
669  // be no resultant transform when this is decoded.
670  tmpExtendedProcBbsTransformIndex.append(0);
671 
672  tmpExtendedProcBbsOrigProc.append(procI);
673  }
674  }
675  else if (nTrans == 3)
676  {
677  label& i = permutationIndices[0];
678  label& j = permutationIndices[1];
679  label& k = permutationIndices[2];
680 
681  for (i = -1; i <= 1; i++)
682  {
683  for (j = -1; j <= 1; j++)
684  {
685  for (k = -1; k <= 1; k++)
686  {
687  if
688  (
689  i == 0
690  && j == 0
691  && k == 0
692  && procI == Pstream::myProcNo()
693  )
694  {
695  // Skip this processor's extended boundBox
696  // when it has no transformation
697  continue;
698  }
699 
700  label transI = globalTransforms.encodeTransformIndex
701  (
702  permutationIndices
703  );
704 
706  globalTransforms.transform(transI);
707 
708  treeBoundBox extendedReferredProcBb
709  (
710  transform.transformPosition
711  (
712  allExtendedProcBbs[procI].points()
713  )
714  );
715 
716  if (procBb.overlaps(extendedReferredProcBb))
717  {
718  tmpExtendedProcBbsInRange.append
719  (
720  extendedReferredProcBb
721  );
722 
723  tmpExtendedProcBbsTransformIndex.append(transI);
724 
725  tmpExtendedProcBbsOrigProc.append(procI);
726  }
727  }
728  }
729  }
730  }
731  else if (nTrans == 2)
732  {
733  label& i = permutationIndices[0];
734  label& j = permutationIndices[1];
735 
736  for (i = -1; i <= 1; i++)
737  {
738  for (j = -1; j <= 1; j++)
739  {
740  if (i == 0 && j == 0 && procI == Pstream::myProcNo())
741  {
742  // Skip this processor's extended boundBox
743  // when it has no transformation
744  continue;
745  }
746 
747  label transI = globalTransforms.encodeTransformIndex
748  (
749  permutationIndices
750  );
751 
753  globalTransforms.transform(transI);
754 
755  treeBoundBox extendedReferredProcBb
756  (
757  transform.transformPosition
758  (
759  allExtendedProcBbs[procI].points()
760  )
761  );
762 
763  if (procBb.overlaps(extendedReferredProcBb))
764  {
765  tmpExtendedProcBbsInRange.append
766  (
767  extendedReferredProcBb
768  );
769 
770  tmpExtendedProcBbsTransformIndex.append(transI);
771 
772  tmpExtendedProcBbsOrigProc.append(procI);
773  }
774  }
775  }
776  }
777  else if (nTrans == 1)
778  {
779  label& i = permutationIndices[0];
780 
781  for (i = -1; i <= 1; i++)
782  {
783  if (i == 0 && procI == Pstream::myProcNo())
784  {
785  // Skip this processor's extended boundBox when it
786  // has no transformation
787  continue;
788  }
789 
790  label transI = globalTransforms.encodeTransformIndex
791  (
792  permutationIndices
793  );
794 
796  globalTransforms.transform(transI);
797 
798  treeBoundBox extendedReferredProcBb
799  (
800  transform.transformPosition
801  (
802  allExtendedProcBbs[procI].points()
803  )
804  );
805 
806  if (procBb.overlaps(extendedReferredProcBb))
807  {
808  tmpExtendedProcBbsInRange.append
809  (
810  extendedReferredProcBb
811  );
812 
813  tmpExtendedProcBbsTransformIndex.append(transI);
814 
815  tmpExtendedProcBbsOrigProc.append(procI);
816  }
817  }
818  }
819  }
820 
821  extendedProcBbsInRange = tmpExtendedProcBbsInRange.xfer();
822  extendedProcBbsTransformIndex = tmpExtendedProcBbsTransformIndex.xfer();
823  extendedProcBbsOrigProc = tmpExtendedProcBbsOrigProc.xfer();
824 }
825 
826 
827 template<class ParticleType>
829 (
830  autoPtr<mapDistribute>& mapPtr,
831  const List<label>& toProc
832 )
833 {
834  // Determine send map
835  // ~~~~~~~~~~~~~~~~~~
836 
837  // 1. Count
838  labelList nSend(Pstream::nProcs(), 0);
839 
840  forAll(toProc, i)
841  {
842  label procI = toProc[i];
843 
844  nSend[procI]++;
845  }
846 
847  // Send over how many I need to receive
848  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
849 
850  labelListList sendSizes(Pstream::nProcs());
851 
852  sendSizes[Pstream::myProcNo()] = nSend;
853 
854  combineReduce(sendSizes, UPstream::listEq());
855 
856  // 2. Size sendMap
857  labelListList sendMap(Pstream::nProcs());
858 
859  forAll(nSend, procI)
860  {
861  sendMap[procI].setSize(nSend[procI]);
862 
863  nSend[procI] = 0;
864  }
865 
866  // 3. Fill sendMap
867  forAll(toProc, i)
868  {
869  label procI = toProc[i];
870 
871  sendMap[procI][nSend[procI]++] = i;
872  }
873 
874  // Determine receive map
875  // ~~~~~~~~~~~~~~~~~~~~~
876 
877  labelListList constructMap(Pstream::nProcs());
878 
879  // Local transfers first
880  constructMap[Pstream::myProcNo()] = identity
881  (
882  sendMap[Pstream::myProcNo()].size()
883  );
884 
885  label constructSize = constructMap[Pstream::myProcNo()].size();
886 
887  forAll(constructMap, procI)
888  {
889  if (procI != Pstream::myProcNo())
890  {
891  label nRecv = sendSizes[procI][Pstream::myProcNo()];
892 
893  constructMap[procI].setSize(nRecv);
894 
895  for (label i = 0; i < nRecv; i++)
896  {
897  constructMap[procI][i] = constructSize++;
898  }
899  }
900  }
901 
902  mapPtr.reset
903  (
904  new mapDistribute
905  (
906  constructSize,
907  sendMap.xfer(),
908  constructMap.xfer()
909  )
910  );
911 }
912 
913 
914 template<class ParticleType>
916 (
918 )
919 {
920  const globalIndexAndTransform& globalTransforms =
921  mesh_.globalData().globalTransforms();
922 
923  referredParticles_.setSize(cellIndexAndTransformToDistribute_.size());
924 
925  // Clear all existing referred particles
926 
927  forAll(referredParticles_, i)
928  {
929  referredParticles_[i].clear();
930  }
931 
932  // Clear all particles that may have been populated into the cloud
933  cloud_.clear();
934 
935  forAll(cellIndexAndTransformToDistribute_, i)
936  {
937  const labelPair ciat = cellIndexAndTransformToDistribute_[i];
938 
939  label cellIndex = globalTransforms.index(ciat);
940 
941  List<ParticleType*> realParticles = cellOccupancy[cellIndex];
942 
943  IDLList<ParticleType>& particlesToRefer = referredParticles_[i];
944 
945  forAll(realParticles, rM)
946  {
947  const ParticleType& particle = *realParticles[rM];
948 
949  particlesToRefer.append(particle.clone().ptr());
950 
951  prepareParticleToBeReferred(particlesToRefer.last(), ciat);
952  }
953  }
954 }
955 
956 
957 template<class ParticleType>
959 (
960  ParticleType* particle,
961  labelPair ciat
962 )
963 {
964  const globalIndexAndTransform& globalTransforms =
965  mesh_.globalData().globalTransforms();
966 
967  const vectorTensorTransform& transform = globalTransforms.transform
968  (
969  globalTransforms.transformIndex(ciat)
970  );
971 
972  particle->position() = transform.invTransformPosition(particle->position());
973 
975 
976  if (transform.hasR())
977  {
979  }
980 }
981 
982 
983 template<class ParticleType>
985 {
986  if (writeCloud_)
987  {
988  forAll(referredParticles_, refCellI)
989  {
990  const IDLList<ParticleType>& refCell =
991  referredParticles_[refCellI];
992 
993  forAllConstIter(typename IDLList<ParticleType>, refCell, iter)
994  {
995  cloud_.addParticle
996  (
997  static_cast<ParticleType*>(iter().clone().ptr())
998  );
999  }
1000  }
1001  }
1002 }
1003 
1004 
1005 template<class ParticleType>
1007 {
1008  const globalIndexAndTransform& globalTransforms =
1009  mesh_.globalData().globalTransforms();
1010 
1011  referredWallData_.setSize
1012  (
1013  wallFaceIndexAndTransformToDistribute_.size()
1014  );
1015 
1016  const volVectorField& U = mesh_.lookupObject<volVectorField>(UName_);
1017 
1018  forAll(referredWallData_, rWVI)
1019  {
1020  const labelPair& wfiat = wallFaceIndexAndTransformToDistribute_[rWVI];
1021 
1022  label wallFaceIndex = globalTransforms.index(wfiat);
1023 
1024  const vectorTensorTransform& transform = globalTransforms.transform
1025  (
1026  globalTransforms.transformIndex(wfiat)
1027  );
1028 
1029  label patchI = mesh_.boundaryMesh().patchID()
1030  [
1031  wallFaceIndex - mesh_.nInternalFaces()
1032  ];
1033 
1034  label patchFaceI =
1035  wallFaceIndex
1036  - mesh_.boundaryMesh()[patchI].start();
1037 
1038  // Need to transform velocity when tensor transforms are
1039  // supported
1040  referredWallData_[rWVI] = U.boundaryField()[patchI][patchFaceI];
1041 
1042  if (transform.hasR())
1043  {
1044  referredWallData_[rWVI] =
1045  transform.R().T() & referredWallData_[rWVI];
1046  }
1047  }
1048 }
1049 
1050 
1051 template<class ParticleType>
1053 {
1054  if (referredWallFaces_.empty())
1055  {
1056  return;
1057  }
1058 
1059  fileName objDir = mesh_.time().timePath()/cloud::prefix;
1060 
1061  mkDir(objDir);
1062 
1063  fileName objFileName = "referredWallFaces.obj";
1064 
1065  OFstream str(objDir/objFileName);
1066 
1067  Info<< " Writing "
1068  << mesh_.time().timeName()/cloud::prefix/objFileName
1069  << endl;
1070 
1071  label offset = 1;
1072 
1073  forAll(referredWallFaces_, rWFI)
1074  {
1075  const referredWallFace& rwf = referredWallFaces_[rWFI];
1076 
1077  forAll(rwf, fPtI)
1078  {
1079  meshTools::writeOBJ(str, rwf.points()[rwf[fPtI]]);
1080  }
1081 
1082  str<< 'f';
1083 
1084  forAll(rwf, fPtI)
1085  {
1086  str<< ' ' << fPtI + offset;
1087  }
1088 
1089  str<< nl;
1090 
1091  offset += rwf.size();
1092  }
1093 }
1094 
1095 
1096 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1097 
1098 template<class ParticleType>
1100 :
1101  mesh_(mesh),
1102  cloud_(mesh_, "NULL_Cloud", IDLList<ParticleType>()),
1103  writeCloud_(false),
1104  cellMapPtr_(),
1105  wallFaceMapPtr_(),
1106  maxDistance_(0.0),
1107  dil_(),
1108  dwfil_(),
1109  ril_(),
1110  rilInverse_(),
1111  cellIndexAndTransformToDistribute_(),
1112  wallFaceIndexAndTransformToDistribute_(),
1113  referredWallFaces_(),
1114  UName_("unknown_UName"),
1115  referredWallData_(),
1116  referredParticles_()
1117 {}
1118 
1119 
1120 template<class ParticleType>
1123  const polyMesh& mesh,
1124  scalar maxDistance,
1125  Switch writeCloud,
1126  const word& UName
1127 )
1128 :
1129  mesh_(mesh),
1130  cloud_(mesh_, "referredParticleCloud", IDLList<ParticleType>()),
1131  writeCloud_(writeCloud),
1132  cellMapPtr_(),
1133  wallFaceMapPtr_(),
1134  maxDistance_(maxDistance),
1135  dil_(),
1136  dwfil_(),
1137  ril_(),
1138  rilInverse_(),
1139  cellIndexAndTransformToDistribute_(),
1140  wallFaceIndexAndTransformToDistribute_(),
1141  referredWallFaces_(),
1142  UName_(UName),
1143  referredWallData_(),
1144  referredParticles_()
1145 {
1146  buildInteractionLists();
1147 }
1148 
1149 
1150 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1151 
1152 template<class ParticleType>
1154 {}
1155 
1156 
1157 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
1158 
1159 template<class ParticleType>
1163  PstreamBuffers& pBufs
1164 )
1165 {
1166  if (mesh_.changing())
1167  {
1169  << "Mesh changing, rebuilding InteractionLists form scratch."
1170  << endl;
1171 
1172  buildInteractionLists();
1173  }
1174 
1175  prepareWallDataToRefer();
1176 
1177  prepareParticlesToRefer(cellOccupancy);
1178 
1179  for (label domain = 0; domain < Pstream::nProcs(); domain++)
1180  {
1181  const labelList& subMap = cellMap().subMap()[domain];
1182 
1183  if (subMap.size())
1184  {
1185  UOPstream toDomain(domain, pBufs);
1186 
1187  UIndirectList<IDLList<ParticleType> > subMappedParticles
1188  (
1189  referredParticles_,
1190  subMap
1191  );
1192 
1193  forAll(subMappedParticles, i)
1194  {
1195  toDomain << subMappedParticles[i];
1196  }
1197  }
1198  }
1199 
1200  // Using the mapDistribute to start sending and receiving the
1201  // buffer but not block, i.e. it is calling
1202  // pBufs.finishedSends(false);
1203  wallFaceMap().send(pBufs, referredWallData_);
1204 }
1205 
1206 
1207 template<class ParticleType>
1210  PstreamBuffers& pBufs,
1211  const label startOfRequests
1212 )
1213 {
1214  Pstream::waitRequests(startOfRequests);
1215 
1216  referredParticles_.setSize(cellMap().constructSize());
1217 
1218  for (label domain = 0; domain < Pstream::nProcs(); domain++)
1219  {
1220  const labelList& constructMap = cellMap().constructMap()[domain];
1221 
1222  if (constructMap.size())
1223  {
1224  UIPstream str(domain, pBufs);
1225 
1226  forAll(constructMap, i)
1227  {
1228  referredParticles_[constructMap[i]] = IDLList<ParticleType>
1229  (
1230  str,
1231  typename ParticleType::iNew(mesh_)
1232  );
1233  }
1234  }
1235  }
1236 
1237  fillReferredParticleCloud();
1238 
1239  wallFaceMap().receive(pBufs, referredWallData_);
1240 }
1241 
1242 
1243 // ************************************************************************* //
volFields.H
Foam::Random
Simple random number generator.
Definition: Random.H:49
meshTools.H
Foam::PackedBoolList
A bit-packed bool list.
Definition: PackedBoolList.H:63
Foam::DynamicList::xfer
Xfer< List< T > > xfer()
Transfer contents to the Xfer container as a plain List.
Definition: DynamicListI.H:301
Foam::InteractionLists::prepareWallDataToRefer
void prepareWallDataToRefer()
Populate the referredWallData container with data that.
Definition: InteractionLists.C:1006
Foam::Switch
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:60
Foam::word
A class for handling words, derived from string.
Definition: word.H:59
Foam::UOPstream
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:54
Foam::InteractionLists::findExtendedProcBbsInRange
void findExtendedProcBbsInRange(const treeBoundBox &procBb, const List< treeBoundBox > &allExtendedProcBbs, const globalIndexAndTransform &globalTransforms, List< treeBoundBox > &extendedProcBbsInRange, List< label > &extendedProcBbsTransformIndex, List< label > &extendedProcBbsOrigProc)
Find the other processors which have interaction range.
Definition: InteractionLists.C:637
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::boundBox::max
const point & max() const
Maximum describing the bounding box.
Definition: boundBoxI.H:60
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
writeOBJ
void writeOBJ(Ostream &os, label &vertI, const tetPoints &tet)
Definition: Test-tetTetOverlap.C:38
Foam::InteractionLists::~InteractionLists
~InteractionLists()
Definition: InteractionLists.C:1153
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:56
Foam::List::xfer
Xfer< List< T > > xfer()
Transfer contents to the Xfer container.
Definition: ListI.H:90
Foam::treeBoundBox
Standard boundBox + extra functionality for use in octree.
Definition: treeBoundBox.H:75
Foam::PstreamBuffers
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Definition: PstreamBuffers.H:85
Foam::globalIndexAndTransform::nIndependentTransforms
label nIndependentTransforms() const
Return the number of independent transforms.
Definition: globalIndexAndTransformI.H:409
indexedOctree.H
Foam::combineReduce
void combineReduce(const List< UPstream::commsStruct > &comms, T &Value, const CombineOp &cop, const int tag, const label comm)
Definition: PstreamCombineReduceOps.H:52
Foam::indexedOctree::shapes
const Type & shapes() const
Reference to shape.
Definition: indexedOctree.H:449
Foam::globalIndexAndTransform::encode
static labelPair encode(const label index, const label transformIndex)
Encode index and bare index as components on own processor.
Definition: globalIndexAndTransformI.H:340
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::InteractionLists::prepareParticlesToRefer
void prepareParticlesToRefer(const List< DynamicList< ParticleType * > > &cellOccupancy)
Fill the referredParticles container with particles that.
Definition: InteractionLists.C:916
Foam::InteractionLists::fillReferredParticleCloud
void fillReferredParticleCloud()
Fill the referredParticles so that it will be written out.
Definition: InteractionLists.C:984
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
Foam::transform
dimensionSet transform(const dimensionSet &)
Definition: dimensionSet.C:465
U
U
Definition: pEqn.H:46
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
treeDataFace.H
Foam::InteractionLists::buildMap
void buildMap(autoPtr< mapDistribute > &mapPtr, const List< label > &toProc)
Build the mapDistribute from information about which entry.
Definition: InteractionLists.C:829
Foam::treeDataCell
Encapsulation of data needed to search in/for cells. Used to find the cell containing a point (e....
Definition: treeDataCell.H:54
Foam::indexedOctree::findBox
void findBox(const label nodeI, const treeBoundBox &searchBox, labelHashSet &elements) const
Find all elements intersecting box.
Definition: indexedOctree.C:1994
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::globalIndexAndTransform::transformIndex
static label transformIndex(const labelPair &globalIAndTransform)
Transform carried by the object.
Definition: globalIndexAndTransformI.H:401
Foam::IDLList
Intrusive doubly-linked list.
Definition: IDLList.H:47
Foam::polyPatch::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
Definition: polyPatch.C:302
cellOccupancy
const List< DynamicList< molecule * > > & cellOccupancy
Definition: calculateMDFields.H:1
Foam::treeBoundBox::extend
treeBoundBox extend(Random &, const scalar s) const
Return slightly wider bounding box.
Definition: treeBoundBoxI.H:317
Foam::List::append
void append(const T &)
Append an element at the end of the list.
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
globalIndexAndTransform.H
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
Foam::mapDistribute
Class containing processor-to-processor mapping information.
Definition: mapDistribute.H:152
Foam::indexedOctree
Non-pointer based hierarchical recursive searching.
Definition: treeDataTriSurface.H:47
Foam::globalIndexAndTransform::index
static label index(const labelPair &globalIAndTransform)
Index carried by the object.
Definition: globalIndexAndTransformI.H:383
Foam::boundBox::min
const point & min() const
Minimum describing the bounding box.
Definition: boundBoxI.H:54
Foam::referredWallFace
Storage for referred wall faces. Stores patch index, face and associated points.
Definition: referredWallFace.H:61
Foam::InteractionLists::prepareParticleToBeReferred
void prepareParticleToBeReferred(ParticleType *particle, labelPair iat)
Prepare particle to be referred.
Definition: InteractionLists.C:959
Foam::particle::clone
virtual autoPtr< particle > clone() const
Construct a clone.
Definition: particle.H:364
Foam::InteractionLists::receiveReferredData
void receiveReferredData(PstreamBuffers &pBufs, const label startReq=0)
Receive referred data.
Definition: InteractionLists.C:1209
Foam::identity
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam::globalIndexAndTransform::encodeTransformIndex
label encodeTransformIndex(const FixedList< Foam::label, 3 > &permutationIndices) const
Encode transform index. Hardcoded to 3 independent transforms max.
Definition: globalIndexAndTransformI.H:110
treeDataCell.H
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:312
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::OFstream
Output to file stream.
Definition: OFstream.H:81
Foam::globalIndexAndTransform::transform
const vectorTensorTransform & transform(label transformIndex) const
Access the overall (permuted) transform corresponding.
Definition: globalIndexAndTransformI.H:443
Foam::InteractionLists::sendReferredData
void sendReferredData(const List< DynamicList< ParticleType * > > &cellOccupancy, PstreamBuffers &pBufs)
Prepare and send referred particles and wall data,.
Definition: InteractionLists.C:1161
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::autoPtr
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:117
Foam::UPstream::listEq
combineReduce operator for lists. Used for counting.
Definition: UPstream.H:160
Foam::referredWallFace::points
const pointField & points() const
Return access to the stored points.
Definition: referredWallFaceI.H:30
Foam::InteractionLists::buildInteractionLists
void buildInteractionLists()
Construct all interaction lists.
Definition: InteractionLists.C:37
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
Foam::InteractionLists::writeReferredWallFaces
void writeReferredWallFaces() const
Write the referred wall faces out for debug.
Definition: InteractionLists.C:1052
f
labelList f(nPoints)
Foam::particle::transformProperties
virtual void transformProperties(const tensor &T)
Transform the physical properties of the particle.
Definition: particle.C:123
InteractionLists.H
Foam::Vector< scalar >
Foam::List< treeBoundBox >
Foam::treeDataFace
Encapsulation of data needed to search for faces.
Definition: treeDataFace.H:58
Foam::vectorTensorTransform
Vector-tensor class used to perform translations and rotations in 3D space.
Definition: vectorTensorTransform.H:61
Foam::particle
Base particle class.
Definition: particle.H:78
k
label k
Boltzmann constant.
Definition: LISASMDCalcMethod2.H:41
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: doubleFloat.H:94
Foam::particle::position
const vector & position() const
Return current particle position.
Definition: particleI.H:586
Foam::inplaceSubset
void inplaceSubset(const UList< T > &select, const T &value, ListType &)
Inplace extract elements of List when select is a certain value.
Definition: ListOpsTemplates.C:326
Foam::InteractionLists::InteractionLists
InteractionLists(const InteractionLists &)
Disallow default bitwise copy construct.
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::autoPtr::reset
void reset(T *=0)
If object pointer already set, delete object and set to given.
Definition: autoPtrI.H:114
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:106
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::treeBoundBox::overlaps
bool overlaps(const boundBox &) const
Overlaps other bounding box?
Definition: boundBoxI.H:120
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::UIPstream
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:53
Foam::GeometricField
Generic GeometricField class.
Definition: surfaceFieldsFwd.H:52
Foam::mkDir
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:419
Foam::globalIndexAndTransform
Determination and storage of the possible independent transforms introduced by coupledPolyPatches,...
Definition: globalIndexAndTransform.H:60
Foam::DynamicList::setSize
void setSize(const label)
Alter the addressed list size.
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:259
rndGen
cachedRandom rndGen(label(0), -1)