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-------------------------------------------------------------------------------
11License
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
36namespace Foam
37{
41
42 // Backwards compatibility for pre v2106 versions
43 // - partialFaceAreaWeightAMI deprecated in v2106
45 (
48 dict,
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 forAll(srcTris_, facei)
67 {
68 const DynamicList<face>& faces = srcTris_[facei];
69 for (const face& f : faces)
70 {
71 srcTriObj.write
72 (
73 triPointRef(srcPts[f[0]], srcPts[f[1]], srcPts[f[2]])
74 );
75 }
76 }
77
78 OBJstream tgtTriObj("tgtTris_" + Foam::name(nAMI) + ".obj");
79 const pointField& tgtPts = tgt.points();
80 forAll(tgtTris_, facei)
81 {
82 const DynamicList<face>& faces = tgtTris_[facei];
83 for (const face& f : faces)
84 {
85 tgtTriObj.write
86 (
87 triPointRef(tgtPts[f[0]], tgtPts[f[1]], tgtPts[f[2]])
88 );
89 }
90 }
91
92 ++nAMI;
93 }
94*/
95
96
98(
99 List<DynamicList<label>>& srcAddr,
100 List<DynamicList<scalar>>& srcWght,
101 List<DynamicList<point>>& srcCtr,
102 List<DynamicList<label>>& tgtAddr,
103 List<DynamicList<scalar>>& tgtWght,
104 label srcFacei,
105 label tgtFacei
106)
107{
108 addProfiling(ami, "faceAreaWeightAMI::calcAddressing");
109
110 // Construct weights and addressing
111 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
112
113 label nFacesRemaining = srcAddr.size();
114
115 // List of tgt face neighbour faces
116 DynamicList<label> nbrFaces(10);
117
118 // List of faces currently visited for srcFacei to avoid multiple hits
119 DynamicList<label> visitedFaces(10);
120
121 // List to keep track of tgt faces used to seed src faces
122 labelList seedFaces(nFacesRemaining, -1);
123 seedFaces[srcFacei] = tgtFacei;
124
125 // List to keep track of whether src face can be mapped
126 bitSet mapFlag(nFacesRemaining, true);
127
128 // Reset starting seed
129 label startSeedi = 0;
130
131 // Should all faces be matched?
132 const bool mustMatch = mustMatchFaces();
133
134 bool continueWalk = true;
135 DynamicList<label> nonOverlapFaces;
136 do
137 {
138 nbrFaces.clear();
139 visitedFaces.clear();
140
141 // Do advancing front starting from srcFacei,tgtFacei
142 bool faceProcessed = processSourceFace
143 (
144 srcFacei,
145 tgtFacei,
146
147 nbrFaces,
148 visitedFaces,
149
150 srcAddr,
151 srcWght,
152 srcCtr,
153 tgtAddr,
154 tgtWght
155 );
156
157 mapFlag.unset(srcFacei);
158
159 if (!faceProcessed)
160 {
161 nonOverlapFaces.append(srcFacei);
162 }
163
164 // Choose new src face from current src face neighbour
165 continueWalk = setNextFaces
166 (
167 startSeedi,
168 srcFacei,
169 tgtFacei,
170 mapFlag,
171 seedFaces,
172 visitedFaces,
173 mustMatch
174 // pass in nonOverlapFaces for failed tree search?
175 );
176 } while (continueWalk);
177
178 srcNonOverlap_.transfer(nonOverlapFaces);
179}
180
181
183(
184 const label srcFacei,
185 const label tgtStartFacei,
186
187 // list of tgt face neighbour faces
188 DynamicList<label>& nbrFaces,
189 // list of faces currently visited for srcFacei to avoid multiple hits
190 DynamicList<label>& visitedFaces,
191
192 // temporary storage for addressing, weights and centroid
193 List<DynamicList<label>>& srcAddr,
194 List<DynamicList<scalar>>& srcWght,
195 List<DynamicList<point>>& srcCtr,
196 List<DynamicList<label>>& tgtAddr,
197 List<DynamicList<scalar>>& tgtWght
198)
199{
200 addProfiling(ami, "faceAreaWeightAMI::processSourceFace");
201
202 if (tgtStartFacei == -1)
203 {
204 return false;
205 }
206
207 const auto& tgtPatch = this->tgtPatch();
208
209 // append initial target face and neighbours
210 nbrFaces.append(tgtStartFacei);
211 appendNbrFaces(tgtStartFacei, tgtPatch, visitedFaces, nbrFaces);
212
213 bool faceProcessed = false;
214
215 label maxNeighbourFaces = nbrFaces.size();
216
217 do
218 {
219 // process new target face
220 label tgtFacei = nbrFaces.remove();
221 visitedFaces.append(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 } while (nbrFaces.size() > 0);
245
246 if (debug > 1)
247 {
248 DebugVar(maxNeighbourFaces);
249 }
250
251 return faceProcessed;
252}
253
254
256(
257 label& startSeedi,
258 label& srcFacei,
259 label& tgtFacei,
260 const bitSet& mapFlag,
261 labelList& seedFaces,
262 const DynamicList<label>& visitedFaces,
263 const bool errorOnNotFound
264) const
265{
266 addProfiling(ami, "faceAreaWeightAMI::setNextFaces");
267
268 if (mapFlag.count() == 0)
269 {
270 // No more faces to map
271 return false;
272 }
273
274 const labelList& srcNbrFaces = this->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 << abort(FatalError);
366 }
367
368 return false;
369}
370
371
373(
374 const label srcFacei,
375 const label tgtFacei,
376 scalar& area,
377 vector& centroid
378) const
379{
380 addProfiling(ami, "faceAreaWeightAMI::interArea");
381
382 // Quick reject if either face has zero area/too far away/wrong orientation
383 if (!isCandidate(srcFacei, tgtFacei))
384 {
385 return;
386 }
387
388 const auto& srcPatch = this->srcPatch();
389 const auto& tgtPatch = this->tgtPatch();
390
391 const pointField& srcPoints = srcPatch.points();
392 const pointField& tgtPoints = tgtPatch.points();
393
394 // Create intersection object
396 (
397 srcPoints,
398 tgtPoints,
399 srcTris_[srcFacei],
400 tgtTris_[tgtFacei],
401 reverseTarget_,
403 );
404
405 // Crude resultant norm
406 vector n(-srcPatch.faceNormals()[srcFacei]);
407 if (reverseTarget_)
408 {
409 n -= tgtPatch.faceNormals()[tgtFacei];
410 }
411 else
412 {
413 n += tgtPatch.faceNormals()[tgtFacei];
414 }
415 scalar magN = mag(n);
416
417 const face& src = srcPatch[srcFacei];
418 const face& tgt = tgtPatch[tgtFacei];
419
420 if (magN > ROOTVSMALL)
421 {
422 inter.calc(src, tgt, n/magN, area, centroid);
423 }
424 else
425 {
427 << "Invalid normal for source face " << srcFacei
428 << " points " << UIndirectList<point>(srcPoints, src)
429 << " target face " << tgtFacei
430 << " points " << UIndirectList<point>(tgtPoints, tgt)
431 << endl;
432 }
433
435 {
436 static OBJstream tris("intersectionTris.obj");
437 const auto& triPts = inter.triangles();
438 for (const auto& tp : triPts)
439 {
440 tris.write(triPointRef(tp[0], tp[1], tp[2]), false);
441 }
442 }
443
444 if ((debug > 1) && (area > 0))
445 {
446 writeIntersectionOBJ(area, src, tgt, srcPoints, tgtPoints);
447 }
448}
449
450
452(
453 const label srcFacei,
454 const label tgtFacei,
455 const scalar threshold
456) const
457{
458 // Quick reject if either face has zero area/too far away/wrong orientation
459 if (!isCandidate(srcFacei, tgtFacei))
460 {
461 return false;
462 }
463
464 const auto& srcPatch = this->srcPatch();
465 const auto& tgtPatch = this->tgtPatch();
466
467 const pointField& srcPoints = srcPatch.points();
468 const pointField& tgtPoints = tgtPatch.points();
469
471 (
472 srcPoints,
473 tgtPoints,
474 srcTris_[srcFacei],
475 tgtTris_[tgtFacei],
476 reverseTarget_,
478 );
479
480 // Crude resultant norm
481 vector n(-srcPatch.faceNormals()[srcFacei]);
482 if (reverseTarget_)
483 {
484 n -= tgtPatch.faceNormals()[tgtFacei];
485 }
486 else
487 {
488 n += tgtPatch.faceNormals()[tgtFacei];
489 }
490 scalar magN = mag(n);
491
492 const face& src = srcPatch[srcFacei];
493 const face& tgt = tgtPatch[tgtFacei];
494
495 if (magN > ROOTVSMALL)
496 {
497 return inter.overlaps(src, tgt, n/magN, threshold);
498 }
499 else
500 {
502 << "Invalid normal for source face " << srcFacei
503 << " points " << UIndirectList<point>(srcPoints, src)
504 << " target face " << tgtFacei
505 << " points " << UIndirectList<point>(tgtPoints, tgt)
506 << endl;
507 }
508
509 return false;
510}
511
512
514(
515 List<DynamicList<label>>& srcAddr,
516 List<DynamicList<scalar>>& srcWght,
517 List<DynamicList<point>>& srcCtr,
518 List<DynamicList<label>>& tgtAddr,
519 List<DynamicList<scalar>>& tgtWght
520)
521{
522 addProfiling(ami, "faceAreaWeightAMI::restartUncoveredSourceFace");
523
524 // Note: exclude faces in srcNonOverlap_ for ACMI?
525
526 label nBelowMinWeight = 0;
527 const scalar minWeight = 0.95;
528
529 // List of tgt face neighbour faces
530 DynamicList<label> nbrFaces(10);
531
532 // List of faces currently visited for srcFacei to avoid multiple hits
533 DynamicList<label> visitedFaces(10);
534
535 const auto& srcPatch = this->srcPatch();
536
537 forAll(srcWght, srcFacei)
538 {
539 const scalar s = sum(srcWght[srcFacei]);
540 const scalar t = s/srcMagSf_[srcFacei];
541
542 if (t < minWeight)
543 {
544 ++nBelowMinWeight;
545
546 const face& f = srcPatch[srcFacei];
547
548 forAll(f, fpi)
549 {
550 const label tgtFacei =
551 findTargetFace(srcFacei, srcAddr[srcFacei], fpi);
552
553 if (tgtFacei != -1)
554 {
555 nbrFaces.clear();
556 visitedFaces = srcAddr[srcFacei];
557
558 (void)processSourceFace
559 (
560 srcFacei,
561 tgtFacei,
562
563 nbrFaces,
564 visitedFaces,
565
566 srcAddr,
567 srcWght,
568 srcCtr,
569 tgtAddr,
570 tgtWght
571 );
572 }
573 }
574 }
575 }
576
577 if (debug && nBelowMinWeight)
578 {
580 << "Restarted search on " << nBelowMinWeight
581 << " faces since sum of weights < " << minWeight
582 << endl;
583 }
584}
585
586
587// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
588
590(
591 const dictionary& dict,
592 const bool reverseTarget
593)
594:
595 advancingFrontAMI(dict, reverseTarget),
596 restartUncoveredSourceFace_
597 (
598 dict.getOrDefault("restartUncoveredSourceFace", true)
599 )
600{}
601
602
604(
605 const bool requireMatch,
606 const bool reverseTarget,
607 const scalar lowWeightCorrection,
609 const bool restartUncoveredSourceFace
610)
611:
613 (
614 requireMatch,
615 reverseTarget,
616 lowWeightCorrection,
617 triMode
618 ),
619 restartUncoveredSourceFace_(restartUncoveredSourceFace)
620{}
621
622
624:
626 restartUncoveredSourceFace_(ami.restartUncoveredSourceFace_)
627{}
628
629
630// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
631
633(
634 const primitivePatch& srcPatch,
635 const primitivePatch& tgtPatch,
636 const autoPtr<searchableSurface>& surfPtr
637)
638{
639 if (upToDate_)
640 {
641 return false;
642 }
643
644 addProfiling(ami, "faceAreaWeightAMI::calculate");
645
646 advancingFrontAMI::calculate(srcPatch, tgtPatch, surfPtr);
647
648 label srcFacei = 0;
649 label tgtFacei = 0;
650
651 bool ok = initialiseWalk(srcFacei, tgtFacei);
652
653 srcCentroids_.setSize(srcAddress_.size());
654
655 const auto& src = this->srcPatch();
656 const auto& tgt = this->tgtPatch(); // might be the extended patch!
657
658 // Temporary storage for addressing and weights
659 List<DynamicList<label>> srcAddr(src.size());
660 List<DynamicList<scalar>> srcWght(srcAddr.size());
661 List<DynamicList<point>> srcCtr(srcAddr.size());
662 List<DynamicList<label>> tgtAddr(tgt.size());
663 List<DynamicList<scalar>> tgtWght(tgtAddr.size());
664
665 if (ok)
666 {
667 calcAddressing
668 (
669 srcAddr,
670 srcWght,
671 srcCtr,
672 tgtAddr,
673 tgtWght,
674 srcFacei,
675 tgtFacei
676 );
677
678 if (debug && !srcNonOverlap_.empty())
679 {
680 Pout<< " AMI: " << srcNonOverlap_.size()
681 << " non-overlap faces identified"
682 << endl;
683 }
684
685 // Check for badly covered faces
686 if (restartUncoveredSourceFace_) // && mustMatchFaces())
687 {
688 restartUncoveredSourceFace
689 (
690 srcAddr,
691 srcWght,
692 srcCtr,
693 tgtAddr,
694 tgtWght
695 );
696 }
697 }
698
699 // Transfer data to persistent storage
700 forAll(srcAddr, i)
701 {
702 srcAddress_[i].transfer(srcAddr[i]);
703 srcWeights_[i].transfer(srcWght[i]);
704 srcCentroids_[i].transfer(srcCtr[i]);
705 }
706
707 forAll(tgtAddr, i)
708 {
709 tgtAddress_[i].transfer(tgtAddr[i]);
710 tgtWeights_[i].transfer(tgtWght[i]);
711 }
712
713 if (distributed())
714 {
715 const primitivePatch& srcPatch0 = this->srcPatch0();
716 const primitivePatch& tgtPatch0 = this->tgtPatch0();
717
718 // Create global indexing for each original patch
719 globalIndex globalSrcFaces(srcPatch0.size());
720 globalIndex globalTgtFaces(tgtPatch0.size());
721
722 for (labelList& addressing : srcAddress_)
723 {
724 for (label& addr : addressing)
725 {
726 addr = extendedTgtFaceIDs_[addr];
727 }
728 }
729
730 for (labelList& addressing : tgtAddress_)
731 {
732 globalSrcFaces.inplaceToGlobal(addressing);
733 }
734
735 // Send data back to originating procs. Note that contributions
736 // from different processors get added (ListOps::appendEqOp)
737
738 mapDistributeBase::distribute
739 (
742 tgtPatch0.size(),
743 extendedTgtMapPtr_->constructMap(),
744 false, // has flip
745 extendedTgtMapPtr_->subMap(),
746 false, // has flip
747 tgtAddress_,
748 labelList(),
750 flipOp() // flip operation
751 );
752
753 mapDistributeBase::distribute
754 (
757 tgtPatch0.size(),
758 extendedTgtMapPtr_->constructMap(),
759 false,
760 extendedTgtMapPtr_->subMap(),
761 false,
762 tgtWeights_,
763 scalarList(),
765 flipOp()
766 );
767
768 // Note: using patch face areas calculated by the AMI method
769 extendedTgtMapPtr_->reverseDistribute(tgtPatch0.size(), tgtMagSf_);
770
771 // Cache maps and reset addresses
772 List<Map<label>> cMapSrc;
773 srcMapPtr_.reset
774 (
775 new mapDistribute(globalSrcFaces, tgtAddress_, cMapSrc)
776 );
777
778 List<Map<label>> cMapTgt;
779 tgtMapPtr_.reset
780 (
781 new mapDistribute(globalTgtFaces, srcAddress_, cMapTgt)
782 );
783 }
784
785 // Convert the weights from areas to normalised values
786 normaliseWeights(requireMatch_, true);
787
788 nonConformalCorrection();
789
790 upToDate_ = true;
791
792 return upToDate_;
793}
794
795
797{
799
800 if (restartUncoveredSourceFace_)
801 {
803 (
804 "restartUncoveredSourceFace",
805 restartUncoveredSourceFace_
806 );
807 }
808}
809
810
811// ************************************************************************* //
label n
Macros for easy insertion into run-time selection tables.
#define addAliasToRunTimeSelectionTable(baseType, thisType, argNames, lookup, other, ver)
Add lookup alias for runTime selection.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
Interpolation class dealing with transfer of data between two primitive patches with an arbitrary mes...
bool mustMatchFaces() const
Return true if requireMatch and lowWeightCorrectionin active.
static bool cacheIntersections_
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:391
T remove()
Remove and return the last element. Fatal on an empty list.
Definition: DynamicListI.H:655
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
void transfer(List< T > &list)
Definition: List.C:447
OFstream that keeps track of vertices.
Definition: OBJstream.H:61
virtual Ostream & write(const char c)
Write character.
Definition: OBJstream.C:78
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:239
int overlaps
Flag to control which overlap calculations are performed.
Definition: PDRparams.H:97
A list of faces which address into the list of points.
A List with indirect addressing. Like IndirectList but does not store addressing.
Definition: IndirectList.H:79
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
@ nonBlocking
"nonBlocking"
Base class for Arbitrary Mesh Interface (AMI) methods.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:66
unsigned int count(const bool on=true) const
Count number of bits set.
Definition: bitSetI.H:500
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:521
bitSet & unset(const bitSet &other)
Definition: bitSetI.H:628
label find_next(label pos) const
Locate the next bit set, starting one beyond the specified position.
Definition: bitSetI.H:401
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
Face intersection class.
void calc(const face &faceA, const face &faceB, const vector &n, scalar &area, vector &centroid) const
bool overlaps(const face &faceA, const face &faceB, const vector &n, const scalar threshold) const
Return area of intersection of faceA with faceB.
const DynamicList< triPoints > triangles() const
Const access to the triangulation.
static scalar & tolerance()
Fraction of local length scale to use as intersection tolerance.
Face area weighted Arbitrary Mesh Interface (AMI) method.
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)
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 bool calculate(const primitivePatch &srcPatch, const primitivePatch &tgtPatch, const autoPtr< searchableSurface > &surfPtr=nullptr)
Update addressing, weights and (optional) centroids.
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.
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 void calcInterArea(const label srcFacei, const label tgtFacei, scalar &area, vector &centroid) const
Area of intersection between source and target faces.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
virtual bool write()
Write the output fields.
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
void inplaceToGlobal(labelUList &labels) const
From local to global index (inplace)
Definition: globalIndexI.H:303
Class containing processor-to-processor mapping information.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
OBJstream os(runTime.globalPath()/outputName)
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))
#define WarningInFunction
Report a warning using Foam::Warning.
#define DebugVar(var)
Report a variable name and value.
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
triangle< point, const point & > triPointRef
A triangle using referred points.
Definition: triangle.H:71
errorManip< error > abort(error &err)
Definition: errorManip.H:144
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
error FatalError
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
#define addProfiling(name, descr)
Define profiling trigger with specified name and description string.
labelList f(nPoints)
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
List helper to append y elements onto the end of x.
Definition: ListOps.H:563
Functor to negate primitives. Dummy for most other types.
Definition: flipOp.H:69