47 { areaNormalisationMode::project,
"project" },
58 if (
debug && (!src.size() || !tgt.size()))
60 Pout<<
"AMI: Patches not on processor: Source faces = " 61 << src.size() <<
", target faces = " << tgt.size()
68 const scalar maxBoundsError = 0.05;
71 boundBox bbSrc(src.points(), src.meshPoints(),
false);
86 boundBox bbTgt(tgt.points(), tgt.meshPoints(),
false);
102 boundBox bbTgtInf(bbTgt);
103 bbTgtInf.inflate(maxBoundsError);
105 if (!bbTgtInf.contains(bbSrc))
108 <<
"Source and target patch bounding boxes are not similar" 110 <<
" source box span : " << bbSrc.span() <<
nl 111 <<
" target box span : " << bbTgt.span() <<
nl 112 <<
" source box : " << bbSrc <<
nl 113 <<
" target box : " << bbTgt <<
nl 114 <<
" inflated target box : " << bbTgtInf <<
endl;
122 const label srcFacei,
126 const auto& srcPatch = this->srcPatch();
127 const auto& tgtPatch = this->tgtPatch();
131 (srcMagSf_[srcFacei] < ROOTVSMALL)
132 || (tgtMagSf_[tgtFacei] < ROOTVSMALL)
138 if (maxDistance2_ > 0)
144 const scalar normalDist((tgtFc-srcFc)&srcN);
146 if (
sqr(normalDist) >= maxDistance2_)
152 if (minCosAngle_ > -1)
161 if ((srcN & tgtN) <= minCosAngle_)
176 extendedTgtMapPtr_.reset(calcProcMap(srcPatch0(), tgtPatch0()));
177 const mapDistribute& map = extendedTgtMapPtr_();
181 globalIndex globalTgtFaces(tgtPatch0().size(), comm_);
182 distributeAndMergePatches
194 extendedTgtPatchPtr_.reset
207 const auto& src = this->srcPatch();
208 const auto& tgt = this->tgtPatch();
210 bool foundFace =
false;
217 else if (!tgt.size())
220 << src.size() <<
" source faces but no target faces" <<
endl;
229 if ((srcFacei == -1) || (tgtFacei == -1))
235 tgtFacei = findTargetFace(facei);
249 <<
"Unable to find initial target face" 259 Pout<<
"AMI: initial target face = " << tgtFacei <<
endl;
275 static label
count = 1;
280 Pout<<
"Face intersection area (" <<
count <<
"):" <<
nl 281 <<
" f1 face = " << f1 <<
nl 282 <<
" f1 pts = " << f1pts <<
nl 283 <<
" f2 face = " << f2 <<
nl 284 <<
" f2 pts = " << f2pts <<
nl 285 <<
" area = " <<
area 290 for (
const point& pt : f1pts)
301 for (
const point& pt : f2pts)
306 const label
n = f1pts.size();
309 os<<
" " <<
n + i + 1;
319 const label srcFacei,
321 const label srcFacePti
324 const auto& src = srcPatch();
326 label targetFacei = -1;
329 const face& srcFace = src[srcFacei];
333 const boundBox bb(srcPts, srcFace,
false);
336 srcFacePti == -1 ? bb.
centre() : srcPts[srcFace[srcFacePti]];
339 treePtr_->findNearest(srcPt, 0.25*bb.
magSqr(), fnOp);
344 sample = treePtr_->findNearest(srcPt,
Foam::sqr(GREAT), fnOp);
347 if (sample.
hit() && isCandidate(srcFacei, sample.
index()))
349 targetFacei = sample.
index();
353 Pout<<
"Source point = " << srcPt <<
", Sample point = " 354 << sample.
point() <<
", Sample index = " << sample.
index()
367 const DynamicList<label>& visitedFaces,
368 DynamicList<label>& faceIDs
376 for (
const label nbrFacei : nbrFaces)
379 if (!visitedFaces.found(nbrFacei) && !faceIDs.found(nbrFacei))
384 const scalar cosI = n1 & n2;
388 faceIDs.append(nbrFacei);
398 List<DynamicList<face>>& tris,
403 tris.setSize(
patch.size());
404 magSf.setSize(
patch.size());
406 const auto& faceNormals =
patch.faceNormals();
427 const DynamicList<face>& triFaces = tris[facei];
430 switch (areaNormalisationMode_)
432 case areaNormalisationMode::project:
434 for (
const face&
f : triFaces)
443 & faceNormals[facei];
449 for (
const face&
f : triFaces)
468 if (!requireMatch_ && distributed())
476 tgtMagSf_ = tgtPatch0().magFaceAreas();
478 for (
const labelList& smap : this->extendedTgtMapPtr_->subMap())
480 UIndirectList<scalar>(tgtMagSf_, smap) =
481 UIndirectList<scalar>(newTgtMagSf, smap);
491 const dictionary&
dict,
492 const bool reverseTarget
495 AMIInterpolation(
dict, reverseTarget),
496 maxDistance2_(
dict.getOrDefault<scalar>(
"maxDistance2", -1)),
497 minCosAngle_(
dict.getOrDefault<scalar>(
"minCosAngle", -1)),
500 extendedTgtPatchPtr_(nullptr),
502 extendedTgtPoints_(),
503 extendedTgtFaceIDs_(),
504 extendedTgtMapPtr_(nullptr),
508 faceAreaIntersect::triangulationModeNames_.getOrDefault
512 faceAreaIntersect::tmMesh
515 areaNormalisationMode_
517 areaNormalisationModeNames_.getOrDefault
519 "areaNormalisationMode",
521 areaNormalisationMode::project
529 <<
" areaNormalisationMode:" 537 const bool requireMatch,
538 const bool reverseTarget,
539 const scalar lowWeightCorrection,
548 extendedTgtPatchPtr_(nullptr),
550 extendedTgtPoints_(),
551 extendedTgtFaceIDs_(),
552 extendedTgtMapPtr_(nullptr),
562 maxDistance2_(ami.maxDistance2_),
563 minCosAngle_(ami.minCosAngle_),
566 extendedTgtPatchPtr_(nullptr),
568 extendedTgtPoints_(),
569 extendedTgtFaceIDs_(),
570 extendedTgtMapPtr_(nullptr),
572 triMode_(ami.triMode_),
573 areaNormalisationMode_(ami.areaNormalisationMode_)
592 createExtendedTgtPatch();
595 const auto& src = this->srcPatch();
596 const auto& tgt = this->tgtPatch();
599 if (maxDistance2_ > 0)
602 (void)src.faceCentres();
603 (void)tgt.faceCentres();
605 (void)src.faceNormals();
606 (void)tgt.faceNormals();
608 if (minCosAngle_ > -1)
611 (void)src.faceNormals();
612 (void)tgt.faceNormals();
617 srcMagSf_.setSize(src.size(), 1.0);
618 tgtMagSf_.setSize(tgt.size(), 1.0);
621 triangulatePatch(src, srcTris_, srcMagSf_);
622 triangulatePatch(tgt, tgtTris_, tgtMagSf_);
628 srcAddress_.setSize(src.size());
629 srcWeights_.setSize(src.size());
630 tgtAddress_.setSize(tgt.size());
631 tgtWeights_.setSize(tgt.size());
653 "areaNormalisationMode",
654 areaNormalisationModeNames_[areaNormalisationMode::project],
655 areaNormalisationModeNames_[areaNormalisationMode_]
List< scalar > scalarList
List of scalar.
areaNormalisationMode
Area normalisation mode.
label findTargetFace(const label srcFacei, const UList< label > &excludeFaces=UList< label >::null(), const label srcFacePti=-1) const
const faceAreaIntersect::triangulationMode triMode_
Face triangulation mode.
void writeIntersectionOBJ(const scalar area, const face &f1, const face &f2, const pointField &f1Points, const pointField &f2Points) const
Write triangle intersection to OBJ file.
A face is a list of labels corresponding to mesh vertices.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const scalar maxDistance2_
Maximum squared distance.
static const Enum< areaNormalisationMode > areaNormalisationModeNames_
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Unit conversion functions.
constexpr char nl
The newline '\n' character (0x0a)
areaNormalisationMode areaNormalisationMode_
Area normalisation mode; default = project.
Ostream & endl(Ostream &os)
Add newline and flush stream.
bool initialiseWalk(label &srcFacei, label &tgtFacei)
Initialise walk and return true if all ok.
A bounding box defined in terms of min/max extrema points.
static int & msgType() noexcept
Message tag of standard messages.
This class describes the interaction of an object (often a face) and a point. It carries the info of ...
void createExtendedTgtPatch()
Create a map that extends tgtPatch so that it covers srcPatch.
label comm_
Communicator to use for parallel operations.
#define forAll(list, i)
Loop across all elements in list.
const scalar minCosAngle_
Minimum (cos of) angle. 1 for perfectly matching.
virtual void write(Ostream &os) const
Write.
const primitivePatch & tgtPatch() const
Return const access to the target patch.
const Field< point_type > & faceNormals() const
Return face unit normals for patch.
scalar magSqr() const
The magnitude/length squared of bounding box diagonal.
A list of faces which address into the list of points.
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
const point_type & point() const noexcept
Return point, no checks.
A List obtained as a section of another List.
vectorField pointField
pointField is a vectorField.
virtual bool calculate(const primitivePatch &srcPatch, const primitivePatch &tgtPatch, const autoPtr< searchableSurface > &surfPtr=nullptr)
Update addressing, weights and (optional) centroids.
dimensionedScalar cos(const dimensionedScalar &ds)
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
static autoPtr< indexedOctree< treeDataPoint > > createTree(const pointField &points)
Construct search tree for points.
const wordList area
Standard area field types (scalar, vector, tensor, etc)
const Field< point_type > & faceCentres() const
Return face centres for patch.
label index() const noexcept
Return the hit index.
errorManip< error > abort(error &err)
Ostream & writeEntryIfDifferent(const word &key, const T &value1, const T &value2)
Write a keyword/value entry only when the two values differ.
#define DebugInfo
Report an information message using Foam::Info.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
bool isCandidate(const label srcFacei, const label tgtFacei) const
Is source/target a valid pair (i.e. not too far/different.
int debug
Static debugging option.
OBJstream os(runTime.globalPath()/outputName)
defineTypeNameAndDebug(combustionModel, 0)
static void triangleFan(const face &f, DynamicList< face > &faces)
Decompose face into triangle fan.
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field...
void checkPatches() const
Check AMI patch coupling.
void appendNbrFaces(const label facei, const primitivePatch &patch, const DynamicList< label > &visitedFaces, DynamicList< label > &faceIDs) const
Add faces neighbouring facei to the ID list.
virtual void nonConformalCorrection()
Correction for non-conformal interpolations, e.g. for ACMI.
virtual bool calculate(const primitivePatch &srcPatch, const primitivePatch &tgtPatch, const autoPtr< searchableSurface > &surfPtr=nullptr)
Update addressing, weights and (optional) centroids.
bool hit() const noexcept
Is there a hit?
bool requireMatch_
Flag to indicate that the two patches must be matched/an overlap exists between them.
vector point
Point is a vector.
#define WarningInFunction
Report a warning using Foam::Warning.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
void triangulatePatch(const primitivePatch &patch, List< DynamicList< face >> &tris, List< scalar > &magSf) const
Helper function to decompose a patch.
Base class for Arbitrary Mesh Interface (AMI) methods.
Interpolation class dealing with transfer of data between two primitive patches with an arbitrary mes...
const std::string patch
OpenFOAM patch number as a std::string.
triangle< point, const point & > triPointRef
A triangle using referred points.
static const Enum< triangulationMode > triangulationModeNames_
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
List< label > labelList
A List of labels.
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
point centre() const
The centre (midpoint) of the bounding box.
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
const primitivePatch & srcPatch() const
Return const access to the source patch.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
void reduce(T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) using linear/tree communication schedule.
virtual void write(Ostream &os) const
Write AMI as a dictionary.
advancingFrontAMI(const dictionary &dict, const bool reverseTarget)
Construct from components.