Loading...
Searching...
No Matches
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-2024 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"
34// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35
36namespace Foam
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 for (const auto& 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 auto& 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 labelUList& 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]
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
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
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)
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
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,
618 triMode
619 ),
620 restartUncoveredSourceFace_(restartUncoveredSourceFace)
621{}
622
623
625:
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 tgtAddress_.setSize(tgtAddr.size());
709 tgtWeights_.setSize(tgtWght.size());
710 forAll(tgtAddr, i)
711 {
712 tgtAddress_[i].transfer(tgtAddr[i]);
713 tgtWeights_[i].transfer(tgtWght[i]);
714 }
715
716 if (distributed() && comm() != -1)
717 {
718 const label myRank = UPstream::myProcNo(comm());
719 // Allocate unique tag for all comms
720 const int oldTag = UPstream::incrMsgType();
721
722 const primitivePatch& srcPatch0 = this->srcPatch0();
723 const primitivePatch& tgtPatch0 = this->tgtPatch0();
724
725 // Create global indexing for each original patch
726 globalIndex globalSrcFaces(srcPatch0.size(), comm());
727 globalIndex globalTgtFaces(tgtPatch0.size(), comm());
728
729 for (labelList& addressing : srcAddress_)
730 {
731 for (label& addr : addressing)
732 {
733 addr = extendedTgtFaceIDs_[addr];
734 }
735 }
736
737 for (labelList& addressing : tgtAddress_)
738 {
739 globalSrcFaces.inplaceToGlobal(myRank, addressing);
740 }
741
742 // Send data back to originating procs. Note that contributions
743 // from different processors get added (ListOps::appendEqOp)
744
746 (
749 tgtPatch0.size(),
750 extendedTgtMapPtr_->constructMap(),
751 false, // has flip
752 extendedTgtMapPtr_->subMap(),
753 false, // has flip
754 tgtAddress_,
755 labelList(),
757 flipOp(), // flip operation
758 UPstream::msgType()+77431,
759 comm()
760 );
761
763 (
766 tgtPatch0.size(),
767 extendedTgtMapPtr_->constructMap(),
768 false,
769 extendedTgtMapPtr_->subMap(),
770 false,
771 tgtWeights_,
772 scalarList(),
774 flipOp(),
775 UPstream::msgType()+77432,
776 comm()
777 );
778
779 // Note: using patch face areas calculated by the AMI method
780 extendedTgtMapPtr_->reverseDistribute(tgtPatch0.size(), tgtMagSf_);
781
782 // Cache maps and reset addresses
783 List<Map<label>> cMapSrc;
784 srcMapPtr_.reset
785 (
786 new mapDistribute
787 (
788 globalSrcFaces,
789 tgtAddress_,
790 cMapSrc,
791 UPstream::msgType()+77433,
792 comm()
793 )
794 );
795
796 List<Map<label>> cMapTgt;
797 tgtMapPtr_.reset
798 (
799 new mapDistribute
800 (
801 globalTgtFaces,
802 srcAddress_,
803 cMapTgt,
804 UPstream::msgType()+77434,
805 comm()
806 )
807 );
808
809 // Reset tag
810 UPstream::msgType(oldTag);
811 }
812
813 // Convert the weights from areas to normalised values
814 normaliseWeights(requireMatch_, true);
815
816 nonConformalCorrection();
818 upToDate_ = true;
819
820 return upToDate_;
821}
822
823
825{
827
828 if (restartUncoveredSourceFace_)
829 {
830 os.writeEntry
831 (
832 "restartUncoveredSourceFace",
833 restartUncoveredSourceFace_
834 );
835 }
836}
837
838
839// ************************************************************************* //
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 requireMatch_
Flag to indicate that the two patches must be matched/an overlap exists between them.
bool mustMatchFaces() const
Return true if requireMatch and but not lowWeightCorrection.
bool reverseTarget() const noexcept
Access to the reverseTarget flag.
labelListList srcAddress_
Addresses of target faces per source face.
label comm() const noexcept
Communicator (local or otherwise) for parallel operations.
bool distributed() const noexcept
Distributed across processors (singlePatchProc == -1).
scalarList tgtMagSf_
Target face areas.
const bool reverseTarget_
Flag to indicate that the two patches are co-directional and that the orientation of the target patch...
autoPtr< mapDistribute > srcMapPtr_
Source map pointer - parallel running only.
bool requireMatch() const noexcept
Return the requireMatch flag.
const primitivePatch & tgtPatch0() const
Return the original tgt patch with optionally updated points.
bool upToDate_
Up-to-date flag.
autoPtr< mapDistribute > tgtMapPtr_
Target map pointer - parallel running only.
labelListList tgtAddress_
Addresses of source faces per target face.
pointListList srcCentroids_
Centroid of target faces per source face.
static bool cacheIntersections_
Flag to store face-to-face intersection triangles; default = false.
static void normaliseWeights(const scalarList &patchAreas, const word &patchName, const labelListList &addr, scalarListList &wght, scalarField &wghtSum, const bool conformal, const bool output, const scalar lowWeightTol, const label comm)
Normalise the (area) weights - suppresses numerical error in weights calculation.
scalar lowWeightCorrection() const
Threshold weight below which interpolation is deactivated.
scalarListList tgtWeights_
Weights of source faces per target face.
scalarListList srcWeights_
Weights of target faces per source face.
scalarList srcMagSf_
Source face areas.
const primitivePatch & srcPatch0() const
Return the original src patch with optionally updated points.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
void pop_back(label n=1)
Reduce size by 1 or more elements. Can be called on an empty list.
void append(const T &val)
Copy append an element to the end of this list.
void push_back(const T &val)
Copy append an element to the end of this list.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition List.C:347
static const List< T > & null() noexcept
Return a null List (reference to a nullObject). Behaves like an empty List.
Definition List.H:138
An OFstream that keeps track of vertices and provides convenience output methods for OBJ files.
Definition OBJstream.H:58
virtual Ostream & write(const char c) override
Write character.
Definition OBJstream.C:69
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
A List with indirect addressing. Like IndirectList but does not store addressing.
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
T & back()
Access last element of the list, position [size()-1].
Definition UListI.H:253
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
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:1706
@ nonBlocking
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
Definition UPstream.H:84
static int & msgType() noexcept
Message tag of standard messages.
Definition UPstream.H:1926
static int incrMsgType(int val=1) noexcept
Increment the message tag for standard messages.
Definition UPstream.H:1948
Base class for Arbitrary Mesh Interface (AMI) methods.
const primitivePatch & tgtPatch() const
Return const access to the target patch.
bool initialiseWalk(label &srcFacei, label &tgtFacei)
Initialise walk and return true if all ok.
List< DynamicList< face > > srcTris_
Storage for src-side triangle decomposition.
virtual bool calculate(const primitivePatch &srcPatch, const primitivePatch &tgtPatch, const autoPtr< searchableSurface > &surfPtr=nullptr)
Update addressing, weights and (optional) centroids.
bool isCandidate(const label srcFacei, const label tgtFacei) const
Is source/target a valid pair (i.e. not too far/different.
virtual void nonConformalCorrection()
Correction for non-conformal interpolations, e.g. for ACMI.
void appendNbrFaces(const label facei, const primitivePatch &patch, const labelUList &visitedFaces, DynamicList< label > &faceIDs) const
Add faces neighbouring facei to the ID list.
virtual void write(Ostream &os) const
Write.
void writeIntersectionOBJ(const scalar area, const face &f1, const face &f2, const pointField &f1Points, const pointField &f2Points) const
Write triangle intersection to OBJ file.
advancingFrontAMI(const dictionary &dict, const bool reverseTarget)
Construct from components.
List< DynamicList< face > > tgtTris_
Storage for tgt-side triangle decomposition.
const primitivePatch & srcPatch() const
Return const access to the source patch.
autoPtr< mapDistribute > extendedTgtMapPtr_
Extended patch map.
labelList extendedTgtFaceIDs_
Extended patch face IDs.
labelList srcNonOverlap_
Labels of faces that are not overlapped by any target faces (should be empty for correct functioning ...
label findTargetFace(const label srcFacei, const UList< label > &excludeFaces=UList< label >::null(), const label srcFacePti=-1) const
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition bitSet.H:61
unsigned int count(const bool on=true) const
Count number of bits set.
Definition bitSetI.H:420
bool test(const label pos) const
Test for True value at specified position, never auto-vivify entries.
Definition bitSet.H:334
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:540
label find_next(label pos) const
Locate the next bit set, starting one beyond the specified position.
Definition bitSetI.H:347
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
Face intersection class.
void calc(const face &faceA, const face &faceB, const vector &n, scalar &area, vector &centroid) const
Return area of intersection of faceA with faceB and effective face centre.
bool overlaps(const face &faceA, const face &faceB, const vector &n, const scalar threshold) const
Return area of intersection of faceA with faceB.
static scalar & tolerance()
Fraction of local length scale to use as intersection tolerance.
const DynamicList< triPoints > & triangles() const noexcept
Const access to the triangulation.
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)
Calculate addressing, weights and centroids using temporary storage.
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.
faceAreaWeightAMI(const dictionary &dict, const bool reverseTarget=false)
Construct from dictionary.
virtual bool calculate(const primitivePatch &srcPatch, const primitivePatch &tgtPatch, const autoPtr< searchableSurface > &surfPtr=nullptr)
Update addressing, weights and (optional) centroids.
virtual void write(Ostream &os) const
Write.
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.
virtual bool setNextFaces(label &startSeedi, label &srcFacei, label &tgtFacei, const bitSet &mapFlag, labelList &seedFaces, const labelUList &visitedFaces, const bool errorOnNotFound=true) const
Set the source and target seed faces.
virtual bool overlaps(const label srcFacei, const label tgtFacei, const scalar threshold) const
Return true if faces overlap.
A face is a list of labels corresponding to mesh vertices.
Definition face.H:71
Calculates a non-overlapping list of offsets based on an input size (eg, number of cells) from differ...
Definition globalIndex.H:77
void inplaceToGlobal(const label proci, labelUList &labels) const
From local to global index on proci (inplace).
static void distribute(const UPstream::commsTypes commsType, const UList< 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).
Class containing processor-to-processor mapping information.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
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 handling debugging switches.
Definition debug.C:45
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:40
List< label > labelList
A List of labels.
Definition List.H:62
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
errorManip< error > abort(error &err)
Definition errorManip.H:139
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &f1, const label comm)
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
triangle< point, const point & > triPointRef
A triangle using referred points.
Definition triangleFwd.H:46
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
vectorField pointField
pointField is a vectorField.
Vector< scalar > vector
Definition vector.H:57
UList< label > labelUList
A UList of labels.
Definition UList.H:75
List< scalar > scalarList
List of scalar.
Definition scalarList.H:32
#define addProfiling(Name,...)
Define profiling trigger with specified name and description string. The description is generated by ...
labelList f(nPoints)
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
List helper to append y elements onto the end of x.
Definition ListOps.H:712
Functor to negate primitives. Dummy for most other types.
Definition flipOp.H:67