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

cellPointWeight.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 "cellPointWeight.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 
00029 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00030 
00031 int Foam::cellPointWeight::debug(debug::debugSwitch("cellPointWeight", 0));
00032 Foam::scalar Foam::cellPointWeight::tol(SMALL);
00033 
00034 // * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
00035 
00036 void Foam::cellPointWeight::findTetrahedron
00037 (
00038     const polyMesh& mesh,
00039     const vector& position,
00040     const label cellIndex
00041 )
00042 {
00043     if (debug)
00044     {
00045         Pout<< "\nFoam::cellPointWeight::findTetrahedron" << nl
00046             << "position = " << position << nl
00047             << "cellIndex = " << cellIndex << endl;
00048     }
00049 
00050     // Initialise closest triangle variables
00051     scalar minUVWClose = VGREAT;
00052     label pointIClose = 0;
00053     label faceClose = 0;
00054 
00055     const vector& P0 = mesh.cellCentres()[cellIndex];
00056     const labelList& cellFaces = mesh.cells()[cellIndex];
00057     const scalar cellVolume = mesh.cellVolumes()[cellIndex];
00058 
00059     // Find the tet that the point occupies
00060     forAll(cellFaces, faceI)
00061     {
00062         // Decompose each face into triangles, making a tet when
00063         // augmented by the cell centre
00064         const labelList& facePoints = mesh.faces()[cellFaces[faceI]];
00065 
00066         label pointI = 1;
00067         while ((pointI + 1) < facePoints.size())
00068         {
00069             // Cartesian co-ordinates of the triangle vertices
00070             const vector& P1 = mesh.points()[facePoints[0]];
00071             const vector& P2 = mesh.points()[facePoints[pointI]];
00072             const vector& P3 = mesh.points()[facePoints[pointI + 1]];
00073 
00074             // Edge vectors
00075             const vector e1 = P1 - P0;
00076             const vector e2 = P2 - P0;
00077             const vector e3 = P3 - P0;
00078 
00079             // Solve for interpolation weighting factors
00080 
00081             // Source term
00082             const vector rhs = position - P0;
00083 
00084             // Determinant of coefficients matrix
00085             // Note: if det(A) = 0 the tet is degenerate
00086             const scalar detA =
00087                 e1.x()*e2.y()*e3.z() + e2.x()*e3.y()*e1.z()
00088               + e3.x()*e1.y()*e2.z() - e1.x()*e3.y()*e2.z()
00089               - e2.x()*e1.y()*e3.z() - e3.x()*e2.y()*e1.z();
00090 
00091             if (mag(detA/cellVolume) > tol)
00092             {
00093                 // Solve using Cramers' rule
00094                 const scalar u =
00095                 (
00096                    rhs.x()*e2.y()*e3.z() + e2.x()*e3.y()*rhs.z()
00097                   + e3.x()*rhs.y()*e2.z() - rhs.x()*e3.y()*e2.z()
00098                   - e2.x()*rhs.y()*e3.z() - e3.x()*e2.y()*rhs.z()
00099                 )/detA;
00100 
00101                 const scalar v =
00102                 (
00103                     e1.x()*rhs.y()*e3.z() + rhs.x()*e3.y()*e1.z()
00104                   + e3.x()*e1.y()*rhs.z() - e1.x()*e3.y()*rhs.z()
00105                   - rhs.x()*e1.y()*e3.z() - e3.x()*rhs.y()*e1.z()
00106                 )/detA;
00107 
00108                 const scalar w =
00109                 (
00110                     e1.x()*e2.y()*rhs.z() + e2.x()*rhs.y()*e1.z()
00111                   + rhs.x()*e1.y()*e2.z() - e1.x()*rhs.y()*e2.z()
00112                   - e2.x()*e1.y()*rhs.z() - rhs.x()*e2.y()*e1.z()
00113                 )/detA;
00114 
00115                 // Check if point is in tet
00116                 // value = 0 indicates position lies on a tet face
00117                 if
00118                 (
00119                    (u + tol > 0) && (v + tol > 0) && (w + tol > 0)
00120                 && (u + v + w < 1 + tol)
00121                 )
00122                 {
00123                     faceVertices_[0] = facePoints[0];
00124                     faceVertices_[1] = facePoints[pointI];
00125                     faceVertices_[2] = facePoints[pointI + 1];
00126 
00127                     weights_[0] = u;
00128                     weights_[1] = v;
00129                     weights_[2] = w;
00130                     weights_[3] = 1.0 - (u + v + w);
00131 
00132                     return;
00133                 }
00134                 else
00135                 {
00136                     scalar minU = mag(u);
00137                     scalar minV = mag(v);
00138                     scalar minW = mag(w);
00139                     if (minU > 1.0)
00140                     {
00141                         minU -= 1.0;
00142                     }
00143                     if (minV > 1.0)
00144                     {
00145                         minV -= 1.0;
00146                     }
00147                     if (minW > 1.0)
00148                     {
00149                         minW -= 1.0;
00150                     }
00151                     const scalar minUVW = mag(minU + minV + minW);
00152 
00153                     if (minUVW < minUVWClose)
00154                     {
00155                         minUVWClose = minUVW;
00156                         pointIClose = pointI;
00157                         faceClose = faceI;
00158                     }
00159                 }
00160             }
00161 
00162             pointI++;
00163         }
00164     }
00165 
00166     if (debug)
00167     {
00168         Pout<< "cellPointWeight::findTetrahedron" << nl
00169             << "    Tetrahedron search failed; using closest tet values to "
00170             << "point " << nl << "    cell: " << cellIndex << nl << endl;
00171     }
00172 
00173     const labelList& facePointsClose = mesh.faces()[cellFaces[faceClose]];
00174     faceVertices_[0] = facePointsClose[0];
00175     faceVertices_[1] = facePointsClose[pointIClose];
00176     faceVertices_[2] = facePointsClose[pointIClose + 1];
00177 
00178     weights_[0] = 0.25;
00179     weights_[1] = 0.25;
00180     weights_[2] = 0.25;
00181     weights_[3] = 0.25;
00182 }
00183 
00184 
00185 void Foam::cellPointWeight::findTriangle
00186 (
00187     const polyMesh& mesh,
00188     const vector& position,
00189     const label faceIndex
00190 )
00191 {
00192     if (debug)
00193     {
00194         Pout<< "\nbool Foam::cellPointWeight::findTriangle" << nl
00195             << "position = " << position << nl
00196             << "faceIndex = " << faceIndex << endl;
00197     }
00198 
00199     // Initialise closest triangle variables
00200     scalar minUVClose = VGREAT;
00201     label pointIClose = 0;
00202 
00203     // Decompose each face into triangles, making a tet when
00204     // augmented by the cell centre
00205     const labelList& facePoints = mesh.faces()[faceIndex];
00206 
00207     const scalar faceArea2 = magSqr(mesh.faceAreas()[faceIndex]);
00208 
00209     label pointI = 1;
00210     while ((pointI + 1) < facePoints.size())
00211     {
00212         // Cartesian co-ordinates of the triangle vertices
00213         const vector& P1 = mesh.points()[facePoints[0]];
00214         const vector& P2 = mesh.points()[facePoints[pointI]];
00215         const vector& P3 = mesh.points()[facePoints[pointI + 1]];
00216 
00217         // Direction vectors
00218         vector v1 = position - P1;
00219         const vector v2 = P2 - P1;
00220         const vector v3 = P3 - P1;
00221 
00222         // Plane normal
00223         vector n = v2 ^ v3;
00224         n /= mag(n);
00225 
00226         // Remove any offset to plane
00227         v1 -= (n & v1)*v1;
00228 
00229         // Helper variables
00230         const scalar d12 = v1 & v2;
00231         const scalar d13 = v1 & v3;
00232         const scalar d22 = v2 & v2;
00233         const scalar d23 = v2 & v3;
00234         const scalar d33 = v3 & v3;
00235 
00236         // Determinant of coefficients matrix
00237         // Note: if det(A) = 0 the triangle is degenerate
00238         const scalar detA = d22*d33 - d23*d23;
00239 
00240         if (0.25*detA/faceArea2 > tol)
00241         {
00242             // Solve using Cramers' rule
00243             const scalar u = (d12*d33 - d23*d13)/detA;
00244             const scalar v = (d22*d13 - d12*d23)/detA;
00245 
00246             // Check if point is in triangle
00247             if ((u + tol > 0) && (v + tol > 0) && (u + v < 1 + tol))
00248             {
00249                 // Indices of the cell vertices making up the triangle
00250                 faceVertices_[0] = facePoints[0];
00251                 faceVertices_[1] = facePoints[pointI];
00252                 faceVertices_[2] = facePoints[pointI + 1];
00253 
00254                 weights_[0] = u;
00255                 weights_[1] = v;
00256                 weights_[2] = 1.0 - (u + v);
00257                 weights_[3] = 0.0;
00258 
00259                 return;
00260             }
00261             else
00262             {
00263                 scalar minU = mag(u);
00264                 scalar minV = mag(v);
00265                 if (minU > 1.0)
00266                 {
00267                     minU -= 1.0;
00268                 }
00269                 if (minV > 1.0)
00270                 {
00271                     minV -= 1.0;
00272                 }
00273                 const scalar minUV = mag(minU + minV);
00274 
00275                 if (minUV < minUVClose)
00276                 {
00277                     minUVClose = minUV;
00278                     pointIClose = pointI;
00279                 }
00280             }
00281         }
00282 
00283         pointI++;
00284     }
00285 
00286     if (debug)
00287     {
00288         Pout<< "Foam::cellPointWeight::findTriangle"
00289             << "Triangle search failed; using closest triangle to point" << nl
00290             << "    cell face: " << faceIndex << nl << endl;
00291     }
00292 
00293     // Indices of the cell vertices making up the triangle
00294     faceVertices_[0] = facePoints[0];
00295     faceVertices_[1] = facePoints[pointIClose];
00296     faceVertices_[2] = facePoints[pointIClose + 1];
00297 
00298     weights_[0] = 1.0/3.0;
00299     weights_[1] = 1.0/3.0;
00300     weights_[2] = 1.0/3.0;
00301     weights_[3] = 0.0;
00302 }
00303 
00304 
00305 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00306 
00307 Foam::cellPointWeight::cellPointWeight
00308 (
00309     const polyMesh& mesh,
00310     const vector& position,
00311     const label cellIndex,
00312     const label faceIndex
00313 )
00314 :
00315     cellIndex_(cellIndex)
00316 {
00317     if (faceIndex < 0)
00318     {
00319         // Face data not supplied
00320         findTetrahedron(mesh, position, cellIndex);
00321     }
00322     else
00323     {
00324         // Face data supplied
00325         findTriangle(mesh, position, faceIndex);
00326     }
00327 }
00328 
00329 
00330 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines