FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

perfectInterface.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 Description
00025     Best thing is probably to look at attachDetach which does almost exactly
00026     the same but for the geometric matching of points and face centres.
00027 
00028 \*---------------------------------------------------------------------------*/
00029 
00030 #include "perfectInterface.H"
00031 #include <dynamicMesh/polyTopoChanger.H>
00032 #include <OpenFOAM/polyMesh.H>
00033 #include <dynamicMesh/polyTopoChange.H>
00034 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00035 #include <OpenFOAM/mapPolyMesh.H>
00036 #include <OpenFOAM/matchPoints.H>
00037 #include <dynamicMesh/polyModifyFace.H>
00038 #include <dynamicMesh/polyRemovePoint.H>
00039 #include <dynamicMesh/polyRemoveFace.H>
00040 
00041 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00042 
00043 namespace Foam
00044 {
00045     defineTypeNameAndDebug(perfectInterface, 0);
00046     addToRunTimeSelectionTable
00047     (
00048         polyMeshModifier,
00049         perfectInterface,
00050         dictionary
00051     );
00052 }
00053 
00054 
00055 // Tolerance used as fraction of minimum edge length.
00056 const Foam::scalar Foam::perfectInterface::tol_ = 1E-3;
00057 
00058 
00059 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00060 
00061 Foam::pointField Foam::perfectInterface::calcFaceCentres
00062 (
00063     const primitivePatch& pp
00064 )
00065 {
00066     const pointField& points = pp.points();
00067 
00068     pointField ctrs(pp.size());
00069 
00070     forAll(ctrs, patchFaceI)
00071     {
00072         ctrs[patchFaceI] = pp[patchFaceI].centre(points);
00073     }
00074 
00075     return ctrs;
00076 }
00077 
00078 
00079 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00080 
00081 // Construct from components
00082 Foam::perfectInterface::perfectInterface
00083 (
00084     const word& name,
00085     const label index,
00086     const polyTopoChanger& mme,
00087     const word& faceZoneName,
00088     const word& masterPatchName,
00089     const word& slavePatchName
00090 )
00091 :
00092     polyMeshModifier(name, index, mme, true),
00093     faceZoneID_(faceZoneName, mme.mesh().faceZones()),
00094     masterPatchID_(masterPatchName, mme.mesh().boundaryMesh()),
00095     slavePatchID_(slavePatchName, mme.mesh().boundaryMesh())
00096 {}
00097 
00098 
00099 // Construct from dictionary
00100 Foam::perfectInterface::perfectInterface
00101 (
00102     const word& name,
00103     const dictionary& dict,
00104     const label index,
00105     const polyTopoChanger& mme
00106 )
00107 :
00108     polyMeshModifier(name, index, mme, readBool(dict.lookup("active"))),
00109     faceZoneID_
00110     (
00111         dict.lookup("faceZoneName"),
00112         mme.mesh().faceZones()
00113     ),
00114     masterPatchID_
00115     (
00116         dict.lookup("masterPatchName"),
00117         mme.mesh().boundaryMesh()
00118     ),
00119     slavePatchID_
00120     (
00121         dict.lookup("slavePatchName"),
00122         mme.mesh().boundaryMesh()
00123     )
00124 {}
00125 
00126 
00127 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00128 
00129 Foam::perfectInterface::~perfectInterface()
00130 {}
00131 
00132 
00133 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00134 
00135 bool Foam::perfectInterface::changeTopology() const
00136 {
00137     // If modifier is inactive, skip change
00138     if (!active())
00139     {
00140         if (debug)
00141         {
00142             Pout<< "bool perfectInterface::changeTopology() const "
00143                 << "for object " << name() << " : "
00144                 << "Inactive" << endl;
00145         }
00146 
00147         return false;
00148     }
00149     else
00150     {
00151         // I want topo change every time step.
00152         return true;
00153     }
00154 }
00155 
00156 
00157 void Foam::perfectInterface::setRefinement(polyTopoChange& ref) const
00158 {
00159     if (debug)
00160     {
00161         Pout<< "bool perfectInterface::setRefinement(polyTopoChange&) const : "
00162             << "for object " << name() << " : "
00163             << "masterPatchID_:" << masterPatchID_
00164             << " slavePatchID_:" << slavePatchID_
00165             << " faceZoneID_:" << faceZoneID_ << endl;
00166     }
00167 
00168     if
00169     (
00170         masterPatchID_.active()
00171      && slavePatchID_.active()
00172      && faceZoneID_.active()
00173     )
00174     {
00175         const polyMesh& mesh = topoChanger().mesh();
00176 
00177         const polyBoundaryMesh& patches = mesh.boundaryMesh();
00178 
00179         const polyPatch& pp0 = patches[masterPatchID_.index()];
00180         const polyPatch& pp1 = patches[slavePatchID_.index()];
00181 
00182         // Some aliases
00183         const edgeList& edges0 = pp0.edges();
00184         const pointField& pts0 = pp0.localPoints();
00185         const pointField& pts1 = pp1.localPoints();    
00186         const labelList& meshPts0 = pp0.meshPoints();
00187         const labelList& meshPts1 = pp1.meshPoints();
00188                         
00189 
00190         // Get local dimension as fraction of minimum edge length
00191 
00192         scalar minLen = GREAT;
00193 
00194         forAll(edges0, edgeI)
00195         {
00196             minLen = min(minLen, edges0[edgeI].mag(pts0));
00197         }
00198         scalar typDim = tol_*minLen;
00199 
00200         if (debug)
00201         {
00202             Pout<< "typDim:" << typDim << " edges0:" << edges0.size()
00203                 << " pts0:" << pts0.size() << " pts1:" << pts1.size()
00204                 << " pp0:" << pp0.size() << " pp1:" << pp1.size() << endl;
00205         }
00206 
00207 
00208         // Determine pointMapping in mesh point labels. Uses geometric
00209         // comparison to find correspondence between patch points.
00210 
00211         labelList renumberPoints(mesh.points().size());
00212         forAll(renumberPoints, i)
00213         {
00214             renumberPoints[i] = i;
00215         }
00216         {
00217             labelList from1To0Points(pts1.size());
00218 
00219             bool matchOk = matchPoints
00220             (
00221                 pts1,
00222                 pts0,
00223                 scalarField(pts1.size(), typDim),   // tolerance
00224                 true,                               // verbose
00225                 from1To0Points
00226             );
00227 
00228             if (!matchOk)
00229             {
00230                 FatalErrorIn
00231                 (
00232                     "perfectInterface::setRefinement(polyTopoChange& ref) const"
00233                 )   << "Points on patches " << pp0.name() << " and "
00234                     << pp1.name() << " do not match to within tolerance "
00235                     << typDim << exit(FatalError);
00236             }
00237 
00238             forAll(pts1, i)
00239             {
00240                 renumberPoints[meshPts1[i]] = meshPts0[from1To0Points[i]];
00241             }
00242         }
00243 
00244 
00245 
00246         // Calculate correspondence between patch faces
00247 
00248         labelList from0To1Faces(pp1.size());
00249 
00250         bool matchOk = matchPoints
00251         (
00252             calcFaceCentres(pp0),
00253             calcFaceCentres(pp1),
00254             scalarField(pp0.size(), typDim),    // tolerance
00255             true,                               // verbose
00256             from0To1Faces
00257         );
00258 
00259         if (!matchOk)
00260         {
00261             FatalErrorIn
00262             (
00263                 "perfectInterface::setRefinement(polyTopoChange& ref) const"
00264             )   << "Face centres of patches " << pp0.name() << " and "
00265                 << pp1.name() << " do not match to within tolerance " << typDim
00266                 << exit(FatalError);
00267         }
00268 
00269 
00270 
00271         // Now
00272         // - renumber faces using pts1 (except patch1 faces)
00273         // - remove patch1 faces. Remember cell label on owner side.
00274         // - modify patch0 faces to be internal.
00275 
00276         // 1. Get faces to be renumbered
00277         labelHashSet affectedFaces(2*pp1.size());
00278         forAll(meshPts1, i)
00279         {
00280             label meshPointI = meshPts1[i];
00281 
00282             if (meshPointI != renumberPoints[meshPointI])
00283             {
00284                 const labelList& pFaces = mesh.pointFaces()[meshPointI];
00285 
00286                 forAll(pFaces, pFaceI)
00287                 {
00288                     affectedFaces.insert(pFaces[pFaceI]);
00289                 }
00290             }
00291         }
00292         forAll(pp1, i)
00293         {
00294             affectedFaces.erase(pp1.start() + i);
00295         }
00296         // Remove patch0 from renumbered faces. Should not be nessecary since
00297         // patch0 and 1 should not share any point (if created by mergeMeshing)
00298         // so affectedFaces should not contain any patch0 faces but you can
00299         // never be sure what the user is doing.
00300         forAll(pp0, i)
00301         {
00302             if (affectedFaces.erase(pp0.start() + i))
00303             {
00304                 WarningIn
00305                 (
00306                     "perfectInterface::setRefinement(polyTopoChange&) const"
00307                 )   << "Found face " << pp0.start() + i << " vertices "
00308                     << mesh.faces()[pp0.start() + i] << " whose points are"
00309                     << " used both by master patch " << pp0.name()
00310                     << " and slave patch " << pp1.name()
00311                     << endl;
00312             }
00313         }
00314 
00315 
00316         // 2. Renumber (non patch0/1) faces.
00317         for
00318         (
00319             labelHashSet::const_iterator iter = affectedFaces.begin();
00320             iter != affectedFaces.end();
00321             ++iter
00322         )
00323         {
00324             label faceI = iter.key();
00325 
00326             const face& f = mesh.faces()[faceI];
00327 
00328             face newFace(f.size());
00329 
00330             forAll(newFace, fp)
00331             {
00332                 newFace[fp] = renumberPoints[f[fp]];
00333             }
00334 
00335             label nbr = -1;
00336 
00337             label patchI = -1;
00338 
00339             if (mesh.isInternalFace(faceI))
00340             {
00341                 nbr = mesh.faceNeighbour()[faceI];
00342             }
00343             else
00344             {
00345                 patchI = patches.whichPatch(faceI);
00346             }
00347 
00348             label zoneID = mesh.faceZones().whichZone(faceI);
00349 
00350             bool zoneFlip = false;
00351 
00352             if (zoneID >= 0)
00353             {
00354                 const faceZone& fZone = mesh.faceZones()[zoneID];
00355 
00356                 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
00357             }
00358 
00359             ref.setAction
00360             (
00361                 polyModifyFace
00362                 (
00363                     newFace,                    // modified face
00364                     faceI,                      // label of face being modified
00365                     mesh.faceOwner()[faceI],    // owner
00366                     nbr,                        // neighbour
00367                     false,                      // face flip
00368                     patchI,                     // patch for face
00369                     false,                      // remove from zone
00370                     zoneID,                     // zone for face
00371                     zoneFlip                    // face flip in zone
00372                 )
00373             );
00374         }
00375 
00376 
00377         // 3. Remove patch1 points
00378         forAll(meshPts1, i)
00379         {
00380             label meshPointI = meshPts1[i];
00381 
00382             if (meshPointI != renumberPoints[meshPointI])
00383             {
00384                 ref.setAction(polyRemovePoint(meshPointI));
00385             }
00386         }
00387 
00388 
00389         // 4. Remove patch1 faces
00390         forAll(pp1, i)
00391         {
00392             ref.setAction(polyRemoveFace(pp1.start() + i));
00393         }
00394 
00395 
00396         // 5. Modify patch0 faces for new points (not really nessecary; see
00397         // comment above about patch1 and patch0 never sharing points) and
00398         // becoming internal.
00399         const boolList& mfFlip =
00400             mesh.faceZones()[faceZoneID_.index()].flipMap();
00401 
00402         forAll(pp0, i)
00403         {
00404             label faceI = pp0.start() + i;
00405 
00406             const face& f = mesh.faces()[faceI];
00407 
00408             face newFace(f.size());
00409 
00410             forAll(newFace, fp)
00411             {
00412                 newFace[fp] = renumberPoints[f[fp]];
00413             }
00414 
00415             label own = mesh.faceOwner()[faceI];
00416 
00417             label pp1FaceI = pp1.start() + from0To1Faces[i];
00418 
00419             label nbr = mesh.faceOwner()[pp1FaceI];
00420 
00421             if (own < nbr)
00422             {
00423                 ref.setAction
00424                 (
00425                     polyModifyFace
00426                     (
00427                         newFace,                // modified face
00428                         faceI,                  // label of face being modified
00429                         own,                    // owner
00430                         nbr,                    // neighbour
00431                         false,                  // face flip
00432                         -1,                     // patch for face
00433                         false,                  // remove from zone
00434                         faceZoneID_.index(),    // zone for face
00435                         mfFlip[i]               // face flip in zone
00436                     )
00437                 );
00438             }
00439             else
00440             {
00441                 ref.setAction
00442                 (
00443                     polyModifyFace
00444                     (
00445                         newFace.reverseFace(),  // modified face
00446                         faceI,                  // label of face being modified
00447                         nbr,                    // owner
00448                         own,                    // neighbour
00449                         false,                  // face flip
00450                         -1,                     // patch for face
00451                         false,                  // remove from zone
00452                         faceZoneID_.index(),    // zone for face
00453                         !mfFlip[i]              // face flip in zone
00454                     )
00455                 );
00456             }
00457         }
00458     }
00459 }
00460 
00461 
00462 void Foam::perfectInterface::modifyMotionPoints(pointField& motionPoints) const
00463 {
00464     // Update only my points. Nothing to be done here as points already
00465     // shared by now.
00466 }
00467 
00468 
00469 void Foam::perfectInterface::updateMesh(const mapPolyMesh& morphMap)
00470 {
00471     // Mesh has changed topologically.  Update local topological data
00472     const polyMesh& mesh = topoChanger().mesh();
00473 
00474     faceZoneID_.update(mesh.faceZones());
00475     masterPatchID_.update(mesh.boundaryMesh());
00476     slavePatchID_.update(mesh.boundaryMesh());
00477 }
00478 
00479 
00480 void Foam::perfectInterface::write(Ostream& os) const
00481 {
00482     os  << nl << type() << nl
00483         << name()<< nl
00484         << faceZoneID_.name() << nl
00485         << masterPatchID_.name() << nl
00486         << slavePatchID_.name() << endl;
00487 }
00488 
00489 
00490 void Foam::perfectInterface::writeDict(Ostream& os) const
00491 {
00492     os  << nl << name() << nl << token::BEGIN_BLOCK << nl
00493 
00494         << "    type " << type()
00495         << token::END_STATEMENT << nl
00496 
00497         << "    active " << active()
00498         << token::END_STATEMENT << nl
00499 
00500         << "    faceZoneName " << faceZoneID_.name()
00501         << token::END_STATEMENT << nl
00502 
00503         << "    masterPatchName " << masterPatchID_.name()
00504         << token::END_STATEMENT << nl
00505 
00506         << "    slavePatchName " << slavePatchID_.name()
00507         << token::END_STATEMENT << nl
00508 
00509         << token::END_BLOCK << endl;
00510 }
00511 
00512 
00513 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
00514 
00515 
00516 // * * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * //
00517 
00518 
00519 // * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
00520 
00521 
00522 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines