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

CalcPatchToPatchWeights.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 "PatchToPatchInterpolation_.H"
00027 #include <OpenFOAM/objectHit.H>
00028 #include <OpenFOAM/pointHit.H>
00029 
00030 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00031 
00032 namespace Foam
00033 {
00034 
00035 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00036 
00037 template<class FromPatch, class ToPatch>
00038 scalar PatchToPatchInterpolation<FromPatch, ToPatch>::projectionTol_ = 0.05;
00039 
00040 
00041 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00042 
00043 template<class FromPatch, class ToPatch>
00044 void PatchToPatchInterpolation<FromPatch, ToPatch>::calcPointAddressing() const
00045 {
00046     // Calculate pointWeights
00047 
00048     pointWeightsPtr_ = new FieldField<Field, scalar>(toPatch_.nPoints());
00049     FieldField<Field, scalar>& pointWeights = *pointWeightsPtr_;
00050 
00051     pointDistancePtr_ = new scalarField(toPatch_.nPoints(), GREAT);
00052     scalarField& pointDistance = *pointDistancePtr_;
00053 
00054     const pointField& fromPatchPoints = fromPatch_.localPoints();
00055     const List<typename FromPatch::FaceType>& fromPatchFaces =
00056         fromPatch_.localFaces();
00057 
00058     const pointField& toPatchPoints = toPatch_.localPoints();
00059     const vectorField& projectionDirection = toPatch_.pointNormals();
00060     const edgeList& toPatchEdges = toPatch_.edges();
00061     const labelListList& toPatchPointEdges = toPatch_.pointEdges();
00062 
00063     if (debug)
00064     {
00065         Info << "projecting points" << endl;
00066     }
00067 
00068     List<objectHit> proj =
00069         toPatch_.projectPoints(fromPatch_, projectionDirection, alg_, dir_);
00070 
00071     pointAddressingPtr_ = new labelList(proj.size(), -1);
00072     labelList& pointAddressing = *pointAddressingPtr_;
00073 
00074     bool doWeights = false;
00075 
00076     forAll (pointAddressing, pointI)
00077     {
00078         doWeights = false;
00079 
00080         const typename FromPatch::FaceType& hitFace =
00081             fromPatchFaces[proj[pointI].hitObject()];
00082 
00083         point hitPoint = point::zero;
00084 
00085         if (proj[pointI].hit())
00086         {
00087             // A hit exists
00088             doWeights = true;
00089 
00090             pointAddressing[pointI] = proj[pointI].hitObject();
00091 
00092             pointHit curHit =
00093                 hitFace.ray
00094                 (
00095                     toPatchPoints[pointI],
00096                     projectionDirection[pointI],
00097                     fromPatchPoints,
00098                     alg_,
00099                     dir_
00100                 );
00101 
00102             // Grab distance to target
00103             if (dir_ == intersection::CONTACT_SPHERE)
00104             {
00105                 pointDistance[pointI] =
00106                     hitFace.contactSphereDiameter
00107                     (
00108                         toPatchPoints[pointI],
00109                         projectionDirection[pointI],
00110                         fromPatchPoints
00111                     );
00112             }
00113             else
00114             {
00115                 pointDistance[pointI] = curHit.distance();
00116             }
00117 
00118             // Grab hit point
00119             hitPoint = curHit.hitPoint();
00120         }
00121         else if (projectionTol_ > SMALL)
00122         {
00123             // Check for a near miss
00124             pointHit ph =
00125                 hitFace.ray
00126                 (
00127                     toPatchPoints[pointI],
00128                     projectionDirection[pointI],
00129                     fromPatchPoints,
00130                     alg_,
00131                     dir_
00132                 );
00133 
00134             scalar dist =
00135                 Foam::mag
00136                 (
00137                     toPatchPoints[pointI]
00138                   + projectionDirection[pointI]*ph.distance()
00139                   - ph.missPoint()
00140                 );
00141                 
00142             // Calculate the local tolerance
00143             scalar minEdgeLength = GREAT;
00144 
00145             // Do shortest edge of hit object
00146             edgeList hitFaceEdges =
00147                 fromPatchFaces[proj[pointI].hitObject()].edges();
00148 
00149             forAll (hitFaceEdges, edgeI)
00150             {
00151                 minEdgeLength =
00152                     min
00153                     (
00154                         minEdgeLength,
00155                         hitFaceEdges[edgeI].mag(fromPatchPoints)
00156                     );
00157             }
00158 
00159             const labelList& curEdges = toPatchPointEdges[pointI];
00160 
00161             forAll (curEdges, edgeI)
00162             {
00163                 minEdgeLength =
00164                     min
00165                     (
00166                         minEdgeLength,
00167                         toPatchEdges[curEdges[edgeI]].mag(toPatchPoints)
00168                     );
00169             }
00170 
00171             if (dist < minEdgeLength*projectionTol_)
00172             {
00173                 // This point is being corrected
00174                 doWeights = true;
00175 
00176                 pointAddressing[pointI] = proj[pointI].hitObject();
00177 
00178                 // Grab nearest point on face as hit point
00179                 hitPoint = ph.missPoint();
00180 
00181                 // Grab distance to target
00182                 if (dir_ == intersection::CONTACT_SPHERE)
00183                 {
00184                     pointDistance[pointI] =
00185                         hitFace.contactSphereDiameter
00186                         (
00187                             toPatchPoints[pointI],
00188                             projectionDirection[pointI],
00189                             fromPatchPoints
00190                         );
00191                 }
00192                 else
00193                 {
00194                     pointDistance[pointI] =
00195                         (
00196                             projectionDirection[pointI]
00197                             /mag(projectionDirection[pointI])
00198                         )
00199                       & (hitPoint - toPatchPoints[pointI]);
00200                 }
00201             }
00202         }
00203 
00204         if (doWeights)
00205         {
00206             // Set interpolation pointWeights
00207             pointWeights.set(pointI, new scalarField(hitFace.size()));
00208 
00209             pointField hitFacePoints = hitFace.points(fromPatchPoints);
00210 
00211             forAll (hitFacePoints, masterPointI)
00212             {
00213                 pointWeights[pointI][masterPointI] =
00214                     1.0/
00215                     (
00216                         mag
00217                         (
00218                             hitFacePoints[masterPointI]
00219                           - hitPoint
00220                         )
00221                       + VSMALL
00222                     );
00223             }
00224 
00225             pointWeights[pointI] /= sum(pointWeights[pointI]);
00226         }
00227         else
00228         {
00229             pointWeights.set(pointI, new scalarField(0));
00230         }
00231     }
00232 }
00233 
00234 
00235 template<class FromPatch, class ToPatch>
00236 void PatchToPatchInterpolation<FromPatch, ToPatch>::calcFaceAddressing() const
00237 {
00238     faceWeightsPtr_ = new FieldField<Field, scalar>(toPatch_.size());
00239     FieldField<Field, scalar>& faceWeights = *faceWeightsPtr_;
00240 
00241     faceDistancePtr_ = new scalarField(toPatch_.size(), GREAT);
00242     scalarField& faceDistance = *faceDistancePtr_;
00243 
00244     if (debug)
00245     {
00246         Info << "projecting face centres" << endl;
00247     }
00248 
00249     const pointField& fromPatchPoints = fromPatch_.points();
00250     const typename FromPatch::FaceListType& fromPatchFaces = fromPatch_;
00251     const labelListList& fromPatchFaceFaces = fromPatch_.faceFaces();
00252 
00253     vectorField fromPatchFaceCentres(fromPatchFaces.size());
00254 
00255     forAll (fromPatchFaceCentres, faceI)
00256     {
00257         fromPatchFaceCentres[faceI] =
00258             fromPatchFaces[faceI].centre(fromPatchPoints);
00259     }
00260 
00261     const pointField& toPatchPoints = toPatch_.points();
00262     const typename ToPatch::FaceListType& toPatchFaces = toPatch_;
00263 
00264     const vectorField& projectionDirection = toPatch_.faceNormals();
00265 
00266     List<objectHit> proj =
00267         toPatch_.projectFaceCentres
00268         (
00269             fromPatch_,
00270             projectionDirection,
00271             alg_,
00272             dir_
00273         );
00274 
00275     faceAddressingPtr_ = new labelList(proj.size(), -1);
00276     labelList& faceAddressing = *faceAddressingPtr_;        
00277 
00278     forAll (faceAddressing, faceI)
00279     {
00280         if (proj[faceI].hit())
00281         {
00282             // A hit exists
00283             faceAddressing[faceI] = proj[faceI].hitObject();
00284 
00285             const typename FromPatch::FaceType& hitFace =
00286                 fromPatchFaces[faceAddressing[faceI]];
00287 
00288             pointHit curHit =
00289                 hitFace.ray
00290                 (
00291                     toPatchFaces[faceI].centre(toPatchPoints),
00292                     projectionDirection[faceI],
00293                     fromPatchPoints,
00294                     alg_,
00295                     dir_
00296                 );
00297 
00298             // grab distance to target
00299             faceDistance[faceI] = curHit.distance();
00300 
00301             // grab face centre of the hit face
00302             const point& hitFaceCentre =
00303                 fromPatchFaceCentres[faceAddressing[faceI]];
00304 
00305             // grab neighbours of hit face
00306             const labelList& neighbours =
00307                 fromPatchFaceFaces[faceAddressing[faceI]];
00308 
00309             scalar m = mag(curHit.hitPoint() - hitFaceCentre);
00310 
00311             if
00312             (
00313                 m < directHitTol                            // Direct hit
00314              || neighbours.empty()
00315             )
00316             {
00317                 faceWeights.set(faceI, new scalarField(1));
00318                 faceWeights[faceI][0] = 1.0;
00319             }
00320             else
00321             {
00322                 // set interpolation faceWeights
00323 
00324                 // The first coefficient corresponds to the centre face.
00325                 // The rest is ordered in the same way as the faceFaces list.
00326                 faceWeights.set(faceI, new scalarField(neighbours.size() + 1));
00327 
00328                 faceWeights[faceI][0] = 1.0/m;
00329 
00330                 forAll (neighbours, nI)
00331                 {
00332                     faceWeights[faceI][nI + 1] =
00333                     1.0/
00334                     (
00335                         mag
00336                         (
00337                             fromPatchFaceCentres[neighbours[nI]]
00338                           - curHit.hitPoint()
00339                         )
00340                       + VSMALL
00341                     );
00342                 }
00343             }
00344 
00345             faceWeights[faceI] /= sum(faceWeights[faceI]);
00346         }
00347         else
00348         {
00349             faceWeights.set(faceI, new scalarField(0));
00350         }
00351     }
00352 }
00353 
00354 
00355 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00356 
00357 } // End namespace Foam
00358 
00359 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines