initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / src / dynamicMesh / slidingInterface / slidingInterface.C
blob80d68749e84ae89a39ec3d900c418fd34457126a
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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
25 \*---------------------------------------------------------------------------*/
27 #include "slidingInterface.H"
28 #include "polyTopoChanger.H"
29 #include "polyMesh.H"
30 #include "primitiveMesh.H"
31 #include "polyTopoChange.H"
32 #include "addToRunTimeSelectionTable.H"
33 #include "triPointRef.H"
34 #include "plane.H"
36 // Index of debug signs:
37 // p - adjusting a projection point
38 // * - adjusting edge intersection
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 namespace Foam
44     defineTypeNameAndDebug(slidingInterface, 0);
45     addToRunTimeSelectionTable
46     (
47         polyMeshModifier,
48         slidingInterface,
49         dictionary
50     );
54 template<>
55 const char* Foam::NamedEnum<Foam::slidingInterface::typeOfMatch, 2>::names[] =
57     "integral",
58     "partial"
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();
72     if
73     (
74         !masterFaceZoneID_.active()
75      || !slaveFaceZoneID_.active()
76      || !cutPointZoneID_.active()
77      || !cutFaceZoneID_.active()
78      || !masterPatchID_.active()
79      || !slavePatchID_.active()
80     )
81     {
82         FatalErrorIn
83         (
84             "void slidingInterface::checkDefinition()"
85         )   << "Not all zones and patches needed in the definition "
86             << "have been found.  Please check your mesh definition."
87             << abort(FatalError);
88     }
90     // Check the sizes and set up state
91     if
92     (
93         mesh.faceZones()[masterFaceZoneID_.index()].empty()
94      || mesh.faceZones()[slaveFaceZoneID_.index()].empty()
95     )
96     {
97         FatalErrorIn("void slidingInterface::checkDefinition()")
98             << "Master or slave face zone contain no faces.  "
99             << "Please check your mesh definition."
100             << abort(FatalError);
101     }
103     if (debug)
104     {
105         Pout<< "Sliding interface object " << name() << " :" << nl
106             << "    master face zone: " << masterFaceZoneID_.index() << nl
107             << "    slave face zone: " << slaveFaceZoneID_.index() << endl;
108     }
112 void Foam::slidingInterface::clearOut() const
114     clearPointProjection();
115     clearAttachedAddressing();
116     clearAddressing();
120 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
123 // Construct from components
124 Foam::slidingInterface::slidingInterface
126     const word& name,
127     const label index,
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),
141     masterFaceZoneID_
142     (
143         masterFaceZoneName,
144         mme.mesh().faceZones()
145     ),
146     slaveFaceZoneID_
147     (
148         slaveFaceZoneName,
149         mme.mesh().faceZones()
150     ),
151     cutPointZoneID_
152     (
153         cutPointZoneName,
154         mme.mesh().pointZones()
155     ),
156     cutFaceZoneID_
157     (
158         cutFaceZoneName,
159         mme.mesh().faceZones()
160     ),
161     masterPatchID_
162     (
163         masterPatchName,
164         mme.mesh().boundaryMesh()
165     ),
166     slavePatchID_
167     (
168         slavePatchName,
169         mme.mesh().boundaryMesh()
170     ),
171     matchType_(tom),
172     coupleDecouple_(coupleDecouple),
173     attached_(false),
174     projectionAlgo_(algo),
175     trigger_(false),
176     cutFaceMasterPtr_(NULL),
177     cutFaceSlavePtr_(NULL),
178     masterFaceCellsPtr_(NULL),
179     slaveFaceCellsPtr_(NULL),
180     masterStickOutFacesPtr_(NULL),
181     slaveStickOutFacesPtr_(NULL),
182     retiredPointMapPtr_(NULL),
183     cutPointEdgePairMapPtr_(NULL),
184     slavePointPointHitsPtr_(NULL),
185     slavePointEdgeHitsPtr_(NULL),
186     slavePointFaceHitsPtr_(NULL),
187     masterPointEdgeHitsPtr_(NULL),
188     projectedSlavePointsPtr_(NULL)
190     checkDefinition();
192     if (attached_)
193     {
194         FatalErrorIn
195         (
196             "Foam::slidingInterface::slidingInterface\n"
197             "(\n"
198             "    const word& name,\n"
199             "    const label index,\n"
200             "    const polyTopoChanger& mme,\n"
201             "    const word& masterFaceZoneName,\n"
202             "    const word& slaveFaceZoneName,\n"
203             "    const word& cutFaceZoneName,\n"
204             "    const word& cutPointZoneName,\n"
205             "    const word& masterPatchName,\n"
206             "    const word& slavePatchName,\n"
207             "    const typeOfMatch tom,\n"
208             "    const bool coupleDecouple\n"
209             ")"
210         )   << "Creation of a sliding interface from components "
211             << "in attached state not supported."
212             << abort(FatalError);
213     }
214     else
215     {
216         calcAttachedAddressing();
217     }
221 // Construct from components
222 Foam::slidingInterface::slidingInterface
224     const word& name,
225     const dictionary& dict,
226     const label index,
227     const polyTopoChanger& mme
230     polyMeshModifier(name, index, mme, Switch(dict.lookup("active"))),
231     masterFaceZoneID_
232     (
233         dict.lookup("masterFaceZoneName"),
234         mme.mesh().faceZones()
235     ),
236     slaveFaceZoneID_
237     (
238         dict.lookup("slaveFaceZoneName"),
239         mme.mesh().faceZones()
240     ),
241     cutPointZoneID_
242     (
243         dict.lookup("cutPointZoneName"),
244         mme.mesh().pointZones()
245     ),
246     cutFaceZoneID_
247     (
248         dict.lookup("cutFaceZoneName"),
249         mme.mesh().faceZones()
250     ),
251     masterPatchID_
252     (
253         dict.lookup("masterPatchName"),
254         mme.mesh().boundaryMesh()
255     ),
256     slavePatchID_
257     (
258         dict.lookup("slavePatchName"),
259         mme.mesh().boundaryMesh()
260     ),
261     matchType_(typeOfMatchNames_.read((dict.lookup("typeOfMatch")))),
262     coupleDecouple_(dict.lookup("coupleDecouple")),
263     attached_(dict.lookup("attached")),
264     projectionAlgo_
265     (
266         intersection::algorithmNames_.read(dict.lookup("projection"))
267     ),
268     trigger_(false),
269     cutFaceMasterPtr_(NULL),
270     cutFaceSlavePtr_(NULL),
271     masterFaceCellsPtr_(NULL),
272     slaveFaceCellsPtr_(NULL),
273     masterStickOutFacesPtr_(NULL),
274     slaveStickOutFacesPtr_(NULL),
275     retiredPointMapPtr_(NULL),
276     cutPointEdgePairMapPtr_(NULL),
277     slavePointPointHitsPtr_(NULL),
278     slavePointEdgeHitsPtr_(NULL),
279     slavePointFaceHitsPtr_(NULL),
280     masterPointEdgeHitsPtr_(NULL),
281     projectedSlavePointsPtr_(NULL)
283     checkDefinition();
285     // If the interface is attached, the master and slave face zone addressing
286     // needs to be read in; otherwise it will be created
287     if (attached_)
288     {
289         if (debug)
290         {
291             Pout<< "slidingInterface::slidingInterface(...) "
292                 << " for object " << name << " : "
293                 << "Interface attached.  Reading master and slave face zones "
294                 << "and retired point lookup." << endl;
295         }
297         // The face zone addressing is written out in the definition dictionary
298         masterFaceCellsPtr_ = new labelList(dict.lookup("masterFaceCells"));
299         slaveFaceCellsPtr_ = new labelList(dict.lookup("slaveFaceCells"));
301         masterStickOutFacesPtr_ =
302             new labelList(dict.lookup("masterStickOutFaces"));
303         slaveStickOutFacesPtr_ =
304             new labelList(dict.lookup("slaveStickOutFaces"));
306         retiredPointMapPtr_ = new Map<label>(dict.lookup("retiredPointMap"));
307         cutPointEdgePairMapPtr_ =
308             new Map<Pair<edge> >(dict.lookup("cutPointEdgePairMap"));
309     }
310     else
311     {
312         calcAttachedAddressing();
313     }
317 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
319 Foam::slidingInterface::~slidingInterface()
321     clearOut();
325 void Foam::slidingInterface::clearAddressing() const
327     deleteDemandDrivenData(cutFaceMasterPtr_);
328     deleteDemandDrivenData(cutFaceSlavePtr_);
332 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
334 const Foam::faceZoneID& Foam::slidingInterface::masterFaceZoneID() const
336     return masterFaceZoneID_;
340 const Foam::faceZoneID& Foam::slidingInterface::slaveFaceZoneID() const
342     return slaveFaceZoneID_;
346 bool Foam::slidingInterface::changeTopology() const
348     if (coupleDecouple_)
349     {
350         // Always changes.  If not attached, project points
351         if (debug)
352         {
353             Pout<< "bool slidingInterface::changeTopology() const "
354                 << "for object " << name() << " : "
355                 << "Couple-decouple mode." << endl;
356         }
358         if (!attached_)
359         {
360             projectPoints();
361         }
362         else
363         {
364         }
366         return true;
367     }
369     if
370     (
371         attached_
372      && !topoChanger().mesh().changing()
373     )
374     {
375         // If the mesh is not moving or morphing and the interface is
376         // already attached, the topology will not change
377         return false;
378     }
379     else
380     {
381         // Check if the motion changes point projection
382         return projectPoints();
383     }
387 void Foam::slidingInterface::setRefinement(polyTopoChange& ref) const
389     if (coupleDecouple_)
390     {
391         if (attached_)
392         {
393             // Attached, coupling
394             decoupleInterface(ref);
395         }
396         else
397         {
398             // Detached, coupling
399             coupleInterface(ref);
400         }
402         return;
403     }
405     if (trigger_)
406     {
407         if (attached_)
408         {
409             // Clear old coupling data
410             clearCouple(ref);
411         }
413         coupleInterface(ref);
414         
415         trigger_ = false;
416     }
420 void Foam::slidingInterface::modifyMotionPoints(pointField& motionPoints) const
422     if (debug)
423     {
424         Pout<< "void slidingInterface::modifyMotionPoints(" 
425             << "pointField& motionPoints) const for object " << name() << " : "
426             << "Adjusting motion points." << endl;
427     }
429     const polyMesh& mesh = topoChanger().mesh();
431     // Get point from the cut zone
432     const labelList& cutPoints = mesh.pointZones()[cutPointZoneID_.index()];
434     if (cutPoints.size() && !projectedSlavePointsPtr_)
435     {
436         return;
437     }
438     else
439     {
440         const pointField& projectedSlavePoints = *projectedSlavePointsPtr_;
442         const Map<label>& rpm = retiredPointMap();
444         const Map<Pair<edge> >& cpepm = cutPointEdgePairMap();
446         const Map<label>& slaveZonePointMap =
447             mesh.faceZones()[slaveFaceZoneID_.index()]().meshPointMap();
449         const primitiveFacePatch& masterPatch =
450             mesh.faceZones()[masterFaceZoneID_.index()]();
451         const edgeList& masterEdges = masterPatch.edges();
452         const pointField& masterLocalPoints = masterPatch.localPoints();
454         const primitiveFacePatch& slavePatch =
455             mesh.faceZones()[slaveFaceZoneID_.index()]();
456         const edgeList& slaveEdges = slavePatch.edges();
457         const pointField& slaveLocalPoints = slavePatch.localPoints();
458         const vectorField& slavePointNormals = slavePatch.pointNormals();
460         forAll (cutPoints, pointI)
461         {
462             // Try to find the cut point in retired points
463             Map<label>::const_iterator rpmIter = rpm.find(cutPoints[pointI]);
465             if (rpmIter != rpm.end())
466             {
467                 if (debug)
468                 {
469                     Pout << "p";
470                 }
472                 // Cut point is a retired point
473                 motionPoints[cutPoints[pointI]] =
474                     projectedSlavePoints[slaveZonePointMap.find(rpmIter())()];
475             }
476             else
477             {
478                 // A cut point is not a projected slave point.  Therefore, it
479                 // must be an edge-to-edge intersection.  
481                 Map<Pair<edge> >::const_iterator cpepmIter =
482                     cpepm.find(cutPoints[pointI]);
484                 if (cpepmIter != cpepm.end())
485                 {
486 //                     Pout << "Need to re-create hit for point " << cutPoints[pointI] << " lookup: " << cpepmIter() << endl;
488                     // Note.
489                     // The edge cutting code is repeated in
490                     // slidingInterface::coupleInterface.  This is done for
491                     // efficiency reasons and avoids multiple creation of
492                     // cutting planes.  Please update both simultaneously.
493                     // 
494                     const edge& globalMasterEdge = cpepmIter().first();
496                     const label curMasterEdgeIndex =
497                         masterPatch.whichEdge
498                         (
499                             edge
500                             (
501                                 masterPatch.whichPoint
502                                 (
503                                     globalMasterEdge.start()
504                                 ),
505                                 masterPatch.whichPoint
506                                 (
507                                     globalMasterEdge.end()
508                                 )
509                             )
510                         );
512                     const edge& cme = masterEdges[curMasterEdgeIndex];
513 //                     Pout << "curMasterEdgeIndex: " << curMasterEdgeIndex << " cme: " << cme << endl;
514                     const edge& globalSlaveEdge = cpepmIter().second();
516                     const label curSlaveEdgeIndex =
517                         slavePatch.whichEdge
518                         (
519                             edge
520                             (
521                                 slavePatch.whichPoint
522                                 (
523                                     globalSlaveEdge.start()
524                                 ),
525                                 slavePatch.whichPoint
526                                 (
527                                     globalSlaveEdge.end()
528                                 )
529                             )
530                         );
532                     const edge& curSlaveEdge = slaveEdges[curSlaveEdgeIndex];
533 //                     Pout << "curSlaveEdgeIndex: " << curSlaveEdgeIndex << " curSlaveEdge: " << curSlaveEdge << endl;
534                     const point& a = projectedSlavePoints[curSlaveEdge.start()];
535                     const point& b = projectedSlavePoints[curSlaveEdge.end()];
537                     point c =
538                         0.5*
539                         (
540                             slaveLocalPoints[curSlaveEdge.start()]
541                           + slavePointNormals[curSlaveEdge.start()]
542                           + slaveLocalPoints[curSlaveEdge.end()]
543                           + slavePointNormals[curSlaveEdge.end()]
544                         );
546                     // Create the plane
547                     plane cutPlane(a, b, c);
549                     linePointRef curSlaveLine =
550                         curSlaveEdge.line(slaveLocalPoints);
551                     const scalar curSlaveLineMag = curSlaveLine.mag();
553                     scalar cutOnMaster =
554                         cutPlane.lineIntersect
555                         (
556                             cme.line(masterLocalPoints)
557                         );
559                     if
560                     (
561                         cutOnMaster > edgeEndCutoffTol_
562                      && cutOnMaster < 1.0 - edgeEndCutoffTol_
563                     )
564                     {
565                         // Master is cut, check the slave
566                         point masterCutPoint =
567                             masterLocalPoints[cme.start()]
568                           + cutOnMaster*cme.vec(masterLocalPoints);
570                         pointHit slaveCut =
571                             curSlaveLine.nearestDist(masterCutPoint);
573                         if (slaveCut.hit())
574                         {
575                             // Strict checking of slave cut to avoid capturing
576                             // end points.  
577                             scalar cutOnSlave =
578                                 (
579                                     (
580                                         slaveCut.hitPoint()
581                                       - curSlaveLine.start()
582                                     ) & curSlaveLine.vec()
583                                 )/sqr(curSlaveLineMag);
585                             // Calculate merge tolerance from the
586                             // target edge length
587                             scalar mergeTol =
588                                 edgeCoPlanarTol_*mag(b - a);
590                             if
591                             (
592                                 cutOnSlave > edgeEndCutoffTol_
593                              && cutOnSlave < 1.0 - edgeEndCutoffTol_
594                              && slaveCut.distance() < mergeTol
595                             )
596                             {
597                                 // Cut both master and slave.
598                                 motionPoints[cutPoints[pointI]] =
599                                     masterCutPoint;
600                             }
601                         }
602                         else
603                         {
604                             Pout<< "Missed slave edge!!!  This is an error.  "
605                                 << "Master edge: "
606                                 << cme.line(masterLocalPoints)
607                                 << " slave edge: " << curSlaveLine
608                                 << " point: " << masterCutPoint
609                                 << " weight: " << 
610                                 (
611                                     (
612                                         slaveCut.missPoint()
613                                       - curSlaveLine.start()
614                                     ) & curSlaveLine.vec()
615                                 )/sqr(curSlaveLineMag)
616                                 << endl;
617                         }
618                     }
619                     else
620                     {
621                         Pout<< "Missed master edge!!!  This is an error"
622                             << endl;
623                     }
624                 }
625                 else
626                 {
627                     FatalErrorIn
628                     (
629                         "void slidingInterface::modifyMotionPoints"
630                         "(pointField&) const"
631                     )   << "Cut point " << cutPoints[pointI]
632                         << " not recognised as either the projected "
633                         << "or as intersection point.  Error in point "
634                         << "projection or data mapping"
635                         << abort(FatalError);
636                 }
637             }
638         }
639         if (debug)
640         {
641             Pout << endl;
642         }
643     }
647 void Foam::slidingInterface::updateMesh(const mapPolyMesh& m)
649     if (debug)
650     {
651         Pout<< "void slidingInterface::updateMesh(const mapPolyMesh& m)" 
652             << " const for object " << name() << " : "
653             << "Updating topology." << endl;
654     }
656     // Mesh has changed topologically.  Update local topological data
657     const polyMesh& mesh = topoChanger().mesh();
659     masterFaceZoneID_.update(mesh.faceZones());
660     slaveFaceZoneID_.update(mesh.faceZones());
661     cutPointZoneID_.update(mesh.pointZones());
662     cutFaceZoneID_.update(mesh.faceZones());
664     masterPatchID_.update(mesh.boundaryMesh());
665     slavePatchID_.update(mesh.boundaryMesh());
667 //MJ:Disabled updating
668 //    if (!attached())
669 //    {
670 //        calcAttachedAddressing();
671 //    }
672 //    else
673 //    {
674 //        renumberAttachedAddressing(m);
675 //    }
679 const Foam::pointField& Foam::slidingInterface::pointProjection() const
681     if (!projectedSlavePointsPtr_)
682     {
683         projectPoints();
684     }
686     return *projectedSlavePointsPtr_;
690 void Foam::slidingInterface::write(Ostream& os) const
692     os  << nl << type() << nl
693         << name()<< nl
694         << masterFaceZoneID_.name() << nl
695         << slaveFaceZoneID_.name() << nl
696         << cutPointZoneID_.name() << nl
697         << cutFaceZoneID_.name() << nl
698         << masterPatchID_.name() << nl
699         << slavePatchID_.name() << nl
700         << typeOfMatchNames_[matchType_] << nl
701         << coupleDecouple_ << nl
702         << attached_ << endl;
706 void Foam::slidingInterface::writeDict(Ostream& os) const
708     os  << nl << name() << nl << token::BEGIN_BLOCK << nl
709         << "    type " << type() << token::END_STATEMENT << nl
710         << "    masterFaceZoneName " << masterFaceZoneID_.name()
711         << token::END_STATEMENT << nl
712         << "    slaveFaceZoneName " << slaveFaceZoneID_.name()
713         << token::END_STATEMENT << nl
714         << "    cutPointZoneName " << cutPointZoneID_.name()
715         << token::END_STATEMENT << nl
716         << "    cutFaceZoneName " << cutFaceZoneID_.name()
717         << token::END_STATEMENT << nl
718         << "    masterPatchName " << masterPatchID_.name()
719         << token::END_STATEMENT << nl
720         << "    slavePatchName " << slavePatchID_.name()
721         << token::END_STATEMENT << nl
722         << "    typeOfMatch " << typeOfMatchNames_[matchType_]
723         << token::END_STATEMENT << nl
724         << "    coupleDecouple " << coupleDecouple_
725         << token::END_STATEMENT << nl
726         << "    projection " << intersection::algorithmNames_[projectionAlgo_]
727         << token::END_STATEMENT << nl
728         << "    attached " << attached_
729         << token::END_STATEMENT << nl
730         << "    active " << active()
731         << token::END_STATEMENT << nl;
733     if (attached_)
734     {
735         masterFaceCellsPtr_->writeEntry("masterFaceCells", os);
736         slaveFaceCellsPtr_->writeEntry("slaveFaceCells", os);
737         masterStickOutFacesPtr_->writeEntry("masterStickOutFaces", os);
738         slaveStickOutFacesPtr_->writeEntry("slaveStickOutFaces", os);
740          os << "    retiredPointMap " << retiredPointMap()
741             << token::END_STATEMENT << nl
742             << "    cutPointEdgePairMap " << cutPointEdgePairMap()
743             << token::END_STATEMENT << nl;
744     }
746     os  << token::END_BLOCK << endl;
750 // ************************************************************************* //