$treeview $search $mathjax
Palabos  Version 1.1
$projectbrief
$projectbrief
$searchbox

geometricOperationTemplates.h

Go to the documentation of this file.
00001 /* This file is part of the Palabos library.
00002  *
00003  * Copyright (C) 2011 FlowKit Sarl
00004  * Avenue de Chailly 23
00005  * 1012 Lausanne, Switzerland
00006  * E-mail contact: contact@flowkit.com
00007  *
00008  * The most recent release of Palabos can be downloaded at 
00009  * <http://www.palabos.org/>
00010  *
00011  * The library Palabos is free software: you can redistribute it and/or
00012  * modify it under the terms of the GNU Affero General Public License as
00013  * published by the Free Software Foundation, either version 3 of the
00014  * License, or (at your option) any later version.
00015  *
00016  * The library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU Affero General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Affero General Public License
00022  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00023 */
00024 
00030 #ifndef GEOMETRIC_OPERATION_TEMPLATES_H
00031 #define GEOMETRIC_OPERATION_TEMPLATES_H
00032 
00033 #include "io/parallelIO.h"
00034 #include "core/globalDefs.h"
00035 #include "core/array.h"
00036 #include "core/util.h"
00037 #include <algorithm>
00038 #include <vector>
00039 #include <cmath>
00040 #include <limits>
00041 
00042 namespace plb {
00043 
00044 template <typename T, int d> struct VectorTemplateImpl;
00045 template <typename T, template<typename U> class Descriptor> struct SymmetricTensor;
00046 template <typename T, template<typename U> class Descriptor> struct SymmetricRankThreeTensor;
00047 template <typename T, int d> struct SymmetricTensorImpl;
00048 template <typename T, int d> struct SymmetricRankThreeTensorImpl;
00049 
00050 template <typename T, template<typename U> class Descriptor>
00051 struct VectorTemplate {
00053     static const int d = Descriptor<T>::d;
00055     static T scalarProduct(Array<T,d> const& u1, Array<T,d> const& u2) {
00056         return VectorTemplateImpl<T,d>::scalarProduct(u1,u2);
00057     }
00059     static T scalarProduct(const T u1[d], Array<T,d> const& u2) {
00060         return VectorTemplateImpl<T,d>::scalarProduct(u1,u2);
00061     }
00063     static T normSqr(Array<T,d> const& u) {
00064         return VectorTemplateImpl<T,d>::normSqr(u);
00065     }
00067     static void multiplyByScalar(Array<T,d>& u, T scalar) {
00068         VectorTemplateImpl<T,d>::multiplyByScalar(u,scalar);
00069     }
00071     static void multiplyByScalar(Array<T,d> const& u, T scalar, Array<T,d>& result) {
00072         VectorTemplateImpl<T,d>::multiplyByScalar(u,scalar,result);
00073     }
00075     static void symTensorProduct( Array<T,d> const &u, Array<T,d> const &v,
00076                                   Array<T,SymmetricTensor<T,Descriptor>::n> &result)
00077     {
00078         VectorTemplateImpl<T,d>::symTensorProduct(u,v,result);
00079     }
00081     static void symTensorProduct(Array<T,d> const &u, Array<T,d> const &v, Array<T,d> const &w,
00082                                  Array<T,SymmetricRankThreeTensor<T,Descriptor>::n> &result)
00083     {
00084         VectorTemplateImpl<T,d>::symTensorProduct(u,v,w,result);
00085     }
00086 };
00087 
00088 template <typename T, int d>
00089 struct VectorTemplateImpl {
00090     static T scalarProduct(Array<T,d> const& u1, Array<T,d> const& u2) {
00091         T result = T();
00092         for (int iD=0; iD<d; ++iD) {
00093             result += u1[iD]*u2[iD];
00094         }
00095         return result;
00096     }
00097     static T scalarProduct(const T u1[d], Array<T,d> const& u2) {
00098         T result = T();
00099         for (int iD=0; iD<d; ++iD) {
00100             result += u1[iD]*u2[iD];
00101         }
00102         return result;
00103     }
00104     static T normSqr(Array<T,d> const& u) {
00105         return scalarProduct(u,u);
00106     }
00107     static void multiplyByScalar(Array<T,d>& u, T scalar) {
00108         for (int iD=0; iD<d; ++iD) {
00109             u[iD] *= scalar;
00110         }
00111     }
00112     
00113     static void multiplyByScalar(Array<T,d> const& u, T scalar, Array<T,d>& result) {
00114         for (int iD=0; iD<d; ++iD) {
00115             result[iD] = u[iD]*scalar;
00116         }
00117     }
00118     
00119     static void symTensorProduct(Array<T,d> const &u, Array<T,d> const &v, Array<T,SymmetricTensorImpl<T,d>::n> &result) {
00120         int iPi = 0;
00121         for (int iA = 0; iA < d; ++iA) {
00122             for (int iB = iA; iB < d; ++iB) {
00123                 result[iPi] = u[iA]*v[iB];
00124                 ++iPi;
00125             }
00126         }
00127     }
00128     
00129     static void symTensorProduct(Array<T,d> const &u, Array<T,d> const &v, Array<T,d> const &w, 
00130                                  Array<T,SymmetricRankThreeTensorImpl<T,d>::n> &result) {
00131         int iPi = 0;
00132         for (int iA = 0; iA < d; ++iA) {
00133             for (int iB = iA; iB < d; ++iB) {
00134                 for (int iC = iB; iC < d; ++iC) {
00135                     result[iPi] = u[iA]*v[iB]*w[iC];
00136                     ++iPi;
00137                 }
00138             }
00139         }
00140     }
00141 };
00142 
00143 
00144 template <typename T>
00145 struct VectorTemplateImpl<T,2> {
00146     static T scalarProduct(Array<T,2> const& u1, Array<T,2> const& u2) {
00147         return u1[0]*u2[0] + u1[1]*u2[1];
00148     }
00149     static T scalarProduct(const T u1[2], Array<T,2> const& u2) {
00150         return u1[0]*u2[0] + u1[1]*u2[1];
00151     }
00152     static T normSqr(Array<T,2> const& u) {
00153         return u[0]*u[0] + u[1]*u[1];
00154     }
00155     static void multiplyByScalar(Array<T,2>& u, T scalar) {
00156         u[0] *= scalar;
00157         u[1] *= scalar;
00158     }
00159     static void multiplyByScalar(Array<T,2> const& u, T scalar, Array<T,2>& result) {
00160         result[0] = u[0]*scalar;
00161         result[1] = u[1]*scalar;
00162     }
00163     static void symTensorProduct(Array<T,2> const &u, Array<T,2> const &v, Array<T,3> &result) {
00164         result[0] = u[0]*v[0];
00165         result[1] = u[0]*v[1];
00166         result[2] = u[1]*v[1];
00167     }
00168     static void symTensorProduct(Array<T,2> const &u, Array<T,2> const &v, Array<T,2> const &w, 
00169                                  Array<T,4> &result) {
00170         result[0] = u[0]*v[0]*w[0];
00171         result[1] = u[0]*v[0]*w[1];
00172         result[2] = u[0]*v[1]*w[1];
00173         result[3] = u[1]*v[1]*w[1];
00174     }
00175 };
00176 
00177 
00178 template <typename T>
00179 struct VectorTemplateImpl<T,3> {
00180     static T scalarProduct(Array<T,3> const& u1, Array<T,3> const& u2) {
00181         return u1[0]*u2[0] + u1[1]*u2[1] + u1[2]*u2[2];
00182     }
00183     static T scalarProduct(const T u1[3], Array<T,3> const& u2) {
00184         return u1[0]*u2[0] + u1[1]*u2[1] + u1[2]*u2[2];
00185     }
00186     static T normSqr(Array<T,3> const& u) {
00187         return u[0]*u[0] + u[1]*u[1] + u[2]*u[2];
00188     }
00189     static void multiplyByScalar(Array<T,3>& u, T scalar) {
00190         u[0] *= scalar;
00191         u[1] *= scalar;
00192         u[2] *= scalar;
00193     }
00194     static void multiplyByScalar(Array<T,3> const& u, T scalar, Array<T,3>& result) {
00195         result[0] = u[0]*scalar;
00196         result[1] = u[1]*scalar;
00197         result[2] = u[2]*scalar;
00198     }
00199     static void symTensorProduct(Array<T,3> const &u, Array<T,3> const &v, Array<T,6> &result) {
00200         result[0] = u[0]*v[0];
00201         result[1] = u[0]*v[1];
00202         result[2] = u[0]*v[2];
00203         result[3] = u[1]*v[1];
00204         result[4] = u[1]*v[2];
00205         result[5] = u[2]*v[2];
00206     }
00207     static void symTensorProduct(Array<T,3> const &u, Array<T,3> const &v, Array<T,3> const &w, 
00208                                  Array<T,10> &result) {
00209         result[0] = u[0]*v[0]*w[0];
00210         result[1] = u[0]*v[0]*w[1];
00211         result[2] = u[0]*v[0]*w[2];
00212         result[3] = u[0]*v[1]*w[1];
00213         result[4] = u[0]*v[1]*w[2];
00214         result[5] = u[0]*v[2]*w[2];
00215         result[6] = u[1]*v[1]*w[1];
00216         result[7] = u[1]*v[1]*w[2];
00217         result[8] = u[1]*v[2]*w[2];
00218         result[9] = u[2]*v[2]*w[2];
00219     }
00220 };
00221 
00222 
00223 template <typename T, int d> struct SymmetricTensorImpl { };
00224 
00225 template<typename T> struct SymmetricTensorImpl<T,2> {
00226     static const int n = 3;
00227     enum Indices { xx=0, xy=1, yy=2 };
00228     static void matVectMult(Array<T,n> const& mat, Array<T,2> const& vect, Array<T,2>& result) {
00229         result[0] = mat[xx]*vect[0] + mat[xy]*vect[1];
00230         result[1] = mat[xy]*vect[0] + mat[yy]*vect[1];
00231     }
00232     static T tensorNormSqr(Array<T,n> const& mat) {
00233         return mat[xx]*mat[xx]+mat[yy]*mat[yy] + (T)2*mat[xy]*mat[xy];
00234     }
00235     static T contractIndexes(Array<T,n> const& A, Array<T,n> const& B) {
00236         return A[xx]*B[xx]+A[yy]*B[yy]+ (T)2*A[xy]*B[xy];
00237     }
00238     static T trace(Array<T,n> const &A) {
00239         return A[xx] + A[yy];
00240     }
00241     static Array<T,n> id() {
00242         return Array<T,n>((T)1,T(),(T)1);
00243     }
00244 };
00245 
00246 template<typename T> struct SymmetricTensorImpl<T,3> {
00247     static const int n = 6;
00248     enum Indices { xx=0, xy=1, xz=2, yy=3, yz=4, zz=5 };
00249     static void matVectMult(Array<T,n> const& mat, Array<T,3> const& vect, Array<T,3>& result) {
00250         result[0] = mat[xx]*vect[0] + mat[xy]*vect[1] + mat[xz]*vect[2];
00251         result[1] = mat[xy]*vect[0] + mat[yy]*vect[1] + mat[yz]*vect[2];
00252         result[2] = mat[xz]*vect[0] + mat[yz]*vect[1] + mat[zz]*vect[2];
00253     }
00254     static T tensorNormSqr(Array<T,n> const& mat) {
00255         return mat[xx]*mat[xx]+mat[yy]*mat[yy]+mat[zz]*mat[zz]
00256                + (T)2*mat[xy]*mat[xy] + (T)2*mat[xz]*mat[xz] + (T)2*mat[yz]*mat[yz];
00257     }
00258     static T contractIndexes(Array<T,n> const& A, Array<T,n> const& B) {
00259         return A[xx]*B[xx]+A[yy]*B[yy]+A[zz]*B[zz]
00260             + (T)2*(A[xy]*B[xy] + A[xz]*B[xz] + A[yz]*B[yz]);
00261     }
00262     static T trace(Array<T,n> const &A) {
00263         return A[xx] + A[yy] + A[zz];
00264     }
00265     static Array<T,n> id() {
00266         Array<T,n> I;
00267         
00268         I[0] = (T)1;
00269         I[1] = T();
00270         I[2] = T();
00271         I[3] = (T)1;
00272         I[4] = T();
00273         I[5] = (T)1;
00274         
00275         return I;
00276     }
00277 };
00278 
00280 template <typename T, template<typename U> class Descriptor>
00281 struct SymmetricTensor {
00283     static const int d = Descriptor<T>::d;
00285     static const int n = SymmetricTensorImpl<T,d>::n;
00286     static void matVectMult(Array<T,n> const& mat, Array<T,d> const& vect, Array<T,d>& result) {
00287         SymmetricTensorImpl<T,d>::matVectMult(mat, vect, result);
00288     }
00289     static T tensorNormSqr(Array<T,n> const& mat) {
00290         return SymmetricTensorImpl<T,d>::tensorNormSqr(mat);
00291     }
00292     static T contractIndexes(Array<T,n> const& A, Array<T,n> const& B) {
00293         return SymmetricTensorImpl<T,d>::contractIndexes(A,B);
00294     }
00295     static T trace(Array<T,n> const &A) {
00296         return SymmetricTensorImpl<T,d>::trace(A);
00297     }
00298     static Array<T,n> id() {
00299         return SymmetricTensorImpl<T,d>::id();
00300     }
00301 };
00302 
00303 template <typename T, int d> struct SymmetricRankThreeTensorImpl { };
00304 
00305 template<typename T> struct SymmetricRankThreeTensorImpl<T,2> {
00306     static const int n = 4;
00307     enum Indices { xxx=0, xxy=1, xyy=2, yyy = 3 };
00308     static void contractLastTwoIndexes(Array<T,n> const& tens, Array<T,2> & res) {
00309         res[0] = tens[xxx] + tens[xyy];
00310         res[1] = tens[xxy] + tens[yyy];
00311     }
00312     
00313     static T contractIndexes(Array<T,n> const& A, Array<T,n> const& B) {
00314         return A[xxx]*B[xxx] + A[yyy]*B[yyy] + (T)3*(A[xxy]*B[xxy] + A[xyy]*B[xyy]);
00315     }
00316     
00317     static void multWithRankTwoSymTensor(Array<T,n> const&A, Array<T,SymmetricTensorImpl<T,2>::n> const &B,
00318                                          Array<T,2> &x) {
00319         x[0] = A[xxx]*B[SymmetricTensorImpl<T,2>::xx] + (T)2*A[xxy]*B[SymmetricTensorImpl<T,2>::xy] + A[xyy]*B[SymmetricTensorImpl<T,2>::yy];
00320         x[1] = A[xxy]*B[SymmetricTensorImpl<T,2>::xx] + (T)2*A[xyy]*B[SymmetricTensorImpl<T,2>::xy] + A[yyy]*B[SymmetricTensorImpl<T,2>::yy];
00321     }
00322 };
00323 
00324 template<typename T> struct SymmetricRankThreeTensorImpl<T,3> {
00325     static const int n = 10;
00326     enum Indices { xxx=0, xxy=1, xxz=2, xyy=3, xyz=4, xzz=5, yyy=6, yyz=7, yzz=8, zzz=9 };
00327     static void contractLastTwoIndexes(Array<T,n> const& tens, Array<T,3> & res) {
00328         res[0] = tens[xxx] + tens[xyy] + tens[xzz];
00329         res[1] = tens[xxy] + tens[yyy] + tens[yzz];
00330         res[2] = tens[xxz] + tens[yyz] + tens[zzz];
00331     }
00332     
00333     static T contractIndexes(Array<T,n> const& A, Array<T,n> const& B) {
00334         return A[xxx]*B[xxx] + A[yyy]*B[yyy] + A[zzz]*B[zzz] 
00335             + (T)3*(A[xxy]*B[xxy] + A[xxz]*B[xxz] + A[xyy]*B[xyy] + A[xzz]*B[xzz] + A[yzz]*B[yzz] + A[yyz]*B[yyz])
00336             + (T)6*A[xyz]*B[xyz];
00337     }
00338     
00339     static void multWithRankTwoSymTensor(Array<T,n> const&A, Array<T,SymmetricTensorImpl<T,3>::n> const &B,
00340                                          Array<T,3> &x) {
00341         x[0] = A[xxx]*B[SymmetricTensorImpl<T,3>::xx] + A[xyy]*B[SymmetricTensorImpl<T,3>::yy] + A[xzz]*B[SymmetricTensorImpl<T,3>::zz]
00342             + (T)2*(A[xxy]*B[SymmetricTensorImpl<T,3>::xy] + A[xxz]*B[SymmetricTensorImpl<T,3>::xz] + A[xyz]*B[SymmetricTensorImpl<T,3>::yz]);
00343         x[1] = A[yyy]*B[SymmetricTensorImpl<T,3>::yy] + A[xxy]*B[SymmetricTensorImpl<T,3>::xx] + A[yzz]*B[SymmetricTensorImpl<T,3>::zz]
00344             + (T)2*(A[xyy]*B[SymmetricTensorImpl<T,3>::xy] + A[yyz]*B[SymmetricTensorImpl<T,3>::yz] + A[xyz]*B[SymmetricTensorImpl<T,3>::xz]);
00345         x[2] = A[zzz]*B[SymmetricTensorImpl<T,3>::zz] + A[xxz]*B[SymmetricTensorImpl<T,3>::xx] + A[yyz]*B[SymmetricTensorImpl<T,3>::yy]
00346             + (T)2*(A[xzz]*B[SymmetricTensorImpl<T,3>::xz] + A[yzz]*B[SymmetricTensorImpl<T,3>::yz] + A[xyz]*B[SymmetricTensorImpl<T,3>::xy]);
00347     }
00348 };
00349 
00351 template <typename T, template<typename U> class Descriptor>
00352 struct SymmetricRankThreeTensor {
00354     static const int d = Descriptor<T>::d;
00356     static const int n = SymmetricRankThreeTensorImpl<T,d>::n;
00358     static void contractLastTwoIndexes(Array<T,n> const& tens, Array<T,d> &res) {
00359         SymmetricRankThreeTensorImpl<T,d>::contractLastTwoIndexes(tens, res);
00360     }
00362     static T contractIndexes(Array<T,n> const& A, Array<T,n> const& B) {
00363         return SymmetricRankThreeTensorImpl<T,d>::contractIndexes(A, B);
00364     }
00365     static void multWithRankTwoSymTensor(Array<T,n> const&A, Array<T,SymmetricTensor<T,Descriptor>::n> const &B,
00366                                          Array<T,d> &x) {
00367         SymmetricRankThreeTensorImpl<T,d>::multWithRankTwoSymTensor(A, B, x);
00368     }
00369 };
00370 
00371 template <typename T, int d> struct SymmetricRankFourTensorImpl { };
00372 
00373 template<typename T> struct SymmetricRankFourTensorImpl<T,2> {
00374     static const int n = 5;
00375     enum Indices { xxxx=0, xxxy=1, xxyy=2, xyyy = 3, yyyy = 4 };
00376     
00377     static T contractIndexes(Array<T,n> const& A, Array<T,n> const& B) {
00378         return A[xxxx]*B[xxxx] + A[yyyy]*B[yyyy] + (T)4*(A[xxxy]*B[xxxy] + A[xyyy]*B[xyyy]) + (T)6*A[xxyy]*B[xxyy];
00379     }
00381     static void contractLastTwoIndexes(Array<T,n> const& tens, Array<T,3> &res) {
00382         res[SymmetricTensorImpl<T,2>::xx] = tens[xxxx]+tens[xxyy];
00383         res[SymmetricTensorImpl<T,2>::xy] = tens[xxxy]+tens[xyyy];
00384         res[SymmetricTensorImpl<T,2>::yy] = tens[xxyy]+tens[yyyy];
00385     }
00387     static void multWithRankThreeSymTensor(Array<T,n> const&A, 
00388                                            Array<T,SymmetricRankThreeTensorImpl<T,2>::n> const &B,
00389                                            Array<T,2> &x) {
00390         typedef SymmetricRankThreeTensorImpl<T,2> SRT;
00391         
00392         x[0] = A[xxxx]*B[SRT::xxx]+(T)3*(A[xxxy]*B[SRT::xxy]+A[xxyy]*B[SRT::xyy])+A[xyyy]*B[SRT::yyy];
00393         x[1] = A[xxxy]*B[SRT::xxx]+(T)3*(A[xxyy]*B[SRT::xxy]+A[xyyy]*B[SRT::xyy])+A[yyyy]*B[SRT::yyy];
00394     }
00395 };
00396 
00397 template<typename T> struct SymmetricRankFourTensorImpl<T,3> {
00398     static const int n = 15;
00399     enum Indices { xxxx=0, xxxy=1, xxxz=2, xxyy=3, xxyz=4, xxzz=5, xyyy=6, xyyz=7, xyzz=8, xzzz=9, 
00400                    yyyy=10, yyyz=11, yyzz=12, yzzz=13, zzzz=14 };
00401                    
00402     static T contractIndexes(Array<T,n> const& A, Array<T,n> const& B) {
00403         return A[xxxx]*B[xxxx] + A[yyyy]*B[yyyy] + A[zzzz]*B[zzzz] 
00404             + (T)4*(A[xxxy]*B[xxxy] + A[xxxz]*B[xxxz] + A[xyyy]*B[xyyy] + A[xzzz]*B[xzzz] + A[yyyz]*B[yyyz] + A[yzzz]*B[yzzz])
00405             + (T)6*(A[xxyy]*B[xxyy] + A[xxzz]*B[xxzz] + A[yyzz]*B[yyzz])
00406             + (T)12*(A[xxyz]*B[xxyz] + A[xyyz]*B[xyyz] + A[xyzz]*B[xyzz]);
00407     }
00409     static void contractLastTwoIndexes(Array<T,n> const& tens, Array<T,6> &res) {
00410         res[SymmetricTensorImpl<T,3>::xx] = tens[xxxx]+tens[xxyy]+tens[xxzz];
00411         res[SymmetricTensorImpl<T,3>::xy] = tens[xxxy]+tens[xyyy]+tens[xyzz];
00412         res[SymmetricTensorImpl<T,3>::xz] = tens[xxxz]+tens[xyyz]+tens[xzzz];
00413         res[SymmetricTensorImpl<T,3>::yy] = tens[xxyy]+tens[yyyy]+tens[yyzz];
00414         res[SymmetricTensorImpl<T,3>::yz] = tens[xxyz]+tens[yyyz]+tens[yzzz];
00415         res[SymmetricTensorImpl<T,3>::zz] = tens[xxzz]+tens[yyzz]+tens[zzzz];
00416     }
00417     static void multWithRankThreeSymTensor(Array<T,n> const&A, 
00418                                            Array<T,SymmetricRankThreeTensorImpl<T,3>::n> const &B,
00419                                            Array<T,3> &x) {
00420         typedef SymmetricRankThreeTensorImpl<T,3> SRT;
00421         
00422         x[0] = A[xxxx]*B[SRT::xxx]+A[xyyy]*B[SRT::yyy]+A[xzzz]*B[SRT::zzz]
00423             +(T)3*(A[xxxy]*B[SRT::xxy]+A[xxyy]*B[SRT::xyy]+A[xxxz]*B[SRT::xxz]+A[xyyz]*B[SRT::yyz]+A[xxzz]*B[SRT::xzz]+A[xyzz]*B[SRT::yzz])
00424             +(T)6*A  [xxyz]*B[SRT::xyz];
00425         
00426         x[1] = A[yyyy]*B[SRT::yyy]+A[xxxy]*B[SRT::xxx]+A[yzzz]*B[SRT::zzz]
00427             +(T)3*(A[xxyy]*B[SRT::xxy]+A[xyyy]*B[SRT::xyy]+A[yyyz]*B[SRT::yyz]+A[yyzz]*B[SRT::yzz]+A[xyzz]*B[SRT::xzz]+A[xxyz]*B[SRT::xxz])
00428             +(T)6*A[xyyz]*B[SRT::xyz];
00429         
00430         x[2] = A[zzzz]*B[SRT::zzz]+A[xxxz]*B[SRT::xxx]+A[yyyz]*B[SRT::yyy]
00431             +(T)3*(A[xxyz]*B[SRT::xxy]+A[xyyz]*B[SRT::xyy]+A[xxzz]*B[SRT::xxz]+A[yyzz]*B[SRT::yyz]+A[xzzz]*B[SRT::xzz]+A[yzzz]*B[SRT::yzz])
00432             +(T)6*A[xyzz]*B[SRT::xyz];
00433     }
00434 };
00435 
00437 template <typename T, template<typename U> class Descriptor>
00438 struct SymmetricRankFourTensor {
00440     static const int d = Descriptor<T>::d;
00442     static const int n = SymmetricRankFourTensorImpl<T,d>::n;
00443     
00445     static T contractIndexes(Array<T,n> const& A, Array<T,n> const& B) {
00446         return SymmetricRankFourTensorImpl<T,d>::contractIndexes(A, B);
00447     }
00449     static void contractLastTwoIndexes(Array<T,n> const& tens, Array<T,SymmetricTensor<T,Descriptor>::n> &res) {
00450         SymmetricRankFourTensorImpl<T,d>::contractLastTwoIndexes(tens, res);
00451     }
00452     static void multWithRankThreeSymTensor(Array<T,n> const&A, 
00453                                            Array<T,SymmetricRankThreeTensor<T,Descriptor>::n> const &B,
00454                                            Array<T,d> &x) {
00455         SymmetricRankFourTensorImpl<T,d>::multWithRankThreeSymTensor(A, B, x);
00456     }
00457 };
00458 
00459 template <typename T>
00460 void crossProduct(Array<T,3> const& u1, Array<T,3> const& u2, Array<T,3>& result)
00461 {
00462     result[0] = u1[1]*u2[2] - u1[2]*u2[1];
00463     result[1] = u1[2]*u2[0] - u1[0]*u2[2];
00464     result[2] = u1[0]*u2[1] - u1[1]*u2[0];
00465 }
00466 
00468 template<typename T, pluint n>
00469 T dot(Array<T,n> const& v1, Array<T,n> const& v2) {
00470     return VectorTemplateImpl<T,n>::scalarProduct(v1,v2);
00471 }
00472 
00474 template<typename T, pluint n>
00475 T dot(T v1[n], Array<T,n> const& v2) {
00476     return VectorTemplateImpl<T,n>::scalarProduct(v1,v2);
00477 }
00478 
00479 template<typename T, pluint n>
00480 T normSqr(Array<T,n> const& v) {
00481     return VectorTemplateImpl<T,n>::normSqr(v);
00482 }
00483 
00484 template<typename T, pluint n>
00485 T norm(Array<T,n> const& v) {
00486     return sqrt(normSqr<T,n>(v));
00487 }
00488 
00489 template<typename T>
00490 T computeTriangleArea(Array<T,3> const& v0, Array<T,3> const& v1, Array<T,3> const& v2)
00491 {
00492     Array<T,3> e01 = v1 - v0;
00493     Array<T,3> e02 = v2 - v0;
00494     Array<T,3> cross;
00495     crossProduct<T>(e01, e02, cross);
00496 
00497     return 0.5 * norm<T,3>(cross);
00498 }
00499 
00500 template<typename T>
00501 T computeTriangleArea(T *v0, T *v1, T *v2)
00502 {
00503     int i;
00504     T e01[3], e02[3], cross[3];
00505 
00506     for (i = 0; i < 3; e01[i] = v1[i] - v0[i], i++)
00507         ;
00508     for (i = 0; i < 3; e02[i] = v2[i] - v0[i], i++)
00509         ;
00510 
00511     cross[0] = e01[1]*e02[2] - e01[2]*e02[1];
00512     cross[1] = e01[2]*e02[0] - e01[0]*e02[2];
00513     cross[2] = e01[0]*e02[1] - e01[1]*e02[0];
00514 
00515     return 0.5 * sqrt(cross[0]*cross[0] + cross[1]*cross[1] + cross[2]*cross[2]);
00516 }
00517 
00520 template<typename T>
00521 T angleBetweenVectors(Array<T,3> const& v1, Array<T,3> const& v2)
00522 {
00523     Array<T,3> cross;
00524     crossProduct<T>(v1, v2, cross); 
00525     return atan2(norm(cross), dot(v1,v2));
00526 }
00527 
00528 template<typename T>
00529 Array<T,3> rotateAtOrigin(Array<T,3> const& p, Array<T,3> const& normedAxis, T theta) {
00530     Array<T,3> const& u = normedAxis;
00531     T d = sqrt(u[1]*u[1] + u[2]*u[2]);
00532 
00533     Array<T,3> q1 = p;
00534     Array<T,3> q2 = q1;
00535 
00536     T eps = 1.e-2;
00537     //T eps = (T)100.*std::numeric_limits<T>::epsilon();
00538     // Rotate about the x-axis to be in xz-plane.
00539     if (!util::fpequal(d, (T)0., eps)) {
00540         q2[0] = q1[0];
00541         q2[1] = q1[1] * u[2] / d - q1[2] * u[1] / d;
00542         q2[2] = q1[1] * u[1] / d + q1[2] * u[2] / d;
00543     }
00544 
00545     // Rotate about the y-axis to fall on z-axis.
00546     q1[0] = q2[0] * d - q2[2] * u[0];
00547     q1[1] = q2[1];
00548     q1[2] = q2[0] * u[0] + q2[2] * d;
00549 
00550     // Perform desired rotation.
00551     T ct = cos(theta);
00552     T st = sin(theta);
00553     q2[0] = q1[0] * ct - q1[1] * st;
00554     q2[1] = q1[0] * st + q1[1] * ct;
00555     q2[2] = q1[2];
00556 
00557     // Rotate backward around y-axis.
00558     q1[0] =   q2[0] * d + q2[2] * u[0];
00559     q1[1] =   q2[1];
00560     q1[2] = - q2[0] * u[0] + q2[2] * d;
00561 
00562     q2 = q1;
00563     // Rotate backward around x-axis.
00564     if (!util::fpequal(d, (T)0., eps)) {
00565         q2[0] =   q1[0];
00566         q2[1] =   q1[1] * u[2] / d + q1[2] * u[1] / d;
00567         q2[2] = - q1[1] * u[1] / d + q1[2] * u[2] / d;
00568     }
00569 
00570     return q2;
00571 }
00572   
00573 }  // namespace plb
00574 
00575 #endif