FvFaceCellWave.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2022 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 "FvFaceCellWave.H"
27 #include "processorFvPatch.H"
28 #include "cyclicFvPatch.H"
29 #include "cyclicAMIFvPatch.H"
30 #include "CompactListList.H"
31 #include "OPstream.H"
32 #include "IPstream.H"
33 #include "PstreamReduceOps.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 template<class Type, class TrackingData>
39 
40 template<class Type, class TrackingData>
42 
43 template<class Type, class TrackingData>
45 
46 
47 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
48 
49 template<class Type, class TrackingData>
50 template<class ListList>
53 (
54  const ListList& ll
55 )
56 {
57  labelList s(ll.size());
58  forAll(ll, i)
59  {
60  s[i] = ll[i].size();
61  }
62  return s;
63 }
64 
65 
66 template<class Type, class TrackingData>
67 template<class ListList, class Value>
69 (
70  const labelList& s,
71  const Value& value
72 )
73 {
74  ListList ll(s.size());
75  forAll(s, i)
76  {
77  ll[i] = typename ListList::value_type(s[i], value);
78  }
79  return ll;
80 }
81 
82 
83 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
84 
85 template<class Type, class TrackingData>
87 (
88  const labelPair& patchAndFacei
89 ) const
90 {
91  return
92  patchAndFacei.first() == -1
93  ? internalFaceInfo_[patchAndFacei.second()]
94  : patchFaceInfo_[patchAndFacei.first()][patchAndFacei.second()];
95 }
96 
97 
98 template<class Type, class TrackingData>
100 (
101  const labelPair& patchAndFacei
102 )
103 {
104  return
105  patchAndFacei.first() == -1
106  ? internalFaceInfo_[patchAndFacei.second()]
107  : patchFaceInfo_[patchAndFacei.first()][patchAndFacei.second()];
108 }
109 
110 
111 template<class Type, class TrackingData>
113 (
114  const labelPair& patchAndFacei
115 )
116 const
117 {
118  return
119  patchAndFacei.first() == -1
120  ? internalFaceChanged_[patchAndFacei.second()]
121  : patchFaceChanged_[patchAndFacei.first()][patchAndFacei.second()];
122 }
123 
124 
125 template<class Type, class TrackingData>
126 Foam::PackedBoolList::iteratorBase
128 (
129  const labelPair& patchAndFacei
130 )
131 {
132  return
133  patchAndFacei.first() == -1
134  ? internalFaceChanged_[patchAndFacei.second()]
135  : patchFaceChanged_[patchAndFacei.first()][patchAndFacei.second()];
136 }
137 
138 
139 template<class Type, class TrackingData>
141 (
142  const label celli,
143  const labelPair& neighbourPatchAndFacei,
144  const Type& neighbourInfo,
145  const scalar tol,
146  Type& cellInfo
147 )
148 {
149  bool propagate =
150  cellInfo.updateCell
151  (
152  mesh_,
153  celli,
154  neighbourPatchAndFacei,
155  neighbourInfo,
156  tol,
157  td_
158  );
159 
160  if (propagate)
161  {
162  if (!cellChanged_[celli])
163  {
164  cellChanged_[celli] = true;
165  changedCells_.append(celli);
166  }
167  }
168 
169  return propagate;
170 }
171 
172 
173 template<class Type, class TrackingData>
175 (
176  const labelPair& patchAndFacei,
177  const label neighbourCelli,
178  const Type& neighbourInfo,
179  const scalar tol,
180  Type& faceInfo
181 )
182 {
183  bool propagate =
184  faceInfo.updateFace
185  (
186  mesh_,
187  patchAndFacei,
188  neighbourCelli,
189  neighbourInfo,
190  tol,
191  td_
192  );
193 
194  if (propagate)
195  {
196  PackedBoolList::iteratorBase changed = faceChanged(patchAndFacei);
197 
198  if (!changed)
199  {
200  changed = true;
201  changedPatchAndFaces_.append(patchAndFacei);
202  }
203  }
204 
205  return propagate;
206 }
207 
208 
209 template<class Type, class TrackingData>
211 (
212  const labelPair& patchAndFacei,
213  const Type& neighbourInfo,
214  const scalar tol,
215  Type& faceInfo
216 )
217 {
218  bool propagate =
219  faceInfo.updateFace
220  (
221  mesh_,
222  patchAndFacei,
223  neighbourInfo,
224  tol,
225  td_
226  );
227 
228  if (propagate)
229  {
230  PackedBoolList::iteratorBase changed = faceChanged(patchAndFacei);
231 
232  if (!changed)
233  {
234  changed = true;
235  changedPatchAndFaces_.append(patchAndFacei);
236  }
237  }
238 
239  return propagate;
240 }
241 
242 
243 template<class Type, class TrackingData>
245 (
246  const fvPatch& patch
247 ) const
248 {
249  const cyclicFvPatch& nbrPatch =
250  refCast<const cyclicFvPatch>(patch).nbrPatch();
251 
252  forAll(patch, patchFacei)
253  {
254  const Type& info = faceInfo({patch.index(), patchFacei});
255  const Type& nbrInfo = faceInfo({nbrPatch.index(), patchFacei});
256 
257  const bool changed = faceChanged({patch.index(), patchFacei});
258  const bool nbrChanged = faceChanged({nbrPatch.index(), patchFacei});
259 
260  if (!info.sameGeometry(mesh_, nbrInfo, geomTol_, td_))
261  {
263  << " faceInfo:" << info
264  << " otherfaceInfo:" << nbrInfo
265  << abort(FatalError);
266  }
267 
268  if (changed != nbrChanged)
269  {
271  << " faceInfo:" << info
272  << " otherfaceInfo:" << nbrInfo
273  << " changedFace:" << changed
274  << " otherchangedFace:" << nbrChanged
275  << abort(FatalError);
276  }
277  }
278 }
279 
280 
281 template<class Type, class TrackingData>
282 template<class PatchType>
284 {
285  forAll(mesh_.boundary(), patchi)
286  {
287  if (isA<PatchType>(mesh_.boundary()[patchi]))
288  {
289  return true;
290  }
291  }
292 
293  return false;
294 }
295 
296 
297 template<class Type, class TrackingData>
299 (
300  const fvPatch& patch,
301  const label nFaces,
302  const labelList& changedPatchFaces,
303  const List<Type>& changedPatchFacesInfo
304 )
305 {
306  for (label changedFacei = 0; changedFacei < nFaces; changedFacei ++)
307  {
308  const label patchFacei = changedPatchFaces[changedFacei];
309 
310  Type& info = faceInfo({patch.index(), patchFacei});
311  const Type& neighbourInfo = changedPatchFacesInfo[changedFacei];
312 
313  if (!info.equal(neighbourInfo, td_))
314  {
315  updateFace
316  (
317  {patch.index(), patchFacei},
318  neighbourInfo,
319  propagationTol_,
320  info
321  );
322  }
323  }
324 }
325 
326 
327 template<class Type, class TrackingData>
330 (
331  const fvPatch& patch,
332  labelList& changedPatchFaces,
333  List<Type>& changedPatchFacesInfo
334 ) const
335 {
336  // Construct compact patchFace change arrays for a single patch.
337  // changedPatchFaces in local patch numbering. Return length of arrays.
338 
339  label i = 0;
340 
341  forAll(patch, patchFacei)
342  {
343  if (patchFaceChanged_[patch.index()][patchFacei])
344  {
345  changedPatchFaces[i] = patchFacei;
346  changedPatchFacesInfo[i] = faceInfo({patch.index(), patchFacei});
347  i ++;
348  }
349  }
350 
351  return i;
352 }
353 
354 
355 template<class Type, class TrackingData>
357 (
358  const fvPatch& patch,
359  const label nFaces,
360  const labelList& patchFaces,
361  const transformer& transform,
362  List<Type>& faceInfo
363 )
364 {
365  for (label i = 0; i < nFaces; i++)
366  {
367  faceInfo[i].transform(patch, patchFaces[i], transform, td_);
368  }
369 }
370 
371 
372 template<class Type, class TrackingData>
374 {
375  // Transfer information to/from neighbouring processors
376 
377  // Which patches are processor patches
378  const labelList& procPatches = mesh_.globalData().processorPatches();
379 
380  // Send all
381  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
382  forAll(procPatches, i)
383  {
384  const label patchi = procPatches[i];
385 
386  const processorFvPatch& procPatch =
387  refCast<const processorFvPatch>(mesh_.boundary()[patchi]);
388 
389  // Allocate buffers
390  label nSendFaces;
391  labelList sendFaces(procPatch.size());
392  List<Type> sendFacesInfo(procPatch.size());
393 
394  // Determine which faces changed on current patch
395  nSendFaces =
396  getChangedPatchFaces
397  (
398  procPatch,
399  sendFaces,
400  sendFacesInfo
401  );
402 
403  if (debug & 2)
404  {
405  Pout<< " Processor patch " << patchi << ' ' << procPatch.name()
406  << " communicating with " << procPatch.neighbProcNo()
407  << " Sending:" << nSendFaces
408  << endl;
409  }
410 
411  // Send
412  UOPstream toNeighbour(procPatch.neighbProcNo(), pBufs);
413  toNeighbour
414  << SubList<label>(sendFaces, nSendFaces)
415  << SubList<Type>(sendFacesInfo, nSendFaces);
416  }
417 
418  pBufs.finishedSends();
419 
420  // Receive all
421  forAll(procPatches, i)
422  {
423  const label patchi = procPatches[i];
424 
425  const processorFvPatch& procPatch =
426  refCast<const processorFvPatch>(mesh_.boundary()[patchi]);
427 
428  // Allocate buffers
429  labelList receiveFaces;
430  List<Type> receiveFacesInfo;
431 
432  // Receive
433  {
434  UIPstream fromNeighbour(procPatch.neighbProcNo(), pBufs);
435  fromNeighbour >> receiveFaces >> receiveFacesInfo;
436  }
437 
438  if (debug & 2)
439  {
440  Pout<< " Processor patch " << patchi << ' ' << procPatch.name()
441  << " communicating with " << procPatch.neighbProcNo()
442  << " Receiving:" << receiveFaces.size()
443  << endl;
444  }
445 
446  // Transform info across the interface
447  transform
448  (
449  procPatch,
450  receiveFaces.size(),
451  receiveFaces,
452  procPatch.transform(),
453  receiveFacesInfo
454  );
455 
456  // Merge received info
457  mergeFaceInfo
458  (
459  procPatch,
460  receiveFaces.size(),
461  receiveFaces,
462  receiveFacesInfo
463  );
464  }
465 }
466 
467 
468 template<class Type, class TrackingData>
469 void
471 {
472  // Transfer information across cyclics
473 
474  forAll(mesh_.boundary(), patchi)
475  {
476  const fvPatch& patch = mesh_.boundary()[patchi];
477 
478  if (!isA<cyclicFvPatch>(patch)) continue;
479 
480  const cyclicFvPatch& cycPatch = refCast<const cyclicFvPatch>(patch);
481  const cyclicFvPatch& nbrCycPatch = cycPatch.nbrPatch();
482 
483  // Allocate buffers
484  label nReceiveFaces;
485  labelList receiveFaces(patch.size());
486  List<Type> receiveFacesInfo(patch.size());
487 
488  // Determine which faces changed
489  nReceiveFaces =
490  getChangedPatchFaces
491  (
492  nbrCycPatch,
493  receiveFaces,
494  receiveFacesInfo
495  );
496 
497  if (debug & 2)
498  {
499  Pout<< " Cyclic patch " << patchi << ' ' << cycPatch.name()
500  << " Changed : " << nReceiveFaces
501  << endl;
502  }
503 
504  // Transform info across the interface
505  transform
506  (
507  cycPatch,
508  nReceiveFaces,
509  receiveFaces,
510  cycPatch.transform(),
511  receiveFacesInfo
512  );
513 
514  // Merge into existing faces
515  mergeFaceInfo
516  (
517  cycPatch,
518  nReceiveFaces,
519  receiveFaces,
520  receiveFacesInfo
521  );
522 
523  if (debug)
524  {
525  checkCyclic(cycPatch);
526  }
527  }
528 }
529 
530 
531 template<class Type, class TrackingData>
532 void
534 {
535  // Define combine operator for AMIInterpolation
536 
537  class combine
538  {
540 
541  const cyclicAMIFvPatch& patch_;
542 
543  public:
544 
545  combine
546  (
548  const cyclicAMIFvPatch& patch
549  )
550  :
551  solver_(solver),
552  patch_(patch)
553  {}
554 
555  void operator()
556  (
557  Type& x,
558  const label patchFacei,
559  const Type& y,
560  const scalar weight
561  ) const
562  {
563  if (y.valid(solver_.data()))
564  {
565  x.updateFace
566  (
567  solver_.mesh(),
568  {patch_.index(), patchFacei},
569  y,
570  solver_.propagationTol(),
571  solver_.data()
572  );
573  }
574  }
575  };
576 
577 
578  // Transfer information across cyclicAMI halves.
579 
580  forAll(mesh_.boundaryMesh(), patchi)
581  {
582  const fvPatch& patch = mesh_.boundary()[patchi];
583 
584  if (isA<cyclicAMIFvPatch>(patch))
585  {
586  const cyclicAMIFvPatch& cycPatch =
587  refCast<const cyclicAMIFvPatch>(patch);
588  const cyclicAMIFvPatch& nbrPatch = cycPatch.nbrPatch();
589 
590  // Create a combine operator to transfer sendInfo from nbrPatch
591  // to cycPatch
592  combine cmb(*this, cycPatch);
593 
594  // Get nbrPatch data (so not just changed faces)
595  List<Type> sendInfo(patchFaceInfo_[nbrPatch.index()]);
596 
597  // Construct default values, if necessary
598  List<Type> defVals;
599  if (cycPatch.applyLowWeightCorrection())
600  {
601  defVals = cycPatch.patch().patchInternalList(cellInfo_);
602  }
603 
604  // Interpolate from nbrPatch to cycPatch, applying AMI
605  // transforms as necessary
606  List<Type> receiveInfo;
607  if (cycPatch.owner())
608  {
609  forAll(cycPatch.AMIs(), i)
610  {
611  if (cycPatch.AMITransforms()[i].transformsPosition())
612  {
613  List<Type> sendInfoT(sendInfo);
614  transform
615  (
616  nbrPatch,
617  nbrPatch.size(),
618  identity(nbrPatch.size()),
619  cycPatch.AMITransforms()[i],
620  sendInfo
621  );
622  cycPatch.AMIs()[i].interpolateToSource
623  (
624  sendInfoT,
625  cmb,
626  receiveInfo,
627  defVals
628  );
629  }
630  else
631  {
632  cycPatch.AMIs()[i].interpolateToSource
633  (
634  sendInfo,
635  cmb,
636  receiveInfo,
637  defVals
638  );
639  }
640  }
641  }
642  else
643  {
644  forAll(nbrPatch.AMIs(), i)
645  {
646  if (nbrPatch.AMITransforms()[i].transformsPosition())
647  {
648  List<Type> sendInfoT(sendInfo);
649  transform
650  (
651  nbrPatch,
652  nbrPatch.size(),
653  identity(nbrPatch.size()),
654  nbrPatch.AMITransforms()[i],
655  sendInfo
656  );
657  cycPatch.nbrPatch().AMIs()[i].interpolateToTarget
658  (
659  sendInfoT,
660  cmb,
661  receiveInfo,
662  defVals
663  );
664  }
665  else
666  {
667  cycPatch.nbrPatch().AMIs()[i].interpolateToTarget
668  (
669  sendInfo,
670  cmb,
671  receiveInfo,
672  defVals
673  );
674  }
675  }
676  }
677 
678  // Shuffle up to remove invalid info
679  DynamicList<label> receiveFaces(cycPatch.size());
680  forAll(receiveInfo, patchFacei)
681  {
682  if (receiveInfo[patchFacei].valid(td_))
683  {
684  if (receiveFaces.size() != patchFacei)
685  {
686  receiveInfo[receiveFaces.size()] =
687  receiveInfo[patchFacei];
688  }
689  receiveFaces.append(patchFacei);
690  }
691  }
692 
693  // Transform info across the interface
694  if (cycPatch.transform().transformsPosition())
695  {
696  transform
697  (
698  cycPatch,
699  receiveFaces.size(),
700  receiveFaces,
701  cycPatch.transform(),
702  receiveInfo
703  );
704  }
705 
706  // Merge into global storage
707  mergeFaceInfo
708  (
709  cycPatch,
710  receiveFaces.size(),
711  receiveFaces,
712  receiveInfo
713  );
714  }
715  }
716 }
717 
718 
719 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
720 
721 template<class Type, class TrackingData>
723 (
724  const fvMesh& mesh,
725  List<Type>& internalFaceInfo,
726  List<List<Type>>& patchFaceInfo,
727  List<Type>& cellInfo,
728  TrackingData& td
729 )
730 :
731  mesh_(mesh),
732  internalFaceInfo_(internalFaceInfo),
733  patchFaceInfo_(patchFaceInfo),
734  cellInfo_(cellInfo),
735  td_(td),
736  internalFaceChanged_
737  (
738  mesh_.nInternalFaces(),
739  false
740  ),
741  patchFaceChanged_
742  (
743  sizesListList<List<PackedBoolList>, bool>
744  (
745  listListSizes(mesh_.boundary()),
746  false
747  )
748  ),
749  cellChanged_
750  (
751  mesh_.nCells(),
752  false
753  ),
754  changedPatchAndFaces_(mesh_.nInternalFaces()),
755  changedCells_(mesh_.nCells()),
756  hasCyclicPatches_(hasPatch<cyclicFvPatch>()),
757  hasCyclicAMIPatches_(hasPatch<cyclicAMIFvPatch>())
758 {
759  if
760  (
761  internalFaceInfo.size() != mesh_.nInternalFaces()
762  || listListSizes(patchFaceInfo) != listListSizes(mesh_.boundary())
763  || cellInfo.size() != mesh_.nCells()
764  )
765  {
767  << "Storage does not match the size of the mesh:" << endl
768  << " internalFaceInfo:" << internalFaceInfo.size() << endl
769  << " mesh_.nInternalFaces():" << mesh_.nInternalFaces() << endl
770  << " patchFaceInfo[i]:" << listListSizes(patchFaceInfo)
771  << endl
772  << "mesh_.boundary()[i].size():" << listListSizes(mesh_.boundary())
773  << endl
774  << " cellInfo:" << cellInfo.size() << endl
775  << " mesh_.nCells():" << mesh_.nCells()
776  << exit(FatalError);
777  }
778 }
779 
780 
781 template<class Type, class TrackingData>
783 (
784  const fvMesh& mesh,
785  const List<labelPair>& initialChangedPatchAndFaces,
786  const List<Type>& initialChangedFacesInfo,
787  List<Type>& internalFaceInfo,
788  List<List<Type>>& patchFaceInfo,
789  List<Type>& cellInfo,
790  const label maxIter,
791  TrackingData& td
792 )
793 :
795  (
796  mesh,
797  internalFaceInfo,
798  patchFaceInfo,
799  cellInfo,
800  td
801  )
802 {
803  // Copy initial changed faces data
804  setFaceInfo(initialChangedPatchAndFaces, initialChangedFacesInfo);
805 
806  // Iterate until nothing changes
807  const label iter = iterate(maxIter);
808 
809  // Error if incomplete
810  if ((maxIter > 0) && (iter >= maxIter))
811  {
813  << "Maximum number of iterations reached. Increase maxIter." << endl
814  << " maxIter:" << maxIter << endl
815  << " changedCells_.size():" << changedCells_.size() << endl
816  << "changedPatchAndFaces_.size():" << changedPatchAndFaces_.size()
817  << endl << exit(FatalError);
818  }
819 }
820 
821 
822 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
823 
824 template<class Type, class TrackingData>
826 (
827  const List<labelPair>& changedPatchAndFaces,
828  const List<Type>& changedFacesInfo
829 )
830 {
831  forAll(changedPatchAndFaces, i)
832  {
833  const labelPair& patchAndFacei = changedPatchAndFaces[i];
834 
835  Type& info = faceInfo(patchAndFacei);
836  PackedBoolList::iteratorBase changed = faceChanged(patchAndFacei);
837 
838  // Copy info for this face
839  info = changedFacesInfo[i];
840 
841  // Mark this face as changed
842  changed = true;
843  changedPatchAndFaces_.append(patchAndFacei);
844  }
845 }
846 
847 
848 template<class Type, class TrackingData>
850 {
851  const labelList& owner = mesh_.owner();
852  const labelList& neighbour = mesh_.neighbour();
853 
854  forAll(changedPatchAndFaces_, changedFacei)
855  {
856  const labelPair& patchAndFacei = changedPatchAndFaces_[changedFacei];
857  const label patchi = patchAndFacei.first();
858  const label facei = patchAndFacei.second();
859 
860  if (!faceChanged(patchAndFacei))
861  {
863  << "Patch and face " << patchAndFacei
864  << " not marked as having been changed"
865  << abort(FatalError);
866  }
867 
868  const Type& info = faceInfo(patchAndFacei);
869 
870  // Propagate to the owner
871  {
872  const label ownerCelli =
873  patchi == -1
874  ? owner[facei]
875  : mesh_.boundary()[patchi].faceCells()[facei];
876 
877  Type& ownerInfo = cellInfo_[ownerCelli];
878 
879  if (!ownerInfo.equal(info, td_))
880  {
881  updateCell
882  (
883  ownerCelli,
884  {patchi, facei},
885  info,
886  propagationTol_,
887  ownerInfo
888  );
889  }
890  }
891 
892  // Propagate to the neighbour
893  if (patchi == -1)
894  {
895  const label neighbourCelli = neighbour[facei];
896 
897  Type& neighbourInfo = cellInfo_[neighbourCelli];
898 
899  if (!neighbourInfo.equal(info, td_))
900  {
901  updateCell
902  (
903  neighbourCelli,
904  {patchi, facei},
905  info,
906  propagationTol_,
907  neighbourInfo
908  );
909  }
910  }
911 
912  // Reset status of face
913  faceChanged(patchAndFacei) = false;
914  }
915 
916  // Handled all changed faces by now
917  changedPatchAndFaces_.clear();
918 
919  if (debug & 2)
920  {
921  Pout<< " Changed cells : " << changedCells_.size() << endl;
922  }
923 
924  return returnReduce(changedCells_.size(), sumOp<label>());
925 }
926 
927 
928 template<class Type, class TrackingData>
930 {
931  const cellList& cells = mesh_.cells();
932 
933  forAll(changedCells_, changedCelli)
934  {
935  const label celli = changedCells_[changedCelli];
936 
937  if (!cellChanged_[celli])
938  {
940  << "Cell " << celli << " not marked as having been changed"
941  << abort(FatalError);
942  }
943 
944  const Type& info = cellInfo_[celli];
945 
946  // Propagate to connected faces
947  forAll(cells[celli], cellFacei)
948  {
949  // Get the patch (if any) and face index
950  label polyFacei = cells[celli][cellFacei];
951 
952  // Get the FV patches and faces associated with this poly face
953  labelUList patches, faces;
954  if (polyFacei < mesh_.nInternalFaces())
955  {
956  static label noPatchi = -1;
957  patches.shallowCopy(labelUList(&noPatchi, 1));
958  faces.shallowCopy(labelUList(&polyFacei, 1));
959  }
960  else
961  {
962  const label polyBFacei = polyFacei - mesh_.nInternalFaces();
963  patches.shallowCopy(mesh_.polyBFacePatches()[polyBFacei]);
964  faces.shallowCopy(mesh_.polyBFacePatchFaces()[polyBFacei]);
965  }
966 
967  // Propagate into the connected FV faces
968  forAll(patches, i)
969  {
970  Type& connectedInfo = faceInfo({patches[i], faces[i]});
971 
972  if (!connectedInfo.equal(info, td_))
973  {
974  updateFace
975  (
976  {patches[i], faces[i]},
977  celli,
978  info,
979  propagationTol_,
980  connectedInfo
981  );
982  }
983  }
984  }
985 
986  // Reset status of cell
987  cellChanged_[celli] = false;
988  }
989 
990  // Handled all changed cells by now
991  changedCells_.clear();
992 
993  if (hasCyclicPatches_)
994  {
995  // Transfer changed faces across cyclics
996  handleCyclicPatches();
997  }
998 
999  if (hasCyclicAMIPatches_)
1000  {
1001  // Transfer changed faces across cyclicAMIs
1002  handleCyclicAMIPatches();
1003  }
1004 
1005  if (Pstream::parRun())
1006  {
1007  // Transfer changed faces from neighbouring processors.
1008  handleProcPatches();
1009  }
1010 
1011  if (debug & 2)
1012  {
1013  Pout<< " Changed faces : "
1014  << changedPatchAndFaces_.size() << endl;
1015  }
1016 
1017  return returnReduce(changedPatchAndFaces_.size(), sumOp<label>());
1018 }
1019 
1020 
1021 template<class Type, class TrackingData>
1024  const label maxIter
1025 )
1026 {
1027  if (hasCyclicPatches_)
1028  {
1029  // Transfer changed faces across cyclics
1030  handleCyclicPatches();
1031  }
1032 
1033  if (hasCyclicAMIPatches_)
1034  {
1035  // Transfer changed faces across cyclicAMIs
1036  handleCyclicAMIPatches();
1037  }
1038 
1039  if (Pstream::parRun())
1040  {
1041  // Transfer changed faces from neighbouring processors.
1042  handleProcPatches();
1043  }
1044 
1045  label iter = 0;
1046 
1047  while (iter < maxIter)
1048  {
1049  if (debug) Info<< " Iteration " << iter << endl;
1050 
1051  label nCells = faceToCell();
1052 
1053  if (debug) Info<< " Total changed cells : " << nCells << endl;
1054 
1055  if (nCells == 0)
1056  {
1057  break;
1058  }
1059 
1060  label nFaces = cellToFace();
1061 
1062  if (debug) Info<< " Total changed faces : " << nFaces << nl;
1063 
1064  if (nFaces == 0)
1065  {
1066  break;
1067  }
1068 
1069  ++iter;
1070  }
1071 
1072  return iter;
1073 }
1074 
1075 
1076 // ************************************************************************* //
const fvPatchList & patches
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
Wave propagation of information through grid. Every iteration information goes through one layer of c...
Inter-processor communication reduction functions.
bool updateCell(const fvMesh &, const label thisCelli, const labelPair &neighbourPatchAndFacei, const FvWallInfoBase< WallInfo, Derived > &neighbourInfo, const scalar tol, TrackingData &td)
Influence of neighbouring face.
Definition: FvWallInfoI.H:56
Vector-tensor class used to perform translations, rotations and scaling operations in 3D space...
Definition: transformer.H:83
void finishedSends(const bool block=true)
Mark all sends as having been done. This will start receives.
const UIndirectList< T > patchInternalList(const UList< T > &internalValues) const
Extract face cell data.
Definition: polyPatch.H:330
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
label index() const
Return the index of this patch in the fvBoundaryMesh.
Definition: fvPatch.H:175
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
Cyclic patch for Arbitrary Mesh Interface (AMI)
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
const TrackingData & data() const
Additional data to be passed into container.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:63
virtual const transformer & transform() const
Return transformation between the coupled patches.
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
static scalar propagationTol()
Access to tolerance.
static labelList listListSizes(const ListList &ll)
...
UList< label > labelUList
Definition: UList.H:65
bool updateCell(const label celli, const labelPair &neighbourPatchAndFacei, const Type &neighbourInfo, const scalar tol, Type &cellInfo)
Updates cellInfo with information from neighbour. Updates all.
virtual int neighbProcNo() const
Return neighbour processor number.
bool updateFace(const fvMesh &, const labelPair &thisPatchAndFacei, const label neighbourCelli, const FvWallInfoBase< WallInfo, Derived > &neighbourInfo, const scalar tol, TrackingData &td)
Influence of neighbouring cell.
Definition: FvWallInfoI.H:79
void handleCyclicAMIPatches()
Merge data from across AMI cyclics.
virtual bool applyLowWeightCorrection() const
Return true if applying the low weight correction.
A topoSetSource to select a faceSet from cells.
Definition: cellToFace.H:53
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:53
scalar y
A List obtained as a section of another List.
Definition: SubList.H:53
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
const cellShapeList & cells
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:125
const polyPatch & patch() const
Return the polyPatch.
Definition: fvPatch.H:139
A topoSetSource to select cells based on usage in faces.
Definition: faceToCell.H:49
virtual const PtrList< AMIInterpolation > & AMIs() const
Return a reference to the AMI interpolators.
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
Processor patch.
bool hasPatch() const
Has cyclic patch?
void handleCyclicPatches()
Merge data from across cyclics.
Cyclic-plane patch.
Definition: cyclicFvPatch.H:51
label getChangedPatchFaces(const fvPatch &patch, labelList &changedPatchFaces, List< Type > &changedPatchFacesInfo) const
Extract info for single patch only.
errorManip< error > abort(error &err)
Definition: errorManip.H:131
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:60
virtual label size() const
Return size.
Definition: fvPatch.H:157
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:54
void setFaceInfo(const List< labelPair > &changedPatchAndFaces, const List< Type > &changedFacesInfo)
Set initial changed faces.
static const char nl
Definition: Ostream.H:260
static ListList sizesListList(const labelList &s, const Value &value)
...
void handleProcPatches()
Merge data from across processor boundaries.
Buffers for inter-processor communications streams (UOPstream, UIPstream).
bool updateFace(const labelPair &patchAndFacei, const label neighbourCelli, const Type &neighbourInfo, const scalar tol, Type &faceInfo)
Updates faceInfo with information from neighbour. Updates all.
virtual const transformer & transform() const
Return transformation between the coupled patches.
bool transformsPosition() const
Return true if the transformer transforms a point.
Definition: transformerI.H:146
FvFaceCellWave(const fvMesh &mesh, List< Type > &internalFaceInfo, List< List< Type >> &patchFaceInfo, List< Type > &cellInfo, TrackingData &td=defaultTrackingData_)
const Type & second() const
Return second.
Definition: Pair.H:110
virtual const transformer & transform() const
Return transformation between the coupled patches.
void mergeFaceInfo(const fvPatch &patch, const label nFaces, const labelList &, const List< Type > &)
Merge received patch data into global data.
virtual label cellToFace()
Propagate from cell to face. Returns total number of faces.
virtual bool owner() const
Is this side the owner?
void shallowCopy(const UList< T > &)
Copy the pointer held by the given UList.
Definition: UListI.H:156
virtual const cyclicAMIFvPatch & nbrPatch() const
Return the neighbour patch.
label patchi
virtual const cyclicFvPatch & nbrPatch() const
Return processor number.
void transform(const fvPatch &patch, const label nFaces, const labelList &patchFaces, const transformer &transform, List< Type > &faceInfo)
Transform across an interface.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:95
messageStream Info
const Type & faceInfo(const labelPair &patchAndFacei) const
...
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
virtual label faceToCell()
Propagate from face to cell. Returns total number of cells.
const fvMesh & mesh() const
Access mesh.
virtual const word & name() const
Return name.
Definition: fvPatch.H:145
void checkCyclic(const fvPatch &patch) const
Debugging: check info on both sides of cyclic.
virtual label iterate(const label maxIter)
Iterate until no changes or maxIter reached. Returns actual.
const Type & first() const
Return first.
Definition: Pair.H:98
const dimensionedScalar e
Elementary charge.
Definition: doubleScalar.H:105
bool faceChanged(const labelPair &patchAndFacei) const
...
dimensionSet transform(const dimensionSet &)
Definition: dimensionSet.C:483
treeBoundBox combine(const treeBoundBox &a, const treeBoundBox &b)
Definition: patchToPatch.C:77
virtual const List< transformer > & AMITransforms() const
Return a reference to the AMI transforms.