/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2019-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . Class Foam::cyclicPolyPatch Description Cyclic plane patch. Note: morph patch face ordering uses geometric matching so with the following restrictions: -coupled patches should be flat planes. -no rotation in patch plane Uses coupledPolyPatch::calcFaceTol to calculate tolerance per face which might need tweaking. Switch on 'cyclicPolyPatch' debug flag to write .obj files to show the matching. SourceFiles cyclicPolyPatch.C \*---------------------------------------------------------------------------*/ #ifndef Foam_cyclicPolyPatch_H #define Foam_cyclicPolyPatch_H #include "coupledPolyPatch.H" #include "edgeList.H" #include "polyBoundaryMesh.H" #include "diagTensorField.H" #include "coupleGroupIdentifier.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { /*---------------------------------------------------------------------------*\ Class cyclicPolyPatch Declaration \*---------------------------------------------------------------------------*/ class cyclicPolyPatch : public coupledPolyPatch { // Private Data //- Name of other half mutable word neighbPatchName_; //- Optional patchGroup to find neighbPatch const coupleGroupIdentifier coupleGroup_; //- Index of other half mutable label neighbPatchID_; // For rotation //- Axis of rotation for rotational cyclics vector rotationAxis_; //- Point on axis of rotation for rotational cyclics point rotationCentre_; // For translation //- Translation vector vector separationVector_; //- List of edges formed from connected points. // From first half of the patch to the corresponding point // on the second half. mutable std::unique_ptr coupledPointsPtr_; //- List of connected edges. // From first half of the patch to the corresponding edge // on the second half. mutable std::unique_ptr coupledEdgesPtr_; //- Temporary storage of owner side patch during ordering. // Saved as autoPtr instead of std::unique_ptr to allow // extra nullptr checking mutable autoPtr ownerPatchPtr_; // Private Member Functions //- Find amongst selected faces the one with the largest area static label findMaxArea(const UList&, const UList&); void calcTransforms ( const primitivePatch& half0, const pointField& half0Ctrs, const vectorField& half0Areas, const pointField& half1Ctrs, const vectorField& half1Areas ); // Face ordering // Given a split of faces into left and right half calculate the // centres and anchor points. Transform the left points so they // align with the right ones void getCentresAndAnchors ( const primitivePatch& pp0, const primitivePatch& pp1, pointField& half0Ctrs, pointField& half1Ctrs, pointField& anchors0, scalarField& tols ) const; //- Return normal of face at max distance from rotation axis vector findFaceMaxRadius(const pointField& faceCentres) const; protected: // Protected Member functions //- Recalculate the transformation tensors virtual void calcTransforms(); //- Initialise the calculation of the patch geometry virtual void initGeometry(PstreamBuffers&); //- Initialise the calculation of the patch geometry virtual void initGeometry ( const primitivePatch& referPatch, pointField& nbrCtrs, vectorField& nbrAreas, pointField& nbrCc ); //- Calculate the patch geometry virtual void calcGeometry(PstreamBuffers&); //- Calculate the patch geometry virtual void calcGeometry ( const primitivePatch& referPatch, const pointField& thisCtrs, const vectorField& thisAreas, const pointField& thisCc, const pointField& nbrCtrs, const vectorField& nbrAreas, const pointField& nbrCc ); //- Initialise the patches for moving points virtual void initMovePoints(PstreamBuffers&, const pointField&); //- Correct patches after moving points virtual void movePoints(PstreamBuffers&, const pointField&); //- Initialise the update of the patch topology virtual void initUpdateMesh(PstreamBuffers&); //- Update of the patch topology virtual void updateMesh(PstreamBuffers&); public: //- Declare friendship with processorCyclicPolyPatch friend class processorCyclicPolyPatch; //- Runtime type information TypeName("cyclic"); // Constructors //- Construct from components cyclicPolyPatch ( const word& name, const label size, const label start, const label index, const polyBoundaryMesh& bm, const word& patchType, const transformType transform = UNKNOWN ); //- Construct from components cyclicPolyPatch ( const word& name, const label size, const label start, const label index, const polyBoundaryMesh& bm, const word& neighbPatchName, const transformType transform, // transformation type const vector& rotationAxis, // for rotation only const point& rotationCentre, // for rotation only const vector& separationVector // for translation only ); //- Construct from dictionary cyclicPolyPatch ( const word& name, const dictionary& dict, const label index, const polyBoundaryMesh& bm, const word& patchType ); //- Copy construct, resetting the boundary mesh cyclicPolyPatch(const cyclicPolyPatch&, const polyBoundaryMesh&); //- Copy construct, resetting nbrPatchID and faceCells cyclicPolyPatch ( const cyclicPolyPatch&, label nbrPatchID, const labelList& faceCells ); //- Construct given the original patch and resetting the //- face list and boundary mesh information cyclicPolyPatch ( const cyclicPolyPatch& pp, const polyBoundaryMesh& bm, const label index, const label newSize, const label newStart, const word& neighbPatchName ); //- Construct given the original patch and a map cyclicPolyPatch ( const cyclicPolyPatch& pp, const polyBoundaryMesh& bm, const label index, const labelUList& mapAddressing, const label newStart ); //- Construct and return a clone, resetting the boundary mesh virtual autoPtr clone(const polyBoundaryMesh& bm) const { return autoPtr(new cyclicPolyPatch(*this, bm)); } //- Construct and return a clone, resetting the face list // and boundary mesh virtual autoPtr clone ( const polyBoundaryMesh& bm, const label index, const label newSize, const label newStart ) const { return autoPtr ( new cyclicPolyPatch ( *this, bm, index, newSize, newStart, neighbPatchName_ ) ); } //- Construct and return a clone, resetting the face list // and boundary mesh virtual autoPtr clone ( const polyBoundaryMesh& bm, const label index, const labelUList& mapAddressing, const label newStart ) const { return autoPtr ( new cyclicPolyPatch(*this, bm, index, mapAddressing, newStart) ); } //- Destructor virtual ~cyclicPolyPatch(); // Member Functions // Implicit Functions //- Return number of new internal of this polyPatch faces virtual void newInternalProcFaces ( label& newFaces, label& newProcFaces ) const { newFaces = this->size(); newProcFaces = neighbPatch().size() - this->size(); } //- Return nbrCells virtual const labelUList& nbrCells() const { return neighbPatch().faceCells(); } virtual label neighbPolyPatchID() const { return this->neighbPatchID(); } virtual refPtr mapCollocatedFaces() const { refPtr tMap(new labelListList(this->size())); labelListList& map = tMap.ref(); forAll (map, i) { labelList& subMap = map[i]; subMap.setSize(1); subMap[0] = i; } return tMap; } //- Return implicit master virtual bool masterImplicit() const { return owner(); } //- Neighbour patch name const word& neighbPatchName() const; //- Neighbour patchID virtual label neighbPatchID() const; virtual bool owner() const { return index() < neighbPatchID(); } virtual bool neighbour() const { return !owner(); } const cyclicPolyPatch& neighbPatch() const { const polyPatch& pp = this->boundaryMesh()[neighbPatchID()]; return refCast(pp); } //- Return connected points (from patch local to neighbour patch local) // Demand driven calculation. Does primitivePatch::clearOut after // calculation! const edgeList& coupledPoints() const; //- Return connected edges (from patch local to neighbour patch local). // Demand driven calculation. Does primitivePatch::clearOut after // calculation! const edgeList& coupledEdges() const; //- Transform a patch-based position from other side to this side virtual void transformPosition(pointField& l) const; //- Transform a patch-based position from other side to this side virtual void transformPosition(point&, const label facei) const; // Transformation label transformGlobalFace(const label facei) const { label offset = facei-start(); label neighbStart = neighbPatch().start(); if (offset >= 0 && offset < size()) { return neighbStart+offset; } else { FatalErrorInFunction << "Face " << facei << " not in patch " << name() << exit(FatalError); return -1; } } //- Axis of rotation for rotational cyclics const vector& rotationAxis() const noexcept { return rotationAxis_; } //- Point on axis of rotation for rotational cyclics const point& rotationCentre() const noexcept { return rotationCentre_; } //- Translation vector for translational cyclics const vector& separationVector() const noexcept { return separationVector_; } //- Initialize ordering for primitivePatch. Does not // refer to *this (except for name() and type() etc.) virtual void initOrder(PstreamBuffers&, const primitivePatch&) const; //- Return new ordering for primitivePatch. // Ordering is -faceMap: for every face // index of the new face -rotation:for every new face the clockwise // shift of the original face. Return false if nothing changes // (faceMap is identity, rotation is 0), true otherwise. virtual bool order ( PstreamBuffers&, const primitivePatch&, labelList& faceMap, labelList& rotation ) const; //- Write the polyPatch data as a dictionary virtual void write(Ostream&) const; }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #endif // ************************************************************************* //