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)
140 const point& srcFc = srcPatch.faceCentres()[srcFacei];
141 const point& tgtFc = tgtPatch.faceCentres()[tgtFacei];
142 const vector& srcN = srcPatch.faceNormals()[srcFacei];
144 const scalar normalDist((tgtFc-srcFc)&srcN);
146 if (
sqr(normalDist) >= maxDistance2_)
152 if (minCosAngle_ > -1)
154 const vector& srcN = srcPatch.faceNormals()[srcFacei];
155 vector tgtN = tgtPatch.faceNormals()[tgtFacei];
161 if ((srcN & tgtN) <= minCosAngle_)
176 extendedTgtMapPtr_.reset(calcProcMap(srcPatch0(), tgtPatch0()));
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
288 OFstream
os(
"areas" +
name(count) +
".obj");
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,
320 const UList<label>& excludeFaces,
321 const label srcFacePti
324 const auto& src = srcPatch();
326 label targetFacei = -1;
329 const face& srcFace = src[srcFacei];
331 findNearestMaskedOp<primitivePatch> fnOp(*treePtr_, excludeFaces);
333 const boundBox bb(srcPts, srcFace,
false);
336 srcFacePti == -1 ? bb.
centre() : srcPts[srcFace[srcFacePti]];
339 treePtr_->findNearest(srcPt, 0.25*bb.magSqr(), 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()
376 for (
const label nbrFacei : nbrFaces)
379 if (!visitedFaces.found(nbrFacei) && !faceIDs.found(nbrFacei))
384 const scalar cosI = n1 & n2;
388 faceIDs.append(nbrFacei);
403 tris.setSize(
patch.size());
404 magSf.setSize(
patch.size());
406 const auto& faceNormals =
patch.faceNormals();
430 switch (areaNormalisationMode_)
432 case areaNormalisationMode::project:
434 for (
const face&
f : triFaces)
443 & faceNormals[facei];
447 case areaNormalisationMode::mag:
449 for (
const face&
f : triFaces)
468 if (!requireMatch_ && distributed() && comm() != -1)
476 tgtMagSf_ = tgtPatch0().magFaceAreas();
478 for (
const labelList& smap : this->extendedTgtMapPtr_->subMap())
492 const bool 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),
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_(),
562 maxDistance2_(ami.maxDistance2_),
563 minCosAngle_(ami.minCosAngle_),
566 extendedTgtPatchPtr_(nullptr),
568 extendedTgtPoints_(),
569 extendedTgtFaceIDs_(),
570 extendedTgtMapPtr_(nullptr),
590 if (distributed() && comm() != -1)
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());
643 os.writeEntryIfDifferent<scalar>(
"maxDistance2", -1, maxDistance2_);
644 os.writeEntryIfDifferent<scalar>(
"minCosAngle", -1, minCosAngle_);
645 os.writeEntryIfDifferent<word>
651 os.writeEntryIfDifferent<word>
653 "areaNormalisationMode",
654 areaNormalisationModeNames_[areaNormalisationMode::project],
655 areaNormalisationModeNames_[areaNormalisationMode_]
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 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...
AMIInterpolation(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.
bool requireMatch() const noexcept
Return the requireMatch flag.
const primitivePatch & tgtPatch0() const
Return the original tgt patch with optionally updated points.
virtual void write(Ostream &os) const
Write AMI as a dictionary.
labelListList tgtAddress_
Addresses of source faces per target face.
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.
void append(const T &val)
Copy append an element to the end of this list.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Minimal example by using system/controlDict.functions:
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
void setSize(label n)
Alias for resize().
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
A non-owning sub-view of a List (allocated or unallocated storage).
A List with indirect addressing. Like IndirectList but does not store addressing.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
bool found(const T &val, label pos=0) const
Same as contains().
void size(const label n)
Older name for setAddressableSize.
static int & msgType() noexcept
Message tag of standard messages.
const Vector< Cmpt > & centre(const Foam::UList< Vector< Cmpt > > &) const noexcept
Return this (for point which is a typedef to Vector<scalar>).
Base class for Arbitrary Mesh Interface (AMI) methods.
const scalar maxDistance2_
Maximum squared distance.
const primitivePatch & tgtPatch() const
Return const access to the target patch.
pointField extendedTgtPoints_
Extended patch points.
areaNormalisationMode areaNormalisationMode_
Area normalisation mode; default = project.
faceList extendedTgtFaces_
Extended patch faces.
bool initialiseWalk(label &srcFacei, label &tgtFacei)
Initialise walk and return true if all ok.
const scalar minCosAngle_
Minimum (cos of) angle. 1 for perfectly matching.
static const Enum< areaNormalisationMode > areaNormalisationModeNames_
void checkPatches() const
Check AMI patch coupling.
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.
areaNormalisationMode
Area normalisation mode.
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 createExtendedTgtPatch()
Create a map that extends tgtPatch so that it covers srcPatch.
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.
autoPtr< indexedOctree< treeType > > treePtr_
Octree used to find face seeds.
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 ...
const faceAreaIntersect::triangulationMode triMode_
Face triangulation mode.
autoPtr< primitivePatch > extendedTgtPatchPtr_
Demand-driven extended target mesh (distributed parallel usage).
void triangulatePatch(const primitivePatch &patch, List< DynamicList< face > > &tris, List< scalar > &magSf) const
Helper function to decompose a patch.
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.
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
A bounding box defined in terms of min/max extrema points.
const point & max() const noexcept
Maximum describing the bounding box.
const point & min() const noexcept
Minimum describing the bounding box.
bool contains(const point &pt) const
Contains point? (inside or on edge).
scalar magSqr() const
The magnitude/length squared of bounding box diagonal.
void inflate(const scalar factor)
Expand box by factor*mag(span) in all dimensions.
vector span() const
The bounding box span (from minimum to maximum).
point centre() const
The centre (midpoint) of the bounding box.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
static void triangleFan(const face &f, DynamicList< face > &faces)
Decompose face into triangle fan.
static const Enum< triangulationMode > triangulationModeNames_
A face is a list of labels corresponding to mesh vertices.
pointField points(const UList< point > &pts) const
Return the points corresponding to this face.
Calculates a non-overlapping list of offsets based on an input size (eg, number of cells) from differ...
Class containing processor-to-processor mapping information.
static vector areaNormal(const Point &p0, const Point &p1, const Point &p2)
The area normal for a triangle defined by three points (right-hand rule). Magnitude equal to area of ...
scalar mag() const
The magnitude of the triangle area.
A class for handling words, derived from Foam::string.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
OBJstream os(runTime.globalPath()/outputName)
#define DebugInfo
Report an information message using Foam::Info.
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for handling debugging switches.
const std::string patch
OpenFOAM patch number as a std::string.
List< label > labelList
A List of labels.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
static autoPtr< indexedOctree< treeDataPoint > > createTree(const pointField &points)
Construct search tree for points.
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.
constexpr scalar degToRad() noexcept
Multiplication factor for degrees to radians conversion.
void reduce(T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce).
errorManip< error > abort(error &err)
vector point
Point is a vector.
triangle< point, const point & > triPointRef
A triangle using referred points.
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.
PointIndexHit< point > pointIndexHit
A PointIndexHit with a 3D point.
UList< label > labelUList
A UList of labels.
List< scalar > scalarList
List of scalar.
dimensionedScalar cos(const dimensionedScalar &ds)
constexpr char nl
The newline '\n' character (0x0a).
#define forAll(list, i)
Loop across all elements in list.
Unit conversion functions.