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

tetrahedron.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     Calculation of shape function product for a tetrahedron
00026 
00027 \*---------------------------------------------------------------------------*/
00028 
00029 #include "tetrahedron.H"
00030 #include <OpenFOAM/triPointRef.H>
00031 #include <OpenFOAM/scalarField.H>
00032 
00033 
00034 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00035 
00036 // (Probably very inefficient) minimum containment sphere calculation.
00037 // From http://www.imr.sandia.gov/papers/imr11/shewchuk2.pdf:
00038 // Sphere ctr is smallest one of
00039 // - tet circumcentre
00040 // - triangle circumcentre
00041 // - edge mids
00042 template<class Point, class PointRef>
00043 Foam::pointHit Foam::tetrahedron<Point, PointRef>::containmentSphere
00044 (
00045     const scalar tol
00046 ) const
00047 {
00048     const scalar fac = 1 + tol;
00049 
00050     // Halve order of tolerance for comparisons of sqr.
00051     const scalar facSqr = Foam::sqrt(fac);
00052 
00053 
00054     // 1. Circumcentre itself.
00055 
00056     pointHit pHit(circumCentre());
00057     pHit.setHit();
00058     scalar minRadiusSqr = magSqr(pHit.rawPoint() - a_);
00059 
00060 
00061     // 2. Try circumcentre of tet triangles. Create circumcircle for triFace and
00062     // check if 4th point is inside.
00063 
00064     {
00065         point ctr = triPointRef(a_, b_, c_).circumCentre();
00066         scalar radiusSqr = magSqr(ctr - a_);
00067 
00068         if
00069         (
00070             radiusSqr < minRadiusSqr
00071          && Foam::magSqr(d_-ctr) <= facSqr*radiusSqr
00072         )
00073         {
00074             pHit.setMiss(false);
00075             pHit.setPoint(ctr);
00076             minRadiusSqr = radiusSqr;
00077         }
00078     }
00079     {
00080         point ctr = triPointRef(a_, b_, d_).circumCentre();
00081         scalar radiusSqr = magSqr(ctr - a_);
00082 
00083         if
00084         (
00085             radiusSqr < minRadiusSqr
00086          && Foam::magSqr(c_-ctr) <= facSqr*radiusSqr
00087         )
00088         {
00089             pHit.setMiss(false);
00090             pHit.setPoint(ctr);
00091             minRadiusSqr = radiusSqr;
00092         }
00093     }
00094     {
00095         point ctr = triPointRef(a_, c_, d_).circumCentre();
00096         scalar radiusSqr = magSqr(ctr - a_);
00097 
00098         if
00099         (
00100             radiusSqr < minRadiusSqr
00101          && Foam::magSqr(b_-ctr) <= facSqr*radiusSqr
00102         )
00103         {
00104             pHit.setMiss(false);
00105             pHit.setPoint(ctr);
00106             minRadiusSqr = radiusSqr;
00107         }
00108     }
00109     {
00110         point ctr = triPointRef(b_, c_, d_).circumCentre();
00111         scalar radiusSqr = magSqr(ctr - b_);
00112 
00113         if
00114         (
00115             radiusSqr < minRadiusSqr
00116          && Foam::magSqr(a_-ctr) <= facSqr*radiusSqr
00117         )
00118         {
00119             pHit.setMiss(false);
00120             pHit.setPoint(ctr);
00121             minRadiusSqr = radiusSqr;
00122         }
00123     }
00124 
00125 
00126     // 3. Try midpoints of edges
00127 
00128     // mid of edge A-B
00129     {
00130         point ctr = 0.5*(a_ + b_);
00131         scalar radiusSqr = magSqr(a_ - ctr);
00132         scalar testRadSrq = facSqr*radiusSqr;
00133 
00134         if
00135         (
00136             radiusSqr < minRadiusSqr
00137          && magSqr(c_-ctr) <= testRadSrq
00138          && magSqr(d_-ctr) <= testRadSrq)
00139         {
00140             pHit.setMiss(false);
00141             pHit.setPoint(ctr);
00142             minRadiusSqr = radiusSqr;
00143         }
00144     }
00145 
00146     // mid of edge A-C
00147     {
00148         point ctr = 0.5*(a_ + c_);
00149         scalar radiusSqr = magSqr(a_ - ctr);
00150         scalar testRadSrq = facSqr*radiusSqr;
00151 
00152         if
00153         (
00154             radiusSqr < minRadiusSqr
00155          && magSqr(b_-ctr) <= testRadSrq
00156          && magSqr(d_-ctr) <= testRadSrq
00157         )
00158         {
00159             pHit.setMiss(false);
00160             pHit.setPoint(ctr);
00161             minRadiusSqr = radiusSqr;
00162         }
00163     }
00164 
00165     // mid of edge A-D
00166     {
00167         point ctr = 0.5*(a_ + d_);
00168         scalar radiusSqr = magSqr(a_ - ctr);
00169         scalar testRadSrq = facSqr*radiusSqr;
00170 
00171         if
00172         (
00173             radiusSqr < minRadiusSqr
00174          && magSqr(b_-ctr) <= testRadSrq
00175          && magSqr(c_-ctr) <= testRadSrq
00176         )
00177         {
00178             pHit.setMiss(false);
00179             pHit.setPoint(ctr);
00180             minRadiusSqr = radiusSqr;
00181         }
00182     }
00183 
00184     // mid of edge B-C
00185     {
00186         point ctr = 0.5*(b_ + c_);
00187         scalar radiusSqr = magSqr(b_ - ctr);
00188         scalar testRadSrq = facSqr*radiusSqr;
00189 
00190         if
00191         (
00192             radiusSqr < minRadiusSqr
00193          && magSqr(a_-ctr) <= testRadSrq
00194          && magSqr(d_-ctr) <= testRadSrq
00195         )
00196         {
00197             pHit.setMiss(false);
00198             pHit.setPoint(ctr);
00199             minRadiusSqr = radiusSqr;
00200         }
00201     }
00202 
00203     // mid of edge B-D
00204     {
00205         point ctr = 0.5*(b_ + d_);
00206         scalar radiusSqr = magSqr(b_ - ctr);
00207         scalar testRadSrq = facSqr*radiusSqr;
00208 
00209         if
00210         (
00211             radiusSqr < minRadiusSqr
00212          && magSqr(a_-ctr) <= testRadSrq
00213          && magSqr(c_-ctr) <= testRadSrq)
00214         {
00215             pHit.setMiss(false);
00216             pHit.setPoint(ctr);
00217             minRadiusSqr = radiusSqr;
00218         }
00219     }
00220 
00221     // mid of edge C-D
00222     {
00223         point ctr = 0.5*(c_ + d_);
00224         scalar radiusSqr = magSqr(c_ - ctr);
00225         scalar testRadSrq = facSqr*radiusSqr;
00226 
00227         if
00228         (
00229             radiusSqr < minRadiusSqr
00230          && magSqr(a_-ctr) <= testRadSrq
00231          && magSqr(b_-ctr) <= testRadSrq
00232         )
00233         {
00234             pHit.setMiss(false);
00235             pHit.setPoint(ctr);
00236             minRadiusSqr = radiusSqr;
00237         }
00238     }
00239 
00240 
00241     pHit.setDistance(sqrt(minRadiusSqr));
00242 
00243     return pHit;
00244 }
00245 
00246 
00247 template<class Point, class PointRef>
00248 void Foam::tetrahedron<Point, PointRef>::gradNiSquared
00249 (
00250     scalarField& buffer
00251 ) const
00252 {
00253     // Change of sign between face area vector and gradient
00254     // does not matter because of square
00255 
00256     // Warning: Added a mag to produce positive coefficients even if
00257     // the tetrahedron is twisted inside out.  This is pretty
00258     // dangerous, but essential for mesh motion.
00259     scalar magVol = Foam::mag(mag());
00260 
00261     buffer[0] = (1.0/9.0)*magSqr(Sa())/magVol;
00262     buffer[1] = (1.0/9.0)*magSqr(Sb())/magVol;
00263     buffer[2] = (1.0/9.0)*magSqr(Sc())/magVol;
00264     buffer[3] = (1.0/9.0)*magSqr(Sd())/magVol;
00265 }
00266 
00267 
00268 template<class Point, class PointRef>
00269 void Foam::tetrahedron<Point, PointRef>::gradNiDotGradNj
00270 (
00271     scalarField& buffer
00272 ) const
00273 {
00274     // Warning. Ordering of edges needs to be the same for a tetrahedron
00275     // class, a tetrahedron cell shape model and a tetCell
00276 
00277     // Warning: Added a mag to produce positive coefficients even if
00278     // the tetrahedron is twisted inside out.  This is pretty
00279     // dangerous, but essential for mesh motion.
00280 
00281     // Double change of sign between face area vector and gradient
00282 
00283     scalar magVol = Foam::mag(mag());
00284     vector sa = Sa();
00285     vector sb = Sb();
00286     vector sc = Sc();
00287     vector sd = Sd();
00288 
00289     buffer[0] = (1.0/9.0)*(sa & sb)/magVol;
00290     buffer[1] = (1.0/9.0)*(sa & sc)/magVol;
00291     buffer[2] = (1.0/9.0)*(sa & sd)/magVol;
00292     buffer[3] = (1.0/9.0)*(sd & sb)/magVol;
00293     buffer[4] = (1.0/9.0)*(sb & sc)/magVol;
00294     buffer[5] = (1.0/9.0)*(sd & sc)/magVol;
00295 }
00296 
00297 
00298 template<class Point, class PointRef>
00299 void Foam::tetrahedron<Point, PointRef>::gradNiGradNi
00300 (
00301     tensorField& buffer
00302 ) const
00303 {
00304     // Change of sign between face area vector and gradient
00305     // does not matter because of square
00306 
00307     scalar magVol = Foam::mag(mag());
00308 
00309     buffer[0] = (1.0/9.0)*sqr(Sa())/magVol;
00310     buffer[1] = (1.0/9.0)*sqr(Sb())/magVol;
00311     buffer[2] = (1.0/9.0)*sqr(Sc())/magVol;
00312     buffer[3] = (1.0/9.0)*sqr(Sd())/magVol;
00313 }
00314 
00315 
00316 template<class Point, class PointRef>
00317 void Foam::tetrahedron<Point, PointRef>::gradNiGradNj
00318 (
00319     tensorField& buffer
00320 ) const
00321 {
00322     // Warning. Ordering of edges needs to be the same for a tetrahedron
00323     // class, a tetrahedron cell shape model and a tetCell
00324 
00325     // Double change of sign between face area vector and gradient
00326 
00327     scalar magVol = Foam::mag(mag());
00328     vector sa = Sa();
00329     vector sb = Sb();
00330     vector sc = Sc();
00331     vector sd = Sd();
00332 
00333     buffer[0] = (1.0/9.0)*(sa * sb)/magVol;
00334     buffer[1] = (1.0/9.0)*(sa * sc)/magVol;
00335     buffer[2] = (1.0/9.0)*(sa * sd)/magVol;
00336     buffer[3] = (1.0/9.0)*(sd * sb)/magVol;
00337     buffer[4] = (1.0/9.0)*(sb * sc)/magVol;
00338     buffer[5] = (1.0/9.0)*(sd * sc)/magVol;
00339 }
00340 
00341 
00342 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines