FaceCellWave.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 | Copyright (C) 2015 OpenCFD Ltd.
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 "FaceCellWave.H"
27 #include "polyMesh.H"
28 #include "processorPolyPatch.H"
29 #include "cyclicPolyPatch.H"
30 #include "cyclicAMIPolyPatch.H"
31 #include "OPstream.H"
32 #include "IPstream.H"
33 #include "PstreamReduceOps.H"
34 #include "debug.H"
35 #include "typeInfo.H"
36 #include "SubField.H"
37 #include "globalMeshData.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 template<class Type, class TrackingData>
43 
44 template<class Type, class TrackingData>
46 
47 template<class Type, class TrackingData>
49 
50 namespace Foam
51 {
52  //- Combine operator for AMIInterpolation
53  template<class Type, class TrackingData>
54  class combine
55  {
57 
59 
60  public:
61 
62  combine
63  (
65  const cyclicAMIPolyPatch& patch
66  )
67  :
68  solver_(solver),
69  patch_(patch)
70  {}
71 
72 
73  void operator()
74  (
75  Type& x,
76  const label faceI,
77  const Type& y,
78  const scalar weight
79  ) const
80  {
81  if (y.valid(solver_.data()))
82  {
83  label meshFaceI = -1;
84  if (patch_.owner())
85  {
86  meshFaceI = patch_.start() + faceI;
87  }
88  else
89  {
90  meshFaceI = patch_.neighbPatch().start() + faceI;
91  }
92  x.updateFace
93  (
94  solver_.mesh(),
95  meshFaceI,
96  y,
97  solver_.propagationTol(),
98  solver_.data()
99  );
100  }
101  }
102  };
103 }
104 
105 
106 
107 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
108 
109 // Update info for cellI, at position pt, with information from
110 // neighbouring face/cell.
111 // Updates:
112 // - changedCell_, changedCells_, nChangedCells_,
113 // - statistics: nEvals_, nUnvisitedCells_
114 template<class Type, class TrackingData>
116 (
117  const label cellI,
118  const label neighbourFaceI,
119  const Type& neighbourInfo,
120  const scalar tol,
121  Type& cellInfo
122 )
123 {
124  nEvals_++;
125 
126  bool wasValid = cellInfo.valid(td_);
127 
128  bool propagate =
130  (
131  mesh_,
132  cellI,
133  neighbourFaceI,
134  neighbourInfo,
135  tol,
136  td_
137  );
138 
139  if (propagate)
140  {
141  if (!changedCell_[cellI])
142  {
143  changedCell_[cellI] = true;
144  changedCells_[nChangedCells_++] = cellI;
145  }
146  }
147 
148  if (!wasValid && cellInfo.valid(td_))
149  {
150  --nUnvisitedCells_;
151  }
152 
153  return propagate;
154 }
155 
156 
157 // Update info for faceI, at position pt, with information from
158 // neighbouring face/cell.
159 // Updates:
160 // - changedFace_, changedFaces_, nChangedFaces_,
161 // - statistics: nEvals_, nUnvisitedFaces_
162 template<class Type, class TrackingData>
164 (
165  const label faceI,
166  const label neighbourCellI,
167  const Type& neighbourInfo,
168  const scalar tol,
169  Type& faceInfo
170 )
171 {
172  nEvals_++;
173 
174  bool wasValid = faceInfo.valid(td_);
175 
176  bool propagate =
177  faceInfo.updateFace
178  (
179  mesh_,
180  faceI,
181  neighbourCellI,
182  neighbourInfo,
183  tol,
184  td_
185  );
186 
187  if (propagate)
188  {
189  if (!changedFace_[faceI])
190  {
191  changedFace_[faceI] = true;
192  changedFaces_[nChangedFaces_++] = faceI;
193  }
194  }
195 
196  if (!wasValid && faceInfo.valid(td_))
197  {
198  --nUnvisitedFaces_;
199  }
200 
201  return propagate;
202 }
203 
204 
205 // Update info for faceI, at position pt, with information from
206 // same face.
207 // Updates:
208 // - changedFace_, changedFaces_, nChangedFaces_,
209 // - statistics: nEvals_, nUnvisitedFaces_
210 template<class Type, class TrackingData>
212 (
213  const label faceI,
214  const Type& neighbourInfo,
215  const scalar tol,
216  Type& faceInfo
217 )
218 {
219  nEvals_++;
220 
221  bool wasValid = faceInfo.valid(td_);
222 
223  bool propagate =
224  faceInfo.updateFace
225  (
226  mesh_,
227  faceI,
228  neighbourInfo,
229  tol,
230  td_
231  );
232 
233  if (propagate)
234  {
235  if (!changedFace_[faceI])
236  {
237  changedFace_[faceI] = true;
238  changedFaces_[nChangedFaces_++] = faceI;
239  }
240  }
241 
242  if (!wasValid && faceInfo.valid(td_))
243  {
244  --nUnvisitedFaces_;
245  }
246 
247  return propagate;
248 }
249 
250 
251 // For debugging: check status on both sides of cyclic
252 template<class Type, class TrackingData>
254 (
255  const polyPatch& patch
256 ) const
257 {
258  const cyclicPolyPatch& nbrPatch =
259  refCast<const cyclicPolyPatch>(patch).neighbPatch();
260 
261  forAll(patch, patchFaceI)
262  {
263  label i1 = patch.start() + patchFaceI;
264  label i2 = nbrPatch.start() + patchFaceI;
265 
266  if
267  (
268  !allFaceInfo_[i1].sameGeometry
269  (
270  mesh_,
271  allFaceInfo_[i2],
272  geomTol_,
273  td_
274  )
275  )
276  {
278  << " faceInfo:" << allFaceInfo_[i1]
279  << " otherfaceInfo:" << allFaceInfo_[i2]
280  << abort(FatalError);
281  }
282 
283  if (changedFace_[i1] != changedFace_[i2])
284  {
286  << " faceInfo:" << allFaceInfo_[i1]
287  << " otherfaceInfo:" << allFaceInfo_[i2]
288  << " changedFace:" << changedFace_[i1]
289  << " otherchangedFace:" << changedFace_[i2]
290  << abort(FatalError);
291  }
292  }
293 }
294 
295 
296 // Check if has cyclic patches
297 template<class Type, class TrackingData>
298 template<class PatchType>
300 {
301  forAll(mesh_.boundaryMesh(), patchI)
302  {
303  if (isA<PatchType>(mesh_.boundaryMesh()[patchI]))
304  {
305  return true;
306  }
307  }
308  return false;
309 }
310 
311 
312 // Copy face information into member data
313 template<class Type, class TrackingData>
315 (
316  const labelList& changedFaces,
317  const List<Type>& changedFacesInfo
318 )
319 {
320  forAll(changedFaces, changedFaceI)
321  {
322  label faceI = changedFaces[changedFaceI];
323 
324  bool wasValid = allFaceInfo_[faceI].valid(td_);
325 
326  // Copy info for faceI
327  allFaceInfo_[faceI] = changedFacesInfo[changedFaceI];
328 
329  // Maintain count of unset faces
330  if (!wasValid && allFaceInfo_[faceI].valid(td_))
331  {
332  --nUnvisitedFaces_;
333  }
334 
335  // Mark faceI as changed, both on list and on face itself.
336 
337  changedFace_[faceI] = true;
338  changedFaces_[nChangedFaces_++] = faceI;
339  }
340 }
341 
342 
343 // Merge face information into member data
344 template<class Type, class TrackingData>
346 (
347  const polyPatch& patch,
348  const label nFaces,
349  const labelList& changedFaces,
350  const List<Type>& changedFacesInfo
351 )
352 {
353  for (label changedFaceI = 0; changedFaceI < nFaces; changedFaceI++)
354  {
355  const Type& neighbourWallInfo = changedFacesInfo[changedFaceI];
356  label patchFaceI = changedFaces[changedFaceI];
357 
358  label meshFaceI = patch.start() + patchFaceI;
359 
360  Type& currentWallInfo = allFaceInfo_[meshFaceI];
361 
362  if (!currentWallInfo.equal(neighbourWallInfo, td_))
363  {
364  updateFace
365  (
366  meshFaceI,
367  neighbourWallInfo,
368  propagationTol_,
369  currentWallInfo
370  );
371  }
372  }
373 }
374 
375 
376 // Construct compact patchFace change arrays for a (slice of a) single patch.
377 // changedPatchFaces in local patch numbering.
378 // Return length of arrays.
379 template<class Type, class TrackingData>
381 (
382  const polyPatch& patch,
383  const label startFaceI,
384  const label nFaces,
385  labelList& changedPatchFaces,
386  List<Type>& changedPatchFacesInfo
387 ) const
388 {
389  label nChangedPatchFaces = 0;
390 
391  for (label i = 0; i < nFaces; i++)
392  {
393  label patchFaceI = i + startFaceI;
394 
395  label meshFaceI = patch.start() + patchFaceI;
396 
397  if (changedFace_[meshFaceI])
398  {
399  changedPatchFaces[nChangedPatchFaces] = patchFaceI;
400  changedPatchFacesInfo[nChangedPatchFaces] = allFaceInfo_[meshFaceI];
401  nChangedPatchFaces++;
402  }
403  }
404  return nChangedPatchFaces;
405 }
406 
407 
408 // Handle leaving domain. Implementation referred to Type
409 template<class Type, class TrackingData>
411 (
412  const polyPatch& patch,
413  const label nFaces,
414  const labelList& faceLabels,
415  List<Type>& faceInfo
416 ) const
417 {
418  const vectorField& fc = mesh_.faceCentres();
419 
420  for (label i = 0; i < nFaces; i++)
421  {
422  label patchFaceI = faceLabels[i];
423 
424  label meshFaceI = patch.start() + patchFaceI;
425  faceInfo[i].leaveDomain(mesh_, patch, patchFaceI, fc[meshFaceI], td_);
426  }
427 }
428 
429 
430 // Handle entering domain. Implementation referred to Type
431 template<class Type, class TrackingData>
433 (
434  const polyPatch& patch,
435  const label nFaces,
436  const labelList& faceLabels,
437  List<Type>& faceInfo
438 ) const
439 {
440  const vectorField& fc = mesh_.faceCentres();
441 
442  for (label i = 0; i < nFaces; i++)
443  {
444  label patchFaceI = faceLabels[i];
445 
446  label meshFaceI = patch.start() + patchFaceI;
447  faceInfo[i].enterDomain(mesh_, patch, patchFaceI, fc[meshFaceI], td_);
448  }
449 }
450 
451 
452 // Transform. Implementation referred to Type
453 template<class Type, class TrackingData>
455 (
456  const tensorField& rotTensor,
457  const label nFaces,
458  List<Type>& faceInfo
459 )
460 {
461  if (rotTensor.size() == 1)
462  {
463  const tensor& T = rotTensor[0];
464 
465  for (label faceI = 0; faceI < nFaces; faceI++)
466  {
467  faceInfo[faceI].transform(mesh_, T, td_);
468  }
469  }
470  else
471  {
472  for (label faceI = 0; faceI < nFaces; faceI++)
473  {
474  faceInfo[faceI].transform(mesh_, rotTensor[faceI], td_);
475  }
476  }
477 }
478 
479 
480 // Offset mesh face. Used for transferring from one cyclic half to the other.
481 template<class Type, class TrackingData>
483 (
484  const polyPatch&,
485  const label cycOffset,
486  const label nFaces,
487  labelList& faces
488 )
489 {
490  for (label faceI = 0; faceI < nFaces; faceI++)
491  {
492  faces[faceI] += cycOffset;
493  }
494 }
495 
496 
497 // Tranfer all the information to/from neighbouring processors
498 template<class Type, class TrackingData>
500 {
501  const globalMeshData& pData = mesh_.globalData();
502 
503  // Which patches are processor patches
504  const labelList& procPatches = pData.processorPatches();
505 
506  // Send all
507 
508  PstreamBuffers pBufs(Pstream::nonBlocking);
509 
510  forAll(procPatches, i)
511  {
512  label patchI = procPatches[i];
513 
514  const processorPolyPatch& procPatch =
515  refCast<const processorPolyPatch>(mesh_.boundaryMesh()[patchI]);
516 
517  // Allocate buffers
518  label nSendFaces;
519  labelList sendFaces(procPatch.size());
520  List<Type> sendFacesInfo(procPatch.size());
521 
522  // Determine which faces changed on current patch
523  nSendFaces = getChangedPatchFaces
524  (
525  procPatch,
526  0,
527  procPatch.size(),
528  sendFaces,
529  sendFacesInfo
530  );
531 
532  // Adapt wallInfo for leaving domain
533  leaveDomain
534  (
535  procPatch,
536  nSendFaces,
537  sendFaces,
538  sendFacesInfo
539  );
540 
541  if (debug & 2)
542  {
543  Pout<< " Processor patch " << patchI << ' ' << procPatch.name()
544  << " communicating with " << procPatch.neighbProcNo()
545  << " Sending:" << nSendFaces
546  << endl;
547  }
548 
549  UOPstream toNeighbour(procPatch.neighbProcNo(), pBufs);
550  //writeFaces(nSendFaces, sendFaces, sendFacesInfo, toNeighbour);
551  toNeighbour
552  << SubList<label>(sendFaces, nSendFaces)
553  << SubList<Type>(sendFacesInfo, nSendFaces);
554  }
555 
556  pBufs.finishedSends();
557 
558  // Receive all
559 
560  forAll(procPatches, i)
561  {
562  label patchI = procPatches[i];
563 
564  const processorPolyPatch& procPatch =
565  refCast<const processorPolyPatch>(mesh_.boundaryMesh()[patchI]);
566 
567  // Allocate buffers
568  labelList receiveFaces;
569  List<Type> receiveFacesInfo;
570 
571  {
572  UIPstream fromNeighbour(procPatch.neighbProcNo(), pBufs);
573  fromNeighbour >> receiveFaces >> receiveFacesInfo;
574  }
575 
576  if (debug & 2)
577  {
578  Pout<< " Processor patch " << patchI << ' ' << procPatch.name()
579  << " communicating with " << procPatch.neighbProcNo()
580  << " Receiving:" << receiveFaces.size()
581  << endl;
582  }
583 
584  // Apply transform to received data for non-parallel planes
585  if (!procPatch.parallel())
586  {
587  transform
588  (
589  procPatch.forwardT(),
590  receiveFaces.size(),
591  receiveFacesInfo
592  );
593  }
594 
595  // Adapt wallInfo for entering domain
596  enterDomain
597  (
598  procPatch,
599  receiveFaces.size(),
600  receiveFaces,
601  receiveFacesInfo
602  );
603 
604  // Merge received info
605  mergeFaceInfo
606  (
607  procPatch,
608  receiveFaces.size(),
609  receiveFaces,
610  receiveFacesInfo
611  );
612  }
613 }
614 
615 
616 // Transfer information across cyclic halves.
617 template<class Type, class TrackingData>
619 {
620  forAll(mesh_.boundaryMesh(), patchI)
621  {
622  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
623 
624  if (isA<cyclicPolyPatch>(patch))
625  {
626  const cyclicPolyPatch& nbrPatch =
627  refCast<const cyclicPolyPatch>(patch).neighbPatch();
628 
629  // Allocate buffers
630  label nReceiveFaces;
631  labelList receiveFaces(patch.size());
632  List<Type> receiveFacesInfo(patch.size());
633 
634  // Determine which faces changed
635  nReceiveFaces = getChangedPatchFaces
636  (
637  nbrPatch,
638  0,
639  nbrPatch.size(),
640  receiveFaces,
641  receiveFacesInfo
642  );
643 
644  // Adapt wallInfo for leaving domain
645  leaveDomain
646  (
647  nbrPatch,
648  nReceiveFaces,
649  receiveFaces,
650  receiveFacesInfo
651  );
652 
653  const cyclicPolyPatch& cycPatch =
654  refCast<const cyclicPolyPatch>(patch);
655 
656  if (!cycPatch.parallel())
657  {
658  // received data from other half
659  transform
660  (
661  cycPatch.forwardT(),
662  nReceiveFaces,
663  receiveFacesInfo
664  );
665  }
666 
667  if (debug & 2)
668  {
669  Pout<< " Cyclic patch " << patchI << ' ' << cycPatch.name()
670  << " Changed : " << nReceiveFaces
671  << endl;
672  }
673 
674  // Half2: Adapt wallInfo for entering domain
675  enterDomain
676  (
677  cycPatch,
678  nReceiveFaces,
679  receiveFaces,
680  receiveFacesInfo
681  );
682 
683  // Merge into global storage
684  mergeFaceInfo
685  (
686  cycPatch,
687  nReceiveFaces,
688  receiveFaces,
689  receiveFacesInfo
690  );
691 
692  if (debug)
693  {
694  checkCyclic(cycPatch);
695  }
696  }
697  }
698 }
699 
700 
701 // Transfer information across cyclic halves.
702 template<class Type, class TrackingData>
704 {
705  forAll(mesh_.boundaryMesh(), patchI)
706  {
707  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
708 
709  if (isA<cyclicAMIPolyPatch>(patch))
710  {
711  const cyclicAMIPolyPatch& cycPatch =
712  refCast<const cyclicAMIPolyPatch>(patch);
713 
714  List<Type> receiveInfo;
715 
716  {
717  const cyclicAMIPolyPatch& nbrPatch =
718  refCast<const cyclicAMIPolyPatch>(patch).neighbPatch();
719 
720  // Get nbrPatch data (so not just changed faces)
721  typename List<Type>::subList sendInfo
722  (
723  nbrPatch.patchSlice
724  (
725  allFaceInfo_
726  )
727  );
728 
729  if (!nbrPatch.parallel() || nbrPatch.separated())
730  {
731  // Adapt sendInfo for leaving domain
732  const vectorField::subField fc = nbrPatch.faceCentres();
733  forAll(sendInfo, i)
734  {
735  sendInfo[i].leaveDomain(mesh_, nbrPatch, i, fc[i], td_);
736  }
737  }
738 
739  // Transfer sendInfo to cycPatch
740  combine<Type, TrackingData> cmb(*this, cycPatch);
741 
742  if (cycPatch.applyLowWeightCorrection())
743  {
744  List<Type> defVals
745  (
746  cycPatch.patchInternalList(allCellInfo_)
747  );
748 
749  cycPatch.interpolate(sendInfo, cmb, receiveInfo, defVals);
750  }
751  else
752  {
753  cycPatch.interpolate(sendInfo, cmb, receiveInfo);
754  }
755  }
756 
757  // Apply transform to received data for non-parallel planes
758  if (!cycPatch.parallel())
759  {
760  transform
761  (
762  cycPatch.forwardT(),
763  receiveInfo.size(),
764  receiveInfo
765  );
766  }
767 
768  if (!cycPatch.parallel() || cycPatch.separated())
769  {
770  // Adapt receiveInfo for entering domain
771  const vectorField::subField fc = cycPatch.faceCentres();
772  forAll(receiveInfo, i)
773  {
774  receiveInfo[i].enterDomain(mesh_, cycPatch, i, fc[i], td_);
775  }
776  }
777 
778  // Merge into global storage
779  forAll(receiveInfo, i)
780  {
781  label meshFaceI = cycPatch.start()+i;
782 
783  Type& currentWallInfo = allFaceInfo_[meshFaceI];
784 
785  if
786  (
787  receiveInfo[i].valid(td_)
788  && !currentWallInfo.equal(receiveInfo[i], td_)
789  )
790  {
791  updateFace
792  (
793  meshFaceI,
794  receiveInfo[i],
795  propagationTol_,
796  currentWallInfo
797  );
798  }
799  }
800  }
801  }
802 }
803 
804 
805 template<class Type, class TrackingData>
807 {
808  // Collect changed information
809 
810  DynamicList<label> f0Baffle(explicitConnections_.size());
811  DynamicList<Type> f0Info(explicitConnections_.size());
812 
813  DynamicList<label> f1Baffle(explicitConnections_.size());
814  DynamicList<Type> f1Info(explicitConnections_.size());
815 
816  forAll(explicitConnections_, connI)
817  {
818  const labelPair& baffle = explicitConnections_[connI];
819 
820  label f0 = baffle[0];
821  if (changedFace_[f0])
822  {
823  f0Baffle.append(connI);
824  f0Info.append(allFaceInfo_[f0]);
825  }
826 
827  label f1 = baffle[1];
828  if (changedFace_[f1])
829  {
830  f1Baffle.append(connI);
831  f1Info.append(allFaceInfo_[f1]);
832  }
833  }
834 
835 
836  // Update other side with changed information
837 
838  forAll(f1Info, index)
839  {
840  const labelPair& baffle = explicitConnections_[f1Baffle[index]];
841 
842  label f0 = baffle[0];
843  Type& currentWallInfo = allFaceInfo_[f0];
844 
845  if (!currentWallInfo.equal(f1Info[index], td_))
846  {
847  updateFace
848  (
849  f0,
850  f1Info[index],
851  propagationTol_,
852  currentWallInfo
853  );
854  }
855  }
856 
857  forAll(f0Info, index)
858  {
859  const labelPair& baffle = explicitConnections_[f0Baffle[index]];
860 
861  label f1 = baffle[1];
862  Type& currentWallInfo = allFaceInfo_[f1];
863 
864  if (!currentWallInfo.equal(f0Info[index], td_))
865  {
866  updateFace
867  (
868  f1,
869  f0Info[index],
870  propagationTol_,
871  currentWallInfo
872  );
873  }
874  }
875 }
876 
877 
878 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
879 
880 // Set up only. Use setFaceInfo and iterate() to do actual calculation.
881 template<class Type, class TrackingData>
883 (
884  const polyMesh& mesh,
885  UList<Type>& allFaceInfo,
886  UList<Type>& allCellInfo,
887  TrackingData& td
888 )
889 :
890  mesh_(mesh),
891  explicitConnections_(0),
892  allFaceInfo_(allFaceInfo),
893  allCellInfo_(allCellInfo),
894  td_(td),
895  changedFace_(mesh_.nFaces(), false),
896  changedFaces_(mesh_.nFaces()),
897  nChangedFaces_(0),
898  changedCell_(mesh_.nCells(), false),
899  changedCells_(mesh_.nCells()),
900  nChangedCells_(0),
901  hasCyclicPatches_(hasPatch<cyclicPolyPatch>()),
902  hasCyclicAMIPatches_
903  (
904  returnReduce(hasPatch<cyclicAMIPolyPatch>(), orOp<bool>())
905  ),
906  nEvals_(0),
907  nUnvisitedCells_(mesh_.nCells()),
908  nUnvisitedFaces_(mesh_.nFaces())
909 {
910  if
911  (
912  allFaceInfo.size() != mesh_.nFaces()
913  || allCellInfo.size() != mesh_.nCells()
914  )
915  {
917  << "face and cell storage not the size of mesh faces, cells:"
918  << endl
919  << " allFaceInfo :" << allFaceInfo.size() << endl
920  << " mesh_.nFaces():" << mesh_.nFaces() << endl
921  << " allCellInfo :" << allCellInfo.size() << endl
922  << " mesh_.nCells():" << mesh_.nCells()
923  << exit(FatalError);
924  }
925 }
926 
927 
928 // Iterate, propagating changedFacesInfo across mesh, until no change (or
929 // maxIter reached). Initial cell values specified.
930 template<class Type, class TrackingData>
932 (
933  const polyMesh& mesh,
934  const labelList& changedFaces,
935  const List<Type>& changedFacesInfo,
936  UList<Type>& allFaceInfo,
937  UList<Type>& allCellInfo,
938  const label maxIter,
939  TrackingData& td
940 )
941 :
942  mesh_(mesh),
943  explicitConnections_(0),
944  allFaceInfo_(allFaceInfo),
945  allCellInfo_(allCellInfo),
946  td_(td),
947  changedFace_(mesh_.nFaces(), false),
948  changedFaces_(mesh_.nFaces()),
949  nChangedFaces_(0),
950  changedCell_(mesh_.nCells(), false),
951  changedCells_(mesh_.nCells()),
952  nChangedCells_(0),
953  hasCyclicPatches_(hasPatch<cyclicPolyPatch>()),
954  hasCyclicAMIPatches_
955  (
956  returnReduce(hasPatch<cyclicAMIPolyPatch>(), orOp<bool>())
957  ),
958  nEvals_(0),
959  nUnvisitedCells_(mesh_.nCells()),
960  nUnvisitedFaces_(mesh_.nFaces())
961 {
962  if
963  (
964  allFaceInfo.size() != mesh_.nFaces()
965  || allCellInfo.size() != mesh_.nCells()
966  )
967  {
969  << "face and cell storage not the size of mesh faces, cells:"
970  << endl
971  << " allFaceInfo :" << allFaceInfo.size() << endl
972  << " mesh_.nFaces():" << mesh_.nFaces() << endl
973  << " allCellInfo :" << allCellInfo.size() << endl
974  << " mesh_.nCells():" << mesh_.nCells()
975  << exit(FatalError);
976  }
977 
978  // Copy initial changed faces data
979  setFaceInfo(changedFaces, changedFacesInfo);
980 
981  // Iterate until nothing changes
982  label iter = iterate(maxIter);
983 
984  if ((maxIter > 0) && (iter >= maxIter))
985  {
987  << "Maximum number of iterations reached. Increase maxIter." << endl
988  << " maxIter:" << maxIter << endl
989  << " nChangedCells:" << nChangedCells_ << endl
990  << " nChangedFaces:" << nChangedFaces_ << endl
991  << exit(FatalError);
992  }
993 }
994 
995 
996 // Iterate, propagating changedFacesInfo across mesh, until no change (or
997 // maxIter reached). Initial cell values specified.
998 template<class Type, class TrackingData>
1001  const polyMesh& mesh,
1002  const List<labelPair>& explicitConnections,
1003  const bool handleCyclicAMI,
1004  const labelList& changedFaces,
1005  const List<Type>& changedFacesInfo,
1006  UList<Type>& allFaceInfo,
1007  UList<Type>& allCellInfo,
1008  const label maxIter,
1009  TrackingData& td
1010 )
1011 :
1012  mesh_(mesh),
1013  explicitConnections_(explicitConnections),
1014  allFaceInfo_(allFaceInfo),
1015  allCellInfo_(allCellInfo),
1016  td_(td),
1017  changedFace_(mesh_.nFaces(), false),
1018  changedFaces_(mesh_.nFaces()),
1019  nChangedFaces_(0),
1020  changedCell_(mesh_.nCells(), false),
1021  changedCells_(mesh_.nCells()),
1022  nChangedCells_(0),
1023  hasCyclicPatches_(hasPatch<cyclicPolyPatch>()),
1024  hasCyclicAMIPatches_
1025  (
1026  handleCyclicAMI
1027  && returnReduce(hasPatch<cyclicAMIPolyPatch>(), orOp<bool>())
1028  ),
1029  nEvals_(0),
1030  nUnvisitedCells_(mesh_.nCells()),
1031  nUnvisitedFaces_(mesh_.nFaces())
1032 {
1033  if
1034  (
1035  allFaceInfo.size() != mesh_.nFaces()
1036  || allCellInfo.size() != mesh_.nCells()
1037  )
1038  {
1040  << "face and cell storage not the size of mesh faces, cells:"
1041  << endl
1042  << " allFaceInfo :" << allFaceInfo.size() << endl
1043  << " mesh_.nFaces():" << mesh_.nFaces() << endl
1044  << " allCellInfo :" << allCellInfo.size() << endl
1045  << " mesh_.nCells():" << mesh_.nCells()
1046  << exit(FatalError);
1047  }
1048 
1049  // Copy initial changed faces data
1050  setFaceInfo(changedFaces, changedFacesInfo);
1051 
1052  // Iterate until nothing changes
1053  label iter = iterate(maxIter);
1054 
1055  if ((maxIter > 0) && (iter >= maxIter))
1056  {
1058  << "Maximum number of iterations reached. Increase maxIter." << endl
1059  << " maxIter:" << maxIter << endl
1060  << " nChangedCells:" << nChangedCells_ << endl
1061  << " nChangedFaces:" << nChangedFaces_ << endl
1062  << exit(FatalError);
1063  }
1064 }
1065 
1066 
1067 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1068 
1069 
1070 template<class Type, class TrackingData>
1072 {
1073  return nUnvisitedCells_;
1074 }
1075 
1076 
1077 template<class Type, class TrackingData>
1079 {
1080  return nUnvisitedFaces_;
1081 }
1082 
1083 
1084 
1085 // Propagate cell to face
1086 template<class Type, class TrackingData>
1088 {
1089  const labelList& owner = mesh_.faceOwner();
1090  const labelList& neighbour = mesh_.faceNeighbour();
1091  label nInternalFaces = mesh_.nInternalFaces();
1092 
1093  for
1094  (
1095  label changedFaceI = 0;
1096  changedFaceI < nChangedFaces_;
1097  changedFaceI++
1098  )
1099  {
1100  label faceI = changedFaces_[changedFaceI];
1101  if (!changedFace_[faceI])
1102  {
1104  << "Face " << faceI
1105  << " not marked as having been changed"
1106  << abort(FatalError);
1107  }
1108 
1109 
1110  const Type& neighbourWallInfo = allFaceInfo_[faceI];
1111 
1112  // Evaluate all connected cells
1113 
1114  // Owner
1115  label cellI = owner[faceI];
1116  Type& currentWallInfo = allCellInfo_[cellI];
1117 
1118  if (!currentWallInfo.equal(neighbourWallInfo, td_))
1119  {
1120  updateCell
1121  (
1122  cellI,
1123  faceI,
1124  neighbourWallInfo,
1125  propagationTol_,
1126  currentWallInfo
1127  );
1128  }
1129 
1130  // Neighbour.
1131  if (faceI < nInternalFaces)
1132  {
1133  cellI = neighbour[faceI];
1134  Type& currentWallInfo2 = allCellInfo_[cellI];
1135 
1136  if (!currentWallInfo2.equal(neighbourWallInfo, td_))
1137  {
1138  updateCell
1139  (
1140  cellI,
1141  faceI,
1142  neighbourWallInfo,
1143  propagationTol_,
1144  currentWallInfo2
1145  );
1146  }
1147  }
1148 
1149  // Reset status of face
1150  changedFace_[faceI] = false;
1151  }
1152 
1153  // Handled all changed faces by now
1154  nChangedFaces_ = 0;
1155 
1156  if (debug & 2)
1157  {
1158  Pout<< " Changed cells : " << nChangedCells_ << endl;
1159  }
1160 
1161  // Sum nChangedCells over all procs
1162  label totNChanged = nChangedCells_;
1163 
1164  reduce(totNChanged, sumOp<label>());
1165 
1166  return totNChanged;
1167 }
1168 
1169 
1170 // Propagate cell to face
1171 template<class Type, class TrackingData>
1173 {
1174  const cellList& cells = mesh_.cells();
1175 
1176  for
1177  (
1178  label changedCellI = 0;
1179  changedCellI < nChangedCells_;
1180  changedCellI++
1181  )
1182  {
1183  label cellI = changedCells_[changedCellI];
1184  if (!changedCell_[cellI])
1185  {
1187  << "Cell " << cellI << " not marked as having been changed"
1188  << abort(FatalError);
1189  }
1190 
1191  const Type& neighbourWallInfo = allCellInfo_[cellI];
1192 
1193  // Evaluate all connected faces
1194 
1195  const labelList& faceLabels = cells[cellI];
1196  forAll(faceLabels, faceLabelI)
1197  {
1198  label faceI = faceLabels[faceLabelI];
1199  Type& currentWallInfo = allFaceInfo_[faceI];
1200 
1201  if (!currentWallInfo.equal(neighbourWallInfo, td_))
1202  {
1203  updateFace
1204  (
1205  faceI,
1206  cellI,
1207  neighbourWallInfo,
1208  propagationTol_,
1209  currentWallInfo
1210  );
1211  }
1212  }
1213 
1214  // Reset status of cell
1215  changedCell_[cellI] = false;
1216  }
1217 
1218  // Handled all changed cells by now
1219  nChangedCells_ = 0;
1220 
1221 
1222  // Transfer across any explicitly provided internal connections
1223  handleExplicitConnections();
1224 
1225  if (hasCyclicPatches_)
1226  {
1227  // Transfer changed faces across cyclic halves
1228  handleCyclicPatches();
1229  }
1230 
1231  if (hasCyclicAMIPatches_)
1232  {
1233  handleAMICyclicPatches();
1234  }
1235 
1236  if (Pstream::parRun())
1237  {
1238  // Transfer changed faces from neighbouring processors.
1239  handleProcPatches();
1240  }
1241 
1242  if (debug & 2)
1243  {
1244  Pout<< " Changed faces : " << nChangedFaces_ << endl;
1245  }
1246 
1247  // Sum nChangedFaces over all procs
1248  label totNChanged = nChangedFaces_;
1249 
1250  reduce(totNChanged, sumOp<label>());
1251 
1252  return totNChanged;
1253 }
1254 
1255 
1256 // Iterate
1257 template<class Type, class TrackingData>
1259 {
1260  if (hasCyclicPatches_)
1261  {
1262  // Transfer changed faces across cyclic halves
1263  handleCyclicPatches();
1264  }
1265 
1266  if (hasCyclicAMIPatches_)
1267  {
1268  handleAMICyclicPatches();
1269  }
1270 
1271  if (Pstream::parRun())
1272  {
1273  // Transfer changed faces from neighbouring processors.
1274  handleProcPatches();
1275  }
1276 
1277  label iter = 0;
1278 
1279  while (iter < maxIter)
1280  {
1281  if (debug)
1282  {
1283  Info<< " Iteration " << iter << endl;
1284  }
1285 
1286  nEvals_ = 0;
1287 
1288  label nCells = faceToCell();
1289 
1290  if (debug)
1291  {
1292  Info<< " Total changed cells : " << nCells << endl;
1293  }
1294 
1295  if (nCells == 0)
1296  {
1297  break;
1298  }
1299 
1300  label nFaces = cellToFace();
1301 
1302  if (debug)
1303  {
1304  Info<< " Total changed faces : " << nFaces << nl
1305  << " Total evaluations : " << nEvals_ << nl
1306  << " Remaining unvisited cells: " << nUnvisitedCells_ << nl
1307  << " Remaining unvisited faces: " << nUnvisitedFaces_ << endl;
1308  }
1309 
1310  if (nFaces == 0)
1311  {
1312  break;
1313  }
1314 
1315  ++iter;
1316  }
1317 
1318  return iter;
1319 }
1320 
1321 
1322 // ************************************************************************* //
Foam::FaceCellWave::updateCell
bool updateCell(const label cellI, const label neighbourFaceI, const Type &neighbourInfo, const scalar tol, Type &cellInfo)
Updates cellInfo with information from neighbour. Updates all.
Definition: FaceCellWave.C:116
Foam::Tensor
Templated 3D tensor derived from VectorSpace adding construction from 9 components,...
Definition: complexI.H:224
debug.H
Foam::cyclicAMIPolyPatch::owner
virtual bool owner() const
Does this side own the patch?
Definition: cyclicAMIPolyPatch.C:738
Foam::FaceCellWave::handleExplicitConnections
void handleExplicitConnections()
Merge data across explicitly provided local connections (usually.
Definition: FaceCellWave.C:806
Foam::UOPstream
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:54
SubField.H
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
typeInfo.H
Foam::combine::patch_
const cyclicAMIPolyPatch & patch_
Definition: FaceCellWave.C:58
cyclicPolyPatch.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::cyclicPolyPatch
Cyclic plane patch.
Definition: cyclicPolyPatch.H:63
Foam::cellToFace
A topoSetSource to select a faceSet from cells.
Definition: cellToFace.H:53
Foam::DynamicList< label >
Foam::globalMeshData::processorPatches
const labelList & processorPatches() const
Return list of processor patch labels.
Definition: globalMeshData.H:404
Foam::cyclicPolyPatch::neighbPatch
const cyclicPolyPatch & neighbPatch() const
Definition: cyclicPolyPatch.H:328
globalMeshData.H
Foam::combine
Combine operator for AMIInterpolation.
Definition: FaceCellWave.C:54
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:53
Foam::coupledPolyPatch::forwardT
virtual const tensorField & forwardT() const
Return face transformation tensor.
Definition: coupledPolyPatch.H:294
Foam::FaceCellWave::updateFace
bool updateFace(const label faceI, const label neighbourCellI, const Type &neighbourInfo, const scalar tol, Type &faceInfo)
Updates faceInfo with information from neighbour. Updates all.
Definition: FaceCellWave.C:164
Foam::PstreamBuffers
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Definition: PstreamBuffers.H:85
Foam::FaceCellWave::FaceCellWave
FaceCellWave(const FaceCellWave &)
Disallow default bitwise copy construct.
OPstream.H
Foam::processorPolyPatch::neighbProcNo
int neighbProcNo() const
Return neigbour processor number.
Definition: processorPolyPatch.H:255
Foam::faceToCell
A topoSetSource to select cells based on usage in faces.
Definition: faceToCell.H:49
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::combine::solver_
FaceCellWave< Type, TrackingData > & solver_
Definition: FaceCellWave.C:56
Foam::FaceCellWave::iterate
label iterate(const label maxIter)
Iterate until no changes or maxIter reached. Returns actual.
Definition: FaceCellWave.C:1258
polyMesh.H
Foam::FaceCellWave::getUnsetFaces
label getUnsetFaces() const
Get number of unvisited faces.
Definition: FaceCellWave.C:1078
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
Foam::transform
dimensionSet transform(const dimensionSet &)
Definition: dimensionSet.C:465
Foam::FaceCellWave::checkCyclic
void checkCyclic(const polyPatch &pPatch) const
Debugging: check info on both sides of cyclic.
Definition: FaceCellWave.C:254
Foam::FaceCellWave::handleProcPatches
void handleProcPatches()
Merge data from across processor boundaries.
Definition: FaceCellWave.C:499
Foam::polyPatch::patchInternalList
const UIndirectList< T > patchInternalList(const UList< T > &internalValues) const
Extract face cell data.
Definition: polyPatch.H:336
Foam::SubField
Pre-declare related SubField type.
Definition: Field.H:61
Foam::coupledPolyPatch::parallel
virtual bool parallel() const
Are the cyclic planes parallel.
Definition: coupledPolyPatch.H:288
Foam::FaceCellWave::hasPatch
bool hasPatch() const
Has cyclic patch?
Definition: FaceCellWave.C:299
Foam::FaceCellWave::faceToCell
label faceToCell()
Propagate from face to cell. Returns total number of cells.
Definition: FaceCellWave.C:1087
Foam::coupledPolyPatch::separated
virtual bool separated() const
Are the planes separated.
Definition: coupledPolyPatch.H:276
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:43
Foam::FaceCellWave::enterDomain
void enterDomain(const polyPatch &patch, const label nFaces, const labelList &faceLabels, List< Type > &faceInfo) const
Handle leaving domain. Implementation referred to Type.
Definition: FaceCellWave.C:433
IPstream.H
Foam::FaceCellWave::handleCyclicPatches
void handleCyclicPatches()
Merge data from across cyclics.
Definition: FaceCellWave.C:618
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::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::polyPatch::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
Definition: polyPatch.C:302
Foam::orOp
Definition: ops.H:178
Foam::cellInfo::updateCell
bool updateCell(const polyMesh &, const label thisCellI, const label neighbourFaceI, const cellInfo &neighbourInfo, const scalar tol, TrackingData &td)
Influence of neighbouring face.
Definition: cellInfoI.H:180
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
f1
scalar f1
Definition: createFields.H:28
Foam::FaceCellWave::handleAMICyclicPatches
void handleAMICyclicPatches()
Merge data from across AMI cyclics.
Definition: FaceCellWave.C:703
Foam::processorPolyPatch
Neighbour processor patch.
Definition: processorPolyPatch.H:55
Foam::FaceCellWave::setFaceInfo
void setFaceInfo(const labelList &changedFaces, const List< Type > &changedFacesInfo)
Set initial changed faces.
Definition: FaceCellWave.C:315
Foam::FaceCellWave::cellToFace
label cellToFace()
Propagate from cell to face. Returns total number of faces.
Definition: FaceCellWave.C:1172
Foam::cyclicAMIPolyPatch::interpolate
tmp< Field< Type > > interpolate(const Field< Type > &fld, const UList< Type > &defaultValues=UList< Type >()) const
Interpolate field.
Foam::PstreamBuffers::finishedSends
void finishedSends(const bool block=true)
Mark all sends as having been done. This will start receives.
Definition: PstreamBuffers.C:82
Foam::FatalError
error FatalError
processorPolyPatch.H
Foam::cyclicAMIPolyPatch::neighbPatch
virtual const cyclicAMIPolyPatch & neighbPatch() const
Return a reference to the neighbour patch.
Definition: cyclicAMIPolyPatch.C:744
Foam::globalMeshData
Various mesh related information for a parallel run. Upon construction, constructs all info using par...
Definition: globalMeshData.H:106
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:312
PstreamReduceOps.H
cyclicAMIPolyPatch.H
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::FaceCellWave
Wave propagation of information through grid. Every iteration information goes through one layer of c...
Definition: FaceCellWave.H:75
Foam::cellInfo
Holds information regarding type of cell. Used in inside/outside determination in cellClassification.
Definition: cellInfo.H:54
Foam::FaceCellWave::transform
void transform(const tensorField &rotTensor, const label nFaces, List< Type > &faceInfo)
Apply transformation to Type.
Definition: FaceCellWave.C:455
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
T
const volScalarField & T
Definition: createFields.H:25
Foam::polyPatch::patchSlice
const List< T >::subList patchSlice(const UList< T > &l) const
Slice list to patch.
Definition: polyPatch.H:345
Foam::sumOp
Definition: ops.H:162
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
Foam::polyPatch::faceCentres
const vectorField::subField faceCentres() const
Return face centres.
Definition: polyPatch.C:308
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Foam::cyclicAMIPolyPatch::applyLowWeightCorrection
bool applyLowWeightCorrection() const
Return true if applying the low weight correction.
Definition: cyclicAMIPolyPatch.C:801
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::cellInfo::valid
bool valid(TrackingData &td) const
Check whether origin has been changed at all or.
Definition: cellInfoI.H:119
FaceCellWave.H
Foam::UList< Type >
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: doubleFloat.H:94
x
x
Definition: LISASMDCalcMethod2.H:52
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
Foam::FaceCellWave::offset
static void offset(const polyPatch &patch, const label off, const label nFaces, labelList &faces)
Offset face labels by constant value.
Definition: FaceCellWave.C:483
Foam::FaceCellWave::getChangedPatchFaces
label getChangedPatchFaces(const polyPatch &patch, const label startFaceI, const label nFaces, labelList &changedPatchFaces, List< Type > &changedPatchFacesInfo) const
Extract info for single patch only.
Definition: FaceCellWave.C:381
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::UList::size
label size() const
Return the number of elements in the UList.
Definition: UListI.H:299
Foam::FaceCellWave::mergeFaceInfo
void mergeFaceInfo(const polyPatch &patch, const label nFaces, const labelList &, const List< Type > &)
Merge received patch data into global data.
Definition: FaceCellWave.C:346
Foam::patchIdentifier::name
const word & name() const
Return name.
Definition: patchIdentifier.H:109
Foam::FaceCellWave::getUnsetCells
label getUnsetCells() const
Get number of unvisited cells, i.e. cells that were not (yet)
Definition: FaceCellWave.C:1071
Foam::FaceCellWave::leaveDomain
void leaveDomain(const polyPatch &patch, const label nFaces, const labelList &faceLabels, List< Type > &faceInfo) const
Handle leaving domain. Implementation referred to Type.
Definition: FaceCellWave.C:411
y
scalar y
Definition: LISASMDCalcMethod1.H:14
Foam::combine::combine
combine(FaceCellWave< Type, TrackingData > &solver, const cyclicAMIPolyPatch &patch)
Definition: FaceCellWave.C:63
Foam::cyclicAMIPolyPatch
Cyclic patch for Arbitrary Mesh Interface (AMI)
Definition: cyclicAMIPolyPatch.H:51