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

slidingInterfaceProjectPoints.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 \*---------------------------------------------------------------------------*/
00025 
00026 #include "slidingInterface.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include <OpenFOAM/line.H>
00029 #include <dynamicMesh/polyTopoChanger.H>
00030 
00031 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00032 
00033 const Foam::scalar Foam::slidingInterface::pointMergeTolDefault_ = 0.05;
00034 const Foam::scalar Foam::slidingInterface::edgeMergeTolDefault_ = 0.01;
00035 const Foam::label Foam::slidingInterface::nFacesPerSlaveEdgeDefault_ = 5;
00036 const Foam::label Foam::slidingInterface::edgeFaceEscapeLimitDefault_ = 10;
00037 
00038 const Foam::scalar Foam::slidingInterface::integralAdjTolDefault_ = 0.05;
00039 const Foam::scalar Foam::slidingInterface::edgeMasterCatchFractionDefault_ = 0.4;
00040 const Foam::scalar Foam::slidingInterface::edgeEndCutoffTolDefault_ = 0.0001;
00041 
00042 
00043 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00044 
00045 // Index of debug signs:
00046 // a - integral match adjustment: point adjusted
00047 // n - integral match adjustment: point not adjusted
00048 // . - loop of the edge-to-face interaction detection
00049 // x - reversal of direction in edge-to-face interaction detection
00050 // + - complete edge-to-face interaction detection
00051 // z - incomplete edge-to-face interaction detection.  This may be OK for edges
00052 //     crossing from one to the other side of multiply connected master patch
00053 // * - colinear triangle: adjusting projection with slave face normal
00054 // m - master point inserted into the edge
00055 
00056 bool Foam::slidingInterface::projectPoints() const
00057 {
00058     if (debug)
00059     {
00060         Pout<< "bool slidingInterface::projectPoints() : "
00061             << " for object " << name() << " : "
00062             << "Projecting slave points onto master surface." << endl;
00063     }
00064 
00065     // Algorithm:
00066     // 1) Go through all the points of the master and slave patch and calculate
00067     //    minimum edge length coming from the point.  Calculate the point
00068     //    merge tolerance as the fraction of mimimum edge length.
00069     // 2) Project all the slave points onto the master patch
00070     //    in the normal direction.
00071     // 3) If some points have missed and the match is integral, the
00072     //    points in question will be adjusted.  Find the nearest face for
00073     //    those points and continue with the procedure.
00074     // 4) For every point, check all the points of the face it has hit.
00075     //    For every pair of points find if their distance is smaller than
00076     //    both the master and slave merge tolerance.  If so, the slave point
00077     //    is moved to the location of the master point.  Remember the master
00078     //    point index.
00079     // 5) For every unmerged slave point, check its distance to all the
00080     //    edges of the face it has hit.  If the distance is smaller than the
00081     //    edge merge tolerance, the point will be moved onto the edge.
00082     //    Remember the master edge index.
00083     // 6) The remaning slave points will be projected into faces.  Remember the
00084     //    master face index.
00085     // 7) For the points that miss the master patch, grab the nearest face
00086     //    on the master and leave the slave point where it started
00087     //    from and the miss is recorded.
00088 
00089     const polyMesh& mesh = topoChanger().mesh();
00090 
00091     const primitiveFacePatch& masterPatch =
00092         mesh.faceZones()[masterFaceZoneID_.index()]();
00093 
00094     const primitiveFacePatch& slavePatch =
00095         mesh.faceZones()[slaveFaceZoneID_.index()]();
00096 
00097     // Get references to local points, local edges and local faces
00098     // for master and slave patch
00099 //     const labelList& masterMeshPoints = masterPatch.meshPoints();
00100     const pointField& masterLocalPoints = masterPatch.localPoints();
00101     const faceList& masterLocalFaces = masterPatch.localFaces();
00102     const edgeList& masterEdges = masterPatch.edges();
00103     const labelListList& masterEdgeFaces = masterPatch.edgeFaces();
00104     const labelListList& masterFaceEdges = masterPatch.faceEdges();
00105     const labelListList& masterFaceFaces = masterPatch.faceFaces();
00106 //     Pout<< "Master patch.  Local points: " << masterLocalPoints << nl
00107 //         << "Master patch.  Mesh points: " << masterPatch.meshPoints() << nl
00108 //         << "Local faces: " << masterLocalFaces << nl
00109 //         << "local edges: " << masterEdges << endl;
00110 
00111 //     const labelList& slaveMeshPoints = slavePatch.meshPoints();
00112     const pointField& slaveLocalPoints = slavePatch.localPoints();
00113     const edgeList& slaveEdges = slavePatch.edges();
00114     const labelListList& slaveEdgeFaces = slavePatch.edgeFaces();
00115     const vectorField& slavePointNormals = slavePatch.pointNormals();
00116 //     const vectorField& slaveFaceNormals = slavePatch.faceNormals();
00117 //     Pout<< "Slave patch.  Local points: " << slaveLocalPoints << nl
00118 //         << "Slave patch.  Mesh points: " << slavePatch.meshPoints() << nl
00119 //         << "Local faces: " << slavePatch.localFaces() << nl
00120 //         << "local edges: " << slaveEdges << endl;
00121 
00122     // Calculate min edge distance for points and faces
00123 
00124     // Calculate min edge length for the points and faces of master patch
00125     scalarField minMasterPointLength(masterLocalPoints.size(), GREAT);
00126     scalarField minMasterFaceLength(masterPatch.size(), GREAT);
00127 
00128     forAll (masterEdges, edgeI)
00129     {
00130         const edge& curEdge = masterEdges[edgeI];
00131 
00132         const scalar curLength =
00133             masterEdges[edgeI].mag(masterLocalPoints);
00134 
00135         // Do points
00136         minMasterPointLength[curEdge.start()] =
00137             min
00138             (
00139                 minMasterPointLength[curEdge.start()],
00140                 curLength
00141             );
00142 
00143         minMasterPointLength[curEdge.end()] =
00144             min
00145             (
00146                 minMasterPointLength[curEdge.end()],
00147                 curLength
00148             );
00149 
00150         // Do faces
00151         const labelList& curFaces = masterEdgeFaces[edgeI];
00152 
00153         forAll (curFaces, faceI)
00154         {
00155             minMasterFaceLength[curFaces[faceI]] =
00156                 min
00157                 (
00158                     minMasterFaceLength[curFaces[faceI]],
00159                     curLength
00160                 );
00161         }
00162     }
00163 
00164 //     Pout << "min length for master points: " << minMasterPointLength << endl
00165 //         << "min length for master faces: " << minMasterFaceLength << endl;
00166 
00167     // Calculate min edge length for the points and faces of slave patch
00168     scalarField minSlavePointLength(slaveLocalPoints.size(), GREAT);
00169     scalarField minSlaveFaceLength(slavePatch.size(), GREAT);
00170 
00171     forAll (slaveEdges, edgeI)
00172     {
00173         const edge& curEdge = slaveEdges[edgeI];
00174 
00175         const scalar curLength =
00176             slaveEdges[edgeI].mag(slaveLocalPoints);
00177 
00178         // Do points
00179         minSlavePointLength[curEdge.start()] = 
00180             min
00181             (
00182                 minSlavePointLength[curEdge.start()],
00183                 curLength
00184             );
00185 
00186         minSlavePointLength[curEdge.end()] = 
00187             min
00188             (
00189                 minSlavePointLength[curEdge.end()],
00190                 curLength
00191             );
00192 
00193         // Do faces
00194         const labelList& curFaces = slaveEdgeFaces[edgeI];
00195 
00196         forAll (curFaces, faceI)
00197         {
00198             minSlaveFaceLength[curFaces[faceI]] =
00199                 min
00200                 (
00201                     minSlaveFaceLength[curFaces[faceI]],
00202                     curLength
00203                 );
00204         }
00205     }
00206 
00207 //     Pout << "min length for slave points: " << minSlavePointLength << endl
00208 //         << "min length for slave faces: " << minSlaveFaceLength << endl;
00209 
00210     // Project slave points onto the master patch
00211 
00212     // Face hit by the slave point
00213     List<objectHit> slavePointFaceHits =
00214         slavePatch.projectPoints
00215         (
00216             masterPatch,
00217             slavePointNormals,
00218             projectionAlgo_
00219         );
00220 
00221 //     Pout << "USING N-SQAURED!!!" << endl;
00222 //     List<objectHit> slavePointFaceHits =
00223 //         projectPointsNSquared<face, List, const pointField&>
00224 //         (
00225 //             slavePatch,
00226 //             masterPatch,
00227 //             slavePointNormals,
00228 //             projectionAlgo_
00229 //         );
00230 
00231     if (debug)
00232     {
00233         label nHits = 0;
00234 
00235         forAll (slavePointFaceHits, pointI)
00236         {
00237             if (slavePointFaceHits[pointI].hit())
00238             {
00239                 nHits++;
00240             }
00241         }
00242 
00243         Pout<< "Number of hits in point projection: " << nHits
00244             << " out of " << slavePointFaceHits.size() << " points."
00245             << endl;
00246     }
00247 
00248     // Projected slave points are stored for mesh motion correction
00249     if (projectedSlavePointsPtr_) delete projectedSlavePointsPtr_;
00250 
00251     projectedSlavePointsPtr_ =
00252         new pointField(slavePointFaceHits.size(), vector::zero);
00253     pointField& projectedSlavePoints = *projectedSlavePointsPtr_;
00254 
00255     // Adjust projection to type of match
00256 
00257     label nAdjustedPoints = 0;
00258 
00259     // If the match is integral and some points have missed,
00260     // find nearest master face
00261     if (matchType_ == INTEGRAL)
00262     {
00263         if (debug)
00264         {
00265             Pout<< "bool slidingInterface::projectPoints() for object "
00266                 << name() << " : "
00267                 << "Adjusting point projection for integral match: ";
00268         }
00269 
00270         forAll (slavePointFaceHits, pointI)
00271         {
00272             if (slavePointFaceHits[pointI].hit())
00273             {
00274                 // Grab the hit point
00275                 projectedSlavePoints[pointI] =
00276                     masterLocalFaces
00277                         [slavePointFaceHits[pointI].hitObject()].ray
00278                         (
00279                             slaveLocalPoints[pointI],
00280                             slavePointNormals[pointI],
00281                             masterLocalPoints,
00282                             projectionAlgo_
00283                         ).hitPoint();
00284             }
00285             else
00286             {
00287                 // Grab the nearest point on the face (edge)
00288                 pointHit missAdjust =
00289                     masterLocalFaces[slavePointFaceHits[pointI].hitObject()].ray
00290                     (
00291                         slaveLocalPoints[pointI],
00292                         slavePointNormals[pointI],
00293                         masterLocalPoints,
00294                         projectionAlgo_
00295                     );
00296 
00297                 const point nearPoint = missAdjust.missPoint();
00298                 const point missPoint =
00299                     slaveLocalPoints[pointI]
00300                   + slavePointNormals[pointI]*missAdjust.distance();
00301 
00302                 // Calculate the tolerance
00303                 const scalar mergeTol =
00304                     integralAdjTol_*minSlavePointLength[pointI];
00305 
00306                 // Adjust the hit
00307                 if (mag(nearPoint - missPoint) < mergeTol)
00308                 {
00309                     if (debug)
00310                     {
00311                         Pout << "a";
00312                     }
00313 
00314 //                     Pout<< "Moving slave point in integral adjustment "
00315 //                         << pointI << " miss point: " << missPoint
00316 //                         << " near point: " << nearPoint
00317 //                         << " mergeTol: " << mergeTol
00318 //                         << " dist: " << mag(nearPoint - missPoint) << endl;
00319 
00320                     projectedSlavePoints[pointI] = nearPoint;
00321 
00322                     slavePointFaceHits[pointI] =
00323                         objectHit(true, slavePointFaceHits[pointI].hitObject());
00324 
00325                     nAdjustedPoints++;
00326                 }
00327                 else
00328                 {
00329                     projectedSlavePoints[pointI] = slaveLocalPoints[pointI];
00330 
00331                     if (debug)
00332                     {
00333                         Pout << "n";
00334                     }
00335                 }
00336             }
00337         }
00338 
00339         if (debug)
00340         {
00341             Pout << " done." << endl;
00342         }
00343     }
00344     else if (matchType_ == PARTIAL)
00345     {
00346         forAll (slavePointFaceHits, pointI)
00347         {
00348             if (slavePointFaceHits[pointI].hit())
00349             {
00350                 // Grab the hit point
00351                 projectedSlavePoints[pointI] =
00352                     masterLocalFaces
00353                         [slavePointFaceHits[pointI].hitObject()].ray
00354                         (
00355                             slaveLocalPoints[pointI],
00356                             slavePointNormals[pointI],
00357                             masterLocalPoints,
00358                             projectionAlgo_
00359                         ).hitPoint();
00360             }
00361             else
00362             {
00363                 // The point remains where it started from
00364                 projectedSlavePoints[pointI] = slaveLocalPoints[pointI];
00365             }
00366         }
00367     }
00368     else
00369     {
00370         FatalErrorIn
00371         (
00372             "bool slidingInterface::projectPoints() const"
00373         )   << "Problem in point projection.  Unknown sliding match type "
00374             << " for object " << name()
00375             << abort(FatalError);
00376     }
00377 
00378     if (debug)
00379     {
00380         Pout<< "Number of adjusted points in projection: "
00381             << nAdjustedPoints << endl;
00382 
00383         // Check for zero-length edges in slave projection
00384         scalar minEdgeLength = GREAT;
00385         scalar el = 0;
00386         label nShortEdges = 0;
00387 
00388         forAll (slaveEdges, edgeI)
00389         {
00390             el = slaveEdges[edgeI].mag(projectedSlavePoints);
00391 
00392             if (el < SMALL)
00393             {
00394                 Pout<< "Point projection problems for edge: "
00395                     << slaveEdges[edgeI] << ". Length = " << el
00396                     << endl;
00397 
00398                 nShortEdges++;
00399             }
00400 
00401             minEdgeLength = min(minEdgeLength, el);
00402         }
00403 
00404         if (nShortEdges > 0)
00405         {
00406             FatalErrorIn
00407             (
00408                 "bool slidingInterface::projectPoints() const"
00409             )   << "Problem in point projection.  " << nShortEdges
00410                 << " short projected edges "
00411                 << "after adjustment for object " << name()
00412                 << abort(FatalError);
00413         }
00414         else
00415         {
00416             Pout << " ... projection OK." << endl;
00417         }
00418     }
00419 //     scalarField magDiffs(mag(slaveLocalPoints - projectedSlavePoints));
00420 //     Pout<< "Slave point face hits: " << slavePointFaceHits << nl
00421 //         << "slave points: " << slaveLocalPoints << nl
00422 //         << "Projected slave points: " << projectedSlavePoints 
00423 //         << "diffs: " << magDiffs << endl;
00424 
00425     // Merge projected points against master points
00426 
00427     labelList slavePointPointHits(slaveLocalPoints.size(), -1);
00428     labelList masterPointPointHits(masterLocalPoints.size(), -1);
00429 
00430     // Go through all the slave points and compare them against all the points
00431     // in the master face they hit.  If the distance between the projected point
00432     // and any of the master face points is smaller than both tolerances,
00433     // merge the projected point by:
00434     // 1) adjusting the projected point to coincide with the
00435     //    master point it merges with
00436     // 2) remembering the hit master point index in slavePointPointHits
00437     // 3) resetting the hit face to -1
00438     // 4) If a master point has been hit directly, it cannot be merged
00439     // into the edge. Mark it as used in the reverse list
00440 
00441     label nMergedPoints = 0;
00442 
00443     forAll (projectedSlavePoints, pointI)
00444     {
00445         if (slavePointFaceHits[pointI].hit())
00446         {
00447             // Taking a non-const reference so the point can be adjusted
00448             point& curPoint = projectedSlavePoints[pointI];
00449 
00450             // Get the hit face
00451             const face& hitFace =
00452                 masterLocalFaces[slavePointFaceHits[pointI].hitObject()];
00453 
00454             label mergePoint = -1;
00455             scalar mergeDist = GREAT;
00456 
00457             // Try all point before deciding on best fit.  
00458             forAll (hitFace, hitPointI)
00459             {
00460                 scalar dist =
00461                     mag(masterLocalPoints[hitFace[hitPointI]] - curPoint);
00462 
00463                 // Calculate the tolerance
00464                 const scalar mergeTol =
00465                     pointMergeTol_*
00466                     min
00467                     (
00468                         minSlavePointLength[pointI],
00469                         minMasterPointLength[hitFace[hitPointI]]
00470                     );
00471 
00472                 if (dist < mergeTol && dist < mergeDist)
00473                 {
00474                     mergePoint = hitFace[hitPointI];
00475                     mergeDist = dist;
00476 
00477 //                     Pout<< "Merging slave point "
00478 //                         << slavePatch.meshPoints()[pointI] << " at "
00479 //                         << slaveLocalPoints[pointI] << " with master "
00480 //                         << masterPatch.meshPoints()[mergePoint] << " at "
00481 //                         << masterLocalPoints[mergePoint]
00482 //                         << ". dist: " << mergeDist
00483 //                         << " mergeTol: " << mergeTol << endl;
00484                 }
00485             }
00486 
00487             if (mergePoint > -1)
00488             {
00489                 // Point is to be merged with master point
00490                 nMergedPoints++;
00491 
00492                 slavePointPointHits[pointI] = mergePoint;
00493                 curPoint = masterLocalPoints[mergePoint];
00494                 masterPointPointHits[mergePoint] = pointI;
00495             }
00496         }
00497     }
00498 
00499 //     Pout<< "slavePointPointHits: " << slavePointPointHits << nl
00500 //         << "masterPointPointHits: " << masterPointPointHits << endl;
00501 
00502     if (debug)
00503     {
00504         // Check for zero-length edges in slave projection
00505         scalar minEdgeLength = GREAT;
00506         scalar el = 0;
00507 
00508         forAll (slaveEdges, edgeI)
00509         {
00510             el = slaveEdges[edgeI].mag(projectedSlavePoints);
00511 
00512             if (el < SMALL)
00513             {
00514                 Pout<< "Point projection problems for edge: "
00515                     << slaveEdges[edgeI] << ". Length = " << el
00516                     << endl;
00517             }
00518 
00519             minEdgeLength = min(minEdgeLength, el);
00520         }
00521 
00522         if (minEdgeLength < SMALL)
00523         {
00524             FatalErrorIn
00525             (
00526                 "bool slidingInterface::projectPoints() const"
00527             )   << "Problem in point projection.  Short projected edge "
00528                 << " after point merge for object " << name()
00529                 << abort(FatalError);
00530         }
00531         else
00532         {
00533             Pout << " ... point merge OK." << endl;
00534         }
00535     }
00536 
00537     // Merge projected points against master edges
00538 
00539     labelList slavePointEdgeHits(slaveLocalPoints.size(), -1);
00540 
00541     label nMovedPoints = 0;
00542 
00543     forAll (projectedSlavePoints, pointI)
00544     {
00545         // Eliminate the points merged into points
00546         if (slavePointPointHits[pointI] < 0)
00547         {
00548             // Get current point position
00549             point& curPoint = projectedSlavePoints[pointI];
00550 
00551             // Get the hit face
00552             const labelList& hitFaceEdges =
00553                 masterFaceEdges[slavePointFaceHits[pointI].hitObject()];
00554 
00555             // Calculate the tolerance
00556             const scalar mergeLength = 
00557                 min
00558                 (
00559                     minSlavePointLength[pointI],
00560                     minMasterFaceLength[slavePointFaceHits[pointI].hitObject()]
00561                 );
00562 
00563             const scalar mergeTol = pointMergeTol_*mergeLength;
00564 
00565             scalar minDistance = GREAT;
00566 
00567             forAll (hitFaceEdges, edgeI)
00568             {
00569                 const edge& curEdge = masterEdges[hitFaceEdges[edgeI]];
00570 
00571                 pointHit edgeHit =
00572                     curEdge.line(masterLocalPoints).nearestDist(curPoint);
00573 
00574                 if (edgeHit.hit())
00575                 {
00576                     scalar dist =
00577                         mag(edgeHit.hitPoint() - projectedSlavePoints[pointI]);
00578 
00579                     if (dist < mergeTol && dist < minDistance)
00580                     {
00581                         // Point is to be moved onto master edge
00582                         nMovedPoints++;
00583 
00584                         slavePointEdgeHits[pointI] = hitFaceEdges[edgeI];
00585                         projectedSlavePoints[pointI] = edgeHit.hitPoint();
00586 
00587                         minDistance = dist;
00588 
00589 //                         Pout<< "Moving slave point "
00590 //                             << slavePatch.meshPoints()[pointI]
00591 //                             << " (" << pointI 
00592 //                             << ") at " << slaveLocalPoints[pointI]
00593 //                             << " onto master edge " << hitFaceEdges[edgeI]
00594 //                             << " or ("
00595 //                             << masterLocalPoints[curEdge.start()]
00596 //                             << masterLocalPoints[curEdge.end()]
00597 //                             << ") hit: " << edgeHit.hitPoint()
00598 //                             << ". dist: " << dist
00599 //                             << " mergeTol: " << mergeTol << endl;
00600                     }
00601                 }
00602             } // end of hit face edges
00603 
00604             if (slavePointEdgeHits[pointI] > -1)
00605             {
00606                 // Projected slave point has moved.  Re-attempt merge with
00607                 // master points of the edge
00608                 point& curPoint = projectedSlavePoints[pointI];
00609 
00610                 const edge& hitMasterEdge =
00611                     masterEdges[slavePointEdgeHits[pointI]];
00612 
00613                 label mergePoint = -1;
00614                 scalar mergeDist = GREAT;
00615 
00616                 forAll (hitMasterEdge, hmeI)
00617                 {
00618                     scalar hmeDist =
00619                         mag(masterLocalPoints[hitMasterEdge[hmeI]] - curPoint);
00620 
00621                     // Calculate the tolerance
00622                     const scalar mergeTol =
00623                         pointMergeTol_*
00624                         min
00625                         (
00626                             minSlavePointLength[pointI],
00627                             minMasterPointLength[hitMasterEdge[hmeI]]
00628                     );
00629 
00630                     if (hmeDist < mergeTol && hmeDist < mergeDist)
00631                     {
00632                         mergePoint = hitMasterEdge[hmeI];
00633                         mergeDist = hmeDist;
00634 
00635 //                     Pout<< "Merging slave point; SECOND TRY "
00636 //                         << slavePatch.meshPoints()[pointI] << " local "
00637 //                         << pointI << " at "
00638 //                         << slaveLocalPoints[pointI] << " with master "
00639 //                         << masterPatch.meshPoints()[mergePoint] << " at "
00640 //                         << masterLocalPoints[mergePoint]
00641 //                         << ". hmeDist: " << mergeDist
00642 //                         << " mergeTol: " << mergeTol << endl;
00643                     }
00644                 }
00645 
00646                 if (mergePoint > -1)
00647                 {
00648                     // Point is to be merged with master point
00649                     slavePointPointHits[pointI] = mergePoint;
00650                     curPoint = masterLocalPoints[mergePoint];
00651                     masterPointPointHits[mergePoint] = pointI;
00652 
00653                     slavePointFaceHits[pointI] =
00654                         objectHit(true, slavePointFaceHits[pointI].hitObject());
00655 
00656 
00657                     // Disable edge merge
00658                     slavePointEdgeHits[pointI] = -1;
00659                 }
00660             }
00661         }
00662     }
00663 
00664     if (debug)
00665     {
00666         Pout<< "Number of merged master points: " << nMergedPoints << nl
00667             << "Number of adjusted slave points: " << nMovedPoints << endl;
00668 
00669         // Check for zero-length edges in slave projection
00670         scalar minEdgeLength = GREAT;
00671         scalar el = 0;
00672 
00673         forAll (slaveEdges, edgeI)
00674         {
00675             el = slaveEdges[edgeI].mag(projectedSlavePoints);
00676 
00677             if (el < SMALL)
00678             {
00679                 Pout<< "Point projection problems for edge: "
00680                     << slaveEdges[edgeI] << ". Length = " << el
00681                     << endl;
00682             }
00683 
00684             minEdgeLength = min(minEdgeLength, el);
00685         }
00686 
00687         if (minEdgeLength < SMALL)
00688         {
00689             FatalErrorIn
00690             (
00691                 "bool slidingInterface::projectPoints() const"
00692             )   << "Problem in point projection.  Short projected edge "
00693             << " after correction for object " << name()
00694             << abort(FatalError);
00695         }
00696     }
00697 
00698 //     Pout << "slavePointEdgeHits: " << slavePointEdgeHits << endl;
00699 
00700     // Insert the master points into closest slave edge if appropriate
00701 
00702     // Algorithm:
00703     //    The face potentially interacts with all the points of the
00704     //    faces covering the path between its two ends.  Since we are
00705     //    examining an arbitrary shadow of the edge on a non-Euclidian
00706     //    surface, it is typically quite hard to do a geometric point
00707     //    search (under a shadow of a straight line).  Therefore, the
00708     //    search will be done topologically.
00709     //
00710     // I) Point collection
00711     // -------------------
00712     // 1) Grab the master faces to which the end points of the edge
00713     //    have been projected.
00714     // 2) Starting from the face containing the edge start, grab all
00715     //    its points and put them into the point lookup map.  Put the
00716     //    face onto the face lookup map.
00717     // 3) If the face of the end point is on the face lookup, complete
00718     //    the point collection step (this is checked during insertion.
00719     // 4) Start a new round of insertion.  Visit all faces in the face
00720     //    lookup and add their neighbours which are not already on the
00721     //    map.  Every time the new neighbour is found, add its points to
00722     //    the point lookup.  If the face of the end point is inserted,
00723     //    continue with the current roundof insertion and stop the
00724     //    algorithm.
00725     //
00726     // II) Point check
00727     // ---------------
00728     //    Grab all the points from the point collection and check them
00729     //    against the current edge.  If the edge-to-point distance is
00730     //    smaller than the smallest tolerance in the game (min of
00731     //    master point tolerance and left and right slave face around
00732     //    the edge tolerance) and the nearest point hits the edge, the
00733     //    master point will break the slave edge.  Check the actual
00734     //    distance of the original master position from the edge.  If
00735     //    the distance is smaller than a fraction of slave edge
00736     //    length, the hit is considered valid.  Store the slave edge
00737     //    index for every master point.
00738 
00739     labelList masterPointEdgeHits(masterLocalPoints.size(), -1);
00740     scalarField masterPointEdgeDist(masterLocalPoints.size(), GREAT);
00741 
00742     // Note.  "Processing slave edges" code is repeated twice in the
00743     // sliding intergace coupling in order to allow the point
00744     // projection to be done separately from the actual cutting.
00745     // Please change consistently with coupleSlidingInterface.C
00746     // 
00747 
00748     if (debug)
00749     {
00750         Pout << "Processing slave edges " << endl;
00751     }
00752 
00753     // Create a map of faces the edge can interact with
00754     labelHashSet curFaceMap
00755     (
00756         nFacesPerSlaveEdge_*primitiveMesh::edgesPerFace_
00757     );
00758 
00759     labelHashSet addedFaces(2*primitiveMesh::edgesPerFace_);
00760 
00761     forAll (slaveEdges, edgeI)
00762     {
00763         const edge& curEdge = slaveEdges[edgeI];
00764 
00765         //HJ: check for all edges even if both ends have missed
00766         //    Experimental.
00767 //         if
00768 //         (
00769 //             slavePointFaceHits[curEdge.start()].hit()
00770 //          || slavePointFaceHits[curEdge.end()].hit()
00771 //         )
00772         {
00773             // Clear the maps
00774             curFaceMap.clear();
00775             addedFaces.clear();
00776 
00777             // Grab the faces for start and end points
00778             const label startFace =
00779                 slavePointFaceHits[curEdge.start()].hitObject();
00780             const label endFace = slavePointFaceHits[curEdge.end()].hitObject();
00781 
00782             // Insert the start face into the list
00783             curFaceMap.insert(startFace);
00784             addedFaces.insert(startFace);
00785 
00786 //             Pout << "Doing edge " << edgeI << " or " << curEdge << " start: " << slavePointFaceHits[curEdge.start()].hitObject() << " end " << slavePointFaceHits[curEdge.end()].hitObject() << endl;
00787             // If the end face is on the list, the face collection is finished
00788             label nSweeps = 0;
00789             bool completed = false;
00790 
00791             while (nSweeps < edgeFaceEscapeLimit_)
00792             {
00793                 nSweeps++;
00794 
00795                 if (addedFaces.found(endFace))
00796                 {
00797                     completed = true;
00798                 }
00799 
00800                 // Add all face neighbours of face in the map
00801                 const labelList cf = addedFaces.toc();
00802                 addedFaces.clear();
00803 
00804                 forAll (cf, cfI)
00805                 {
00806                     const labelList& curNbrs = masterFaceFaces[cf[cfI]];
00807 
00808                     forAll (curNbrs, nbrI)
00809                     {
00810                         if (!curFaceMap.found(curNbrs[nbrI]))
00811                         {
00812                             curFaceMap.insert(curNbrs[nbrI]);
00813                             addedFaces.insert(curNbrs[nbrI]);
00814                         }
00815                     }
00816                 }
00817 
00818                 if (completed) break;
00819 
00820                 if (debug)
00821                 {
00822                     Pout << ".";
00823                 }
00824             }
00825 
00826             if (!completed)
00827             {
00828                 if (debug)
00829                 {
00830                     Pout << "x";
00831                 }
00832 
00833                 // It is impossible to reach the end from the start, probably
00834                 // due to disconnected domain.  Do search in opposite direction
00835 
00836                 label nReverseSweeps = 0;
00837 
00838                 addedFaces.clear();
00839                 curFaceMap.insert(endFace);
00840                 addedFaces.insert(endFace);
00841 
00842                 while (nReverseSweeps < edgeFaceEscapeLimit_)
00843                 {
00844                     nReverseSweeps++;
00845 
00846                     if (addedFaces.found(startFace))
00847                     {
00848                         completed = true;
00849                     }
00850 
00851                     // Add all face neighbours of face in the map
00852                     const labelList cf = addedFaces.toc();
00853                     addedFaces.clear();
00854 
00855                     forAll (cf, cfI)
00856                     {
00857                         const labelList& curNbrs = masterFaceFaces[cf[cfI]];
00858 
00859                         forAll (curNbrs, nbrI)
00860                         {
00861                             if (!curFaceMap.found(curNbrs[nbrI]))
00862                             {
00863                                 curFaceMap.insert(curNbrs[nbrI]);
00864                                 addedFaces.insert(curNbrs[nbrI]);
00865                             }
00866                         }
00867                     }
00868 
00869                     if (completed) break;
00870 
00871                     if (debug)
00872                     {
00873                         Pout << ".";
00874                     }
00875                 }
00876             }
00877 
00878             if (completed)
00879             {
00880                 if (debug)
00881                 {
00882                     Pout << "+ ";
00883                 }
00884             }
00885             else
00886             {
00887                 if (debug)
00888                 {
00889                     Pout << "z ";
00890                 }
00891             }
00892 
00893             // Collect the points
00894 
00895             // Create a map of points the edge can interact with
00896             labelHashSet curPointMap
00897             (
00898                 nFacesPerSlaveEdge_*primitiveMesh::pointsPerFace_
00899             );
00900 
00901             const labelList curFaces = curFaceMap.toc();
00902 //             Pout << "curFaces: " << curFaces << endl;
00903             forAll (curFaces, faceI)
00904             {
00905                 const face& f = masterLocalFaces[curFaces[faceI]];
00906 
00907                 forAll (f, pointI)
00908                 {
00909                     curPointMap.insert(f[pointI]);
00910                 }
00911             }
00912 
00913             const labelList curMasterPoints = curPointMap.toc();
00914 
00915             // Check all the points against the edge.
00916 
00917             linePointRef edgeLine = curEdge.line(projectedSlavePoints);
00918 
00919             const vector edgeVec = edgeLine.vec();
00920             const scalar edgeMag = edgeLine.mag();
00921 
00922             // Calculate actual distance involved in projection.  This
00923             // is used to reject master points out of reach.
00924             // Calculated as a combination of travel distance in projection and
00925             // edge length
00926             scalar slaveCatchDist =
00927                 edgeMasterCatchFraction_*edgeMag
00928               + 0.5*
00929                 (
00930                     mag
00931                     (
00932                         projectedSlavePoints[curEdge.start()]
00933                       - slaveLocalPoints[curEdge.start()]
00934                     )
00935                   + mag
00936                     (
00937                         projectedSlavePoints[curEdge.end()]
00938                       - slaveLocalPoints[curEdge.end()]
00939                     )
00940                 );
00941 
00942             // The point merge distance needs to be measured in the
00943             // plane of the slave edge.  The unit vector is calculated
00944             // as a cross product of the edge vector and the edge
00945             // projection direction.  When checking for the distance
00946             // in plane, a minimum of the master-to-edge and
00947             // projected-master-to-edge distance is used, to avoid
00948             // problems with badly defined master planes.  HJ,
00949             // 17/Oct/2004
00950             vector edgeNormalInPlane =
00951                 edgeVec
00952               ^ (
00953                     slavePointNormals[curEdge.start()]
00954                   + slavePointNormals[curEdge.end()]
00955                 );
00956 
00957             edgeNormalInPlane /= mag(edgeNormalInPlane);
00958 
00959             forAll (curMasterPoints, pointI)
00960             {
00961                 const label cmp = curMasterPoints[pointI];
00962 
00963                 // Skip the current point if the edge start or end has
00964                 // been adjusted onto in
00965                 if
00966                 (
00967                     slavePointPointHits[curEdge.start()] == cmp
00968                  || slavePointPointHits[curEdge.end()] == cmp
00969                  || masterPointPointHits[cmp] > -1
00970                 )
00971                 {
00972 // Pout << "Edge already snapped to point.  Skipping." << endl;
00973                     continue;
00974                 }
00975 
00976                 // Check if the point actually hits the edge within bounds
00977                 pointHit edgeLineHit =
00978                     edgeLine.nearestDist(masterLocalPoints[cmp]);
00979 
00980                 if (edgeLineHit.hit())
00981                 {
00982                     // If the distance to the line is smaller than
00983                     // the tolerance the master point needs to be
00984                     // inserted into the edge
00985 
00986                     // Strict checking of slave cut to avoid capturing
00987                     // end points.  
00988                     scalar cutOnSlave =
00989                         ((edgeLineHit.hitPoint() - edgeLine.start()) & edgeVec)
00990                         /sqr(edgeMag);
00991 
00992                     scalar distInEdgePlane =
00993                         min
00994                         (
00995                             edgeLineHit.distance(),
00996                             mag
00997                             (
00998                                 (
00999                                     masterLocalPoints[cmp]
01000                                   - edgeLineHit.hitPoint()
01001                                 )
01002                               & edgeNormalInPlane
01003                             )
01004                         );
01005 //                     Pout << "master point: " << cmp
01006 //                         << " cutOnSlave " << cutOnSlave
01007 //                         << " distInEdgePlane: " << distInEdgePlane
01008 //                         << " tol1: " << pointMergeTol_*edgeMag
01009 //                         << " hitDist: " << edgeLineHit.distance()
01010 //                         << " tol2: " <<
01011 //                         min
01012 //                         (
01013 //                             slaveCatchDist,
01014 //                             masterPointEdgeDist[cmp]
01015 //                         ) << endl;
01016 
01017                     // Not a point hit, check for edge
01018                     if
01019                     (
01020                         cutOnSlave > edgeEndCutoffTol_
01021                      && cutOnSlave < 1.0 - edgeEndCutoffTol_ // check edge cut
01022                      && distInEdgePlane < edgeMergeTol_*edgeMag // merge plane
01023                      && edgeLineHit.distance()
01024                       < min
01025                         (
01026                             slaveCatchDist,
01027                             masterPointEdgeDist[cmp]
01028                         )
01029                     )
01030                     {
01031                         if (debug)
01032                         {
01033                             if (masterPointEdgeHits[cmp] == -1)
01034                             {
01035                                 // First hit
01036                                 Pout << "m";
01037                             }
01038                             else
01039                             {
01040                                 // Repeat hit
01041                                 Pout << "M";
01042                             }
01043                         }
01044 
01045                         // Snap to point onto edge
01046                         masterPointEdgeHits[cmp] = edgeI;
01047                         masterPointEdgeDist[cmp] = edgeLineHit.distance();
01048 
01049 //                         Pout<< "Inserting master point "
01050 //                             << masterPatch.meshPoints()[cmp]
01051 //                             << " (" << cmp
01052 //                             << ") at " << masterLocalPoints[cmp]
01053 //                             << " into slave edge " << edgeI
01054 //                             << " " << curEdge
01055 //                             << " cutOnSlave: " << cutOnSlave
01056 //                             << " distInEdgePlane: " << distInEdgePlane
01057 //                             << ". dist: " << edgeLineHit.distance()
01058 //                             << " mergeTol: "
01059 //                             << edgeMergeTol_*edgeMag
01060 //                             << " other tol: " <<
01061 //                             min
01062 //                             (
01063 //                                 slaveCatchDist,
01064 //                                 masterPointEdgeDist[cmp]
01065 //                             )
01066 //                             << endl;
01067                     }
01068                 }
01069             }
01070         } // End if both ends missing
01071     } // End all slave edges
01072 
01073     if (debug)
01074     {
01075         Pout << endl;
01076     }
01077 //     Pout << "masterPointEdgeHits: " << masterPointEdgeHits << endl;
01078 
01079     if (debug)
01080     {
01081         Pout<< "bool slidingInterface::projectPoints() for object "
01082             << name() << " : "
01083             << "Finished projecting  points. Topology = ";
01084     }
01085 
01086 //     Pout<< "slavePointPointHits: " << slavePointPointHits << nl
01087 //         << "slavePointEdgeHits: " << slavePointEdgeHits << nl
01088 //         << "slavePointFaceHits: " << slavePointFaceHits << nl
01089 //         << "masterPointEdgeHits: " << masterPointEdgeHits << endl;
01090 
01091     // The four lists:
01092     // - slavePointPointHits
01093     // - slavePointEdgeHits
01094     // - slavePointFaceHits
01095     // - masterPointEdgeHits
01096     //   define how the two patches will be merged topologically.
01097     //   If the lists have not changed since the last merge, the
01098     //   sliding interface changes only geometrically and simple mesh
01099     //   motion will suffice.  Otherwise, a topological change is
01100     //   required.
01101 
01102     // Compare the result with the current state
01103     if (!attached_)
01104     {
01105         // The mesh needs to change topologically
01106         trigger_ = true;
01107 
01108         // Store the addressing arrays and projected points
01109         deleteDemandDrivenData(slavePointPointHitsPtr_);
01110         slavePointPointHitsPtr_ = new labelList(slavePointPointHits);
01111 
01112         deleteDemandDrivenData(slavePointEdgeHitsPtr_);
01113         slavePointEdgeHitsPtr_ = new labelList(slavePointEdgeHits);
01114 
01115         deleteDemandDrivenData(slavePointFaceHitsPtr_);
01116         slavePointFaceHitsPtr_ = new List<objectHit>(slavePointFaceHits);
01117 
01118         deleteDemandDrivenData(masterPointEdgeHitsPtr_);
01119         masterPointEdgeHitsPtr_ = new labelList(masterPointEdgeHits);
01120 
01121         if (debug)
01122         {
01123             Pout << "(Detached interface) changing." << endl;
01124         }
01125     }
01126     else
01127     {
01128         // Compare the lists against the stored lists.  If any of them
01129         // has changed, topological change will be executed.
01130         trigger_ = false;
01131 
01132         if
01133         (
01134             !slavePointPointHitsPtr_
01135          || !slavePointEdgeHitsPtr_
01136          || !slavePointFaceHitsPtr_
01137          || !masterPointEdgeHitsPtr_
01138         )
01139         {
01140             // Must be restart.  Force topological change.
01141             deleteDemandDrivenData(slavePointPointHitsPtr_);
01142             slavePointPointHitsPtr_ = new labelList(slavePointPointHits);
01143 
01144             deleteDemandDrivenData(slavePointEdgeHitsPtr_);
01145             slavePointEdgeHitsPtr_ = new labelList(slavePointEdgeHits);
01146 
01147             deleteDemandDrivenData(slavePointFaceHitsPtr_);
01148             slavePointFaceHitsPtr_ = new List<objectHit>(slavePointFaceHits);
01149 
01150             deleteDemandDrivenData(masterPointEdgeHitsPtr_);
01151             masterPointEdgeHitsPtr_ = new labelList(masterPointEdgeHits);
01152 
01153             if (debug)
01154             {
01155                 Pout << "(Attached interface restart) changing." << endl;
01156             }
01157 
01158             trigger_ = true;
01159             return trigger_;
01160         }
01161 
01162         if (slavePointPointHits != (*slavePointPointHitsPtr_))
01163         {
01164             if (debug)
01165             {
01166                 Pout << "(Point projection) ";
01167             }
01168 
01169             trigger_ = true;
01170         }
01171 
01172         if (slavePointEdgeHits != (*slavePointEdgeHitsPtr_))
01173         {
01174             if (debug)
01175             {
01176                 Pout << "(Edge projection) ";
01177             }
01178 
01179             trigger_ = true;
01180         }
01181 
01182         // Comparison for face hits needs to exclude points that have hit
01183         // another point or edge
01184         bool faceHitsDifferent = false;
01185 
01186         const List<objectHit>& oldPointFaceHits = *slavePointFaceHitsPtr_;
01187 
01188         forAll (slavePointFaceHits, pointI)
01189         {
01190             if
01191             (
01192                 slavePointPointHits[pointI] < 0
01193              && slavePointEdgeHits[pointI] < 0
01194             )
01195             {
01196                 // This is a straight face hit
01197                 if (slavePointFaceHits[pointI] != oldPointFaceHits[pointI])
01198                 {
01199                     // Two lists are different
01200                     faceHitsDifferent = true;
01201                     break;
01202                 }
01203             }
01204         }
01205 
01206         if (faceHitsDifferent)
01207         {
01208             if (debug)
01209             {
01210                 Pout << "(Face projection) ";
01211             }
01212 
01213             trigger_ = true;
01214 
01215         }
01216 
01217         if (masterPointEdgeHits != (*masterPointEdgeHitsPtr_))
01218         {
01219             if (debug)
01220             {
01221                 Pout << "(Master point projection) ";
01222             }
01223 
01224             trigger_ = true;
01225         }
01226 
01227 
01228         if (trigger_)
01229         {
01230             // Grab new data
01231             deleteDemandDrivenData(slavePointPointHitsPtr_);
01232             slavePointPointHitsPtr_ = new labelList(slavePointPointHits);
01233 
01234             deleteDemandDrivenData(slavePointEdgeHitsPtr_);
01235             slavePointEdgeHitsPtr_ = new labelList(slavePointEdgeHits);
01236 
01237             deleteDemandDrivenData(slavePointFaceHitsPtr_);
01238             slavePointFaceHitsPtr_ = new List<objectHit>(slavePointFaceHits);
01239 
01240             deleteDemandDrivenData(masterPointEdgeHitsPtr_);
01241             masterPointEdgeHitsPtr_ = new labelList(masterPointEdgeHits);
01242 
01243             if (debug)
01244             {
01245                 Pout << "changing." << endl;
01246             }
01247         }
01248         else
01249         {
01250             if (debug)
01251             {
01252                 Pout << "preserved." << endl;
01253             }
01254         }
01255     }
01256 
01257     return trigger_;
01258 }
01259 
01260 
01261 void Foam::slidingInterface::clearPointProjection() const
01262 {
01263     deleteDemandDrivenData(slavePointPointHitsPtr_);
01264     deleteDemandDrivenData(slavePointEdgeHitsPtr_);
01265     deleteDemandDrivenData(slavePointFaceHitsPtr_);
01266     deleteDemandDrivenData(masterPointEdgeHitsPtr_);
01267 
01268     deleteDemandDrivenData(projectedSlavePointsPtr_);
01269 }
01270 
01271 
01272 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines