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  do
135  {
136  nbrFaces.clear();
137  visitedFaces.clear();
138 
139  // Do advancing front starting from srcFacei,tgtFacei
140  bool faceProcessed = processSourceFace
141  (
142  srcFacei,
143  tgtFacei,
144 
145  nbrFaces,
146  visitedFaces,
147 
148  srcAddr,
149  srcWght,
150  srcCtr,
151  tgtAddr,
152  tgtWght
153  );
154 
155  mapFlag.unset(srcFacei);
156 
157  if (!faceProcessed)
158  {
159  nonOverlapFaces.append(srcFacei);
160  }
161 
162  // Choose new src face from current src face neighbour
163  continueWalk = setNextFaces
164  (
165  startSeedi,
166  srcFacei,
167  tgtFacei,
168  mapFlag,
169  seedFaces,
170  visitedFaces,
171  mustMatch
172  // pass in nonOverlapFaces for failed tree search?
173  );
174  } while (continueWalk);
175 
176  srcNonOverlap_.transfer(nonOverlapFaces);
177 }
178 
179 
181 (
182  const label srcFacei,
183  const label tgtStartFacei,
184 
185  // list of tgt face neighbour faces
186  DynamicList<label>& nbrFaces,
187  // list of faces currently visited for srcFacei to avoid multiple hits
188  DynamicList<label>& visitedFaces,
189 
190  // temporary storage for addressing, weights and centroid
191  List<DynamicList<label>>& srcAddr,
192  List<DynamicList<scalar>>& srcWght,
193  List<DynamicList<point>>& srcCtr,
194  List<DynamicList<label>>& tgtAddr,
195  List<DynamicList<scalar>>& tgtWght
196 )
197 {
198  addProfiling(ami, "faceAreaWeightAMI::processSourceFace");
199 
200  if (tgtStartFacei == -1)
201  {
202  return false;
203  }
204 
205  const auto& tgtPatch = this->tgtPatch();
206 
207  // append initial target face and neighbours
208  nbrFaces.append(tgtStartFacei);
209  appendNbrFaces(tgtStartFacei, tgtPatch, visitedFaces, nbrFaces);
210 
211  bool faceProcessed = false;
212 
213  label maxNeighbourFaces = nbrFaces.size();
214 
215  do
216  {
217  // process new target face
218  label tgtFacei = nbrFaces.remove();
219  visitedFaces.append(tgtFacei);
220 
221  scalar interArea = 0;
222  vector interCentroid(Zero);
223  calcInterArea(srcFacei, tgtFacei, interArea, interCentroid);
224 
225  // store when intersection fractional area > tolerance
226  if (interArea/srcMagSf_[srcFacei] > faceAreaIntersect::tolerance())
227  {
228  srcAddr[srcFacei].append(tgtFacei);
229  srcWght[srcFacei].append(interArea);
230  srcCtr[srcFacei].append(interCentroid);
231 
232  tgtAddr[tgtFacei].append(srcFacei);
233  tgtWght[tgtFacei].append(interArea);
234 
235  appendNbrFaces(tgtFacei, tgtPatch, visitedFaces, nbrFaces);
236 
237  faceProcessed = true;
238 
239  maxNeighbourFaces = max(maxNeighbourFaces, nbrFaces.size());
240  }
241 
242  } while (nbrFaces.size() > 0);
243 
244  if (debug > 1)
245  {
246  DebugVar(maxNeighbourFaces);
247  }
248 
249  return faceProcessed;
250 }
251 
252 
254 (
255  label& startSeedi,
256  label& srcFacei,
257  label& tgtFacei,
258  const bitSet& mapFlag,
259  labelList& seedFaces,
260  const DynamicList<label>& visitedFaces,
261  const bool errorOnNotFound
262 ) const
263 {
264  addProfiling(ami, "faceAreaWeightAMI::setNextFaces");
265 
266  if (mapFlag.count() == 0)
267  {
268  // No more faces to map
269  return false;
270  }
271 
272  const labelList& srcNbrFaces = this->srcPatch().faceFaces()[srcFacei];
273 
274  // Initialise tgtFacei
275  tgtFacei = -1;
276 
277  // Set possible seeds for later use
278  bool valuesSet = false;
279  for (label faceS: srcNbrFaces)
280  {
281  if (mapFlag.test(faceS) && seedFaces[faceS] == -1)
282  {
283  for (label faceT : visitedFaces)
284  {
285  const scalar threshold =
286  srcMagSf_[faceS]*faceAreaIntersect::tolerance();
287 
288  // Store when intersection fractional area > threshold
289  if (overlaps(faceS, faceT, threshold))
290  {
291  seedFaces[faceS] = faceT;
292 
293  if (!valuesSet)
294  {
295  srcFacei = faceS;
296  tgtFacei = faceT;
297  valuesSet = true;
298  }
299  }
300  }
301  }
302  }
303 
304  if (valuesSet)
305  {
306  return true;
307  }
308 
309  // Set next src and tgt faces if not set above
310  // - try to use existing seed
311  label facei = startSeedi;
312  if (!mapFlag.test(startSeedi))
313  {
314  facei = mapFlag.find_next(facei);
315  }
316  const label startSeedi0 = facei;
317 
318  bool foundNextSeed = false;
319  while (facei != -1)
320  {
321  if (!foundNextSeed)
322  {
323  startSeedi = facei;
324  foundNextSeed = true;
325  }
326 
327  if (seedFaces[facei] != -1)
328  {
329  srcFacei = facei;
330  tgtFacei = seedFaces[facei];
331 
332  return true;
333  }
334 
335  facei = mapFlag.find_next(facei);
336  }
337 
338  // Perform new search to find match
339  if (debug)
340  {
341  Pout<< "Advancing front stalled: searching for new "
342  << "target face" << endl;
343  }
344 
345  facei = startSeedi0;
346  while (facei != -1)
347  {
348  srcFacei = facei;
349  tgtFacei = findTargetFace(srcFacei, visitedFaces);
350 
351  if (tgtFacei >= 0)
352  {
353  return true;
354  }
355 
356  facei = mapFlag.find_next(facei);
357  }
358 
359  if (errorOnNotFound)
360  {
362  << "Unable to set target face for source face " << srcFacei
363  << abort(FatalError);
364  }
365 
366  return false;
367 }
368 
369 
371 (
372  const label srcFacei,
373  const label tgtFacei,
374  scalar& area,
375  vector& centroid
376 ) const
377 {
378  addProfiling(ami, "faceAreaWeightAMI::interArea");
379 
380  // Quick reject if either face has zero area/too far away/wrong orientation
381  if (!isCandidate(srcFacei, tgtFacei))
382  {
383  return;
384  }
385 
386  const auto& srcPatch = this->srcPatch();
387  const auto& tgtPatch = this->tgtPatch();
388 
389  const pointField& srcPoints = srcPatch.points();
390  const pointField& tgtPoints = tgtPatch.points();
391 
392  // Create intersection object
393  faceAreaIntersect inter
394  (
395  srcPoints,
396  tgtPoints,
397  srcTris_[srcFacei],
398  tgtTris_[tgtFacei],
399  reverseTarget_,
401  );
402 
403  // Crude resultant norm
404  vector n(-srcPatch.faceNormals()[srcFacei]);
405  if (reverseTarget_)
406  {
407  n -= tgtPatch.faceNormals()[tgtFacei];
408  }
409  else
410  {
411  n += tgtPatch.faceNormals()[tgtFacei];
412  }
413  scalar magN = mag(n);
414 
415  const face& src = srcPatch[srcFacei];
416  const face& tgt = tgtPatch[tgtFacei];
417 
418  if (magN > ROOTVSMALL)
419  {
420  inter.calc(src, tgt, n/magN, area, centroid);
421  }
422  else
423  {
425  << "Invalid normal for source face " << srcFacei
426  << " points " << UIndirectList<point>(srcPoints, src)
427  << " target face " << tgtFacei
428  << " points " << UIndirectList<point>(tgtPoints, tgt)
429  << endl;
430  }
431 
433  {
434  static OBJstream tris("intersectionTris.obj");
435  const auto& triPts = inter.triangles();
436  for (const auto& tp : triPts)
437  {
438  tris.write(triPointRef(tp[0], tp[1], tp[2]), false);
439  }
440  }
441 
442  if ((debug > 1) && (area > 0))
443  {
444  writeIntersectionOBJ(area, src, tgt, srcPoints, tgtPoints);
445  }
446 }
447 
448 
450 (
451  const label srcFacei,
452  const label tgtFacei,
453  const scalar threshold
454 ) const
455 {
456  // Quick reject if either face has zero area/too far away/wrong orientation
457  if (!isCandidate(srcFacei, tgtFacei))
458  {
459  return false;
460  }
461 
462  const auto& srcPatch = this->srcPatch();
463  const auto& tgtPatch = this->tgtPatch();
464 
465  const pointField& srcPoints = srcPatch.points();
466  const pointField& tgtPoints = tgtPatch.points();
467 
468  faceAreaIntersect inter
469  (
470  srcPoints,
471  tgtPoints,
472  srcTris_[srcFacei],
473  tgtTris_[tgtFacei],
474  reverseTarget_,
476  );
477 
478  // Crude resultant norm
479  vector n(-srcPatch.faceNormals()[srcFacei]);
480  if (reverseTarget_)
481  {
482  n -= tgtPatch.faceNormals()[tgtFacei];
483  }
484  else
485  {
486  n += tgtPatch.faceNormals()[tgtFacei];
487  }
488  scalar magN = mag(n);
489 
490  const face& src = srcPatch[srcFacei];
491  const face& tgt = tgtPatch[tgtFacei];
492 
493  if (magN > ROOTVSMALL)
494  {
495  return inter.overlaps(src, tgt, n/magN, threshold);
496  }
497  else
498  {
500  << "Invalid normal for source face " << srcFacei
501  << " points " << UIndirectList<point>(srcPoints, src)
502  << " target face " << tgtFacei
503  << " points " << UIndirectList<point>(tgtPoints, tgt)
504  << endl;
505  }
506 
507  return false;
508 }
509 
510 
512 (
513  List<DynamicList<label>>& srcAddr,
514  List<DynamicList<scalar>>& srcWght,
515  List<DynamicList<point>>& srcCtr,
516  List<DynamicList<label>>& tgtAddr,
517  List<DynamicList<scalar>>& tgtWght
518 )
519 {
520  addProfiling(ami, "faceAreaWeightAMI::restartUncoveredSourceFace");
521 
522  // Note: exclude faces in srcNonOverlap_ for ACMI?
523 
524  label nBelowMinWeight = 0;
525  const scalar minWeight = 0.95;
526 
527  // List of tgt face neighbour faces
528  DynamicList<label> nbrFaces(10);
529 
530  // List of faces currently visited for srcFacei to avoid multiple hits
531  DynamicList<label> visitedFaces(10);
532 
533  const auto& srcPatch = this->srcPatch();
534 
535  forAll(srcWght, srcFacei)
536  {
537  const scalar s = sum(srcWght[srcFacei]);
538  const scalar t = s/srcMagSf_[srcFacei];
539 
540  if (t < minWeight)
541  {
542  ++nBelowMinWeight;
543 
544  const face& f = srcPatch[srcFacei];
545 
546  forAll(f, fpi)
547  {
548  const label tgtFacei =
549  findTargetFace(srcFacei, srcAddr[srcFacei], fpi);
550 
551  if (tgtFacei != -1)
552  {
553  nbrFaces.clear();
554  visitedFaces = srcAddr[srcFacei];
555 
556  (void)processSourceFace
557  (
558  srcFacei,
559  tgtFacei,
560 
561  nbrFaces,
562  visitedFaces,
563 
564  srcAddr,
565  srcWght,
566  srcCtr,
567  tgtAddr,
568  tgtWght
569  );
570  }
571  }
572  }
573  }
574 
575  if (debug && nBelowMinWeight)
576  {
578  << "Restarted search on " << nBelowMinWeight
579  << " faces since sum of weights < " << minWeight
580  << endl;
581  }
582 }
583 
584 
585 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
586 
588 (
589  const dictionary& dict,
590  const bool reverseTarget
591 )
592 :
593  advancingFrontAMI(dict, reverseTarget),
594  restartUncoveredSourceFace_
595  (
596  dict.getOrDefault("restartUncoveredSourceFace", true)
597  )
598 {}
599 
600 
602 (
603  const bool requireMatch,
604  const bool reverseTarget,
605  const scalar lowWeightCorrection,
607  const bool restartUncoveredSourceFace
608 )
609 :
611  (
612  requireMatch,
613  reverseTarget,
614  lowWeightCorrection,
615  triMode
616  ),
617  restartUncoveredSourceFace_(restartUncoveredSourceFace)
618 {}
619 
620 
622 :
623  advancingFrontAMI(ami),
624  restartUncoveredSourceFace_(ami.restartUncoveredSourceFace_)
625 {}
626 
627 
628 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
629 
631 (
632  const primitivePatch& srcPatch,
633  const primitivePatch& tgtPatch,
634  const autoPtr<searchableSurface>& surfPtr
635 )
636 {
637  if (upToDate_)
638  {
639  return false;
640  }
641 
642  addProfiling(ami, "faceAreaWeightAMI::calculate");
643 
644  advancingFrontAMI::calculate(srcPatch, tgtPatch, surfPtr);
645 
646  label srcFacei = 0;
647  label tgtFacei = 0;
648 
649  bool ok = initialiseWalk(srcFacei, tgtFacei);
650 
651  srcCentroids_.setSize(srcAddress_.size());
652 
653  const auto& src = this->srcPatch();
654  const auto& tgt = this->tgtPatch(); // might be the extended patch!
655 
656  // Temporary storage for addressing and weights
657  List<DynamicList<label>> srcAddr(src.size());
658  List<DynamicList<scalar>> srcWght(srcAddr.size());
659  List<DynamicList<point>> srcCtr(srcAddr.size());
660  List<DynamicList<label>> tgtAddr(tgt.size());
661  List<DynamicList<scalar>> tgtWght(tgtAddr.size());
662 
663  if (ok)
664  {
665  calcAddressing
666  (
667  srcAddr,
668  srcWght,
669  srcCtr,
670  tgtAddr,
671  tgtWght,
672  srcFacei,
673  tgtFacei
674  );
675 
676  if (debug && !srcNonOverlap_.empty())
677  {
678  Pout<< " AMI: " << srcNonOverlap_.size()
679  << " non-overlap faces identified"
680  << endl;
681  }
682 
683  // Check for badly covered faces
684  if (restartUncoveredSourceFace_) // && mustMatchFaces())
685  {
686  restartUncoveredSourceFace
687  (
688  srcAddr,
689  srcWght,
690  srcCtr,
691  tgtAddr,
692  tgtWght
693  );
694  }
695  }
696 
697  // Transfer data to persistent storage
698  forAll(srcAddr, i)
699  {
700  srcAddress_[i].transfer(srcAddr[i]);
701  srcWeights_[i].transfer(srcWght[i]);
702  srcCentroids_[i].transfer(srcCtr[i]);
703  }
704 
705  forAll(tgtAddr, i)
706  {
707  tgtAddress_[i].transfer(tgtAddr[i]);
708  tgtWeights_[i].transfer(tgtWght[i]);
709  }
710 
711  if (distributed())
712  {
713  const primitivePatch& srcPatch0 = this->srcPatch0();
714  const primitivePatch& tgtPatch0 = this->tgtPatch0();
715 
716  // Create global indexing for each original patch
717  globalIndex globalSrcFaces(srcPatch0.size());
718  globalIndex globalTgtFaces(tgtPatch0.size());
719 
720  for (labelList& addressing : srcAddress_)
721  {
722  for (label& addr : addressing)
723  {
724  addr = extendedTgtFaceIDs_[addr];
725  }
726  }
727 
728  for (labelList& addressing : tgtAddress_)
729  {
730  globalSrcFaces.inplaceToGlobal(addressing);
731  }
732 
733  // Send data back to originating procs. Note that contributions
734  // from different processors get added (ListOps::appendEqOp)
735 
737  (
740  tgtPatch0.size(),
741  extendedTgtMapPtr_->constructMap(),
742  false, // has flip
743  extendedTgtMapPtr_->subMap(),
744  false, // has flip
745  tgtAddress_,
746  labelList(),
747  ListOps::appendEqOp<label>(),
748  flipOp() // flip operation
749  );
750 
752  (
755  tgtPatch0.size(),
756  extendedTgtMapPtr_->constructMap(),
757  false,
758  extendedTgtMapPtr_->subMap(),
759  false,
760  tgtWeights_,
761  scalarList(),
762  ListOps::appendEqOp<scalar>(),
763  flipOp()
764  );
765 
766  // Note: using patch face areas calculated by the AMI method
767  extendedTgtMapPtr_->reverseDistribute(tgtPatch0.size(), tgtMagSf_);
768 
769  // Cache maps and reset addresses
770  List<Map<label>> cMapSrc;
771  srcMapPtr_.reset
772  (
773  new mapDistribute(globalSrcFaces, tgtAddress_, cMapSrc)
774  );
775 
776  List<Map<label>> cMapTgt;
777  tgtMapPtr_.reset
778  (
779  new mapDistribute(globalTgtFaces, srcAddress_, cMapTgt)
780  );
781  }
782 
783  // Convert the weights from areas to normalised values
784  normaliseWeights(requireMatch_, true);
785 
786  nonConformalCorrection();
788  upToDate_ = true;
789 
790  return upToDate_;
791 }
792 
793 
795 {
797 
798  if (restartUncoveredSourceFace_)
799  {
800  os.writeEntry
801  (
802  "restartUncoveredSourceFace",
803  restartUncoveredSourceFace_
804  );
805  }
806 }
807 
808 
809 // ************************************************************************* //
faceAreaWeightAMI(const dictionary &dict, const bool reverseTarget=false)
Construct from dictionary.
dictionary dict
#define addProfiling(name, descr)
Define profiling trigger with specified name and description string.
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:439
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 lowWeightCorrectionin active.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
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:487
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:312
static const List< T > & null()
Return a null List.
Definition: ListI.H:102
static bool cacheIntersections_
Macros for easy insertion into run-time selection tables.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
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.
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:621
const wordList area
Standard area field types (scalar, vector, tensor, etc)
List< scalar > scalarList
A List of scalars.
Definition: scalarList.H:61
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:558
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:55
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:384
labelList f(nPoints)
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field...
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
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.
static void distribute(const Pstream::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 NegateOp &negOp, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Distribute data with specified negate operator (for flips).
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.
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157