50 if (
debug && (!src.size() || !tgt.size()))
52 Pout<<
"AMI: Patches not on processor: Source faces = " 53 << src.size() <<
", target faces = " << tgt.size()
60 const scalar maxBoundsError = 0.05;
63 boundBox bbSrc(src.points(), src.meshPoints(),
true);
64 boundBox bbTgt(tgt.points(), tgt.meshPoints(),
true);
66 boundBox bbTgtInf(bbTgt);
67 bbTgtInf.inflate(maxBoundsError);
69 if (!bbTgtInf.contains(bbSrc))
72 <<
"Source and target patch bounding boxes are not similar" 74 <<
" source box span : " << bbSrc.span() <<
nl 75 <<
" target box span : " << bbTgt.span() <<
nl 76 <<
" source box : " << bbSrc <<
nl 77 <<
" target box : " << bbTgt <<
nl 78 <<
" inflated target box : " << bbTgtInf <<
endl;
90 const auto& srcPatch = this->srcPatch();
91 const auto& tgtPatch = this->tgtPatch();
95 (srcMagSf_[srcFacei] < ROOTVSMALL)
96 || (tgtMagSf_[tgtFacei] < ROOTVSMALL)
102 if (maxDistance2_ > 0)
108 const scalar normalDist((tgtFc-srcFc)&srcN);
110 if (
sqr(normalDist) >= maxDistance2_)
116 if (minCosAngle_ > -1)
125 if ((srcN & tgtN) <= minCosAngle_)
140 extendedTgtMapPtr_.reset(calcProcMap(srcPatch0(), tgtPatch0()));
141 const mapDistribute& map = extendedTgtMapPtr_();
145 globalIndex globalTgtFaces(tgtPatch0().size());
146 distributeAndMergePatches
158 extendedTgtPatchPtr_.reset
171 const auto& src = this->srcPatch();
172 const auto& tgt = this->tgtPatch();
174 bool foundFace =
false;
181 else if (!tgt.size())
184 << src.size() <<
" source faces but no target faces" <<
endl;
193 if ((srcFacei == -1) || (tgtFacei == -1))
199 tgtFacei = findTargetFace(facei);
213 <<
"Unable to find initial target face" 223 Pout<<
"AMI: initial target face = " << tgtFacei <<
endl;
239 static label
count = 1;
244 Pout<<
"Face intersection area (" <<
count <<
"):" <<
nl 245 <<
" f1 face = " << f1 <<
nl 246 <<
" f1 pts = " << f1pts <<
nl 247 <<
" f2 face = " << f2 <<
nl 248 <<
" f2 pts = " << f2pts <<
nl 249 <<
" area = " <<
area 254 for (
const point& pt : f1pts)
265 for (
const point& pt : f2pts)
270 const label
n = f1pts.size();
273 os<<
" " <<
n + i + 1;
283 const label srcFacei,
285 const label srcFacePti
288 const auto& src = srcPatch();
290 label targetFacei = -1;
293 const face& srcFace = src[srcFacei];
297 const boundBox bb(srcPts, srcFace,
false);
300 srcFacePti == -1 ? bb.
centre() : srcPts[srcFace[srcFacePti]];
303 treePtr_->findNearest(srcPt, 0.25*bb.
magSqr(), fnOp);
305 if (sample.
hit() && isCandidate(srcFacei, sample.
index()))
307 targetFacei = sample.
index();
311 Pout<<
"Source point = " << srcPt <<
", Sample point = " 312 << sample.
point() <<
", Sample index = " << sample.
index()
325 const DynamicList<label>& visitedFaces,
326 DynamicList<label>& faceIDs
334 for (
const label nbrFacei : nbrFaces)
337 if (!visitedFaces.found(nbrFacei) && !faceIDs.found(nbrFacei))
342 const scalar cosI = n1 & n2;
346 faceIDs.append(nbrFacei);
356 List<DynamicList<face>>& tris,
361 tris.setSize(
patch.size());
362 magSf.setSize(
patch.size());
364 const auto& faceNormals =
patch.faceNormals();
385 const DynamicList<face>& triFaces = tris[facei];
387 for (
const face&
f : triFaces)
396 & faceNormals[facei];
404 if (!requireMatch_ && distributed())
412 tgtMagSf_ = tgtPatch0().magFaceAreas();
414 for (
const labelList& smap : this->extendedTgtMapPtr_->subMap())
416 UIndirectList<scalar>(tgtMagSf_, smap) =
417 UIndirectList<scalar>(newTgtMagSf, smap);
427 const dictionary&
dict,
428 const bool reverseTarget
431 AMIInterpolation(
dict, reverseTarget),
432 maxDistance2_(
dict.getOrDefault<scalar>(
"maxDistance2", -1)),
433 minCosAngle_(
dict.getOrDefault<scalar>(
"minCosAngle", -1)),
436 extendedTgtPatchPtr_(nullptr),
438 extendedTgtPoints_(),
439 extendedTgtFaceIDs_(),
440 extendedTgtMapPtr_(nullptr),
444 faceAreaIntersect::triangulationModeNames_.getOrDefault
456 const bool requireMatch,
457 const bool reverseTarget,
458 const scalar lowWeightCorrection,
467 extendedTgtPatchPtr_(nullptr),
469 extendedTgtPoints_(),
470 extendedTgtFaceIDs_(),
471 extendedTgtMapPtr_(nullptr),
480 maxDistance2_(ami.maxDistance2_),
481 minCosAngle_(ami.minCosAngle_),
484 extendedTgtPatchPtr_(nullptr),
486 extendedTgtPoints_(),
487 extendedTgtFaceIDs_(),
488 extendedTgtMapPtr_(nullptr),
490 triMode_(ami.triMode_)
509 createExtendedTgtPatch();
512 const auto& src = this->srcPatch();
513 const auto& tgt = this->tgtPatch();
516 if (maxDistance2_ > 0)
519 (void)src.faceCentres();
520 (void)tgt.faceCentres();
522 (void)src.faceNormals();
523 (void)tgt.faceNormals();
525 if (minCosAngle_ > -1)
528 (void)src.faceNormals();
529 (void)tgt.faceNormals();
534 srcMagSf_.setSize(src.size(), 1.0);
535 tgtMagSf_.setSize(tgt.size(), 1.0);
538 triangulatePatch(src, srcTris_, srcMagSf_);
539 triangulatePatch(tgt, tgtTris_, tgtMagSf_);
545 srcAddress_.setSize(src.size());
546 srcWeights_.setSize(src.size());
547 tgtAddress_.setSize(tgt.size());
548 tgtWeights_.setSize(tgt.size());
List< scalar > scalarList
List of scalar.
label findTargetFace(const label srcFacei, const UList< label > &excludeFaces=UList< label >::null(), const label srcFacePti=-1) const
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.
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.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Unit conversion functions.
constexpr char nl
The newline '\n' character (0x0a)
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.
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.
#define forAll(list, i)
Loop across all elements in list.
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 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.
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.
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.
virtual void write(Ostream &os) const
Write.
advancingFrontAMI(const dictionary &dict, const bool reverseTarget)
Construct from components.