faceAreaWeightAMI.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) 2018-2021 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 "faceAreaWeightAMI.H"
30 #include "profiling.H"
31 #include "OBJstream.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38  defineTypeNameAndDebug(faceAreaWeightAMI, 0);
39  addToRunTimeSelectionTable(AMIInterpolation, faceAreaWeightAMI, dict);
40  addToRunTimeSelectionTable(AMIInterpolation, faceAreaWeightAMI, component);
41 
42  // Backwards compatibility for pre v2106 versions
43  // - partialFaceAreaWeightAMI deprecated in v2106
45  (
46  AMIInterpolation,
47  faceAreaWeightAMI,
48  dict,
49  faceAreaWeightAMI,
50  partialFaceAreaWeightAMI,
51  2012
52  );
53 }
54 
55 
56 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
57 
58 /*
59  if (debug)
60  {
61  static label nAMI = 0;
62 
63  // Write out triangulated surfaces as OBJ files
64  OBJstream srcTriObj("srcTris_" + Foam::name(nAMI) + ".obj");
65  const pointField& srcPts = src.points();
66  for (const DynamicList<face>& faces : srcTris_)
67  {
68  for (const face& f : faces)
69  {
70  srcTriObj.write
71  (
72  triPointRef(srcPts[f[0]], srcPts[f[1]], srcPts[f[2]])
73  );
74  }
75  }
76 
77  OBJstream tgtTriObj("tgtTris_" + Foam::name(nAMI) + ".obj");
78  const pointField& tgtPts = tgt.points();
79  for (const DynamicList<face>& faces : tgtTris_)
80  {
81  for (const face& f : faces)
82  {
83  tgtTriObj.write
84  (
85  triPointRef(tgtPts[f[0]], tgtPts[f[1]], tgtPts[f[2]])
86  );
87  }
88  }
89 
90  ++nAMI;
91  }
92 */
93 
94 
96 (
97  List<DynamicList<label>>& srcAddr,
98  List<DynamicList<scalar>>& srcWght,
99  List<DynamicList<point>>& srcCtr,
100  List<DynamicList<label>>& tgtAddr,
101  List<DynamicList<scalar>>& tgtWght,
102  label srcFacei,
103  label tgtFacei
104 )
105 {
106  addProfiling(ami, "faceAreaWeightAMI::calcAddressing");
107 
108  // Construct weights and addressing
109  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
110 
111  label nFacesRemaining = srcAddr.size();
112 
113  // List of tgt face neighbour faces
114  DynamicList<label> nbrFaces(10);
115 
116  // List of faces currently visited for srcFacei to avoid multiple hits
117  DynamicList<label> visitedFaces(10);
118 
119  // List to keep track of tgt faces used to seed src faces
120  labelList seedFaces(nFacesRemaining, -1);
121  seedFaces[srcFacei] = tgtFacei;
122 
123  // List to keep track of whether src face can be mapped
124  bitSet mapFlag(nFacesRemaining, true);
125 
126  // Reset starting seed
127  label startSeedi = 0;
128 
129  // Should all faces be matched?
130  const bool mustMatch = mustMatchFaces();
131 
132  bool continueWalk = true;
133  DynamicList<label> nonOverlapFaces;
134 
135  do
136  {
137  nbrFaces.clear();
138  visitedFaces.clear();
139 
140  // Do advancing front starting from srcFacei,tgtFacei
141  bool faceProcessed = processSourceFace
142  (
143  srcFacei,
144  tgtFacei,
145 
146  nbrFaces,
147  visitedFaces,
148 
149  srcAddr,
150  srcWght,
151  srcCtr,
152  tgtAddr,
153  tgtWght
154  );
155 
156  mapFlag.unset(srcFacei);
157 
158  if (!faceProcessed)
159  {
160  nonOverlapFaces.append(srcFacei);
161  }
162 
163  // Choose new src face from current src face neighbour
164  continueWalk = setNextFaces
165  (
166  startSeedi,
167  srcFacei,
168  tgtFacei,
169  mapFlag,
170  seedFaces,
171  visitedFaces,
172  mustMatch
173  // pass in nonOverlapFaces for failed tree search?
174  );
175  } while (continueWalk);
176 
177  srcNonOverlap_.transfer(nonOverlapFaces);
178 }
179 
180 
182 (
183  const label srcFacei,
184  const label tgtStartFacei,
185 
186  // list of tgt face neighbour faces
187  DynamicList<label>& nbrFaces,
188  // list of faces currently visited for srcFacei to avoid multiple hits
189  DynamicList<label>& visitedFaces,
190 
191  // temporary storage for addressing, weights and centroid
192  List<DynamicList<label>>& srcAddr,
193  List<DynamicList<scalar>>& srcWght,
194  List<DynamicList<point>>& srcCtr,
195  List<DynamicList<label>>& tgtAddr,
196  List<DynamicList<scalar>>& tgtWght
197 )
198 {
199  addProfiling(ami, "faceAreaWeightAMI::processSourceFace");
200 
201  if (tgtStartFacei == -1)
202  {
203  return false;
204  }
205 
206  const auto& tgtPatch = this->tgtPatch();
207 
208  // append initial target face and neighbours
209  nbrFaces.append(tgtStartFacei);
210  appendNbrFaces(tgtStartFacei, tgtPatch, visitedFaces, nbrFaces);
211 
212  bool faceProcessed = false;
213 
214  label maxNeighbourFaces = nbrFaces.size();
215 
216  while (!nbrFaces.empty())
217  {
218  // Process new target face as LIFO
219  label tgtFacei = nbrFaces.back();
220  nbrFaces.pop_back();
221  visitedFaces.push_back(tgtFacei);
222 
223  scalar interArea = 0;
224  vector interCentroid(Zero);
225  calcInterArea(srcFacei, tgtFacei, interArea, interCentroid);
226 
227  // store when intersection fractional area > tolerance
228  if (interArea/srcMagSf_[srcFacei] > faceAreaIntersect::tolerance())
229  {
230  srcAddr[srcFacei].append(tgtFacei);
231  srcWght[srcFacei].append(interArea);
232  srcCtr[srcFacei].append(interCentroid);
233 
234  tgtAddr[tgtFacei].append(srcFacei);
235  tgtWght[tgtFacei].append(interArea);
236 
237  appendNbrFaces(tgtFacei, tgtPatch, visitedFaces, nbrFaces);
238 
239  faceProcessed = true;
240 
241  maxNeighbourFaces = max(maxNeighbourFaces, nbrFaces.size());
242  }
243  }
244 
245  if (debug > 1)
246  {
247  DebugVar(maxNeighbourFaces);
248  }
249 
250  return faceProcessed;
251 }
252 
253 
255 (
256  label& startSeedi,
257  label& srcFacei,
258  label& tgtFacei,
259  const bitSet& mapFlag,
260  labelList& seedFaces,
261  const DynamicList<label>& visitedFaces,
262  const bool errorOnNotFound
263 ) const
264 {
265  addProfiling(ami, "faceAreaWeightAMI::setNextFaces");
266 
267  if (mapFlag.count() == 0)
268  {
269  // No more faces to map
270  return false;
271  }
272 
273  const auto& srcPatch = this->srcPatch();
274  const labelList& srcNbrFaces = srcPatch.faceFaces()[srcFacei];
275 
276  // Initialise tgtFacei
277  tgtFacei = -1;
278 
279  // Set possible seeds for later use
280  bool valuesSet = false;
281  for (label faceS: srcNbrFaces)
282  {
283  if (mapFlag.test(faceS) && seedFaces[faceS] == -1)
284  {
285  for (label faceT : visitedFaces)
286  {
287  const scalar threshold =
288  srcMagSf_[faceS]*faceAreaIntersect::tolerance();
289 
290  // Store when intersection fractional area > threshold
291  if (overlaps(faceS, faceT, threshold))
292  {
293  seedFaces[faceS] = faceT;
294 
295  if (!valuesSet)
296  {
297  srcFacei = faceS;
298  tgtFacei = faceT;
299  valuesSet = true;
300  }
301  }
302  }
303  }
304  }
305 
306  if (valuesSet)
307  {
308  return true;
309  }
310 
311  // Set next src and tgt faces if not set above
312  // - try to use existing seed
313  label facei = startSeedi;
314  if (!mapFlag.test(startSeedi))
315  {
316  facei = mapFlag.find_next(facei);
317  }
318  const label startSeedi0 = facei;
319 
320  bool foundNextSeed = false;
321  while (facei != -1)
322  {
323  if (!foundNextSeed)
324  {
325  startSeedi = facei;
326  foundNextSeed = true;
327  }
328 
329  if (seedFaces[facei] != -1)
330  {
331  srcFacei = facei;
332  tgtFacei = seedFaces[facei];
333 
334  return true;
335  }
336 
337  facei = mapFlag.find_next(facei);
338  }
339 
340  // Perform new search to find match
341  if (debug)
342  {
343  Pout<< "Advancing front stalled: searching for new "
344  << "target face" << endl;
345  }
346 
347  facei = startSeedi0;
348  while (facei != -1)
349  {
350  srcFacei = facei;
351  tgtFacei = findTargetFace(srcFacei, visitedFaces);
352 
353  if (tgtFacei >= 0)
354  {
355  return true;
356  }
357 
358  facei = mapFlag.find_next(facei);
359  }
360 
361  if (errorOnNotFound)
362  {
364  << "Unable to set target face for source face " << srcFacei
365  << " with centre: " << srcPatch.faceCentres()[srcFacei]
366  << abort(FatalError);
367  }
368 
369  return false;
370 }
371 
372 
374 (
375  const label srcFacei,
376  const label tgtFacei,
377  scalar& area,
378  vector& centroid
379 ) const
380 {
381  addProfiling(ami, "faceAreaWeightAMI::interArea");
382 
383  // Quick reject if either face has zero area/too far away/wrong orientation
384  if (!isCandidate(srcFacei, tgtFacei))
385  {
386  return;
387  }
388 
389  const auto& srcPatch = this->srcPatch();
390  const auto& tgtPatch = this->tgtPatch();
391 
392  const pointField& srcPoints = srcPatch.points();
393  const pointField& tgtPoints = tgtPatch.points();
394 
395  // Create intersection object
396  faceAreaIntersect inter
397  (
398  srcPoints,
399  tgtPoints,
400  srcTris_[srcFacei],
401  tgtTris_[tgtFacei],
402  reverseTarget_,
404  );
405 
406  // Crude resultant norm
407  vector n(-srcPatch.faceNormals()[srcFacei]);
408  if (reverseTarget_)
409  {
410  n -= tgtPatch.faceNormals()[tgtFacei];
411  }
412  else
413  {
414  n += tgtPatch.faceNormals()[tgtFacei];
415  }
416  scalar magN = mag(n);
417 
418  const face& src = srcPatch[srcFacei];
419  const face& tgt = tgtPatch[tgtFacei];
420 
421  if (magN > ROOTVSMALL)
422  {
423  inter.calc(src, tgt, n/magN, area, centroid);
424  }
425  else
426  {
428  << "Invalid normal for source face " << srcFacei
429  << " points " << UIndirectList<point>(srcPoints, src)
430  << " target face " << tgtFacei
431  << " points " << UIndirectList<point>(tgtPoints, tgt)
432  << endl;
433  }
434 
436  {
437  static OBJstream tris("intersectionTris.obj");
438  const auto& triPts = inter.triangles();
439  for (const auto& tp : triPts)
440  {
441  tris.write(triPointRef(tp[0], tp[1], tp[2]), false);
442  }
443  }
444 
445  if ((debug > 1) && (area > 0))
446  {
447  writeIntersectionOBJ(area, src, tgt, srcPoints, tgtPoints);
448  }
449 }
450 
451 
453 (
454  const label srcFacei,
455  const label tgtFacei,
456  const scalar threshold
457 ) const
458 {
459  // Quick reject if either face has zero area/too far away/wrong orientation
460  if (!isCandidate(srcFacei, tgtFacei))
461  {
462  return false;
463  }
464 
465  const auto& srcPatch = this->srcPatch();
466  const auto& tgtPatch = this->tgtPatch();
467 
468  const pointField& srcPoints = srcPatch.points();
469  const pointField& tgtPoints = tgtPatch.points();
470 
471  faceAreaIntersect inter
472  (
473  srcPoints,
474  tgtPoints,
475  srcTris_[srcFacei],
476  tgtTris_[tgtFacei],
477  reverseTarget_,
479  );
480 
481  // Crude resultant norm
482  vector n(-srcPatch.faceNormals()[srcFacei]);
483  if (reverseTarget_)
484  {
485  n -= tgtPatch.faceNormals()[tgtFacei];
486  }
487  else
488  {
489  n += tgtPatch.faceNormals()[tgtFacei];
490  }
491  scalar magN = mag(n);
492 
493  const face& src = srcPatch[srcFacei];
494  const face& tgt = tgtPatch[tgtFacei];
495 
496  if (magN > ROOTVSMALL)
497  {
498  return inter.overlaps(src, tgt, n/magN, threshold);
499  }
500  else
501  {
503  << "Invalid normal for source face " << srcFacei
504  << " points " << UIndirectList<point>(srcPoints, src)
505  << " target face " << tgtFacei
506  << " points " << UIndirectList<point>(tgtPoints, tgt)
507  << endl;
508  }
509 
510  return false;
511 }
512 
513 
515 (
516  List<DynamicList<label>>& srcAddr,
517  List<DynamicList<scalar>>& srcWght,
518  List<DynamicList<point>>& srcCtr,
519  List<DynamicList<label>>& tgtAddr,
520  List<DynamicList<scalar>>& tgtWght
521 )
522 {
523  addProfiling(ami, "faceAreaWeightAMI::restartUncoveredSourceFace");
524 
525  // Note: exclude faces in srcNonOverlap_ for ACMI?
526 
527  label nBelowMinWeight = 0;
528  const scalar minWeight = 0.95;
529 
530  // List of tgt face neighbour faces
531  DynamicList<label> nbrFaces(10);
532 
533  // List of faces currently visited for srcFacei to avoid multiple hits
534  DynamicList<label> visitedFaces(10);
535 
536  const auto& srcPatch = this->srcPatch();
537 
538  forAll(srcWght, srcFacei)
539  {
540  const scalar s = sum(srcWght[srcFacei]);
541  const scalar t = s/srcMagSf_[srcFacei];
542 
543  if (t < minWeight)
544  {
545  ++nBelowMinWeight;
546 
547  const face& f = srcPatch[srcFacei];
548 
549  forAll(f, fpi)
550  {
551  const label tgtFacei =
552  findTargetFace(srcFacei, srcAddr[srcFacei], fpi);
553 
554  if (tgtFacei != -1)
555  {
556  nbrFaces.clear();
557  visitedFaces = srcAddr[srcFacei];
558 
559  (void)processSourceFace
560  (
561  srcFacei,
562  tgtFacei,
563 
564  nbrFaces,
565  visitedFaces,
566 
567  srcAddr,
568  srcWght,
569  srcCtr,
570  tgtAddr,
571  tgtWght
572  );
573  }
574  }
575  }
576  }
577 
578  if (debug && nBelowMinWeight)
579  {
581  << "Restarted search on " << nBelowMinWeight
582  << " faces since sum of weights < " << minWeight
583  << endl;
584  }
585 }
586 
587 
588 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
589 
591 (
592  const dictionary& dict,
593  const bool reverseTarget
594 )
595 :
596  advancingFrontAMI(dict, reverseTarget),
597  restartUncoveredSourceFace_
598  (
599  dict.getOrDefault("restartUncoveredSourceFace", true)
600  )
601 {}
602 
603 
605 (
606  const bool requireMatch,
607  const bool reverseTarget,
608  const scalar lowWeightCorrection,
610  const bool restartUncoveredSourceFace
611 )
612 :
614  (
615  requireMatch,
616  reverseTarget,
617  lowWeightCorrection,
618  triMode
619  ),
620  restartUncoveredSourceFace_(restartUncoveredSourceFace)
621 {}
622 
623 
625 :
626  advancingFrontAMI(ami),
627  restartUncoveredSourceFace_(ami.restartUncoveredSourceFace_)
628 {}
629 
630 
631 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
632 
634 (
635  const primitivePatch& srcPatch,
636  const primitivePatch& tgtPatch,
637  const autoPtr<searchableSurface>& surfPtr
638 )
639 {
640  if (upToDate_)
641  {
642  return false;
643  }
644 
645  addProfiling(ami, "faceAreaWeightAMI::calculate");
646 
647  advancingFrontAMI::calculate(srcPatch, tgtPatch, surfPtr);
648 
649  label srcFacei = 0;
650  label tgtFacei = 0;
651 
652  bool ok = initialiseWalk(srcFacei, tgtFacei);
653 
654  srcCentroids_.setSize(srcAddress_.size());
655 
656  const auto& src = this->srcPatch();
657  const auto& tgt = this->tgtPatch(); // might be the extended patch!
658 
659  // Temporary storage for addressing and weights
660  List<DynamicList<label>> srcAddr(src.size());
661  List<DynamicList<scalar>> srcWght(srcAddr.size());
662  List<DynamicList<point>> srcCtr(srcAddr.size());
663  List<DynamicList<label>> tgtAddr(tgt.size());
664  List<DynamicList<scalar>> tgtWght(tgtAddr.size());
665 
666  if (ok)
667  {
668  calcAddressing
669  (
670  srcAddr,
671  srcWght,
672  srcCtr,
673  tgtAddr,
674  tgtWght,
675  srcFacei,
676  tgtFacei
677  );
678 
679  if (debug && !srcNonOverlap_.empty())
680  {
681  Pout<< " AMI: " << srcNonOverlap_.size()
682  << " non-overlap faces identified"
683  << endl;
684  }
685 
686  // Check for badly covered faces
687  if (restartUncoveredSourceFace_) // && mustMatchFaces())
688  {
689  restartUncoveredSourceFace
690  (
691  srcAddr,
692  srcWght,
693  srcCtr,
694  tgtAddr,
695  tgtWght
696  );
697  }
698  }
699 
700  // Transfer data to persistent storage
701  forAll(srcAddr, i)
702  {
703  srcAddress_[i].transfer(srcAddr[i]);
704  srcWeights_[i].transfer(srcWght[i]);
705  srcCentroids_[i].transfer(srcCtr[i]);
706  }
707 
708  forAll(tgtAddr, i)
709  {
710  tgtAddress_[i].transfer(tgtAddr[i]);
711  tgtWeights_[i].transfer(tgtWght[i]);
712  }
713 
714  if (distributed())
715  {
716  const label myRank = UPstream::myProcNo(comm_);
717 
718  const primitivePatch& srcPatch0 = this->srcPatch0();
719  const primitivePatch& tgtPatch0 = this->tgtPatch0();
720 
721  // Create global indexing for each original patch
722  globalIndex globalSrcFaces(srcPatch0.size(), comm_);
723  globalIndex globalTgtFaces(tgtPatch0.size(), comm_);
724 
725  for (labelList& addressing : srcAddress_)
726  {
727  for (label& addr : addressing)
728  {
729  addr = extendedTgtFaceIDs_[addr];
730  }
731  }
732 
733  for (labelList& addressing : tgtAddress_)
734  {
735  globalSrcFaces.inplaceToGlobal(myRank, addressing);
736  }
737 
738  // Send data back to originating procs. Note that contributions
739  // from different processors get added (ListOps::appendEqOp)
740 
742  (
745  tgtPatch0.size(),
746  extendedTgtMapPtr_->constructMap(),
747  false, // has flip
748  extendedTgtMapPtr_->subMap(),
749  false, // has flip
750  tgtAddress_,
751  labelList(),
752  ListOps::appendEqOp<label>(),
753  flipOp(), // flip operation
755  comm_
756  );
757 
759  (
762  tgtPatch0.size(),
763  extendedTgtMapPtr_->constructMap(),
764  false,
765  extendedTgtMapPtr_->subMap(),
766  false,
767  tgtWeights_,
768  scalarList(),
769  ListOps::appendEqOp<scalar>(),
770  flipOp(),
772  comm_
773  );
774 
775  // Note: using patch face areas calculated by the AMI method
776  extendedTgtMapPtr_->reverseDistribute(tgtPatch0.size(), tgtMagSf_);
777 
778  // Cache maps and reset addresses
779  List<Map<label>> cMapSrc;
780  srcMapPtr_.reset
781  (
782  new mapDistribute
783  (
784  globalSrcFaces,
785  tgtAddress_,
786  cMapSrc,
788  comm_
789  )
790  );
791 
792  List<Map<label>> cMapTgt;
793  tgtMapPtr_.reset
794  (
795  new mapDistribute
796  (
797  globalTgtFaces,
798  srcAddress_,
799  cMapTgt,
801  comm_
802  )
803  );
804  }
805 
806  // Convert the weights from areas to normalised values
807  normaliseWeights(requireMatch_, true);
808 
809  nonConformalCorrection();
811  upToDate_ = true;
812 
813  return upToDate_;
814 }
815 
816 
818 {
820 
821  if (restartUncoveredSourceFace_)
822  {
823  os.writeEntry
824  (
825  "restartUncoveredSourceFace",
826  restartUncoveredSourceFace_
827  );
828  }
829 }
830 
831 
832 // ************************************************************************* //
faceAreaWeightAMI(const dictionary &dict, const bool reverseTarget=false)
Construct from dictionary.
List< scalar > scalarList
List of scalar.
Definition: scalarList.H:32
dictionary dict
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &f1)
static scalar & tolerance()
Fraction of local length scale to use as intersection tolerance.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition: List.C:326
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
bool mustMatchFaces() const
Return true if requireMatch and but not lowWeightCorrection.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
virtual bool setNextFaces(label &startSeedi, label &srcFacei, label &tgtFacei, const bitSet &mapFlag, labelList &seedFaces, const DynamicList< label > &visitedFaces, const bool errorOnNotFound=true) const
Set the source and target seed faces.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:321
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1229
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1074
static const List< T > & null()
Return a null List.
Definition: ListI.H:130
static bool cacheIntersections_
Macros for easy insertion into run-time selection tables.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
Face area weighted Arbitrary Mesh Interface (AMI) method.
virtual void write(Ostream &os) const
Write.
const Field< point_type > & faceNormals() const
Return face unit normals for patch.
addAliasToRunTimeSelectionTable(AMIInterpolation, faceAreaWeightAMI, dict, faceAreaWeightAMI, partialFaceAreaWeightAMI, 2012)
A list of faces which address into the list of points.
const labelListList & faceFaces() const
Return face-face addressing.
#define addProfiling(Name, Descr)
Define profiling trigger with specified name and description string.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
bitSet & unset(const bitSet &other)
Unset (subtract) the bits specified in the other bitset, which is a set difference corresponds to the...
Definition: bitSetI.H:542
const wordList area
Standard area field types (scalar, vector, tensor, etc)
const Field< point_type > & faceCentres() const
Return face centres for patch.
virtual void calcInterArea(const label srcFacei, const label tgtFacei, scalar &area, vector &centroid) const
Area of intersection between source and target faces.
virtual bool overlaps(const label srcFacei, const label tgtFacei, const scalar threshold) const
Return true if faces overlap.
Vector< scalar > vector
Definition: vector.H:57
const Field< point_type > & points() const noexcept
Return reference to global points.
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicList.H:584
errorManip< error > abort(error &err)
Definition: errorManip.H:139
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
int debug
Static debugging option.
virtual void write(Ostream &os) const
Write.
OBJstream os(runTime.globalPath()/outputName)
defineTypeNameAndDebug(combustionModel, 0)
virtual bool calculate(const primitivePatch &srcPatch, const primitivePatch &tgtPatch, const autoPtr< searchableSurface > &surfPtr=nullptr)
Update addressing, weights and (optional) centroids.
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:405
labelList f(nPoints)
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field...
virtual bool calculate(const primitivePatch &srcPatch, const primitivePatch &tgtPatch, const autoPtr< searchableSurface > &surfPtr=nullptr)
Update addressing, weights and (optional) centroids.
virtual void restartUncoveredSourceFace(List< DynamicList< label >> &srcAddr, List< DynamicList< scalar >> &srcWght, List< DynamicList< point >> &srcCtr, List< DynamicList< label >> &tgtAddr, List< DynamicList< scalar >> &tgtWght)
Attempt to re-evaluate source faces that have not been included.
virtual bool processSourceFace(const label srcFacei, const label tgtStartFacei, DynamicList< label > &nbrFaces, DynamicList< label > &visitedFaces, List< DynamicList< label >> &srcAddr, List< DynamicList< scalar >> &srcWght, List< DynamicList< point >> &srcCtr, List< DynamicList< label >> &tgtAddr, List< DynamicList< scalar >> &tgtWght)
Determine overlap contributions for source face srcFacei.
virtual void calcAddressing(List< DynamicList< label >> &srcAddress, List< DynamicList< scalar >> &srcWeights, List< DynamicList< point >> &srcCentroids, List< DynamicList< label >> &tgtAddress, List< DynamicList< scalar >> &tgtWeights, label srcFacei, label tgtFacei)
Calculate addressing, weights and centroids using temporary storage.
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:59
#define WarningInFunction
Report a warning using Foam::Warning.
Base class for Arbitrary Mesh Interface (AMI) methods.
triangle< point, const point & > triPointRef
A triangle using referred points.
Definition: triangleFwd.H:39
"nonBlocking" : (MPI_Isend, MPI_Irecv)
label n
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
#define DebugVar(var)
Report a variable name and value.
List< label > labelList
A List of labels.
Definition: List.H:62
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.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))
labelList srcNonOverlap_
Labels of faces that are not overlapped by any target faces (should be empty for correct functioning ...
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
static void distribute(const UPstream::commsTypes commsType, const List< labelPair > &schedule, const label constructSize, const labelListList &subMap, const bool subHasFlip, const labelListList &constructMap, const bool constructHasFlip, List< T > &field, const T &nullValue, const CombineOp &cop, const NegateOp &negOp, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Distribute combine data with specified combine operation and negate operator (for flips)...
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127