1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 Hrvoje Jasak, Wikki Ltd. All rights reserved. Copyright Hrvoje Jasak.
35 \*---------------------------------------------------------------------------*/
37 #include "slidingInterface.H"
38 #include "polyTopoChanger.H"
40 #include "primitiveMesh.H"
41 #include "polyTopoChange.H"
42 #include "mapPolyMesh.H"
43 #include "addToRunTimeSelectionTable.H"
44 #include "triPointRef.H"
47 // Index of debug signs:
48 // p - adjusting a projection point
49 // * - adjusting edge intersection
51 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
55 defineTypeNameAndDebug(slidingInterface, 0);
56 addToRunTimeSelectionTable
66 const char* Foam::NamedEnum<Foam::slidingInterface::typeOfMatch, 2>::names[] =
73 const Foam::NamedEnum<Foam::slidingInterface::typeOfMatch, 2>
74 Foam::slidingInterface::typeOfMatchNames_;
77 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
79 void Foam::slidingInterface::checkDefinition() const
81 const polyMesh& mesh = topoChanger().mesh();
85 !masterFaceZoneID_.active()
86 || !slaveFaceZoneID_.active()
87 || !cutPointZoneID_.active()
88 || !cutFaceZoneID_.active()
89 || !masterPatchID_.active()
90 || !slavePatchID_.active()
95 "void slidingInterface::checkDefinition()"
96 ) << "Not all zones and patches needed in the definition "
97 << "have been found. Please check your mesh definition." << nl
99 << masterFaceZoneID_.active() << slaveFaceZoneID_.active()
100 << cutPointZoneID_.active() << cutFaceZoneID_.active()
101 << masterPatchID_.active() << slavePatchID_.active()
102 << abort(FatalError);
105 // Check the sizes and set up state
108 mesh.faceZones()[masterFaceZoneID_.index()].size() == 0
109 || mesh.faceZones()[slaveFaceZoneID_.index()].size() == 0
112 FatalErrorIn("void slidingInterface::checkDefinition()")
113 << "Master or slave face zone contain no faces. "
114 << "Please check your mesh definition."
115 << abort(FatalError);
122 // Check for points shared between master and slave. If a point
123 // is shared, the projection will be illegal
124 const primitiveFacePatch& masterPatch =
125 mesh.faceZones()[masterFaceZoneID_.index()]();
127 const primitiveFacePatch& slavePatch =
128 mesh.faceZones()[slaveFaceZoneID_.index()]();
130 const labelList& smp = slavePatch.meshPoints();
131 const pointField& slp = slavePatch.localPoints();
133 label nSharedPoints = 0;
137 if (masterPatch.whichPoint(smp[i]) != -1)
139 Warning<< "Shared point between master and slave: "
140 << smp[i] << " " << slp[i] << endl;
146 if (nSharedPoints > 0)
148 FatalErrorIn("void slidingInterface::checkDefinition()")
149 << "Master and slave face zone share " << nSharedPoints
150 << " point. This is not allowed." << nl
151 << "Please check mesh for topological errors."
152 << abort(FatalError);
156 Pout<< "Sliding interface object " << name() << " :" << nl
157 << " master face zone: " << masterFaceZoneID_.index() << nl
158 << " slave face zone: " << slaveFaceZoneID_.index() << endl;
163 void Foam::slidingInterface::clearOut() const
165 clearPointProjection();
166 clearAttachedAddressing();
171 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
174 // Construct from components
175 Foam::slidingInterface::slidingInterface
179 const polyTopoChanger& mme,
180 const word& masterFaceZoneName,
181 const word& slaveFaceZoneName,
182 const word& cutPointZoneName,
183 const word& cutFaceZoneName,
184 const word& masterPatchName,
185 const word& slavePatchName,
186 const typeOfMatch tom,
187 const bool coupleDecouple,
188 const intersection::algorithm algo
191 polyMeshModifier(name, index, mme, true),
195 mme.mesh().faceZones()
200 mme.mesh().faceZones()
205 mme.mesh().pointZones()
210 mme.mesh().faceZones()
215 mme.mesh().boundaryMesh()
220 mme.mesh().boundaryMesh()
223 coupleDecouple_(coupleDecouple),
225 projectionAlgo_(algo),
227 cutFaceMasterPtr_(NULL),
228 cutFaceSlavePtr_(NULL),
229 masterFaceCellsPtr_(NULL),
230 slaveFaceCellsPtr_(NULL),
231 masterStickOutFacesPtr_(NULL),
232 slaveStickOutFacesPtr_(NULL),
233 retiredPointMapPtr_(NULL),
234 cutPointEdgePairMapPtr_(NULL),
235 slavePointPointHitsPtr_(NULL),
236 slavePointEdgeHitsPtr_(NULL),
237 slavePointFaceHitsPtr_(NULL),
238 masterPointEdgeHitsPtr_(NULL),
239 projectedSlavePointsPtr_(NULL)
247 "Foam::slidingInterface::slidingInterface\n"
249 " const word& name,\n"
250 " const label index,\n"
251 " const polyTopoChanger& mme,\n"
252 " const word& masterFaceZoneName,\n"
253 " const word& slaveFaceZoneName,\n"
254 " const word& cutFaceZoneName,\n"
255 " const word& cutPointZoneName,\n"
256 " const word& masterPatchName,\n"
257 " const word& slavePatchName,\n"
258 " const typeOfMatch tom,\n"
259 " const bool coupleDecouple\n"
261 ) << "Creation of a sliding interface from components "
262 << "in attached state not supported."
263 << abort(FatalError);
267 calcAttachedAddressing();
272 // Construct from components
273 Foam::slidingInterface::slidingInterface
276 const dictionary& dict,
278 const polyTopoChanger& mme
281 polyMeshModifier(name, index, mme, Switch(dict.lookup("active"))),
284 dict.lookup("masterFaceZoneName"),
285 mme.mesh().faceZones()
289 dict.lookup("slaveFaceZoneName"),
290 mme.mesh().faceZones()
294 dict.lookup("cutPointZoneName"),
295 mme.mesh().pointZones()
299 dict.lookup("cutFaceZoneName"),
300 mme.mesh().faceZones()
304 dict.lookup("masterPatchName"),
305 mme.mesh().boundaryMesh()
309 dict.lookup("slavePatchName"),
310 mme.mesh().boundaryMesh()
312 matchType_(typeOfMatchNames_.read((dict.lookup("typeOfMatch")))),
313 coupleDecouple_(dict.lookup("coupleDecouple")),
314 attached_(dict.lookup("attached")),
317 intersection::algorithmNames_.read(dict.lookup("projection"))
320 cutFaceMasterPtr_(NULL),
321 cutFaceSlavePtr_(NULL),
322 masterFaceCellsPtr_(NULL),
323 slaveFaceCellsPtr_(NULL),
324 masterStickOutFacesPtr_(NULL),
325 slaveStickOutFacesPtr_(NULL),
326 retiredPointMapPtr_(NULL),
327 cutPointEdgePairMapPtr_(NULL),
328 slavePointPointHitsPtr_(NULL),
329 slavePointEdgeHitsPtr_(NULL),
330 slavePointFaceHitsPtr_(NULL),
331 masterPointEdgeHitsPtr_(NULL),
332 projectedSlavePointsPtr_(NULL)
336 // If the interface is attached, the master and slave face zone addressing
337 // needs to be read in; otherwise it will be created
342 Pout<< "slidingInterface::slidingInterface(...) "
343 << " for object " << name << " : "
344 << "Interface attached. Reading master and slave face zones "
345 << "and retired point lookup." << endl;
348 // The face zone addressing is written out in the definition dictionary
349 masterFaceCellsPtr_ = new labelList(dict.lookup("masterFaceCells"));
350 slaveFaceCellsPtr_ = new labelList(dict.lookup("slaveFaceCells"));
352 masterStickOutFacesPtr_ =
353 new labelList(dict.lookup("masterStickOutFaces"));
354 slaveStickOutFacesPtr_ =
355 new labelList(dict.lookup("slaveStickOutFaces"));
357 retiredPointMapPtr_ = new Map<label>(dict.lookup("retiredPointMap"));
358 cutPointEdgePairMapPtr_ =
359 new Map<Pair<edge> >(dict.lookup("cutPointEdgePairMap"));
363 calcAttachedAddressing();
368 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
370 Foam::slidingInterface::~slidingInterface()
376 void Foam::slidingInterface::clearAddressing() const
378 deleteDemandDrivenData(cutFaceMasterPtr_);
379 deleteDemandDrivenData(cutFaceSlavePtr_);
383 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
385 const Foam::faceZoneID& Foam::slidingInterface::masterFaceZoneID() const
387 return masterFaceZoneID_;
391 const Foam::faceZoneID& Foam::slidingInterface::slaveFaceZoneID() const
393 return slaveFaceZoneID_;
397 const Foam::pointZoneID& Foam::slidingInterface::cutPointZoneID() const
399 return cutPointZoneID_;
403 const Foam::faceZoneID& Foam::slidingInterface::cutFaceZoneID() const
405 return cutFaceZoneID_;
409 bool Foam::slidingInterface::changeTopology() const
413 // Always changes. If not attached, project points
416 Pout<< "bool slidingInterface::changeTopology() const "
417 << "for object " << name() << " : "
418 << "Couple-decouple mode." << endl;
435 && !topoChanger().mesh().changing()
438 // If the mesh is not moving or morphing and the interface is
439 // already attached, the topology will not change
444 // Check if the motion changes point projection
445 return projectPoints();
450 void Foam::slidingInterface::setRefinement(polyTopoChange& ref) const
456 // Attached, coupling
457 decoupleInterface(ref);
461 // Detached, coupling
462 coupleInterface(ref);
472 // Clear old coupling data
476 coupleInterface(ref);
483 void Foam::slidingInterface::modifyMotionPoints(pointField& motionPoints) const
487 Pout<< "void slidingInterface::modifyMotionPoints("
488 << "pointField& motionPoints) const for object " << name() << " : "
489 << "Adjusting motion points." << endl;
492 const polyMesh& mesh = topoChanger().mesh();
494 // Get point from the cut zone
495 const labelList& cutPoints = mesh.pointZones()[cutPointZoneID_.index()];
497 if (cutPoints.size() > 0 && !projectedSlavePointsPtr_)
503 const pointField& projectedSlavePoints = *projectedSlavePointsPtr_;
505 const Map<label>& rpm = retiredPointMap();
507 const Map<Pair<edge> >& cpepm = cutPointEdgePairMap();
509 const Map<label>& slaveZonePointMap =
510 mesh.faceZones()[slaveFaceZoneID_.index()]().meshPointMap();
512 const primitiveFacePatch& masterPatch =
513 mesh.faceZones()[masterFaceZoneID_.index()]();
514 const edgeList& masterEdges = masterPatch.edges();
515 const pointField& masterLocalPoints = masterPatch.localPoints();
517 const primitiveFacePatch& slavePatch =
518 mesh.faceZones()[slaveFaceZoneID_.index()]();
519 const edgeList& slaveEdges = slavePatch.edges();
520 const pointField& slaveLocalPoints = slavePatch.localPoints();
521 const vectorField& slavePointNormals = slavePatch.pointNormals();
523 forAll (cutPoints, pointI)
525 // Try to find the cut point in retired points
526 Map<label>::const_iterator rpmIter = rpm.find(cutPoints[pointI]);
528 if (rpmIter != rpm.end())
535 // Cut point is a retired point
536 motionPoints[cutPoints[pointI]] =
537 projectedSlavePoints[slaveZonePointMap.find(rpmIter())()];
541 // A cut point is not a projected slave point. Therefore, it
542 // must be an edge-to-edge intersection.
544 Map<Pair<edge> >::const_iterator cpepmIter =
545 cpepm.find(cutPoints[pointI]);
547 if (cpepmIter != cpepm.end())
549 // Pout << "Need to re-create hit for point " << cutPoints[pointI] << " lookup: " << cpepmIter() << endl;
552 // The edge cutting code is repeated in
553 // slidingInterface::coupleInterface. This is done for
554 // efficiency reasons and avoids multiple creation of
555 // cutting planes. Please update both simultaneously.
557 const edge& globalMasterEdge = cpepmIter().first();
559 const label curMasterEdgeIndex =
560 masterPatch.whichEdge
564 masterPatch.whichPoint
566 globalMasterEdge.start()
568 masterPatch.whichPoint
570 globalMasterEdge.end()
575 const edge& cme = masterEdges[curMasterEdgeIndex];
576 // Pout << "curMasterEdgeIndex: " << curMasterEdgeIndex << " cme: " << cme << endl;
577 const edge& globalSlaveEdge = cpepmIter().second();
579 const label curSlaveEdgeIndex =
584 slavePatch.whichPoint
586 globalSlaveEdge.start()
588 slavePatch.whichPoint
590 globalSlaveEdge.end()
595 const edge& curSlaveEdge = slaveEdges[curSlaveEdgeIndex];
596 // Pout << "curSlaveEdgeIndex: " << curSlaveEdgeIndex << " curSlaveEdge: " << curSlaveEdge << endl;
597 const point& a = projectedSlavePoints[curSlaveEdge.start()];
598 const point& b = projectedSlavePoints[curSlaveEdge.end()];
603 slaveLocalPoints[curSlaveEdge.start()]
604 + slavePointNormals[curSlaveEdge.start()]
605 + slaveLocalPoints[curSlaveEdge.end()]
606 + slavePointNormals[curSlaveEdge.end()]
610 plane cutPlane(a, b, c);
612 linePointRef curSlaveLine =
613 curSlaveEdge.line(slaveLocalPoints);
614 const scalar curSlaveLineMag = curSlaveLine.mag();
617 cutPlane.lineIntersect
619 cme.line(masterLocalPoints)
624 cutOnMaster > edgeEndCutoffTol_
625 && cutOnMaster < 1.0 - edgeEndCutoffTol_
628 // Master is cut, check the slave
629 point masterCutPoint =
630 masterLocalPoints[cme.start()]
631 + cutOnMaster*cme.vec(masterLocalPoints);
634 curSlaveLine.nearestDist(masterCutPoint);
638 // Strict checking of slave cut to avoid capturing
644 - curSlaveLine.start()
645 ) & curSlaveLine.vec()
646 )/sqr(curSlaveLineMag);
648 // Calculate merge tolerance from the
649 // target edge length
651 edgeCoPlanarTol_*mag(b - a);
655 cutOnSlave > edgeEndCutoffTol_
656 && cutOnSlave < 1.0 - edgeEndCutoffTol_
657 && slaveCut.distance() < mergeTol
660 // Cut both master and slave.
661 motionPoints[cutPoints[pointI]] =
667 Pout<< "Missed slave edge!!! This is an error. "
669 << cme.line(masterLocalPoints)
670 << " slave edge: " << curSlaveLine
671 << " point: " << masterCutPoint
676 - curSlaveLine.start()
677 ) & curSlaveLine.vec()
678 )/sqr(curSlaveLineMag)
684 Pout<< "Missed master edge!!! This is an error"
692 "void slidingInterface::modifyMotionPoints"
693 "(pointField&) const"
694 ) << "Cut point " << cutPoints[pointI]
695 << " not recognised as either the projected "
696 << "or as intersection point. Error in point "
697 << "projection or data mapping"
698 << abort(FatalError);
710 void Foam::slidingInterface::updateMesh(const mapPolyMesh& m)
714 Pout<< "void slidingInterface::updateMesh(const mapPolyMesh& m)"
715 << " const for object " << name() << " : "
716 << "Updating topology." << endl;
719 // Mesh has changed topologically. Update local topological data
720 const polyMesh& mesh = topoChanger().mesh();
722 masterFaceZoneID_.update(mesh.faceZones());
723 slaveFaceZoneID_.update(mesh.faceZones());
724 cutPointZoneID_.update(mesh.pointZones());
725 cutFaceZoneID_.update(mesh.faceZones());
727 masterPatchID_.update(mesh.boundaryMesh());
728 slavePatchID_.update(mesh.boundaryMesh());
732 calcAttachedAddressing();
736 renumberAttachedAddressing(m);
741 const Foam::pointField& Foam::slidingInterface::pointProjection() const
743 if (!projectedSlavePointsPtr_)
748 return *projectedSlavePointsPtr_;
752 void Foam::slidingInterface::write(Ostream& os) const
754 os << nl << type() << nl
756 << masterFaceZoneID_.name() << nl
757 << slaveFaceZoneID_.name() << nl
758 << cutPointZoneID_.name() << nl
759 << cutFaceZoneID_.name() << nl
760 << masterPatchID_.name() << nl
761 << slavePatchID_.name() << nl
762 << typeOfMatchNames_[matchType_] << nl
763 << coupleDecouple_ << nl
764 << attached_ << endl;
768 void Foam::slidingInterface::writeDict(Ostream& os) const
770 os << nl << name() << nl << token::BEGIN_BLOCK << nl
771 << " type " << type() << token::END_STATEMENT << nl
772 << " masterFaceZoneName " << masterFaceZoneID_.name()
773 << token::END_STATEMENT << nl
774 << " slaveFaceZoneName " << slaveFaceZoneID_.name()
775 << token::END_STATEMENT << nl
776 << " cutPointZoneName " << cutPointZoneID_.name()
777 << token::END_STATEMENT << nl
778 << " cutFaceZoneName " << cutFaceZoneID_.name()
779 << token::END_STATEMENT << nl
780 << " masterPatchName " << masterPatchID_.name()
781 << token::END_STATEMENT << nl
782 << " slavePatchName " << slavePatchID_.name()
783 << token::END_STATEMENT << nl
784 << " typeOfMatch " << typeOfMatchNames_[matchType_]
785 << token::END_STATEMENT << nl
786 << " coupleDecouple " << coupleDecouple_
787 << token::END_STATEMENT << nl
788 << " projection " << intersection::algorithmNames_[projectionAlgo_]
789 << token::END_STATEMENT << nl
790 << " attached " << attached_
791 << token::END_STATEMENT << nl
792 << " active " << active()
793 << token::END_STATEMENT << nl;
797 masterFaceCellsPtr_->writeEntry("masterFaceCells", os);
798 slaveFaceCellsPtr_->writeEntry("slaveFaceCells", os);
799 masterStickOutFacesPtr_->writeEntry("masterStickOutFaces", os);
800 slaveStickOutFacesPtr_->writeEntry("slaveStickOutFaces", os);
802 os << " retiredPointMap " << retiredPointMap()
803 << token::END_STATEMENT << nl
804 << " cutPointEdgePairMap " << cutPointEdgePairMap()
805 << token::END_STATEMENT << nl;
808 os << token::END_BLOCK << endl;
812 // ************************************************************************* //