patchToPatch.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 "patchToPatch.H"
27 #include "cpuTime.H"
28 #include "distributionMap.H"
29 #include "globalIndex.H"
30 #include "indexedOctree.H"
31 #include "treeDataPrimitivePatch.H"
32 #include "vtkWritePolyData.H"
33 
34 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
39  {
40  labelList f(p.size());
41  forAll(p, i)
42  {
43  f[i] = p[i].first();
44  }
45  return f;
46  }
47 
49  {
50  labelList s(p.size());
51  forAll(p, i)
52  {
53  s[i] = p[i].second();
54  }
55  return s;
56  }
57 
58  template<class ListType>
60  (
61  const ListType& l,
62  typename ListType::const_reference t,
63  const label start=0
64  )
65  {
66  for (label i = start; i < l.size(); i++)
67  {
68  if (l[i] != t)
69  {
70  return i;
71  }
72  }
73 
74  return -1;
75  }
76 
78  {
79  return treeBoundBox(min(a.min(), b.min()), max(a.max(), b.max()));
80  }
81 }
82 
83 
84 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
85 
86 namespace Foam
87 {
90 }
91 
92 
93 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
94 
97 (
98  const List<DynamicList<label>>& localFaces,
99  const List<procFace>& map
100 )
101 {
102  List<List<procFace>> result(localFaces.size());
103 
104  forAll(localFaces, thisFacei)
105  {
106  result[thisFacei].resize(localFaces[thisFacei].size());
107 
108  forAll(localFaces[thisFacei], i)
109  {
110  result[thisFacei][i] =
111  isNull(map)
112  ? procFace({Pstream::myProcNo(), localFaces[thisFacei][i]})
113  : map[localFaces[thisFacei][i]];
114  }
115  }
116 
117  return result;
118 }
119 
120 
123 (
124  const List<List<procFace>>& procFaces,
125  const HashTable<label, procFace, Hash<procFace>>& map
126 )
127 {
128  List<DynamicList<label>> result(procFaces.size());
129 
130  forAll(procFaces, tgtFacei)
131  {
132  result[tgtFacei].resize(procFaces[tgtFacei].size());
133 
134  forAll(procFaces[tgtFacei], i)
135  {
136  result[tgtFacei][i] =
137  isNull(map)
138  ? procFaces[tgtFacei][i].facei
139  : map[procFaces[tgtFacei][i]];
140  }
141  }
142 
143  return result;
144 }
145 
146 
148 (
149  const primitiveOldTimePatch& srcPatch,
150  const vectorField& srcPointNormals,
151  const vectorField& srcPointNormals0,
152  const label srcFacei
153 ) const
154 {
155  const face& srcFace = srcPatch.localFaces()[srcFacei];
156  const pointField& srcPoints = srcPatch.localPoints();
157  treeBoundBox box = srcBox(srcFace, srcPoints, srcPointNormals);
158 
159  if (srcPatch.has0())
160  {
161  const pointField& srcPoints0 = srcPatch.localPoints();
162  box = combine(box, srcBox(srcFace, srcPoints0, srcPointNormals0));
163  }
164 
165  return box;
166 }
167 
168 
170 (
171  const primitiveOldTimePatch& srcPatch,
172  const vectorField& srcPointNormals,
173  const vectorField& srcPointNormals0
174 ) const
175 {
177 
178  forAll(srcPatch, srcFacei)
179  {
180  box =
181  combine
182  (
183  box,
184  srcBox(srcPatch, srcPointNormals, srcPointNormals0, srcFacei)
185  );
186  }
187 
188  box.inflate(rootSmall);
189 
190  return box;
191 }
192 
193 
195 (
196  const primitiveOldTimePatch& tgtPatch,
197  const label tgtFacei
198 ) const
199 {
200  const face& tgtFace = tgtPatch.localFaces()[tgtFacei];
201  const pointField& tgtPoints = tgtPatch.localPoints();
202  treeBoundBox box(tgtPoints, tgtFace);
203 
204  if (tgtPatch.has0())
205  {
206  const pointField& tgtPoints0 = tgtPatch.localPoints();
207  box = combine(box, treeBoundBox(tgtPoints0, tgtFace));
208  }
209 
210  return box;
211 }
212 
213 
215 (
216  const primitiveOldTimePatch& tgtPatch
217 ) const
218 {
220 
221  forAll(tgtPatch, tgtFacei)
222  {
223  box = combine(box, tgtBox(tgtPatch, tgtFacei));
224  }
225 
226  box.inflate(rootSmall);
227 
228  return box;
229 }
230 
231 
233 (
234  const primitiveOldTimePatch& srcPatch,
235  const vectorField& srcPointNormals,
236  const vectorField& srcPointNormals0,
237  const primitiveOldTimePatch& tgtPatch,
238  const label srcFacei,
239  const label tgtFacei
240 )
241 {
242  // Return if these faces have already been intersected
243  auto intersected = []
244  (
245  const List<DynamicList<label>>& faceLocalFaces,
246  const label facei,
247  const label otherFacei
248  )
249  {
250  forAll(faceLocalFaces[facei], i)
251  {
252  if (faceLocalFaces[facei][i] == otherFacei)
253  {
254  return true;
255  }
256  }
257  return false;
258  };
259  if
260  (
261  intersected(srcLocalTgtFaces_, srcFacei, tgtFacei)
262  || intersected(tgtLocalSrcFaces_, tgtFacei, srcFacei)
263  )
264  {
265  return true;
266  }
267 
268  // Try to intersect these faces
269  return
270  intersectFaces
271  (
272  srcPatch,
273  srcPointNormals,
274  srcPointNormals0,
275  tgtPatch,
276  srcFacei,
277  tgtFacei
278  );
279 }
280 
281 
283 (
284  const primitiveOldTimePatch& srcPatch,
285  const vectorField& srcPointNormals,
286  const vectorField& srcPointNormals0,
287  const primitiveOldTimePatch& tgtPatch,
288  const bool isSrc,
289  const DynamicList<labelPair>& queue,
290  labelList& faceComplete,
291  DynamicList<labelPair>& otherQueue,
292  const labelList& otherFaceComplete,
293  boolList& otherFaceQueued,
294  boolList& otherFaceVisited
295 )
296 {
297  const primitivePatch& otherPatch = isSrc ? tgtPatch : srcPatch;
298 
299  const faceList& otherLocalFaces = otherPatch.localFaces();
300  //const labelListList& otherFaceFaces = otherPatch.faceFaces();
301  const labelListList& otherPointFaces = otherPatch.pointFaces();
302 
303  DynamicList<label> otherQueuedFaces;
304  label nFaceComplete = 0;
305  forAll(queue, queuei)
306  {
307  const label facei = queue[queuei].first();
308  const label otherFacei = queue[queuei].second();
309 
310  // Wave out from the initial target face until all intersections fail
311  DynamicList<label> otherCurrentFaces(1, otherFacei);
312  DynamicList<label> otherVisitedFaces(1, otherFacei);
313  otherFaceVisited[otherFacei] = true;
314  label otherPerimeterReached = false;
315  while (otherCurrentFaces.size())
316  {
317  labelList otherNextFaces;
318  forAll(otherCurrentFaces, otheri)
319  {
320  const label otherFacej = otherCurrentFaces[otheri];
321 
322  if
323  (
324  findOrIntersectFaces
325  (
326  srcPatch,
327  srcPointNormals,
328  srcPointNormals0,
329  tgtPatch,
330  isSrc ? facei : otherFacej,
331  isSrc ? otherFacej : facei
332  )
333  )
334  {
335  /*
336  // Propagate to edge neighbours
337  forAll(otherFaceFaces[otherFacej], otherFaceFacej)
338  {
339  const label otherFacek =
340  otherFaceFaces[otherFacej][otherFaceFacej];
341  if (!otherFaceVisited[otherFacek])
342  {
343  otherFaceVisited[otherFacek] = true;
344  otherVisitedFaces.append(otherFacek);
345  otherNextFaces.append(otherFacek);
346  }
347  }
348  */
349 
350  // Propagate to point neighbours
351  forAll(otherPatch[otherFacej], otherFacePointj)
352  {
353  const label otherPointj =
354  otherLocalFaces[otherFacej][otherFacePointj];
355  forAll(otherPointFaces[otherPointj], otherPointFacej)
356  {
357  const label otherFacek =
358  otherPointFaces[otherPointj][otherPointFacej];
359  if (!otherFaceVisited[otherFacek])
360  {
361  otherFaceVisited[otherFacek] = true;
362  otherVisitedFaces.append(otherFacek);
363  otherNextFaces.append(otherFacek);
364  }
365  }
366  }
367 
368  // Check if this face is connected to the perimeter
369  forAll(otherPatch[otherFacej], otherFaceEdgej)
370  {
371  const label otherEdgej =
372  otherPatch.faceEdges()[otherFacej][otherFaceEdgej];
373 
374  // !!! Two face-edges is not a sufficient condition for
375  // manifoldness. The edges also need to be numbered in
376  // opposite directions in the two faces.
377  if (otherPatch.edgeFaces()[otherEdgej].size() != 2)
378  {
379  otherPerimeterReached = true;
380  }
381  }
382 
383  // If this face is not complete, then add it to the next
384  // iteration's queue
385  if
386  (
387  otherFaceComplete[otherFacej] == 0
388  && !otherFaceQueued[otherFacej]
389  )
390  {
391  otherFaceQueued[otherFacej] = true;
392  otherQueuedFaces.append(otherFacej);
393  otherQueue.append(labelPair(otherFacej, facei));
394  }
395  }
396  }
397 
398  otherCurrentFaces.transfer(otherNextFaces);
399  }
400 
401  // Reset the visited array
402  forAll(otherVisitedFaces, otherVisitedFacei)
403  {
404  otherFaceVisited[otherVisitedFaces[otherVisitedFacei]] = false;
405  }
406 
407  // Set this face as complete
408  nFaceComplete -= faceComplete[facei] == 2;
409  faceComplete[facei] =
410  max(faceComplete[facei], otherPerimeterReached ? 1 : 2);
411  nFaceComplete += faceComplete[facei] == 2;
412  }
413 
414  // Reset the queued array
415  forAll(otherQueuedFaces, otherQueuedFacei)
416  {
417  otherFaceQueued[otherQueuedFaces[otherQueuedFacei]] = false;
418  }
419 
420  return nFaceComplete;
421 }
422 
423 
425 (
426  const primitiveOldTimePatch& srcPatch,
427  const vectorField& srcPointNormals,
428  const vectorField& srcPointNormals0,
429  const primitiveOldTimePatch& tgtPatch
430 )
431 {
432  if (srcPatch.empty() || tgtPatch.empty()) return;
433 
434  if (debug)
435  {
436  Info<< indent << "Writing patches" << incrIndent << endl;
437 
438  const fileName srcFileName = typeName + "_srcPatch.vtk";
439  Info<< indent << "Writing patch to " << srcFileName << endl;
441  (
442  srcFileName,
443  "source",
444  false,
445  srcPatch.localPoints(),
446  labelList(),
447  labelListList(),
448  srcPatch.localFaces()
449  );
450 
451  const fileName tgtFileName = typeName + "_tgtPatch.vtk";
452  Info<< indent << "Writing patch to " << tgtFileName << endl;
454  (
455  tgtFileName,
456  "target",
457  false,
458  tgtPatch.localPoints(),
459  labelList(),
460  labelListList(),
461  tgtPatch.localFaces()
462  );
463 
464  Info<< decrIndent;
465  }
466 
467  auto writeQueue = [&]
468  (
469  const label restarti,
470  const label iterationi,
471  const bool isSrc,
472  const DynamicList<labelPair>& queue
473  )
474  {
475  const primitivePatch& patch = isSrc ? srcPatch : tgtPatch;
476 
477  const fileName queueFileNamePart0 =
478  typeName + "_restarti=" + name(restarti) + "_iterationi=";
479  const fileName queueFileNamePart1 =
480  word(isSrc ? "src" : "tgt") + "Queue";
481 
482  Info<< incrIndent;
483 
484  if (iterationi == 0 || iterationi % 2 == !isSrc)
485  {
486  const fileName queueFileName =
487  queueFileNamePart0 + name(iterationi) + '_'
488  + queueFileNamePart1 + ".vtk";
489  Info<< indent << "Writing queue to " << queueFileName << endl;
491  (
492  queueFileName,
493  queueFileNamePart1,
494  false,
495  patch.localPoints(),
496  labelList(),
497  labelListList(),
498  IndirectList<face>(patch.localFaces(), first(queue))
499  );
500  }
501  else
502  {
503  ln
504  (
505  queueFileNamePart0 + name(iterationi - 1) + '_'
506  + queueFileNamePart1 + ".vtk",
507  queueFileNamePart0 + name(iterationi) + '_'
508  + queueFileNamePart1 + ".vtk"
509  );
510  }
511 
512  Info<< decrIndent;
513  };
514 
515  auto writeQueues = [&]
516  (
517  const label restarti,
518  const label iterationi,
519  const DynamicList<labelPair>& srcQueue,
520  const DynamicList<labelPair>& tgtQueue
521  )
522  {
523  if (debug)
524  {
525  Info<< indent << "Iteration #" << iterationi
526  << ": processing " << srcQueue.size() << '/'
527  << srcPatch.size() << " source and "
528  << tgtQueue.size() << '/' << tgtPatch.size()
529  << " target faces " << endl;
530  }
531 
532  if (debug > 1)
533  {
534  writeQueue(restarti, iterationi, true, srcQueue);
535  writeQueue(restarti, iterationi, false, tgtQueue);
536  }
537  };
538 
539  // Build a search tree for the target patch
541  const treeBoundBox tgtTreeBox =
542  treeBoundBox(tgtPatch.localPoints()).extend(1e-4);
544  (
545  treeType
546  (
547  false,
548  tgtPatch,
550  ),
551  tgtTreeBox,
552  8,
553  10,
554  3
555  );
556 
557  // Set up complete arrays and loop until they are full. Note that the
558  // *FaceComplete lists can take three values; 0 is incomplete, 1 is
559  // complete for this iteration only, 2 is fully complete.
560  if (debug)
561  {
562  Info<< indent << "Calculating coupling" << incrIndent << endl;
563  }
564 
565  label nSrcFaceComplete = 0, nTgtFaceComplete = 0;
566  labelList srcFaceComplete(srcPatch.size(), 0);
567  labelList tgtFaceComplete(tgtPatch.size(), 0);
568  boolList srcFaceQueued(srcPatch.size(), false);
569  boolList tgtFaceQueued(tgtPatch.size(), false);
570  boolList srcFaceVisited(srcPatch.size(), false);
571  boolList tgtFaceVisited(tgtPatch.size(), false);
572  label srcFacei = 0;
573  label restarti = 0;
574  while (srcFacei < srcPatch.size() && srcFacei != -1)
575  {
576  // Consider this face only once
577  srcFaceComplete[srcFacei] = 2;
578  nSrcFaceComplete ++;
579 
580  // Find target faces that overlap this source face's bound box
581  const labelList seedTgtFaces =
582  tgtTree.findBox
583  (
584  srcBox(srcPatch, srcPointNormals, srcPointNormals0, srcFacei)
585  );
586 
587  if (!seedTgtFaces.empty())
588  {
589  if (debug)
590  {
591  Info<< indent << "Restart #" << restarti
592  << " from at source face at "
593  << srcPatch.faceCentres()[srcFacei]
594  << incrIndent << endl;
595  }
596 
597  // Initialise queues with the target faces identified
598  DynamicList<labelPair> srcQueue, tgtQueue;
599  forAll(seedTgtFaces, seedTgtFacei)
600  {
601  const label tgtFacei = seedTgtFaces[seedTgtFacei];
602  srcQueue.append(labelPair(srcFacei, tgtFacei));
603  tgtQueue.append(labelPair(tgtFacei, srcFacei));
604  }
605 
606  if (debug)
607  {
608  writeQueues(restarti, 0, srcQueue, tgtQueue);
609  }
610 
611  // Do intersections until queues are empty
612  label iterationi = 0;
613  while (true)
614  {
615  tgtQueue.clear();
616 
617  nSrcFaceComplete +=
618  intersectPatchQueue
619  (
620  srcPatch,
621  srcPointNormals,
622  srcPointNormals0,
623  tgtPatch,
624  true,
625  srcQueue,
626  srcFaceComplete,
627  tgtQueue,
628  tgtFaceComplete,
629  tgtFaceQueued,
630  tgtFaceVisited
631  );
632 
633  if (debug)
634  {
635  writeQueues(restarti, 2*iterationi + 1, srcQueue, tgtQueue);
636  }
637 
638  if (!tgtQueue.size()) break;
639 
640  srcQueue.clear();
641 
642  nTgtFaceComplete +=
643  intersectPatchQueue
644  (
645  srcPatch,
646  srcPointNormals,
647  srcPointNormals0,
648  tgtPatch,
649  false,
650  tgtQueue,
651  tgtFaceComplete,
652  srcQueue,
653  srcFaceComplete,
654  srcFaceQueued,
655  srcFaceVisited
656  );
657 
658  if (debug)
659  {
660  writeQueues(restarti, 2*iterationi + 2, srcQueue, tgtQueue);
661  }
662 
663  if (!srcQueue.size()) break;
664 
665  ++ iterationi;
666  }
667 
668  if (debug)
669  {
670  Info<< indent << "Completed " << nSrcFaceComplete << '/'
671  << srcPatch.size() << " source faces " << decrIndent
672  << endl;
673  }
674  }
675 
676  // Find the next incomplete face
677  srcFacei = findNotIndex(srcFaceComplete, 2, srcFacei);
678 
679  ++ restarti;
680  }
681 
682  if (debug)
683  {
684  Info<< decrIndent;
685  }
686 }
687 
688 
690 (
691  const primitiveOldTimePatch& srcPatch,
692  const vectorField& srcPointNormals,
693  const vectorField& srcPointNormals0,
694  const primitiveOldTimePatch& tgtPatch
695 )
696 {
697  srcLocalTgtFaces_.resize(srcPatch.size());
698  forAll(srcLocalTgtFaces_, i)
699  {
700  srcLocalTgtFaces_[i].clear();
701  }
702 
703  tgtLocalSrcFaces_.resize(tgtPatch.size());
704  forAll(tgtLocalSrcFaces_, i)
705  {
706  tgtLocalSrcFaces_[i].clear();
707  }
708 }
709 
710 
713 (
714  const primitiveOldTimePatch& srcPatch,
715  const vectorField& srcPointNormals,
716  const vectorField& srcPointNormals0,
717  const primitiveOldTimePatch& tgtPatch,
718  distributionMap& tgtMap
719 )
720 {
721  tgtMap =
722  patchDistributionMap
723  (
724  tgtPatchSendFaces
725  (
726  srcPatch,
727  srcPointNormals,
728  srcPointNormals0,
729  tgtPatch
730  )
731  );
732 
733  if (localTgtProcFacesPtr_.empty())
734  {
735  localTgtProcFacesPtr_.set(new List<procFace>());
736  }
737 
738  return
740  (
742  (
743  distributePatch(tgtMap, tgtPatch, localTgtProcFacesPtr_())
744  )
745  );
746 }
747 
748 
751 (
752  const primitiveOldTimePatch& srcPatch,
753  distributionMap& srcMap
754 )
755 {
756  srcMap = patchDistributionMap(srcPatchSendFaces());
757 
758  if (localSrcProcFacesPtr_.empty())
759  {
760  localSrcProcFacesPtr_.set(new List<procFace>());
761  }
762 
763  return
765  (
767  (
768  distributePatch(srcMap, srcPatch, localSrcProcFacesPtr_())
769  )
770  );
771 }
772 
773 
775 (
776  const primitiveOldTimePatch& tgtPatch,
777  const distributionMap& tgtMap
778 )
779 {
780  // Create a map from source procFace to local source face
781  HashTable<label, procFace, Hash<procFace>> srcProcFaceToLocal;
782  forAll(localSrcProcFacesPtr_(), localSrcFacei)
783  {
784  srcProcFaceToLocal.insert
785  (
786  localSrcProcFacesPtr_()[localSrcFacei],
787  localSrcFacei
788  );
789  }
790 
791  // Collect the source procFaces on the target and convert to local
792  // source face addressing
793  List<List<procFace>> tgtSrcProcFaces =
794  localFacesToProcFaces(tgtLocalSrcFaces_);
795 
796  rDistributeListList(tgtPatch.size(), tgtMap, tgtSrcProcFaces);
797 
798  tgtLocalSrcFaces_ =
799  procFacesToLocalFaces(tgtSrcProcFaces, srcProcFaceToLocal);
800 }
801 
802 
804 (
805  const primitiveOldTimePatch& srcPatch,
806  const vectorField& srcPointNormals,
807  const vectorField& srcPointNormals0,
808  const primitiveOldTimePatch& tgtPatch,
809  const transformer& tgtToSrc
810 )
811 {
812  label nCouples = 0;
813 
814  forAll(srcLocalTgtFaces_, srcFacei)
815  {
816  nCouples += srcLocalTgtFaces_[srcFacei].size();
817  }
818  forAll(tgtLocalSrcFaces_, tgtFacei)
819  {
820  nCouples += tgtLocalSrcFaces_[tgtFacei].size();
821  }
822 
823  reduce(nCouples, sumOp<label>());
824 
825  return nCouples;
826 }
827 
828 
829 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
830 
832 :
833  reverse_(reverse),
834  singleProcess_(-labelMax),
835  localSrcProcFacesPtr_(nullptr),
836  localTgtProcFacesPtr_(nullptr),
837  srcLocalTgtFaces_(),
838  tgtLocalSrcFaces_()
839 {}
840 
841 
842 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
843 
845 {}
846 
847 
848 // * * * * * * * * * * * * * * * * Selector * * * * * * * * * * * * * * * * //
849 
851 (
852  const word& patchToPatchType,
853  const bool reverse
854 )
855 {
856  boolConstructorTable::iterator cstrIter =
857  boolConstructorTablePtr_->find(patchToPatchType);
858 
859  if (cstrIter == boolConstructorTablePtr_->end())
860  {
862  << "Unknown " << typeName << " type "
863  << patchToPatchType << endl << endl
864  << "Valid " << typeName << " types are : " << endl
865  << boolConstructorTablePtr_->sortedToc()
866  << exit(FatalError);
867  }
868 
869  return cstrIter()(reverse);
870 }
871 
872 
873 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
874 
876 (
877  const primitiveOldTimePatch& srcPatch,
878  const vectorField& srcPointNormals,
879  const vectorField& srcPointNormals0,
880  const primitiveOldTimePatch& tgtPatch,
881  const transformer& tgtToSrc
882 )
883 {
884  cpuTime time;
885 
886  // Determine numbers of faces on both sides, report, and quit if either
887  // side is empty
888  const label srcTotalSize = returnReduce(srcPatch.size(), sumOp<label>());
889  const label tgtTotalSize = returnReduce(tgtPatch.size(), sumOp<label>());
890  if (srcTotalSize == 0 || tgtTotalSize == 0)
891  {
892  return;
893  }
894 
895  // If a transformation is given then transform the target to the source
896  tmpNrc<primitiveOldTimePatch> tTgtPatchPtr(tgtPatch);
897  tmpNrc<pointField> tTgtPointsPtr(tgtPatch.localPoints());
898  tmpNrc<pointField> tTgtPoints0Ptr
899  (
900  tgtPatch.has0() ? tgtPatch.localPoints0() : NullObjectRef<pointField>()
901  );
902  if (!isNull(tgtToSrc))
903  {
904  tTgtPointsPtr = new pointField(tgtPatch.localPoints());
905  tgtToSrc.transformPosition
906  (
907  tTgtPointsPtr.ref(),
908  tTgtPointsPtr.ref()
909  );
910 
911  if (tgtPatch.has0())
912  {
913  tTgtPoints0Ptr = new pointField(tgtPatch.localPoints0());
914  tgtToSrc.transformPosition
915  (
916  tTgtPoints0Ptr.ref(),
917  tTgtPoints0Ptr.ref()
918  );
919  }
920 
921  tTgtPatchPtr =
922  tgtPatch.has0()
924  (
925  SubList<face>(tgtPatch.localFaces(), tgtPatch.size()),
926  tTgtPointsPtr(),
927  tTgtPoints0Ptr()
928  )
930  (
931  SubList<face>(tgtPatch.localFaces(), tgtPatch.size()),
932  tTgtPointsPtr()
933  );
934  }
935  const primitiveOldTimePatch& tTgtPatch = tTgtPatchPtr();
936 
937  Info<< indent << typeName << ": Calculating couplings between "
938  << srcTotalSize << " source faces and " << tgtTotalSize
939  << " target faces" << incrIndent << endl;
940 
941  // Determine if patches are present on multiple processors
942  calcSingleProcess(srcPatch, tTgtPatch);
943 
944  // Do intersection in serial or parallel as appropriate
945  if (isSingleProcess())
946  {
947  // Initialise the workspace
948  initialise(srcPatch, srcPointNormals, srcPointNormals0, tTgtPatch);
949 
950  // Intersect the patches
951  const treeBoundBox srcPatchBox =
952  srcBox(srcPatch, srcPointNormals, srcPointNormals0);
953  const treeBoundBox tgtPatchBox = tgtBox(tTgtPatch);
954  if (srcPatchBox.overlaps(tgtPatchBox))
955  {
957  (
958  srcPatch,
959  srcPointNormals,
960  srcPointNormals0,
961  tTgtPatch
962  );
963  }
964  }
965  else
966  {
967  // Distribute the target
968  distributionMap tgtMap;
971  (
972  srcPatch,
973  srcPointNormals,
974  srcPointNormals0,
975  tTgtPatch,
976  tgtMap
977  );
978 
979  // Massage target patch into form that can be used by the serial
980  // intersection interface
981  const primitiveOldTimePatch localTTgtPatch =
982  tgtPatch.has0()
984  (
985  SubList<face>(localTTgtPatchPtr(), localTTgtPatchPtr().size()),
986  localTTgtPatchPtr().points(),
987  localTTgtPatchPtr().points0()
988  )
990  (
991  SubList<face>(localTTgtPatchPtr(), localTTgtPatchPtr().size()),
992  localTTgtPatchPtr().points()
993  );
994 
995  // Initialise the workspace
996  initialise(srcPatch, srcPointNormals, srcPointNormals, localTTgtPatch);
997 
998  // Intersect the patches
999  if (localTTgtPatch.size())
1000  {
1002  (
1003  srcPatch,
1004  srcPointNormals,
1005  srcPointNormals,
1006  localTTgtPatch
1007  );
1008  }
1009 
1010  // Distribute the source
1011  distributionMap srcMap;
1013  distributeSrc(srcPatch, srcMap);
1014 
1015  // Reverse distribute coupling data back to the target
1016  rDistributeTgt(tgtPatch, tgtMap);
1017  }
1018 
1019  // Finalise the intersection
1020  const label nCouples =
1021  finalise
1022  (
1023  srcPatch,
1024  srcPointNormals,
1025  srcPointNormals,
1026  tgtPatch,
1027  tgtToSrc
1028  );
1029 
1030  if (nCouples != 0)
1031  {
1032  Info<< indent << nCouples << " couplings calculated in "
1033  << time.cpuTimeIncrement() << 's' << endl;
1034  }
1035  else
1036  {
1037  Info<< indent << "No couplings found" << endl;
1038  }
1039 
1040  Info<< decrIndent;
1041 }
1042 
1043 
1046  const primitivePatch& srcPatch,
1047  const vectorField& srcPointNormals,
1048  const primitivePatch& tgtPatch,
1049  const transformer& tgtToSrc
1050 )
1051 {
1052  update
1053  (
1054  primitiveOldTimePatch(srcPatch),
1055  srcPointNormals,
1056  NullObjectRef<vectorField>(),
1057  primitiveOldTimePatch(tgtPatch),
1058  tgtToSrc
1059  );
1060 }
1061 
1062 
1063 // ************************************************************************* //
bool overlaps(const boundBox &) const
Overlaps/touches boundingBox?
Definition: boundBoxI.H:120
labelList first(const UList< labelPair > &p)
Definition: patchToPatch.C:38
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
virtual treeBoundBox srcBox(const face &srcFace, const pointField &srcPoints, const vectorField &srcPointNormals) const =0
Get the bound box for a source face.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
bool empty() const
Return true if the UList is empty (ie, size() is zero)
Definition: UListI.H:325
virtual void rDistributeTgt(const primitiveOldTimePatch &tgtPatch, const distributionMap &tgtMap)
Send data that resulted from an intersection between the source.
Definition: patchToPatch.C:775
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
A class for handling file names.
Definition: fileName.H:79
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:221
Vector-tensor class used to perform translations, rotations and scaling operations in 3D space...
Definition: transformer.H:83
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
error FatalError
patchToPatch(const bool reverse)
Construct from components.
Definition: patchToPatch.C:831
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
const Field< PointType > & faceCentres() const
Return face centres for patch.
Structure to conveniently store processor and face indices.
Definition: patchToPatch.H:60
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
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
bool reverse() const
Flag to indicate that the two patches are co-directional and.
Definition: patchToPatchI.H:87
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
const dimensionedScalar b
Wien displacement law constant: default SI units: [m K].
Definition: createFields.H:27
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
void intersectPatches(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch)
Intersect the patches.
Definition: patchToPatch.C:425
T & ref()
Return non-const reference or generate a fatal error.
Definition: tmpNrcI.H:136
static List< DynamicList< label > > procFacesToLocalFaces(const List< List< procFace >> &procFaces, const HashTable< label, procFace, Hash< procFace >> &map)
Map proc faces to local faces.
Definition: patchToPatch.C:123
const Field< PointType > & localPoints() const
Return pointField of points in patch.
T & first()
Return the first element of the list.
Definition: UListI.H:114
bool has0() const
Return whether or not old-time geometry is available.
label findNotIndex(const ListType &l, typename ListType::const_reference t, const label start=0)
Definition: patchToPatch.C:60
virtual tmpNrc< PrimitiveOldTimePatch< faceList, pointField > > distributeSrc(const primitiveOldTimePatch &srcPatch, distributionMap &srcMap)
Distribute the source patch so that everything the target.
Definition: patchToPatch.C:751
static List< List< procFace > > localFacesToProcFaces(const List< DynamicList< label >> &localFaces, const List< procFace > &map=NullObjectRef< List< procFace >>())
Map local faces to proc faces.
Definition: patchToPatch.C:97
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
label intersectPatchQueue(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch, const bool isSrc, const DynamicList< labelPair > &queue, labelList &faceComplete, DynamicList< labelPair > &otherQueue, const labelList &otherFaceComplete, boolList &otherFaceQueued, boolList &otherFaceVisited)
Intersect a queue of source-target face pairs. Update completion.
Definition: patchToPatch.C:283
A list of faces which address into the list of points.
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))
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
bool isNull(const T &t)
Return true if t is a reference to the nullObject of type T.
Definition: nullObjectI.H:46
static autoPtr< patchToPatch > New(const word &patchToPatchType, const bool reverse)
Select from name.
Definition: patchToPatch.C:851
const pointField & points
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
PrimitiveOldTimePatch< SubList< face >, const pointField & > primitiveOldTimePatch
Addressing for a faceList slice.
A class for handling words, derived from string.
Definition: word.H:59
double cpuTimeIncrement() const
Return CPU time (in seconds) since last call to cpuTimeIncrement()
Definition: cpuTime.C:60
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
Encapsulation of data needed to search on PrimitivePatches.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
virtual tmpNrc< PrimitiveOldTimePatch< faceList, pointField > > distributeTgt(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch, distributionMap &tgtMap)
Distribute the target patch so that enough is locally available.
Definition: patchToPatch.C:713
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
const labelListList & edgeFaces() const
Return edge-face addressing.
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48
static const label labelMax
Definition: label.H:62
List< label > labelList
A List of labels.
Definition: labelList.H:56
virtual ~patchToPatch()
Destructor.
Definition: patchToPatch.C:844
An STL-conforming hash table.
Definition: HashTable.H:61
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
bool ln(const fileName &src, const fileName &dst)
Create a softlink. dst should not exist. Returns true if successful.
Definition: POSIX.C:908
void inflate(const scalar s)
Inflate box by factor*mag(span) in all dimensions.
Definition: boundBox.C:210
const labelListList & pointFaces() const
Return point-face addressing.
bool findOrIntersectFaces(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch, const label srcFacei, const label tgtFacei)
Intersect two faces.
Definition: patchToPatch.C:233
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
defineTypeNameAndDebug(combustionModel, 0)
void update(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch, const transformer &tgtToSrc=NullObjectRef< transformer >())
Update addressing and weights for the given patches.
Definition: patchToPatch.C:876
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:235
void write(const fileName &file, const word &title, const bool binary, const PointField &points, const VertexList &vertices, const LineList &lines, const FaceList &faces, const wordList &fieldNames, const boolList &fieldIsPointValues, const UPtrList< const Field< label >> &fieldLabelValues #define FieldTypeValuesConstArg(Type, nullArg))
Write VTK polygonal data to a file. Takes a PtrList of fields of labels and.
labelList f(nPoints)
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
labelList second(const UList< labelPair > &p)
Definition: patchToPatch.C:48
A class for managing temporary objects without reference counting.
Definition: tmpNrc.H:52
virtual label finalise(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch, const transformer &tgtToSrc)
Finalising.
Definition: patchToPatch.C:804
const point & max() const
Maximum point defining the bounding box.
Definition: boundBoxI.H:60
Class containing processor-to-processor mapping information.
void calcSingleProcess(const primitiveOldTimePatch &srcPatch, const primitiveOldTimePatch &tgtPatch)
Determine whether or not the intersection of the given patches.
Non-pointer based hierarchical recursive searching.
Definition: treeDataEdge.H:47
const Field< PointType > & localPoints0() const
Return pointField of old-time points in patch.
const List< FaceType > & localFaces() const
Return patch faces addressing into local point list.
static const treeBoundBox invertedBox
As per boundBox::invertedBox, but with great instead of vGreat.
Definition: treeBoundBox.H:108
Hash function class for primitives. All non-primitives used to hash entries on hash tables likely nee...
Definition: Hash.H:52
Standard boundBox + extra functionality for use in octree.
Definition: treeBoundBox.H:87
messageStream Info
const labelListList & faceEdges() const
Return face-edge addressing.
treeBoundBox tgtBox(const primitiveOldTimePatch &tgtPatch, const label tgtFacei) const
Get the bound box for a target face.
Definition: patchToPatch.C:195
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
vector transformPosition(const vector &v) const
Transform the given position.
Definition: transformerI.H:153
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:52
const doubleScalar e
Elementary charge.
Definition: doubleScalar.H:105
Starts timing CPU usage and return elapsed time from start.
Definition: cpuTime.H:54
const point & min() const
Minimum point defining the bounding box.
Definition: boundBoxI.H:54
virtual void initialise(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch)
Initialisation.
Definition: patchToPatch.C:690
volScalarField & p
label size() const
Return the number of elements in the UList.
Definition: UListI.H:311
void clear()
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:236
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:228
void transfer(List< T > &)
Transfer contents of the argument List into this.
Definition: DynamicListI.H:285
Class to generate coupling geometry between two primitive patches.
Definition: patchToPatch.H:53
Namespace for OpenFOAM.
treeBoundBox combine(const treeBoundBox &a, const treeBoundBox &b)
Definition: patchToPatch.C:77
bool isSingleProcess() const
Is this intersection on a single process?
Definition: patchToPatchI.H:99