55 const label neighbProcNo
77 const int neighbProcNo,
87 neighbFaceCellCentres_()
98 const int neighbProcNo,
100 const word& patchType
105 newName(myProcNo, neighbProcNo),
115 neighbFaceCentres_(),
117 neighbFaceCellCentres_()
127 const word& patchType
131 myProcNo_(
dict.get<label>(
"myProcNo")),
132 neighbProcNo_(
dict.
get<label>(
"neighbProcNo")),
133 neighbFaceCentres_(),
135 neighbFaceCellCentres_()
146 myProcNo_(
pp.myProcNo_),
147 neighbProcNo_(
pp.neighbProcNo_),
148 neighbFaceCentres_(),
150 neighbFaceCellCentres_()
164 myProcNo_(
pp.myProcNo_),
165 neighbProcNo_(
pp.neighbProcNo_),
166 neighbFaceCentres_(),
168 neighbFaceCellCentres_()
182 myProcNo_(
pp.myProcNo_),
183 neighbProcNo_(
pp.neighbProcNo_),
184 neighbFaceCentres_(),
186 neighbFaceCellCentres_()
194 neighbPointsPtr_.clear();
195 neighbEdgesPtr_.clear();
205 if (neighbProcNo() >= pBufs.
nProcs())
208 <<
"On patch " <<
name()
209 <<
" trying to access out of range neighbour processor "
210 << neighbProcNo() <<
". This can happen if" <<
nl
211 <<
" trying to run on an incorrect number of processors"
215 UOPstream toNeighbProc(neighbProcNo(), pBufs);
230 UIPstream fromNeighbProc(neighbProcNo(), pBufs);
233 >> neighbFaceCentres_
235 >> neighbFaceCellCentres_;
242 vectorField nbrFaceNormals(neighbFaceAreas_.size());
248 forAll(faceNormals, facei)
250 const scalar magSf =
mag(faceAreas()[facei]);
251 const scalar nbrMagSf =
mag(neighbFaceAreas_[facei]);
255 if (magSf < SMALL || nbrMagSf < SMALL)
259 faceNormals[facei] =
point(1, 0, 0);
260 nbrFaceNormals[facei] = -faceNormals[facei];
263 else if (
mag(magSf - nbrMagSf) > matchTolerance()*
sqr(tols[facei]))
265 const scalar avgMagSf = 0.5*(magSf + nbrMagSf);
273 Pout<<
"processorPolyPatch::calcGeometry : Writing my "
275 <<
" faces to OBJ file " << nm <<
endl;
282 /
name() +
"_faceCentresConnections.obj"
285 Pout<<
"processorPolyPatch::calcGeometry :"
286 <<
" Dumping cell centre lines between"
287 <<
" corresponding face centres to OBJ file" << ccStr.name()
294 forAll(ownFaceCentres, facej)
296 const point& c0 = neighbFaceCentres_[facej];
297 const point&
c1 = ownFaceCentres[facej];
303 <<
"face " << facei <<
" area does not match neighbour by "
304 << 100*
mag(magSf - nbrMagSf)/avgMagSf
305 <<
"% -- possible face ordering problem." <<
endl
306 <<
"patch:" <<
name()
307 <<
" my area:" << magSf
308 <<
" neighbour area:" << nbrMagSf
309 <<
" matching tolerance:"
310 << matchTolerance()*
sqr(tols[facei])
312 <<
"Mesh face:" << start()+facei
316 <<
"If you are certain your matching is correct"
317 <<
" you can increase the 'matchTolerance' setting"
318 <<
" in the patch dictionary in the boundary file."
320 <<
"Rerun with processor debug flag set for"
325 faceNormals[facei] = faceAreas()[facei]/magSf;
326 nbrFaceNormals[facei] = neighbFaceAreas_[facei]/nbrMagSf;
336 matchTolerance()*tols,
346 PstreamBuffers& pBufs,
371 if (neighbProcNo() >= pBufs.
nProcs())
374 <<
"On patch " <<
name()
375 <<
" trying to access out of range neighbour processor "
376 << neighbProcNo() <<
". This can happen if" <<
nl
377 <<
" trying to run on an incorrect number of processors"
385 for (label patchPointi = 0; patchPointi <
nPoints(); patchPointi++)
387 label facei = pointFaces()[patchPointi][0];
389 pointFace[patchPointi] = facei;
391 const face&
f = localFaces()[facei];
393 pointIndex[patchPointi] =
f.find(patchPointi);
400 for (label patchEdgeI = 0; patchEdgeI < nEdges(); patchEdgeI++)
402 label facei = edgeFaces()[patchEdgeI][0];
404 edgeFace[patchEdgeI] = facei;
406 const labelList& fEdges = faceEdges()[facei];
408 edgeIndex[patchEdgeI] = fEdges.find(patchEdgeI);
411 UOPstream toNeighbProc(neighbProcNo(), pBufs);
427 neighbPointsPtr_.clear();
428 neighbEdgesPtr_.clear();
446 UIPstream fromNeighbProc(neighbProcNo(), pBufs);
462 labelList& neighbPoints = neighbPointsPtr_();
464 forAll(nbrPointFace, nbrPointi)
467 const face&
f = localFaces()[nbrPointFace[nbrPointi]];
469 label index = (
f.
size() - nbrPointIndex[nbrPointi]) %
f.
size();
470 label patchPointi =
f[index];
472 if (neighbPoints[patchPointi] == -1)
475 neighbPoints[patchPointi] = nbrPointi;
477 else if (neighbPoints[patchPointi] >= 0)
480 neighbPoints[patchPointi] = -2;
485 forAll(neighbPoints, patchPointi)
487 if (neighbPoints[patchPointi] == -2)
489 neighbPoints[patchPointi] = -1;
496 neighbEdgesPtr_.reset(
new labelList(nEdges(), -1));
497 labelList& neighbEdges = neighbEdgesPtr_();
499 forAll(nbrEdgeFace, nbrEdgeI)
502 const labelList&
f = faceEdges()[nbrEdgeFace[nbrEdgeI]];
503 label index = (
f.
size() - nbrEdgeIndex[nbrEdgeI] - 1) %
f.
size();
504 label patchEdgeI =
f[index];
506 if (neighbEdges[patchEdgeI] == -1)
509 neighbEdges[patchEdgeI] = nbrEdgeI;
511 else if (neighbEdges[patchEdgeI] >= 0)
514 neighbEdges[patchEdgeI] = -2;
519 forAll(neighbEdges, patchEdgeI)
521 if (neighbEdges[patchEdgeI] == -2)
523 neighbEdges[patchEdgeI] = -1;
536 if (!neighbPointsPtr_)
539 <<
"No extended addressing calculated for patch " <<
name()
542 return *neighbPointsPtr_;
548 if (!neighbEdgesPtr_)
551 <<
"No extended addressing calculated for patch " <<
name()
554 return *neighbEdgesPtr_;
560 PstreamBuffers& pBufs,
580 Pout<<
"processorPolyPatch::order : Writing my " <<
pp.
size()
581 <<
" faces to OBJ file " << nm <<
endl;
590 /
name() +
"_localFaceCentres.obj"
592 Pout<<
"processorPolyPatch::order : "
593 <<
"Dumping " << fc.size()
594 <<
" local faceCentres to " << localStr.name() <<
endl;
607 UOPstream toNeighbour(neighbProcNo(), pBufs);
627 facePointAverages[fI] += ppPoints[facePoints[pI]];
630 facePointAverages[fI] /= facePoints.size();
634 UOPstream toNeighbour(neighbProcNo(), pBufs);
635 toNeighbour <<
pp.faceCentres() <<
pp.faceNormals()
636 << anchors << facePointAverages;
648 const bool sameOrientation,
649 const scalar absTolSqr,
653 if (a.size() !=
b.
size())
661 if (!sameOrientation)
668 scalar closestMatchDistSqr =
sqr(GREAT);
675 const scalar diffSqr =
magSqr(aPts[*aCirc] - bPts[*bCirc]);
677 if (diffSqr < absTolSqr)
683 bCirc2.setFulcrumToIterator();
685 if (!sameOrientation)
694 matchDistSqr = diffSqr;
698 const scalar diffSqr2 =
magSqr(aPts[*aCirc] - bPts[*bCirc2]);
700 if (diffSqr2 > absTolSqr)
706 matchDistSqr += diffSqr2;
711 bCirc2.circulate(circulateDirection)
714 if (!aCirc.circulate())
716 if (matchDistSqr < closestMatchDistSqr)
718 closestMatchDistSqr = matchDistSqr;
720 if (!sameOrientation)
722 matchFp = a.size() - bCirc.nRotations();
726 matchFp = bCirc.nRotations();
729 if (closestMatchDistSqr == 0)
737 aCirc.setIteratorToFulcrum();
740 }
while (bCirc.circulate(circulateDirection));
742 matchDistSqr = closestMatchDistSqr;
781 faceMap[patchFacei] = patchFacei;
798 const point& wantedAnchor = anchors[patchFacei];
800 rotation[patchFacei] = getRotation
808 if (rotation[patchFacei] > 0)
831 UIPstream fromNeighbour(neighbProcNo(), pBufs);
832 fromNeighbour >> masterPts >> masterFaces;
842 const face& localFace = localFaces[lFacei];
843 label faceRotation = -1;
845 const scalar absTolSqr =
sqr(tols[lFacei]);
847 scalar closestMatchDistSqr =
sqr(GREAT);
848 scalar matchDistSqr =
sqr(GREAT);
849 label closestFaceMatch = -1;
850 label closestFaceRotation = -1;
852 forAll(masterFaces, mFacei)
854 const face& masterFace = masterFaces[mFacei];
856 faceRotation = matchFace
870 && matchDistSqr < closestMatchDistSqr
873 closestMatchDistSqr = matchDistSqr;
874 closestFaceMatch = mFacei;
875 closestFaceRotation = faceRotation;
878 if (closestMatchDistSqr == 0)
886 closestFaceRotation != -1
887 && closestMatchDistSqr < absTolSqr
890 faceMap[lFacei] = closestFaceMatch;
892 rotation[lFacei] = closestFaceRotation;
894 if (lFacei != closestFaceMatch || closestFaceRotation > 0)
903 Pout<<
"Number of matches = " << nMatches <<
" / "
909 const label localPtI = localFace[pI];
910 pts[pI] = localPts[localPtI];
914 <<
"No match for face " << localFace <<
nl <<
pts
930 UIPstream fromNeighbour(neighbProcNo(), pBufs);
931 fromNeighbour >> masterCtrs >> masterNormals
932 >> masterAnchors >> masterFacePointAverages;
941 /
name() +
"_nbrFaceCentres.obj"
943 Pout<<
"processorPolyPatch::order : "
944 <<
"Dumping neighbour faceCentres to " << nbrStr.name()
948 writeOBJ(nbrStr, masterCtrs[facei]);
952 if (masterCtrs.size() !=
pp.
size())
955 <<
"in patch:" <<
name() <<
" : "
956 <<
"Local size of patch is " <<
pp.
size() <<
" (faces)."
958 <<
"Received from neighbour " << masterCtrs.size()
991 facePointAverages[fI] += ppPoints[facePoints[pI]];
994 facePointAverages[fI] /= facePoints.size();
1000 *calcFaceTol(
pp,
pp.
points(), facePointAverages)
1012 masterFacePointAverages,
1024 faceMap[oldFacei] = faceMap2[oldFacei];
1034 if (!matchedAll ||
debug)
1040 /
name() +
"_faces.obj"
1042 Pout<<
"processorPolyPatch::order :"
1043 <<
" Writing faces to OBJ file " << str.name() <<
endl;
1049 /
name() +
"_faceCentresConnections.obj"
1052 Pout<<
"processorPolyPatch::order :"
1053 <<
" Dumping newly found match as lines between"
1054 <<
" corresponding face centres to OBJ file "
1062 label masterFacei =
faceMap[facei];
1064 if (masterFacei != -1)
1066 const point& c0 = masterCtrs[masterFacei];
1076 <<
"in patch:" <<
name() <<
" : "
1077 <<
"Cannot match vectors to faces on both sides of patch"
1079 <<
" masterCtrs[0]:" << masterCtrs[0] <<
endl
1081 <<
" Check your topology changes or maybe you have"
1082 <<
" multiple separated (from cyclics) processor patches"
1084 <<
" Continuing with incorrect face ordering from now on"
1097 label newFacei =
faceMap[oldFacei];
1099 const point& wantedAnchor = masterAnchors[newFacei];
1101 rotation[newFacei] = getRotation
1109 if (rotation[newFacei] == -1)
1112 <<
"in patch " <<
name()
1114 <<
"Cannot find point on face " <<
pp[oldFacei]
1115 <<
" with vertices "
1117 <<
" that matches point " << wantedAnchor
1118 <<
" when matching the halves of processor patch "
1120 <<
"Continuing with incorrect face ordering from now on"
1129 if (
faceMap[facei] != facei || rotation[facei] != 0)
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
direction
Direction type enumeration.
void setFulcrumToIterator()
Set the fulcrum to the current position of the iterator.
bool circulate(const CirculatorBase::direction dir=CirculatorBase::NONE)
Circulate around the list in the given direction.
void setIteratorToFulcrum()
Set the iterator to the current position of the fulcrum.
Like Foam::Circulator, but with const-access iterators.
SubField< vector > subField
label size() const noexcept
The number of elements in the list.
void setSize(label n)
Alias for resize().
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
virtual const fileName & name() const override
Read/write access to the name of the stream.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
const Field< point_type > & localPoints() const
Return pointField of points in patch.
const Field< point_type > & faceNormals() const
const Field< point_type > & points() const noexcept
Return reference to global points.
const Field< point_type > & faceCentres() const
Return face centres for patch.
const labelListList & pointFaces() const
const labelListList & edgeFaces() const
const labelListList & faceEdges() const
const List< face_type > & localFaces() const
Buffers for inter-processor communications streams (UOPstream, UIPstream).
int nProcs() const noexcept
Number of ranks associated with PstreamBuffers.
Input inter-processor communications stream using MPI send/recv etc. - operating on external buffer.
A List with indirect addressing. Like IndirectList but does not store addressing.
bool get(const label i) const
label find(const T &val) const
Find index of the first occurrence of the value.
Output inter-processor communications stream using MPI send/recv etc. - operating on external buffer.
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
static bool & parRun() noexcept
Test if this a parallel run.
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
virtual transformType transform() const
Type of transform.
scalar matchTolerance() const
virtual void write(Ostream &os) const
Write the polyPatch data as a dictionary.
void calcTransformTensors(const vectorField &Cf, const vectorField &Cr, const vectorField &nf, const vectorField &nr, const scalarField &smallDist, const scalar absTol, const transformType=UNKNOWN) const
Calculate the transformation tensors.
coupledPolyPatch(const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm, const word &patchType, const transformType transform)
Construct from components.
static scalarField calcFaceTol(const UList< face > &faces, const pointField &points, const pointField &faceCentres)
Calculate typical tolerance per face. Is currently max distance.
static label getRotation(const pointField &points, const face &f, const point &anchor, const scalar tol)
Get the number of vertices face f needs to be rotated such that.
static pointField getAnchorPoints(const UList< face > &, const pointField &, const transformType)
Get a unique anchor point for all faces.
static void writeOBJ(Ostream &os, const point &pt)
Write point in OBJ format.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
A face is a list of labels corresponding to mesh vertices.
A class for handling file names.
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
label index() const noexcept
The index of this patch in the boundaryMesh.
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
A patch is a list of labels that address the faces in the global face list.
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
const vectorField::subField faceAreas() const
Return face normals.
const vectorField::subField faceCentres() const
Return face centres.
virtual void movePoints(PstreamBuffers &, const pointField &p)
Correct patches after moving points.
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
label start() const noexcept
Return start label of this patch in the polyMesh face list.
tmp< vectorField > faceCellCentres() const
Return face cell centres.
Neighbour processor patch.
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
void initMovePoints(PstreamBuffers &, const pointField &)
Initialise the patches for moving points.
virtual bool owner() const
Does the processor own the patch ?
virtual ~processorPolyPatch()
Destructor.
void calcGeometry(PstreamBuffers &)
Calculate the patch geometry.
const labelList & neighbPoints() const
Return neighbour point labels. WIP.
int neighbProcNo() const noexcept
Return neighbour processor number.
void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
virtual void initOrder(PstreamBuffers &, const primitivePatch &) const
Initialize ordering for primitivePatch. Does not.
static word newName(const label myProcNo, const label neighbProcNo)
Return the name of a processorPolyPatch ("procBoundary..") constructed from the pair of processor IDs...
processorPolyPatch(const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm, const int myProcNo, const int neighbProcNo, const transformType transform=UNKNOWN, const word &patchType=typeName)
Construct from components with specified name.
const labelList & neighbEdges() const
Return neighbour edge labels. WIP.
int myProcNo() const noexcept
Return processor number.
virtual bool order(PstreamBuffers &, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for primitivePatch.
void movePoints(PstreamBuffers &, const pointField &)
Correct patches after moving points.
static label matchFace(const face &localFace, const pointField &localPts, const face &masterFace, const pointField &masterPts, const bool sameOrientation, const scalar absTolSqr, scalar &matchDistSqr)
Returns rotation.
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
A class for handling words, derived from Foam::string.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
OBJstream os(runTime.globalPath()/outputName)
Determine correspondence between points. See below.
#define SeriousErrorInFunction
Report an error message using Foam::SeriousError.
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
Namespace for handling debugging switches.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
List< label > labelList
A List of labels.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
List< face > faceList
List of faces.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
errorManip< error > abort(error &err)
Field< vector > vectorField
Specialisation of Field<T> for vector.
vector point
Point is a vector.
static constexpr const zero Zero
Global zero (0).
bool matchPoints(const UList< point > &pts0, const UList< point > &pts1, const UList< scalar > &matchDistance, const bool verbose, labelList &from0To1, const point &origin=point::zero)
Determine correspondence between pointFields. Gets passed.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
UList< label > labelUList
A UList of labels.
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
constexpr char nl
The newline '\n' character (0x0a).
#define forAll(list, i)
Loop across all elements in list.