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);
341 if (sample.
hit() && isCandidate(srcFacei, sample.
index()))
343 targetFacei = sample.
index();
347 Pout<<
"Source point = " << srcPt <<
", Sample point = " 348 << sample.
point() <<
", Sample index = " << sample.
index()
361 const DynamicList<label>& visitedFaces,
362 DynamicList<label>& faceIDs
370 for (
const label nbrFacei : nbrFaces)
373 if (!visitedFaces.found(nbrFacei) && !faceIDs.found(nbrFacei))
378 const scalar cosI = n1 & n2;
382 faceIDs.append(nbrFacei);
392 List<DynamicList<face>>& tris,
397 tris.setSize(
patch.size());
398 magSf.setSize(
patch.size());
400 const auto& faceNormals =
patch.faceNormals();
421 const DynamicList<face>& triFaces = tris[facei];
424 switch (areaNormalisationMode_)
426 case areaNormalisationMode::project:
428 for (
const face&
f : triFaces)
437 & faceNormals[facei];
443 for (
const face&
f : triFaces)
462 if (!requireMatch_ && distributed())
470 tgtMagSf_ = tgtPatch0().magFaceAreas();
472 for (
const labelList& smap : this->extendedTgtMapPtr_->subMap())
474 UIndirectList<scalar>(tgtMagSf_, smap) =
475 UIndirectList<scalar>(newTgtMagSf, smap);
485 const dictionary&
dict,
486 const bool reverseTarget
489 AMIInterpolation(
dict, reverseTarget),
490 maxDistance2_(
dict.getOrDefault<scalar>(
"maxDistance2", -1)),
491 minCosAngle_(
dict.getOrDefault<scalar>(
"minCosAngle", -1)),
494 extendedTgtPatchPtr_(nullptr),
496 extendedTgtPoints_(),
497 extendedTgtFaceIDs_(),
498 extendedTgtMapPtr_(nullptr),
502 faceAreaIntersect::triangulationModeNames_.getOrDefault
506 faceAreaIntersect::tmMesh
509 areaNormalisationMode_
511 areaNormalisationModeNames_.getOrDefault
513 "areaNormalisationMode",
515 areaNormalisationMode::project
523 <<
" areaNormalisationMode:" 531 const bool requireMatch,
532 const bool reverseTarget,
533 const scalar lowWeightCorrection,
542 extendedTgtPatchPtr_(nullptr),
544 extendedTgtPoints_(),
545 extendedTgtFaceIDs_(),
546 extendedTgtMapPtr_(nullptr),
556 maxDistance2_(ami.maxDistance2_),
557 minCosAngle_(ami.minCosAngle_),
560 extendedTgtPatchPtr_(nullptr),
562 extendedTgtPoints_(),
563 extendedTgtFaceIDs_(),
564 extendedTgtMapPtr_(nullptr),
566 triMode_(ami.triMode_),
567 areaNormalisationMode_(ami.areaNormalisationMode_)
586 createExtendedTgtPatch();
589 const auto& src = this->srcPatch();
590 const auto& tgt = this->tgtPatch();
593 if (maxDistance2_ > 0)
596 (void)src.faceCentres();
597 (void)tgt.faceCentres();
599 (void)src.faceNormals();
600 (void)tgt.faceNormals();
602 if (minCosAngle_ > -1)
605 (void)src.faceNormals();
606 (void)tgt.faceNormals();
611 srcMagSf_.setSize(src.size(), 1.0);
612 tgtMagSf_.setSize(tgt.size(), 1.0);
615 triangulatePatch(src, srcTris_, srcMagSf_);
616 triangulatePatch(tgt, tgtTris_, tgtMagSf_);
622 srcAddress_.setSize(src.size());
623 srcWeights_.setSize(src.size());
624 tgtAddress_.setSize(tgt.size());
625 tgtWeights_.setSize(tgt.size());
647 "areaNormalisationMode",
648 areaNormalisationModeNames_[areaNormalisationMode::project],
649 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.
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
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.
virtual void write(Ostream &os) const
Write AMI as a dictionary.
advancingFrontAMI(const dictionary &dict, const bool reverseTarget)
Construct from components.