cyclicACMIGAMGInterface.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2013-2016 OpenFOAM Foundation
9  Copyright (C) 2019-2025 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "AMIInterpolation.H"
32 #include "Map.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38  defineTypeNameAndDebug(cyclicACMIGAMGInterface, 0);
40  (
41  GAMGInterface,
42  cyclicACMIGAMGInterface,
43  lduInterface
44  );
46  (
47  GAMGInterface,
48  cyclicACMIGAMGInterface,
49  Istream
50  );
51 }
52 
53 
54 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
55 
56 Foam::cyclicACMIGAMGInterface::cyclicACMIGAMGInterface
57 (
58  const label index,
59  const lduInterfacePtrsList& coarseInterfaces,
60  const lduInterface& fineInterface,
61  const labelField& localRestrictAddressing,
62  const labelField& neighbourRestrictAddressing,
63  const label fineLevelIndex,
64  const label coarseComm
65 )
66 :
68  (
69  index,
70  coarseInterfaces
71  ),
72  neighbPatchID_
73  (
74  refCast<const cyclicACMILduInterface>(fineInterface).neighbPatchID()
75  ),
76  owner_
77  (
78  refCast<const cyclicACMILduInterface>(fineInterface).owner()
79  ),
80  forwardT_
81  (
82  refCast<const cyclicACMILduInterface>(fineInterface).forwardT()
83  ),
84  reverseT_
85  (
86  refCast<const cyclicACMILduInterface>(fineInterface).reverseT()
87  ),
88  myProcNo_(-1)
89 {
90  const auto& fineCyclicACMIInterface =
91  refCast<const cyclicACMILduInterface>(fineInterface);
92 
93  // Construct face agglomeration from cell agglomeration
94  {
95  // From coarse face to cell
96  DynamicList<label> dynFaceCells(localRestrictAddressing.size());
97 
98  // From face to coarse face
99  DynamicList<label> dynFaceRestrictAddressing
100  (
101  localRestrictAddressing.size()
102  );
103 
104  Map<label> masterToCoarseFace(localRestrictAddressing.size());
105 
106  for (const label curMaster : localRestrictAddressing)
107  {
108  const auto iter = masterToCoarseFace.cfind(curMaster);
109 
110  if (iter.good())
111  {
112  // Already have coarse face
113  dynFaceRestrictAddressing.append(iter.val());
114  }
115  else
116  {
117  // New coarse face
118  const label coarseI = dynFaceCells.size();
119  dynFaceRestrictAddressing.append(coarseI);
120  dynFaceCells.append(curMaster);
121  masterToCoarseFace.insert(curMaster, coarseI);
122  }
123  }
124 
125  faceCells_.transfer(dynFaceCells);
126  faceRestrictAddressing_.transfer(dynFaceRestrictAddressing);
127  }
128 
129 
130  // On the owner side construct the AMI
131 
132  if (fineCyclicACMIInterface.owner())
133  {
134  // Construct the neighbour side agglomeration (as the neighbour would
135  // do it so it the exact loop above using neighbourRestrictAddressing
136  // instead of localRestrictAddressing)
137 
138  labelList nbrFaceRestrictAddressing;
139  {
140  // From face to coarse face
141  DynamicList<label> dynNbrFaceRestrictAddressing
142  (
143  neighbourRestrictAddressing.size()
144  );
145 
146  Map<label> masterToCoarseFace(neighbourRestrictAddressing.size());
147 
148  for (const label curMaster : neighbourRestrictAddressing)
149  {
150  const auto iter = masterToCoarseFace.cfind(curMaster);
151 
152  if (iter.good())
153  {
154  // Already have coarse face
155  dynNbrFaceRestrictAddressing.append(iter.val());
156  }
157  else
158  {
159  // New coarse face
160  const label coarseI = masterToCoarseFace.size();
161  dynNbrFaceRestrictAddressing.append(coarseI);
162  masterToCoarseFace.insert(curMaster, coarseI);
163  }
164  }
165 
166  nbrFaceRestrictAddressing.transfer(dynNbrFaceRestrictAddressing);
167  }
168 
169 
170  amiPtr_.reset
171  (
173  (
174  fineCyclicACMIInterface.AMI(),
176  nbrFaceRestrictAddressing
177  )
178  );
179  }
180 }
181 
182 
183 Foam::cyclicACMIGAMGInterface::cyclicACMIGAMGInterface
184 (
185  const label index,
186  const lduInterfacePtrsList& coarseInterfaces,
187  Istream& is
188 )
189 :
190  GAMGInterface(index, coarseInterfaces, is),
191  neighbPatchID_(readLabel(is)),
192  owner_(readBool(is)),
193  forwardT_(is),
194  reverseT_(is),
195  myProcNo_(-1)
196 {
197  const bool hasAMI(readBool(is));
198 
199  if (hasAMI)
200  {
201  amiPtr_.reset(new AMIPatchToPatchInterpolation(is));
202 
203  // Store originating ranks locally - used when processor agglomerating
204  // onto a processor that wasn't in the communicator originally (since
205  // it had no faces)
206  const label comm = AMI().comm();
207 
208  if (comm != -1)
209  {
210  is >> myProcNo_;
211  }
212  }
213 }
214 
215 
216 Foam::cyclicACMIGAMGInterface::cyclicACMIGAMGInterface
217 (
218  const label index,
219  const lduInterfacePtrsList& coarseInterfaces,
220  const lduInterface& fineInterface,
221  const labelList& interfaceMap,
222  const labelUList& faceCells,
223  const labelUList& faceRestrictAddresssing,
224  const labelUList& faceOffsets,
225  const lduInterfacePtrsList& allInterfaces,
226  const label coarseComm,
227  const label myProcNo,
228  const labelList& procAgglomMap
229 )
230 :
231  GAMGInterface
232  (
233  index,
234  coarseInterfaces,
235  faceCells,
236  faceRestrictAddresssing
237  ),
238  neighbPatchID_
239  (
240  interfaceMap.find
241  (
242  refCast
243  <
244  const cyclicACMILduInterface
245  >(fineInterface).neighbPatchID()
246  )
247  ),
248  owner_
249  (
250  refCast<const cyclicACMILduInterface>(fineInterface).owner()
251  ),
252  forwardT_
253  (
254  refCast<const cyclicACMILduInterface>(fineInterface).forwardT()
255  ),
256  reverseT_
257  (
258  refCast<const cyclicACMILduInterface>(fineInterface).reverseT()
259  ),
260  myProcNo_(-1)
261 {
262  if (!owner_)
263  {
264  return;
265  }
266 
267 
268  // Get stats, sizes from the input interfaces. For the global settings
269  // the problem is that the
270  // local processor might not have any valid interfaces so here just
271  // collect and do a global reduction afterwards.
272 
273  // Structure to pack all. First element is used to decide who has the
274  // valid AMI.
275  typedef
276  Tuple2
277  <
278  label,
279  Tuple2
280  <
281  Tuple2
282  <
283  FixedList<bool, 4>,
284  scalar
285  >,
286  label
287  >
288  > AMIType;
289 
290  AMIType globalInfo;
291  FixedList<bool, 4>& bools = globalInfo.second().first().first();
292 
293  // Define aliases to make our life easier
294  label& firstValidAMI = globalInfo.first();
295  bool& requireMatch = bools[0];
296  bool& reverseTarget = bools[1];
297  bool& srcHasFlip = bools[2];
298  bool& tgtHasFlip = bools[3];
299  scalar& lowWeightCorrection = globalInfo.second().first().second();
300  label& singlePatchProc = globalInfo.second().second();
301 
302  // Initialise all global variables
303  firstValidAMI = labelMax;
304  requireMatch = false;
305  reverseTarget = false;
306  srcHasFlip = false;
307  tgtHasFlip = false;
308  lowWeightCorrection = -1;
309  singlePatchProc = -1;
310 
311  // Initialise all local variables
312  bool hasSrcMagSf = false;
313  bool hasSrcCentroids = false;
314  bool hasTgtMagSf = false;
315  label nSrc = 0;
316  label nTgt = 0;
317 
318  forAll(allInterfaces, inti)
319  {
320  if (allInterfaces.set(inti))
321  {
322  const auto& intf =
323  refCast<const cyclicACMIGAMGInterface>(allInterfaces[inti]);
324 
325  if (!intf.amiPtr_)
326  {
327  continue;
328  }
329 
330  if (firstValidAMI == labelMax)
331  {
332  firstValidAMI = inti;
333  }
334 
335  const auto& AMI = intf.AMI();
336 
337  if (AMI.distributed() && AMI.comm() != -1)
338  {
339  singlePatchProc = -1;
340  srcHasFlip =
341  srcHasFlip || AMI.srcMap().constructHasFlip();
342  tgtHasFlip =
343  tgtHasFlip || AMI.tgtMap().constructHasFlip();
344  }
345  requireMatch = AMI.requireMatch();
346  reverseTarget = AMI.reverseTarget();
347  lowWeightCorrection = AMI.lowWeightCorrection();
348 
349  nSrc += AMI.srcAddress().size();
350  nTgt += AMI.tgtAddress().size();
351 
352  if (AMI.srcMagSf().size())
353  {
354  hasSrcMagSf = true;
355  if (AMI.srcMagSf().size() != AMI.srcAddress().size())
356  {
358  << "srcMagSf size:" << AMI.srcMagSf().size()
359  << "srcAddress size:" << AMI.srcAddress().size()
360  << exit(FatalError);
361  }
362  }
363  if (AMI.srcCentroids().size())
364  {
365  hasSrcCentroids = true;
366  if (AMI.srcCentroids().size() != AMI.srcAddress().size())
367  {
369  << "srcCentroids size:" << AMI.srcCentroids().size()
370  << "srcAddress size:" << AMI.srcAddress().size()
371  << exit(FatalError);
372  }
373  }
374  if (AMI.tgtMagSf().size())
375  {
376  hasTgtMagSf = true;
377  if (AMI.tgtMagSf().size() != AMI.tgtAddress().size())
378  {
380  << "tgtMagSf size:" << AMI.tgtMagSf().size()
381  << "tgtAddress size:" << AMI.tgtAddress().size()
382  << exit(FatalError);
383  }
384  }
385  }
386  }
387 
388 
389  // Reduce global information in case one of the coarse ranks does not
390  // have an input AMI to get data from. Could use minFirstEqOp from Tuple2
391  // instead ...
393  (
394  globalInfo,
395  [](AMIType& x, const AMIType& y)
396  {
397  if (y.first() < x.first())
398  {
399  x = y;
400  }
401  },
403  coarseComm
404  );
405 
406  DebugPout
407  << "Input amis :"
408  << " singlePatchProc:" << singlePatchProc
409  << " srcHasFlip:" << srcHasFlip
410  << " tgtHasFlip:" << tgtHasFlip
411  << " requireMatch:" << requireMatch
412  << " reverseTarget:" << reverseTarget
413  << " lowWeightCorrection:" << lowWeightCorrection
414  << " hasSrcMagSf:" << hasSrcMagSf
415  << " hasSrcCentroids:" << hasSrcCentroids
416  << " hasTgtMagSf:" << hasTgtMagSf
417  << " nSrc:" << nSrc
418  << " nTgt:" << nTgt
419  << endl;
420 
421 
422  labelListList srcAddress;
423  scalarListList srcWeights;
424  scalarList srcMagSf;
425  // Needed?
426  pointListList srcCentroids;
427 
428  labelListList tgtAddress;
429  scalarListList tgtWeights;
430  scalarList tgtMagSf;
431 
432 
433  // Map to send src side data to tgt side
434  autoPtr<mapDistribute> srcToTgtMap;
435 
436  // Map to send tgt side data to src side
437  autoPtr<mapDistribute> tgtToSrcMap;
438 
439  if (singlePatchProc == -1)
440  {
441  // Find ranks that agglomerate together
442  const label myAgglom = UPstream::myProcNo(coarseComm);
443 
444  // Per input map either -1 or the index in the maps that is local
445  // data.
446  labelList localRanks(allInterfaces.size(), -1);
447  // From rank in coarse communicator back to rank in original (fine)
448  // communicator.
449  labelListList newToOldRanks;
450  {
451  // Pass 1: count number of valid maps
452  label nOldRanks = 0;
453  forAll(allInterfaces, inti)
454  {
455  if (allInterfaces.set(inti))
456  {
457  const auto& intf = refCast<const cyclicACMIGAMGInterface>
458  (
459  allInterfaces[inti]
460  );
461 
462  if (!intf.amiPtr_ || intf.AMI().comm() == -1)
463  {
464  continue;
465  }
466  nOldRanks++;
467  }
468  }
469 
470  // Pass 2: collect
471  DynamicList<label> oldRanks(nOldRanks);
472  forAll(allInterfaces, inti)
473  {
474  if (allInterfaces.set(inti))
475  {
476  const auto& intf = refCast<const cyclicACMIGAMGInterface>
477  (
478  allInterfaces[inti]
479  );
480 
481  if (!intf.amiPtr_ || intf.AMI().comm() == -1)
482  {
483  continue;
484  }
485 
486  label fineRank = -1;
487  if (intf.myProcNo() == -1)
488  {
489  // The interface was already local so got never
490  // sent across so myProcNo_ is never set ...
491  fineRank = UPstream::myProcNo(intf.AMI().comm());
492  }
493  else
494  {
495  fineRank = intf.myProcNo();
496  }
497 
498  oldRanks.append(fineRank);
499  localRanks[inti] = fineRank;
500  }
501  }
502 
503  // Pull individual parts together - this is the only communication
504  // needed.
505  newToOldRanks = Pstream::listGatherValues
506  (
507  labelList(std::move(oldRanks)),
508  coarseComm
509  );
510  Pstream::broadcast(newToOldRanks, coarseComm);
511  }
512 
513 
514  // Create combined maps
515  UPtrList<const mapDistribute> srcMaps(allInterfaces.size());
516  UPtrList<const mapDistribute> tgtMaps(allInterfaces.size());
517  forAll(allInterfaces, inti)
518  {
519  if (allInterfaces.set(inti))
520  {
521  const auto& intf = refCast<const cyclicACMIGAMGInterface>
522  (
523  allInterfaces[inti]
524  );
525 
526  if (!intf.amiPtr_)
527  {
528  // Should not be in allInterfaces?
529  continue;
530  }
531 
532  const auto& AMI = intf.AMI();
533 
534  if (AMI.comm() != -1)
535  {
536  srcMaps.set(inti, &AMI.srcMap());
537  tgtMaps.set(inti, &AMI.tgtMap());
538  }
539  }
540  }
541 
542 
543  // Offsets for slots into results of srcToTgtMap
544  labelList srcStartOfLocal;
545  List<Map<label>> srcCompactMaps;
546 
547  srcToTgtMap.reset
548  (
549  new mapDistribute
550  (
551  srcMaps,
552  localRanks, // per src map which rank represents local data
553  coarseComm,
554  newToOldRanks, // destination rank to source ranks
555  srcStartOfLocal,
556  srcCompactMaps
557  )
558  );
559 
560 
561  // Assemble tgtAddress
562  tgtAddress.setSize(nTgt);
563  if (tgtAddress.size())
564  {
565  label alli = 0;
566  forAll(allInterfaces, inti)
567  {
568  if (allInterfaces.set(inti))
569  {
570  const auto& intf = refCast<const cyclicACMIGAMGInterface>
571  (
572  allInterfaces[inti]
573  );
574 
575  if (!intf.amiPtr_)
576  {
577  continue;
578  }
579 
580  const auto& AMI = intf.AMI();
581  const auto& tgtSlots = AMI.tgtAddress();
582  const label localSize =
583  srcStartOfLocal[inti+1]
584  - srcStartOfLocal[inti];
585 
586  forAll(tgtSlots, tgti)
587  {
588  // Append old slots: copy old values and adapt
589  auto& newSlots = tgtAddress[alli++];
590  newSlots = tgtSlots[tgti];
591 
592  // Renumber to new indices
594  (
595  newSlots,
596  localSize,
597  srcStartOfLocal[inti],
598  srcCompactMaps[inti],
599  srcHasFlip //hasFlip
600  );
601 
602  for (const label slot : newSlots)
603  {
604  if
605  (
606  slot < 0
607  || slot >= srcToTgtMap().constructSize()
608  )
609  {
610  FatalErrorInFunction << " newSlots:"
611  << newSlots << exit(FatalError);
612  }
613  }
614  }
615  }
616  }
617 
618  if (nTgt != alli)
619  {
620  FatalErrorInFunction << "nTgt:" << nTgt
621  << " alli:" << alli << exit(FatalError);
622  }
623  }
624 
625  // Offsets for slots into results of tgtToSrcMap
626  labelList tgtStartOfLocal;
627  List<Map<label>> tgtCompactMaps;
628 
629  tgtToSrcMap.reset
630  (
631  new mapDistribute
632  (
633  tgtMaps,
634  localRanks,
635  coarseComm,
636  newToOldRanks,
637  tgtStartOfLocal,
638  tgtCompactMaps
639  )
640  );
641 
642 
643  // Assemble srcAddress
644  srcAddress.setSize(nSrc);
645  if (srcAddress.size())
646  {
647  label alli = 0;
648  forAll(allInterfaces, inti)
649  {
650  if (allInterfaces.set(inti))
651  {
652  const auto& intf = refCast<const cyclicACMIGAMGInterface>
653  (
654  allInterfaces[inti]
655  );
656 
657  if (!intf.amiPtr_)
658  {
659  continue;
660  }
661 
662  const auto& AMI = intf.AMI();
663  const auto& srcSlots = AMI.srcAddress();
664  const label localSize =
665  tgtStartOfLocal[inti+1]
666  - tgtStartOfLocal[inti];
667 
668  forAll(srcSlots, srci)
669  {
670  // Append old slots: copy old values and adapt
671  auto& newSlots = srcAddress[alli++];
672  newSlots = srcSlots[srci];
673  // Renumber to new indices
675  (
676  newSlots,
677  localSize,
678  tgtStartOfLocal[inti],
679  tgtCompactMaps[inti],
680  tgtHasFlip
681  );
682 
683  for (const label slot : newSlots)
684  {
685  if
686  (
687  slot < 0
688  || slot >= tgtToSrcMap().constructSize()
689  )
690  {
691  FatalErrorInFunction << " newSlots:"
692  << newSlots << exit(FatalError);
693  }
694  }
695  }
696  }
697  }
698 
699  if (nSrc != alli)
700  {
701  FatalErrorInFunction << "nSrc:" << nSrc
702  << " alli:" << alli << exit(FatalError);
703  }
704  }
705 
706 
707  // Clean up: if no remote elements sent/received mark as
708  // non-distributed. We could do this at the start but this
709  // needs to take all the internal transport into account. Easier
710  // (but less efficient) to do afterwards now all is compacted.
711  {
712  const auto& map = srcToTgtMap().subMap();
713 
714  bool usesRemote = false;
715  forAll(map, proci)
716  {
717  if (proci != myAgglom)
718  {
719  const auto& ss = srcToTgtMap().subMap()[proci];
720  const auto& sc = srcToTgtMap().constructMap()[proci];
721  const auto& ts = tgtToSrcMap().subMap()[proci];
722  const auto& tc = tgtToSrcMap().constructMap()[proci];
723 
724  if (ss.size() || sc.size() || ts.size() || tc.size())
725  {
726  usesRemote = true;
727  break;
728  }
729  }
730  }
731 
732  // We can't have a single rank become fully-local since we
733  // expect singlePatchProc to be synchronised. So make sure all
734  // have become local
735 
736  if (!returnReduceOr(usesRemote, coarseComm))
737  {
738  DebugPout<< "** making fully local on new rank "
739  << myAgglom << " in comm:" << coarseComm << endl;
740  singlePatchProc = myAgglom;
741  srcToTgtMap.clear();
742  tgtToSrcMap.clear();
743  }
744  }
745  }
746  else
747  {
748  // src/tgt address are straight indices
749 
750  srcAddress.setSize(nSrc);
751  tgtAddress.setSize(nTgt);
752 
753  nSrc = 0;
754  nTgt = 0;
755  forAll(allInterfaces, inti)
756  {
757  if (allInterfaces.set(inti))
758  {
759  const auto& intf = refCast<const cyclicACMIGAMGInterface>
760  (
761  allInterfaces[inti]
762  );
763 
764  if (!intf.amiPtr_)
765  {
766  continue;
767  }
768 
769  const auto& AMI = intf.AMI();
770 
771  const auto& srcA = AMI.srcAddress();
772  if (srcAddress.size())
773  {
774  label srci = nSrc;
775  forAll(srcA, i)
776  {
777  srcAddress[srci++] = srcA[i]+nTgt;
778  }
779  }
780 
781  const auto& tgtA = AMI.tgtAddress();
782  if (tgtAddress.size())
783  {
784  label tgti = nTgt;
785  forAll(tgtA, i)
786  {
787  tgtAddress[tgti++] = tgtA[i]+nSrc;
788  }
789  }
790 
791  nSrc += srcA.size();
792  nTgt += tgtA.size();
793  }
794  }
795  }
796 
797  srcWeights.setSize(nSrc);
798  if (hasSrcMagSf)
799  {
800  srcMagSf.setSize(nSrc);
801  }
802  if (hasSrcCentroids)
803  {
804  srcCentroids.setSize(nSrc);
805  }
806  tgtWeights.setSize(nTgt);
807  if (hasTgtMagSf)
808  {
809  tgtMagSf.setSize(nTgt);
810  }
811 
812 
813  // Append individual data
814  nSrc = 0;
815  nTgt = 0;
816  forAll(allInterfaces, inti)
817  {
818  if (allInterfaces.set(inti))
819  {
820  const auto& intf = refCast<const cyclicACMIGAMGInterface>
821  (
822  allInterfaces[inti]
823  );
824 
825  if (!intf.amiPtr_)
826  {
827  continue;
828  }
829 
830  const auto& AMI = intf.AMI();
831 
832  const auto& srcA = AMI.srcAddress();
833  {
834  // weights
835  SubList<scalarList>(srcWeights, srcA.size(), nSrc) =
836  AMI.srcWeights();
837 
838  // magSf
839  if (hasSrcMagSf)
840  {
841  SubList<scalar>(srcMagSf, srcA.size(), nSrc) =
842  AMI.srcMagSf();
843  }
844 
845  // centroids
846  if (hasSrcCentroids)
847  {
848  SubList<pointList>(srcCentroids, srcA.size(), nSrc) =
849  AMI.srcCentroids();
850  }
851  }
852 
853  const auto& tgtA = AMI.tgtAddress();
854  {
855  // weights
856  SubList<scalarList>(tgtWeights, tgtA.size(), nTgt) =
857  AMI.tgtWeights();
858 
859  if (hasTgtMagSf)
860  {
861  SubList<scalar>(tgtMagSf, tgtA.size(), nTgt) =
862  AMI.tgtMagSf();
863  }
864  }
865 
866  nSrc += srcA.size();
867  nTgt += tgtA.size();
868  }
869  }
870 
871 
872  // Construct with same arguments as original
873  amiPtr_.reset
874  (
876  (
877  requireMatch,
878  reverseTarget,
879  lowWeightCorrection
880  )
881  );
882  amiPtr_().comm(coarseComm),
883  amiPtr_().reset
884  (
885  std::move(srcToTgtMap),
886  std::move(tgtToSrcMap),
887  std::move(srcAddress),
888  std::move(srcWeights),
889  std::move(tgtAddress),
890  std::move(tgtWeights),
891  singlePatchProc
892  );
893  amiPtr_().srcMagSf() = std::move(srcMagSf);
894  amiPtr_().srcCentroids() = std::move(srcCentroids);
895  amiPtr_().tgtMagSf() = std::move(tgtMagSf);
896 
897  //Pout<< "** constructed new ami:"
898  // << " comm:" << amiPtr_().comm()
899  // << " srcMap.comm:" << amiPtr_().srcMap().comm()
900  // << " tgtMap.comm:" << amiPtr_().tgtMap().comm()
901  // << endl;
902 }
903 
904 
905 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
906 
908 (
909  const Pstream::commsTypes commsType,
910  const labelUList& iF
911 ) const
912 {
913  const cyclicACMIGAMGInterface& nbr =
914  dynamic_cast<const cyclicACMIGAMGInterface&>(neighbPatch());
915  const labelUList& nbrFaceCells = nbr.faceCells();
916 
917  auto tpnf = tmp<labelField>::New(nbrFaceCells.size());
918  labelField& pnf = tpnf.ref();
919 
920  forAll(pnf, facei)
921  {
922  pnf[facei] = iF[nbrFaceCells[facei]];
923  }
924 
925  return tpnf;
926 }
927 
928 
929 void Foam::cyclicACMIGAMGInterface::write(Ostream& os) const
930 {
932 
933  const bool hasAMI = bool(amiPtr_);
934 
935  os << token::SPACE << neighbPatchID_
936  << token::SPACE << owner_
937  << token::SPACE << forwardT_
938  << token::SPACE << reverseT_
939  << token::SPACE << hasAMI;
940 
941  if (hasAMI)
942  {
943  os << token::SPACE;
944  AMI().writeData(os);
945 
946  // Write processors in communicator
947  const label comm = AMI().comm();
948 
949  if (comm != -1)
950  {
951  os << token::SPACE
952  << UPstream::myProcNo(comm);
953  }
954  }
955 }
956 
957 
958 // ************************************************************************* //
List< scalar > scalarList
List of scalar.
Definition: scalarList.H:32
label find(const ListType &input, const UnaryPredicate &pred, const label start=0)
Same as ListOps::find_if.
Definition: ListOps.H:840
GAMG agglomerated cyclic ACMI interface.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
const pointListList & srcCentroids() const
Return const access to source patch face centroids.
label comm() const noexcept
Communicator (local or otherwise) for parallel operations.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
commsTypes
Communications types.
Definition: UPstream.H:77
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition: List.C:337
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
const scalarListList & tgtWeights() const
Return const access to target patch weights.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:526
AMIInterpolation AMIPatchToPatchInterpolation
Patch-to-patch interpolation == Foam::AMIInterpolation.
virtual const labelUList & faceCells() const
Return faceCell addressing.
const mapDistribute & srcMap() const
Source map - valid only if singlePatchProc = -1 This gets source data into a form to be consumed by t...
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
Definition: typeInfo.H:172
virtual void write(Ostream &) const
Write to stream.
const labelListList & tgtAddress() const
Return const access to target patch addressing.
T & first()
Access first element of the list, position [0].
Definition: UList.H:886
bool requireMatch() const noexcept
Return the requireMatch flag.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:63
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1787
static void broadcast(Type &value, const int communicator=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
labelList faceRestrictAddressing_
Face restrict addressing.
Definition: GAMGInterface.H:76
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition: UPstream.H:1611
bool distributed() const noexcept
Distributed across processors (singlePatchProc == -1)
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
Macros for easy insertion into run-time selection tables.
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
scalar y
void setSize(const label n)
Alias for resize()
Definition: List.H:325
const List< scalar > & tgtMagSf() const
Return const access to target patch face areas.
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
Definition: HashTableI.H:113
List< scalarList > scalarListList
List of scalarList.
Definition: scalarList.H:35
Space [isspace].
Definition: token.H:131
UPtrList< const lduInterface > lduInterfacePtrsList
Store lists of lduInterface as a UPtrList.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition: tmp.H:206
An abstract base class for cyclic ACMI coupled interfaces.
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
List< bool > bools(const labelHashSet &locations)
Transform the on locations to a boolList, with true for each non-negative location and false for all ...
Definition: HashOps.C:72
const scalarListList & srcWeights() const
Return const access to source patch weights.
bool constructHasFlip() const noexcept
Does constructMap include a sign.
OBJstream os(runTime.globalPath()/outputName)
defineTypeNameAndDebug(combustionModel, 0)
bool reverseTarget() const noexcept
Access to the reverseTarget flag.
const List< scalar > & srcMagSf() const
Return const access to source patch face areas.
Abstract base class for GAMG agglomerated interfaces.
Definition: GAMGInterface.H:50
static void combineReduce(T &value, CombineOp cop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) applying cop to inplace combine value from different processors...
virtual void write(Ostream &) const =0
Write to stream.
An abstract base class for implicitly-coupled interfaces e.g. processor and cyclic patches...
Definition: lduInterface.H:53
virtual const AMIPatchToPatchInterpolation & AMI() const
#define DebugPout
Report an information message using Foam::Pout.
static List< T > listGatherValues(const T &localValue, const int communicator=UPstream::worldComm, const int tag=UPstream::msgType())
Gather individual values into list locations.
constexpr label labelMax
Definition: label.H:55
labelList faceCells_
Face-cell addressing.
Definition: GAMGInterface.H:71
virtual tmp< labelField > internalFieldTransfer(const Pstream::commsTypes commsType, const labelUList &iF) const
Transfer and return internal field adjacent to the interface.
List< label > labelList
A List of labels.
Definition: List.H:61
const mapDistribute & tgtMap() const
Target map - valid only if singlePatchProc=-1. This gets target data into a form to be consumed by sr...
List< pointList > pointListList
List of pointList.
Definition: pointList.H:35
A class for managing temporary objects.
Definition: HashPtrTable.H:50
scalar lowWeightCorrection() const
Threshold weight below which interpolation is deactivated.
const labelListList & srcAddress() const
Return const access to source patch addressing.
bool readBool(Istream &is)
Read bool from stream using Foam::Switch(Istream&)
Definition: bool.C:62
Namespace for OpenFOAM.
static label renumberMap(labelListList &mapElements, const labelUList &oldToNew, const bool hasFlip)
Helper for renumbering the (compacted) map elements using the supplied old-to-new mapping...
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)