1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "slidingInterface.H"
27 #include "polyTopoChanger.H"
29 #include "polyTopoChange.H"
30 #include "addToRunTimeSelectionTable.H"
33 // Index of debug signs:
34 // p - adjusting a projection point
35 // * - adjusting edge intersection
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 defineTypeNameAndDebug(slidingInterface, 0);
42 addToRunTimeSelectionTable
50 const char* Foam::NamedEnum
52 Foam::slidingInterface::typeOfMatch,
62 const Foam::NamedEnum<Foam::slidingInterface::typeOfMatch, 2>
63 Foam::slidingInterface::typeOfMatchNames_;
66 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
68 void Foam::slidingInterface::checkDefinition()
70 const polyMesh& mesh = topoChanger().mesh();
74 !masterFaceZoneID_.active()
75 || !slaveFaceZoneID_.active()
76 || !cutPointZoneID_.active()
77 || !cutFaceZoneID_.active()
78 || !masterPatchID_.active()
79 || !slavePatchID_.active()
84 "void slidingInterface::checkDefinition()"
85 ) << "Not all zones and patches needed in the definition "
86 << "have been found. Please check your mesh definition."
90 // Check the sizes and set up state
93 mesh.faceZones()[masterFaceZoneID_.index()].empty()
94 || mesh.faceZones()[slaveFaceZoneID_.index()].empty()
97 FatalErrorIn("void slidingInterface::checkDefinition()")
98 << "Master or slave face zone contain no faces. "
99 << "Please check your mesh definition."
100 << abort(FatalError);
105 Pout<< "Sliding interface object " << name() << " :" << nl
106 << " master face zone: " << masterFaceZoneID_.index() << nl
107 << " slave face zone: " << slaveFaceZoneID_.index() << endl;
112 void Foam::slidingInterface::clearOut() const
114 clearPointProjection();
115 clearAttachedAddressing();
120 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
123 // Construct from components
124 Foam::slidingInterface::slidingInterface
128 const polyTopoChanger& mme,
129 const word& masterFaceZoneName,
130 const word& slaveFaceZoneName,
131 const word& cutPointZoneName,
132 const word& cutFaceZoneName,
133 const word& masterPatchName,
134 const word& slavePatchName,
135 const typeOfMatch tom,
136 const bool coupleDecouple,
137 const intersection::algorithm algo
140 polyMeshModifier(name, index, mme, true),
144 mme.mesh().faceZones()
149 mme.mesh().faceZones()
154 mme.mesh().pointZones()
159 mme.mesh().faceZones()
164 mme.mesh().boundaryMesh()
169 mme.mesh().boundaryMesh()
172 coupleDecouple_(coupleDecouple),
174 projectionAlgo_(algo),
176 pointMergeTol_(pointMergeTolDefault_),
177 edgeMergeTol_(edgeMergeTolDefault_),
178 nFacesPerSlaveEdge_(nFacesPerSlaveEdgeDefault_),
179 edgeFaceEscapeLimit_(edgeFaceEscapeLimitDefault_),
180 integralAdjTol_(integralAdjTolDefault_),
181 edgeMasterCatchFraction_(edgeMasterCatchFractionDefault_),
182 edgeCoPlanarTol_(edgeCoPlanarTolDefault_),
183 edgeEndCutoffTol_(edgeEndCutoffTolDefault_),
184 cutFaceMasterPtr_(NULL),
185 cutFaceSlavePtr_(NULL),
186 masterFaceCellsPtr_(NULL),
187 slaveFaceCellsPtr_(NULL),
188 masterStickOutFacesPtr_(NULL),
189 slaveStickOutFacesPtr_(NULL),
190 retiredPointMapPtr_(NULL),
191 cutPointEdgePairMapPtr_(NULL),
192 slavePointPointHitsPtr_(NULL),
193 slavePointEdgeHitsPtr_(NULL),
194 slavePointFaceHitsPtr_(NULL),
195 masterPointEdgeHitsPtr_(NULL),
196 projectedSlavePointsPtr_(NULL)
204 "Foam::slidingInterface::slidingInterface\n"
206 " const word& name,\n"
207 " const label index,\n"
208 " const polyTopoChanger& mme,\n"
209 " const word& masterFaceZoneName,\n"
210 " const word& slaveFaceZoneName,\n"
211 " const word& cutFaceZoneName,\n"
212 " const word& cutPointZoneName,\n"
213 " const word& masterPatchName,\n"
214 " const word& slavePatchName,\n"
215 " const typeOfMatch tom,\n"
216 " const bool coupleDecouple\n"
218 ) << "Creation of a sliding interface from components "
219 << "in attached state not supported."
220 << abort(FatalError);
224 calcAttachedAddressing();
229 // Construct from components
230 Foam::slidingInterface::slidingInterface
233 const dictionary& dict,
235 const polyTopoChanger& mme
238 polyMeshModifier(name, index, mme, Switch(dict.lookup("active"))),
241 dict.lookup("masterFaceZoneName"),
242 mme.mesh().faceZones()
246 dict.lookup("slaveFaceZoneName"),
247 mme.mesh().faceZones()
251 dict.lookup("cutPointZoneName"),
252 mme.mesh().pointZones()
256 dict.lookup("cutFaceZoneName"),
257 mme.mesh().faceZones()
261 dict.lookup("masterPatchName"),
262 mme.mesh().boundaryMesh()
266 dict.lookup("slavePatchName"),
267 mme.mesh().boundaryMesh()
269 matchType_(typeOfMatchNames_.read((dict.lookup("typeOfMatch")))),
270 coupleDecouple_(dict.lookup("coupleDecouple")),
271 attached_(dict.lookup("attached")),
274 intersection::algorithmNames_.read(dict.lookup("projection"))
277 cutFaceMasterPtr_(NULL),
278 cutFaceSlavePtr_(NULL),
279 masterFaceCellsPtr_(NULL),
280 slaveFaceCellsPtr_(NULL),
281 masterStickOutFacesPtr_(NULL),
282 slaveStickOutFacesPtr_(NULL),
283 retiredPointMapPtr_(NULL),
284 cutPointEdgePairMapPtr_(NULL),
285 slavePointPointHitsPtr_(NULL),
286 slavePointEdgeHitsPtr_(NULL),
287 slavePointFaceHitsPtr_(NULL),
288 masterPointEdgeHitsPtr_(NULL),
289 projectedSlavePointsPtr_(NULL)
291 // Optionally default tolerances from dictionary
296 // If the interface is attached, the master and slave face zone addressing
297 // needs to be read in; otherwise it will be created
302 Pout<< "slidingInterface::slidingInterface(...) "
303 << " for object " << name << " : "
304 << "Interface attached. Reading master and slave face zones "
305 << "and retired point lookup." << endl;
308 // The face zone addressing is written out in the definition dictionary
309 masterFaceCellsPtr_ = new labelList(dict.lookup("masterFaceCells"));
310 slaveFaceCellsPtr_ = new labelList(dict.lookup("slaveFaceCells"));
312 masterStickOutFacesPtr_ =
313 new labelList(dict.lookup("masterStickOutFaces"));
314 slaveStickOutFacesPtr_ =
315 new labelList(dict.lookup("slaveStickOutFaces"));
317 retiredPointMapPtr_ = new Map<label>(dict.lookup("retiredPointMap"));
318 cutPointEdgePairMapPtr_ =
319 new Map<Pair<edge> >(dict.lookup("cutPointEdgePairMap"));
323 calcAttachedAddressing();
328 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
330 Foam::slidingInterface::~slidingInterface()
336 void Foam::slidingInterface::clearAddressing() const
338 deleteDemandDrivenData(cutFaceMasterPtr_);
339 deleteDemandDrivenData(cutFaceSlavePtr_);
343 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
345 const Foam::faceZoneID& Foam::slidingInterface::masterFaceZoneID() const
347 return masterFaceZoneID_;
351 const Foam::faceZoneID& Foam::slidingInterface::slaveFaceZoneID() const
353 return slaveFaceZoneID_;
357 bool Foam::slidingInterface::changeTopology() const
361 // Always changes. If not attached, project points
364 Pout<< "bool slidingInterface::changeTopology() const "
365 << "for object " << name() << " : "
366 << "Couple-decouple mode." << endl;
383 && !topoChanger().mesh().changing()
386 // If the mesh is not moving or morphing and the interface is
387 // already attached, the topology will not change
392 // Check if the motion changes point projection
393 return projectPoints();
398 void Foam::slidingInterface::setRefinement(polyTopoChange& ref) const
404 // Attached, coupling
405 decoupleInterface(ref);
409 // Detached, coupling
410 coupleInterface(ref);
420 // Clear old coupling data
424 coupleInterface(ref);
431 void Foam::slidingInterface::modifyMotionPoints(pointField& motionPoints) const
435 Pout<< "void slidingInterface::modifyMotionPoints("
436 << "pointField& motionPoints) const for object " << name() << " : "
437 << "Adjusting motion points." << endl;
440 const polyMesh& mesh = topoChanger().mesh();
442 // Get point from the cut zone
443 const labelList& cutPoints = mesh.pointZones()[cutPointZoneID_.index()];
445 if (cutPoints.size() && !projectedSlavePointsPtr_)
451 const pointField& projectedSlavePoints = *projectedSlavePointsPtr_;
453 const Map<label>& rpm = retiredPointMap();
455 const Map<Pair<edge> >& cpepm = cutPointEdgePairMap();
457 const Map<label>& slaveZonePointMap =
458 mesh.faceZones()[slaveFaceZoneID_.index()]().meshPointMap();
460 const primitiveFacePatch& masterPatch =
461 mesh.faceZones()[masterFaceZoneID_.index()]();
462 const edgeList& masterEdges = masterPatch.edges();
463 const pointField& masterLocalPoints = masterPatch.localPoints();
465 const primitiveFacePatch& slavePatch =
466 mesh.faceZones()[slaveFaceZoneID_.index()]();
467 const edgeList& slaveEdges = slavePatch.edges();
468 const pointField& slaveLocalPoints = slavePatch.localPoints();
469 const vectorField& slavePointNormals = slavePatch.pointNormals();
471 forAll(cutPoints, pointI)
473 // Try to find the cut point in retired points
474 Map<label>::const_iterator rpmIter = rpm.find(cutPoints[pointI]);
476 if (rpmIter != rpm.end())
483 // Cut point is a retired point
484 motionPoints[cutPoints[pointI]] =
485 projectedSlavePoints[slaveZonePointMap.find(rpmIter())()];
489 // A cut point is not a projected slave point. Therefore, it
490 // must be an edge-to-edge intersection.
492 Map<Pair<edge> >::const_iterator cpepmIter =
493 cpepm.find(cutPoints[pointI]);
495 if (cpepmIter != cpepm.end())
497 // Pout<< "Need to re-create hit for point "
498 // << cutPoints[pointI]
499 // << " lookup: " << cpepmIter()
503 // The edge cutting code is repeated in
504 // slidingInterface::coupleInterface. This is done for
505 // efficiency reasons and avoids multiple creation of
506 // cutting planes. Please update both simultaneously.
508 const edge& globalMasterEdge = cpepmIter().first();
510 const label curMasterEdgeIndex =
511 masterPatch.whichEdge
515 masterPatch.whichPoint
517 globalMasterEdge.start()
519 masterPatch.whichPoint
521 globalMasterEdge.end()
526 const edge& cme = masterEdges[curMasterEdgeIndex];
528 // Pout<< "curMasterEdgeIndex: " << curMasterEdgeIndex
529 // << " cme: " << cme
532 const edge& globalSlaveEdge = cpepmIter().second();
534 const label curSlaveEdgeIndex =
539 slavePatch.whichPoint
541 globalSlaveEdge.start()
543 slavePatch.whichPoint
545 globalSlaveEdge.end()
550 const edge& curSlaveEdge = slaveEdges[curSlaveEdgeIndex];
551 // Pout<< "curSlaveEdgeIndex: " << curSlaveEdgeIndex
552 // << " curSlaveEdge: " << curSlaveEdge
554 const point& a = projectedSlavePoints[curSlaveEdge.start()];
555 const point& b = projectedSlavePoints[curSlaveEdge.end()];
560 slaveLocalPoints[curSlaveEdge.start()]
561 + slavePointNormals[curSlaveEdge.start()]
562 + slaveLocalPoints[curSlaveEdge.end()]
563 + slavePointNormals[curSlaveEdge.end()]
567 plane cutPlane(a, b, c);
569 linePointRef curSlaveLine =
570 curSlaveEdge.line(slaveLocalPoints);
571 const scalar curSlaveLineMag = curSlaveLine.mag();
574 cutPlane.lineIntersect
576 cme.line(masterLocalPoints)
581 cutOnMaster > edgeEndCutoffTol_
582 && cutOnMaster < 1.0 - edgeEndCutoffTol_
585 // Master is cut, check the slave
586 point masterCutPoint =
587 masterLocalPoints[cme.start()]
588 + cutOnMaster*cme.vec(masterLocalPoints);
591 curSlaveLine.nearestDist(masterCutPoint);
595 // Strict checking of slave cut to avoid capturing
601 - curSlaveLine.start()
602 ) & curSlaveLine.vec()
603 )/sqr(curSlaveLineMag);
605 // Calculate merge tolerance from the
606 // target edge length
608 edgeCoPlanarTol_*mag(b - a);
612 cutOnSlave > edgeEndCutoffTol_
613 && cutOnSlave < 1.0 - edgeEndCutoffTol_
614 && slaveCut.distance() < mergeTol
617 // Cut both master and slave.
618 motionPoints[cutPoints[pointI]] =
624 Pout<< "Missed slave edge!!! This is an error. "
626 << cme.line(masterLocalPoints)
627 << " slave edge: " << curSlaveLine
628 << " point: " << masterCutPoint
633 - curSlaveLine.start()
634 ) & curSlaveLine.vec()
635 )/sqr(curSlaveLineMag)
641 Pout<< "Missed master edge!!! This is an error"
649 "void slidingInterface::modifyMotionPoints"
650 "(pointField&) const"
651 ) << "Cut point " << cutPoints[pointI]
652 << " not recognised as either the projected "
653 << "or as intersection point. Error in point "
654 << "projection or data mapping"
655 << abort(FatalError);
667 void Foam::slidingInterface::updateMesh(const mapPolyMesh& m)
671 Pout<< "void slidingInterface::updateMesh(const mapPolyMesh& m)"
672 << " const for object " << name() << " : "
673 << "Updating topology." << endl;
676 // Mesh has changed topologically. Update local topological data
677 const polyMesh& mesh = topoChanger().mesh();
679 masterFaceZoneID_.update(mesh.faceZones());
680 slaveFaceZoneID_.update(mesh.faceZones());
681 cutPointZoneID_.update(mesh.pointZones());
682 cutFaceZoneID_.update(mesh.faceZones());
684 masterPatchID_.update(mesh.boundaryMesh());
685 slavePatchID_.update(mesh.boundaryMesh());
687 //MJ:Disabled updating
690 // calcAttachedAddressing();
694 // renumberAttachedAddressing(m);
699 const Foam::pointField& Foam::slidingInterface::pointProjection() const
701 if (!projectedSlavePointsPtr_)
706 return *projectedSlavePointsPtr_;
709 void Foam::slidingInterface::setTolerances(const dictionary&dict, bool report)
711 pointMergeTol_ = dict.lookupOrDefault<scalar>
716 edgeMergeTol_ = dict.lookupOrDefault<scalar>
721 nFacesPerSlaveEdge_ = dict.lookupOrDefault<label>
723 "nFacesPerSlaveEdge",
726 edgeFaceEscapeLimit_ = dict.lookupOrDefault<label>
728 "edgeFaceEscapeLimit",
731 integralAdjTol_ = dict.lookupOrDefault<scalar>
736 edgeMasterCatchFraction_ = dict.lookupOrDefault<scalar>
738 "edgeMasterCatchFraction",
739 edgeMasterCatchFraction_
741 edgeCoPlanarTol_ = dict.lookupOrDefault<scalar>
746 edgeEndCutoffTol_ = dict.lookupOrDefault<scalar>
754 Info<< "Sliding interface parameters:" << nl
755 << "pointMergeTol : " << pointMergeTol_ << nl
756 << "edgeMergeTol : " << edgeMergeTol_ << nl
757 << "nFacesPerSlaveEdge : " << nFacesPerSlaveEdge_ << nl
758 << "edgeFaceEscapeLimit : " << edgeFaceEscapeLimit_ << nl
759 << "integralAdjTol : " << integralAdjTol_ << nl
760 << "edgeMasterCatchFraction : " << edgeMasterCatchFraction_ << nl
761 << "edgeCoPlanarTol : " << edgeCoPlanarTol_ << nl
762 << "edgeEndCutoffTol : " << edgeEndCutoffTol_ << endl;
767 void Foam::slidingInterface::write(Ostream& os) const
769 os << nl << type() << nl
771 << masterFaceZoneID_.name() << nl
772 << slaveFaceZoneID_.name() << nl
773 << cutPointZoneID_.name() << nl
774 << cutFaceZoneID_.name() << nl
775 << masterPatchID_.name() << nl
776 << slavePatchID_.name() << nl
777 << typeOfMatchNames_[matchType_] << nl
778 << coupleDecouple_ << nl
779 << attached_ << endl;
783 // To write out all those tolerances
784 #define WRITE_NON_DEFAULT(name) \
785 if ( name ## _ != name ## Default_ )\
787 os << " " #name " " << name ## _ << token::END_STATEMENT << nl; \
791 void Foam::slidingInterface::writeDict(Ostream& os) const
793 os << nl << name() << nl << token::BEGIN_BLOCK << nl
794 << " type " << type() << token::END_STATEMENT << nl
795 << " masterFaceZoneName " << masterFaceZoneID_.name()
796 << token::END_STATEMENT << nl
797 << " slaveFaceZoneName " << slaveFaceZoneID_.name()
798 << token::END_STATEMENT << nl
799 << " cutPointZoneName " << cutPointZoneID_.name()
800 << token::END_STATEMENT << nl
801 << " cutFaceZoneName " << cutFaceZoneID_.name()
802 << token::END_STATEMENT << nl
803 << " masterPatchName " << masterPatchID_.name()
804 << token::END_STATEMENT << nl
805 << " slavePatchName " << slavePatchID_.name()
806 << token::END_STATEMENT << nl
807 << " typeOfMatch " << typeOfMatchNames_[matchType_]
808 << token::END_STATEMENT << nl
809 << " coupleDecouple " << coupleDecouple_
810 << token::END_STATEMENT << nl
811 << " projection " << intersection::algorithmNames_[projectionAlgo_]
812 << token::END_STATEMENT << nl
813 << " attached " << attached_
814 << token::END_STATEMENT << nl
815 << " active " << active()
816 << token::END_STATEMENT << nl;
820 masterFaceCellsPtr_->writeEntry("masterFaceCells", os);
821 slaveFaceCellsPtr_->writeEntry("slaveFaceCells", os);
822 masterStickOutFacesPtr_->writeEntry("masterStickOutFaces", os);
823 slaveStickOutFacesPtr_->writeEntry("slaveStickOutFaces", os);
825 os << " retiredPointMap " << retiredPointMap()
826 << token::END_STATEMENT << nl
827 << " cutPointEdgePairMap " << cutPointEdgePairMap()
828 << token::END_STATEMENT << nl;
831 WRITE_NON_DEFAULT(pointMergeTol)
832 WRITE_NON_DEFAULT(edgeMergeTol)
833 WRITE_NON_DEFAULT(nFacesPerSlaveEdge)
834 WRITE_NON_DEFAULT(edgeFaceEscapeLimit)
835 WRITE_NON_DEFAULT(integralAdjTol)
836 WRITE_NON_DEFAULT(edgeMasterCatchFraction)
837 WRITE_NON_DEFAULT(edgeCoPlanarTol)
838 WRITE_NON_DEFAULT(edgeEndCutoffTol)
840 os << token::END_BLOCK << endl;
844 // ************************************************************************* //