50 partialFaceAreaWeightAMI,
111 label nFacesRemaining = srcAddr.size();
120 labelList seedFaces(nFacesRemaining, -1);
121 seedFaces[srcFacei] = tgtFacei;
124 bitSet mapFlag(nFacesRemaining,
true);
127 label startSeedi = 0;
132 bool continueWalk =
true;
137 visitedFaces.
clear();
155 mapFlag.
unset(srcFacei);
159 nonOverlapFaces.
append(srcFacei);
174 }
while (continueWalk);
182 const label srcFacei,
183 const label tgtStartFacei,
186 DynamicList<label>& nbrFaces,
188 DynamicList<label>& visitedFaces,
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
198 addProfiling(ami,
"faceAreaWeightAMI::processSourceFace");
200 if (tgtStartFacei == -1)
205 const auto& tgtPatch = this->tgtPatch();
208 nbrFaces.append(tgtStartFacei);
209 appendNbrFaces(tgtStartFacei, tgtPatch, visitedFaces, nbrFaces);
211 bool faceProcessed =
false;
213 label maxNeighbourFaces = nbrFaces.size();
218 label tgtFacei = nbrFaces.remove();
219 visitedFaces.append(tgtFacei);
221 scalar interArea = 0;
223 calcInterArea(srcFacei, tgtFacei, interArea, interCentroid);
228 srcAddr[srcFacei].append(tgtFacei);
229 srcWght[srcFacei].append(interArea);
230 srcCtr[srcFacei].append(interCentroid);
232 tgtAddr[tgtFacei].append(srcFacei);
233 tgtWght[tgtFacei].append(interArea);
235 appendNbrFaces(tgtFacei, tgtPatch, visitedFaces, nbrFaces);
237 faceProcessed =
true;
239 maxNeighbourFaces =
max(maxNeighbourFaces, nbrFaces.size());
242 }
while (nbrFaces.size() > 0);
249 return faceProcessed;
258 const bitSet& mapFlag,
260 const DynamicList<label>& visitedFaces,
261 const bool errorOnNotFound
266 if (mapFlag.count() == 0)
278 bool valuesSet =
false;
279 for (label faceS: srcNbrFaces)
281 if (mapFlag.test(faceS) && seedFaces[faceS] == -1)
283 for (label faceT : visitedFaces)
285 const scalar threshold =
289 if (overlaps(faceS, faceT, threshold))
291 seedFaces[faceS] = faceT;
311 label facei = startSeedi;
312 if (!mapFlag.test(startSeedi))
314 facei = mapFlag.find_next(facei);
316 const label startSeedi0 = facei;
318 bool foundNextSeed =
false;
324 foundNextSeed =
true;
327 if (seedFaces[facei] != -1)
330 tgtFacei = seedFaces[facei];
335 facei = mapFlag.find_next(facei);
341 Pout<<
"Advancing front stalled: searching for new " 342 <<
"target face" <<
endl;
349 tgtFacei = findTargetFace(srcFacei, visitedFaces);
356 facei = mapFlag.find_next(facei);
362 <<
"Unable to set target face for source face " << srcFacei
372 const label srcFacei,
373 const label tgtFacei,
381 if (!isCandidate(srcFacei, tgtFacei))
386 const auto& srcPatch = this->srcPatch();
387 const auto& tgtPatch = this->tgtPatch();
393 faceAreaIntersect inter
413 scalar magN =
mag(
n);
415 const face& src = srcPatch[srcFacei];
416 const face& tgt = tgtPatch[tgtFacei];
418 if (magN > ROOTVSMALL)
420 inter.calc(src, tgt,
n/magN,
area, centroid);
425 <<
"Invalid normal for source face " << srcFacei
426 <<
" points " << UIndirectList<point>(srcPoints, src)
427 <<
" target face " << tgtFacei
428 <<
" points " << UIndirectList<point>(tgtPoints, tgt)
434 static OBJstream tris(
"intersectionTris.obj");
435 const auto& triPts = inter.triangles();
436 for (
const auto& tp : triPts)
438 tris.write(
triPointRef(tp[0], tp[1], tp[2]),
false);
444 writeIntersectionOBJ(
area, src, tgt, srcPoints, tgtPoints);
451 const label srcFacei,
452 const label tgtFacei,
453 const scalar threshold
457 if (!isCandidate(srcFacei, tgtFacei))
462 const auto& srcPatch = this->srcPatch();
463 const auto& tgtPatch = this->tgtPatch();
468 faceAreaIntersect inter
488 scalar magN =
mag(
n);
490 const face& src = srcPatch[srcFacei];
491 const face& tgt = tgtPatch[tgtFacei];
493 if (magN > ROOTVSMALL)
495 return inter.overlaps(src, tgt,
n/magN, threshold);
500 <<
"Invalid normal for source face " << srcFacei
501 <<
" points " << UIndirectList<point>(srcPoints, src)
502 <<
" target face " << tgtFacei
503 <<
" points " << UIndirectList<point>(tgtPoints, tgt)
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
520 addProfiling(ami,
"faceAreaWeightAMI::restartUncoveredSourceFace");
524 label nBelowMinWeight = 0;
525 const scalar minWeight = 0.95;
528 DynamicList<label> nbrFaces(10);
531 DynamicList<label> visitedFaces(10);
533 const auto& srcPatch = this->srcPatch();
537 const scalar
s =
sum(srcWght[srcFacei]);
538 const scalar t =
s/srcMagSf_[srcFacei];
544 const face&
f = srcPatch[srcFacei];
548 const label tgtFacei =
549 findTargetFace(srcFacei, srcAddr[srcFacei], fpi);
554 visitedFaces = srcAddr[srcFacei];
556 (void)processSourceFace
575 if (
debug && nBelowMinWeight)
578 <<
"Restarted search on " << nBelowMinWeight
579 <<
" faces since sum of weights < " << minWeight
589 const dictionary&
dict,
590 const bool reverseTarget
593 advancingFrontAMI(
dict, reverseTarget),
594 restartUncoveredSourceFace_
596 dict.getOrDefault(
"restartUncoveredSourceFace", true)
603 const bool requireMatch,
604 const bool reverseTarget,
605 const scalar lowWeightCorrection,
607 const bool restartUncoveredSourceFace
617 restartUncoveredSourceFace_(restartUncoveredSourceFace)
624 restartUncoveredSourceFace_(ami.restartUncoveredSourceFace_)
649 bool ok = initialiseWalk(srcFacei, tgtFacei);
651 srcCentroids_.setSize(srcAddress_.size());
653 const auto& src = this->srcPatch();
654 const auto& tgt = this->tgtPatch();
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());
676 if (
debug && !srcNonOverlap_.empty())
678 Pout<<
" AMI: " << srcNonOverlap_.size()
679 <<
" non-overlap faces identified" 684 if (restartUncoveredSourceFace_)
686 restartUncoveredSourceFace
700 srcAddress_[i].transfer(srcAddr[i]);
701 srcWeights_[i].transfer(srcWght[i]);
702 srcCentroids_[i].transfer(srcCtr[i]);
707 tgtAddress_[i].transfer(tgtAddr[i]);
708 tgtWeights_[i].transfer(tgtWght[i]);
717 globalIndex globalSrcFaces(srcPatch0.size());
718 globalIndex globalTgtFaces(tgtPatch0.size());
720 for (
labelList& addressing : srcAddress_)
722 for (label& addr : addressing)
724 addr = extendedTgtFaceIDs_[addr];
728 for (
labelList& addressing : tgtAddress_)
730 globalSrcFaces.inplaceToGlobal(addressing);
741 extendedTgtMapPtr_->constructMap(),
743 extendedTgtMapPtr_->subMap(),
747 ListOps::appendEqOp<label>(),
756 extendedTgtMapPtr_->constructMap(),
758 extendedTgtMapPtr_->subMap(),
762 ListOps::appendEqOp<scalar>(),
767 extendedTgtMapPtr_->reverseDistribute(tgtPatch0.size(), tgtMagSf_);
770 List<Map<label>> cMapSrc;
773 new mapDistribute(globalSrcFaces, tgtAddress_, cMapSrc)
776 List<Map<label>> cMapTgt;
779 new mapDistribute(globalTgtFaces, srcAddress_, cMapTgt)
784 normaliseWeights(requireMatch_,
true);
786 nonConformalCorrection();
798 if (restartUncoveredSourceFace_)
802 "restartUncoveredSourceFace",
803 restartUncoveredSourceFace_
faceAreaWeightAMI(const dictionary &dict, const bool reverseTarget=false)
Construct from dictionary.
#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.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
bool mustMatchFaces() const
Return true if requireMatch and lowWeightCorrectionin active.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
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.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
static const List< T > & null()
Return a null List.
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.
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.
bitSet & unset(const bitSet &other)
Unset (subtract) the bits specified in the other bitset, which is a set difference corresponds to the...
const wordList area
Standard area field types (scalar, vector, tensor, etc)
List< scalar > scalarList
A List of scalars.
virtual void calcInterArea(const label srcFacei, const label tgtFacei, scalar &area, vector ¢roid) 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.
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.
errorManip< error > abort(error &err)
An Ostream is an abstract base class for all output systems (streams, files, token lists...
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.
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...
#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.
"nonBlocking" : (MPI_Isend, MPI_Irecv)
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
#define DebugVar(var)
Report a variable name and value.
List< label > labelList
A List of labels.
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 constexpr const zero Zero
Global zero (0)