35 namespace patchToPatches
52 Foam::patchToPatches::intersection::triPointValues
61 result[i] = values[t[i]];
80 const scalar l =
sqrt(
mag(srcFace.
area(srcPoints)));
82 forAll(srcFace, srcFacePointi)
84 const label srcPointi = srcFace[srcFacePointi];
86 const point&
p = srcPoints[srcPointi];
87 const vector&
n = srcPointNormals[srcPointi];
106 return srcBoxStatic(srcFace, srcPoints, srcPointNormals);
110 bool Foam::patchToPatches::intersection::intersectFaces
116 const label srcFacei,
129 if (!srcFaceBox.
overlaps(tgtFaceBox))
return false;
132 if (srcTriPoints_[srcFacei].empty())
134 triEngine_.triangulate
143 srcTriPoints_[srcFacei] =
144 triEngine_.triPoints(srcPatch.
localFaces()[srcFacei]);
145 srcTriFaceEdges_[srcFacei] = triEngine_.triEdges();
147 if (tgtTriPoints_[tgtFacei].empty())
149 triEngine_.triangulate
158 tgtTriPoints_[tgtFacei] =
159 triEngine_.triPoints(tgtPatch.
localFaces()[tgtFacei]);
160 tgtTriFaceEdges_[tgtFacei] = triEngine_.triEdges();
164 bool srcCouples =
false;
166 srcFaceEdgePart_.resize(srcPatch[srcFacei].size());
167 forAll(srcFaceEdgePart_, srcFaceEdgei)
170 srcPatch.
localFaces()[srcFacei].faceEdge(srcFaceEdgei);
172 srcFaceEdgePart_[srcFaceEdgei] = part(
Zero, eC);
175 bool tgtCouples =
false;
177 tgtFaceEdgePart_.resize(tgtPatch[tgtFacei].size());
178 forAll(tgtFaceEdgePart_, tgtFaceEdgei)
181 tgtPatch.
localFaces()[tgtFacei].faceEdge(tgtFaceEdgei);
183 tgtFaceEdgePart_[tgtFaceEdgei] = part(
Zero, eC);
189 const scalar srcMagA =
mag(srcPatch.
faceAreas()[srcFacei]);
190 const scalar tgtMagA =
mag(tgtPatch.
faceAreas()[tgtFacei]);
193 const bool debugTriIntersect =
194 (debugSrcFacei != -1 || debugTgtFacei != -1)
195 && (debugSrcFacei == -1 || debugSrcFacei == srcFacei)
196 && (debugTgtFacei == -1 || debugTgtFacei == tgtFacei);
199 bool anyCouples =
false;
200 forAll(srcTriPoints_[srcFacei], srcFaceTrii)
202 const triFace& srcT = srcTriPoints_[srcFacei][srcFaceTrii];
204 const FixedList<point, 3> srcPs =
206 const FixedList<vector, 3> srcNs =
207 triPointValues(srcT, srcPointNormals);
209 forAll(tgtTriPoints_[tgtFacei], tgtFaceTrii)
213 ? tgtTriPoints_[tgtFacei][tgtFaceTrii].reverseFace()
214 : tgtTriPoints_[tgtFacei][tgtFaceTrii];
216 const FixedList<point, 3> tgtPs =
220 ictSrcPoints_.clear();
221 ictSrcPointNormals_.clear();
222 ictTgtPoints_.clear();
223 ictPointLocations_.clear();
228 {
false,
false,
false},
231 {
false,
false,
false},
245 (srcFaceTrii*tgtTriPoints_[tgtFacei].size() + tgtFaceTrii)
251 if (ictPointLocations_.empty())
260 const part ictSrcPart(ictSrcPoints_);
261 const part ictTgtPart(ictTgtPoints_);
266 mag(ictSrcPart.area) < small*srcMagA
267 ||
mag(ictTgtPart.area) < small*tgtMagA
274 srcCouples = tgtCouples =
true;
277 srcCouple += ictSrcPart;
278 srcCouple.nbr += ictTgtPart;
281 tgtCouple += ictTgtPart;
282 tgtCouple.nbr += ictSrcPart;
286 tgtCouple -= ictTgtPart;
287 tgtCouple.nbr -= ictSrcPart;
291 const label debugSrcPoint0 = debugPoints_.size();
292 const label debugTgtPoint0 =
293 debugPoints_.size() + ictSrcPoints_.size();
296 debugPoints_.append(ictSrcPoints_);
297 debugPoints_.append(ictTgtPoints_);
302 debugFaceSrcFaces_.append(srcFacei);
303 debugFaceTgtFaces_.append(tgtFacei);
304 debugFaceSides_.append(1);
309 debugFaceSrcFaces_.append(srcFacei);
310 debugFaceTgtFaces_.append(tgtFacei);
311 debugFaceSides_.append(-1);
315 forAll(ictPointLocations_, i0)
317 const label i1 = ictPointLocations_.fcIndex(i0);
321 const triIntersect::location l0 = ictPointLocations_[i0];
322 const triIntersect::location l1 = ictPointLocations_[i1];
325 const part ictEdgePart
344 l0.isSrcNotTgtPoint()
345 || l1.isSrcNotTgtPoint()
348 && l1.isIntersection()
349 && l0.srcEdgei() == l1.srcEdgei()
354 l0.isSrcPoint() ? l0.srcPointi()
355 : l1.isSrcPoint() ? (l1.srcPointi() + 2) % 3
358 const label srcFaceEdgei =
359 srcTriFaceEdges_[srcFacei][srcFaceTrii][srcEi];
361 if (srcFaceEdgei < srcPatch[srcFacei].size())
363 srcFaceEdgePart_[srcFaceEdgei] += ictEdgePart;
368 errorPart += ictEdgePart;
377 l0.isTgtNotSrcPoint()
378 || l1.isTgtNotSrcPoint()
381 && l1.isIntersection()
382 && l0.tgtEdgei() == l1.tgtEdgei()
387 l0.isTgtPoint() ? (l0.tgtPointi() + 2) % 3
388 : l1.isTgtPoint() ? l1.tgtPointi()
391 const label tgtFaceEdgei =
392 tgtTriFaceEdges_[tgtFacei][tgtFaceTrii]
393 [
reverse() ? 2 - tgtEi : tgtEi];
395 if (tgtFaceEdgei < tgtPatch[tgtFacei].size())
399 tgtFaceEdgePart_[tgtFaceEdgei] += ictEdgePart;
403 tgtFaceEdgePart_[tgtFaceEdgei] -= ictEdgePart;
409 errorPart += ictEdgePart;
419 <<
"Tri-intersection topology not recognised. "
436 debugFaceSrcFaces_.append(srcFacei);
437 debugFaceTgtFaces_.append(tgtFacei);
438 debugFaceSides_.append(ictEdgeSide);
447 srcLocalTgtFaces_[srcFacei].append(tgtFacei);
448 srcCouples_[srcFacei].append(srcCouple);
454 forAll(srcFaceEdgeParts_[srcFacei], srcFaceEdgei)
456 srcFaceEdgeParts_[srcFacei][srcFaceEdgei] +=
457 srcFaceEdgePart_[srcFaceEdgei];
459 srcErrorParts_[srcFacei] -=
sum(tgtFaceEdgePart_);
460 srcErrorParts_[srcFacei] += errorPart;
466 tgtLocalSrcFaces_[tgtFacei].append(srcFacei);
467 tgtCouples_[tgtFacei].append(tgtCouple);
474 void Foam::patchToPatches::intersection::initialise
490 srcCouples_.resize(srcPatch.size());
491 forAll(srcLocalTgtFaces_, i)
493 srcCouples_[i].clear();
496 srcEdgeParts_.resize(srcPatch.nEdges());
497 forAll(srcEdgeParts_, srcEdgei)
499 const edge&
e = srcPatch.edges()[srcEdgei];
500 const point c =
e.centre(srcPatch.localPoints());
501 srcEdgeParts_[srcEdgei] = part(
Zero,
c);
504 srcErrorParts_.resize(srcPatch.size());
505 forAll(srcErrorParts_, srcFacei)
507 srcErrorParts_[srcFacei] =
508 part(
Zero, srcPatch.faceCentres()[srcFacei]);
511 tgtCouples_.resize(tgtPatch.size());
512 forAll(tgtLocalSrcFaces_, i)
514 tgtCouples_[i].clear();
517 srcTriPoints_ = List<triFaceList>(srcPatch.size());
518 srcTriFaceEdges_ = List<List<FixedList<label, 3>>>(srcPatch.size());
519 tgtTriPoints_ = List<triFaceList>(tgtPatch.size());
520 tgtTriFaceEdges_ = List<List<FixedList<label, 3>>>(tgtPatch.size());
522 srcFaceEdgeParts_.resize(srcPatch.size());
523 forAll(srcFaceEdgeParts_, srcFacei)
525 srcFaceEdgeParts_[srcFacei].resize(srcPatch[srcFacei].size());
526 forAll(srcFaceEdgeParts_[srcFacei], srcFaceEdgei)
528 const label srcEdgei =
529 srcPatch.faceEdges()[srcFacei][srcFaceEdgei];
530 srcFaceEdgeParts_[srcFacei][srcFaceEdgei] = srcEdgeParts_[srcEdgei];
536 debugPoints_.clear();
538 debugFaceSrcFaces_.clear();
539 debugFaceTgtFaces_.clear();
540 debugFaceSides_.clear();
562 tgtCouples_ = List<DynamicList<couple>>(tgtCouples_, newToOldLocalTgtFace);
564 return newToOldLocalTgtFace;
568 void Foam::patchToPatches::intersection::rDistributeTgt
584 Foam::label Foam::patchToPatches::intersection::finalise
590 const transformer& tgtToSrc
593 const label nCouples =
604 labelList srcEdgeNParts(srcEdgeParts_.size(), 0);
605 forAll(srcEdgeParts_, srcEdgei)
607 const edge&
e = srcPatch.edges()[srcEdgei];
609 srcEdgeParts_[srcEdgei] = part();
611 forAll(srcPatch.edgeFaces()[srcEdgei], i)
613 const label srcFacei = srcPatch.edgeFaces()[srcEdgei][i];
614 const label srcFaceEdgei =
615 findIndex(srcPatch.faceEdges()[srcFacei], srcEdgei);
618 srcPatch.localFaces()[srcFacei].faceEdge(srcFaceEdgei);
622 srcEdgeParts_[srcEdgei] +=
623 srcFaceEdgeParts_[srcFacei][srcFaceEdgei];
627 srcEdgeParts_[srcEdgei] -=
628 srcFaceEdgeParts_[srcFacei][srcFaceEdgei];
631 srcEdgeNParts[srcEdgei] ++;
634 forAll(srcEdgeParts_, srcEdgei)
636 srcEdgeParts_[srcEdgei].area /= srcEdgeNParts[srcEdgei];
641 forAll(srcEdgeParts_, srcEdgei)
643 const edge&
e = srcPatch.edges()[srcEdgei];
645 forAll(srcPatch.edgeFaces()[srcEdgei], i)
647 const label srcFacei = srcPatch.edgeFaces()[srcEdgei][i];
648 const label srcFaceEdgei =
649 findIndex(srcPatch.faceEdges()[srcFacei], srcEdgei);
652 srcPatch.localFaces()[srcFacei].faceEdge(srcFaceEdgei);
656 srcErrorParts_[srcFacei] -= srcEdgeParts_[srcEdgei];
660 srcErrorParts_[srcFacei] += srcEdgeParts_[srcEdgei];
663 srcErrorParts_[srcFacei] +=
664 srcFaceEdgeParts_[srcFacei][srcFaceEdgei];
671 forAll(tgtCouples_, tgtFacei)
673 forAll(tgtCouples_[tgtFacei], i)
675 couple&
c = tgtCouples_[tgtFacei][i];
677 c.area = tgtToSrc.invTransform(
c.area);
678 c.centre = tgtToSrc.invTransformPosition(
c.centre);
679 c.nbr.area = tgtToSrc.invTransform(
c.nbr.area);
680 c.nbr.centre = tgtToSrc.invTransformPosition(
c.nbr.centre);
689 const List<DynamicList<couple>>& couples,
692 List<scalar>& coverage
697 coverage.resize(patch.size());
701 const scalar magA =
mag(patch.faceAreas()[facei]);
706 aCouple += couples[facei][i].area;
708 const scalar magACouple =
mag(aCouple);
711 coupleArea += magACouple;
712 coverage[facei] = magACouple/magA;
715 reduce(area, sumOp<scalar>());
716 reduce(coupleArea, sumOp<scalar>());
718 scalar srcArea = 0, srcCoupleArea = 0;
719 scalar tgtArea = 0, tgtCoupleArea = 0;
720 coverage(srcPatch, srcCouples_, srcArea, srcCoupleArea, srcCoverage_);
721 coverage(tgtPatch, tgtCouples_, tgtArea, tgtCoupleArea, tgtCoverage_);
724 srcTriPoints_.clear();
725 srcTriFaceEdges_.clear();
726 tgtTriPoints_.clear();
727 tgtTriFaceEdges_.clear();
730 srcFaceEdgePart_.clear();
731 tgtFaceEdgePart_.clear();
732 srcFaceEdgeParts_.clear();
741 forAll(srcPatch, srcFacei)
743 const vector& a = srcPatch.faceAreas()[srcFacei];
744 const scalar magA =
mag(a);
745 const point&
c = srcPatch.faceCentres()[srcFacei];
748 forAll(srcCouples_[srcFacei], srcTgtFacei)
750 const couple& cpl = srcCouples_[srcFacei][srcTgtFacei];
757 scalar projectionV = 0;
758 forAll(srcCouples_[srcFacei], srcTgtFacei)
760 const couple& cpl = srcCouples_[srcFacei][srcTgtFacei];
762 projectionA += cpl.nbr.area;
764 - (cpl.area/3 & (cpl.centre - Cpl.centre))
765 + (cpl.nbr.area/3 & (cpl.nbr.centre - Cpl.centre));
767 forAll(srcPatch.faceEdges()[srcFacei], srcFaceEdgei)
769 const label srcEdgei =
770 srcPatch.faceEdges()[srcFacei][srcFaceEdgei];
772 const edge&
e = srcPatch.edges()[srcEdgei];
774 srcPatch.localFaces()[srcFacei].faceEdge(srcFaceEdgei);
778 projectionA +=
sign*srcEdgeParts_[srcEdgei].area;
780 sign*srcEdgeParts_[srcEdgei].area/3
781 & (srcEdgeParts_[srcEdgei].centre - Cpl.centre);
783 projectionA += srcErrorParts_[srcFacei].area;
785 srcErrorParts_[srcFacei].area/3
786 & (srcErrorParts_[srcFacei].centre - Cpl.centre);
792 srcOpenness[srcFacei] =
mag(projectionA - Cpl.area)/magA;
793 srcError[srcFacei] =
mag(srcErrorParts_[srcFacei].area)/magA;
794 srcDepth[srcFacei] =
mag(projectionV)/
pow3(
sqrt(magA));
797 reduce(tgtArea, sumOp<scalar>());
798 reduce(tgtCoupleArea, sumOp<scalar>());
800 Info<<
indent <<
"Source min/average/max coverage = "
801 <<
gMin(srcCoverage_) <<
'/' << srcCoupleArea/srcArea <<
'/'
803 <<
indent <<
"Target min/average/max coverage = "
804 <<
gMin(tgtCoverage_) <<
'/' << tgtCoupleArea/tgtArea <<
'/'
806 <<
indent <<
"Source average openness/error/depth/angle = "
809 <<
indent <<
"Source max openness/error/depth/angle = "
810 <<
gMax(srcOpenness) <<
'/' <<
gMax(srcError) <<
'/'
815 word
name = patchToPatch::typeName +
'_' + typeName;
822 Info<<
indent <<
"Writing intersected faces to "
833 "srcFace",
false, Field<label>(debugFaceSrcFaces_),
834 "tgtFace",
false, Field<label>(debugFaceTgtFaces_),
835 "side",
false, Field<label>(debugFaceSides_)
838 debugPoints_.clear();
840 debugFaceSrcFaces_.clear();
841 debugFaceTgtFaces_.clear();
842 debugFaceSides_.clear();
848 name +
"_srcPatch" +
".vtk",
851 srcPatch.localPoints(),
854 srcPatch.localFaces(),
856 "openness",
false, srcOpenness,
857 "error",
false, srcError,
858 "depth",
false, srcDepth,
859 "angle",
false, srcAngle,
860 "normals",
true, srcPointNormals
867 name +
"_tgtPatch" +
".vtk",
870 tgtPatch.localPoints(),
873 tgtPatch.localFaces(),
884 Foam::patchToPatches::intersection::srcWeights()
const
886 List<DynamicList<scalar>>* resultPtr
888 new List<DynamicList<scalar>>(srcCouples_.size())
890 List<DynamicList<scalar>>& result = *resultPtr;
892 forAll(srcCouples_, srcFacei)
894 result[srcFacei].resize(srcCouples_[srcFacei].size());
897 forAll(srcCouples_[srcFacei], i)
899 const scalar a =
mag(srcCouples_[srcFacei][i].area);
900 result[srcFacei][i] = a;
904 forAll(srcCouples_[srcFacei], i)
906 result[srcFacei][i] *= srcCoverage_[srcFacei]/aSum;
910 return tmpNrc<List<DynamicList<scalar>>>(resultPtr);
915 Foam::patchToPatches::intersection::tgtWeights()
const
917 List<DynamicList<scalar>>* resultPtr
919 new List<DynamicList<scalar>>(tgtCouples_.size())
921 List<DynamicList<scalar>>& result = *resultPtr;
923 forAll(tgtCouples_, tgtFacei)
925 result[tgtFacei].resize(tgtCouples_[tgtFacei].size());
928 forAll(tgtCouples_[tgtFacei], i)
930 const scalar a =
mag(tgtCouples_[tgtFacei][i].area);
931 result[tgtFacei][i] = a;
935 forAll(tgtCouples_[tgtFacei], i)
937 result[tgtFacei][i] *= tgtCoverage_[tgtFacei]/aSum;
941 return tmpNrc<List<DynamicList<scalar>>>(resultPtr);
966 ictSrcPointNormals_(),
968 ictPointLocations_(),
977 debugFaceSrcFaces_(),
978 debugFaceTgtFaces_(),
#define forAll(list, i)
Loop across all elements in list.
Macros for easy insertion into run-time selection tables.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
void clear()
Clear the addressed list, i.e. set the size to zero.
const Field< PointType > & faceAreas() const
Return face areas for patch.
const Field< PointType > & points() const
Return reference to global points.
const List< FaceType > & localFaces() const
Return patch faces addressing into local point list.
const Field< PointType > & localPoints() const
Return pointField of points in patch.
const Field< PointType > & faceCentres() const
Return face centres for patch.
A List with indirect addressing.
static bool & parRun()
Is this a parallel run?
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
static int compare(const edge &, const edge &)
Compare edges.
A face is a list of labels corresponding to mesh vertices.
static vector area(const PointField &ps)
Return vector area given face points.
Class to generate coupling geometry between two primitive patches.
virtual void rDistributeTgt(const primitiveOldTimePatch &tgtPatch)
Send data that resulted from an intersection between the source.
virtual labelList finaliseLocal(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch)
Finalise the intersection locally. Trims the local target patch.
virtual void initialise(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch)
Initialisation.
virtual label finalise(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch, const transformer &tgtToSrc)
Finalising.
Class to generate patchToPatch coupling geometry. A full geometric intersection is done between a fac...
~intersection()
Destructor.
static treeBoundBox srcBoxStatic(const face &srcFace, const pointField &srcPoints, const vectorField &srcPointNormals)
Get the bound box for a source face.
static int debugSrcFacei
Extra debugging for intersections between specific faces. Named.
intersection(const bool reverse)
Construct from components.
A class for managing temporary objects without reference counting.
Standard boundBox + extra functionality for use in octree.
bool overlaps(const boundBox &) const
Overlaps other bounding box?
A triangular face using a FixedList of labels corresponding to mesh vertices.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const dimensionedScalar c
Speed of light in a vacuum.
int debugSwitch(const char *name, const int defaultValue=0)
Lookup debug switch or add default value.
addToRunTimeSelectionTable(patchToPatch, intersection, bool)
defineTypeNameAndDebug(intersection, 0)
void intersectTris(const FixedList< point, 3 > &srcPs, const FixedList< vector, 3 > &srcNs, const FixedList< bool, 3 > &srcOwns, const FixedList< label, 3 > &srcTgtPis, const FixedList< point, 3 > &tgtPs, const FixedList< bool, 3 > &tgtOwns, const FixedList< label, 3 > &tgtSrcPis, DynamicList< point > &srcPoints, DynamicList< vector > &srcPointNormals, DynamicList< point > &tgtPoints, DynamicList< location > &pointLocations, const bool debug, const word &writePrefix=word::null)
Construct the intersection of a source triangle's projected volume and a.
void write(const fileName &file, const word &title, const bool binary, const PointField &points, const VertexList &vertices, const LineList &lines, const FaceList &faces, const wordList &fieldNames, const boolList &fieldIsPointValues, const UPtrList< const Field< label >> &fieldLabelValues #define FieldTypeValuesConstArg(Type, nullArg))
Write VTK polygonal data to a file. Takes a PtrList of fields of labels and.
errorManipArg< error, int > exit(error &err, const int errNo=1)
List< label > labelList
A List of labels.
dimensionedScalar sign(const dimensionedScalar &ds)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensionedScalar pow3(const dimensionedScalar &ds)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
scalar radToDeg(const scalar rad)
Conversion from radians to degrees.
vector point
Point is a vector.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
void reverse(UList< T > &, const label n)
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
Addressing for a faceList slice.
Vector< scalar > vector
A scalar version of the templated Vector.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
dimensionedScalar sqrt(const dimensionedScalar &ds)
PrimitiveOldTimePatch< SubList< face >, const pointField & > primitiveOldTimePatch
Addressing for a faceList slice.
List< labelList > labelListList
A List of labelList.
dimensioned< scalar > mag(const dimensioned< Type > &)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
Form normalised(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Field< vector > vectorField
Specialisation of Field<T> for vector.
Type gAverage(const FieldField< Field, Type > &f)
bool isNull(const T &t)
Return true if t is a reference to the nullObject of type T.
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
Type gMin(const FieldField< Field, Type > &f)
static const label labelMax
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
word name(const complex &)
Return a string representation of a complex.
Ostream & indent(Ostream &os)
Indent stream.
Type gMax(const FieldField< Field, Type > &f)
dimensionedScalar acos(const dimensionedScalar &ds)
Functions with which to perform an intersection of a pair of triangles; the source and target....