UblasCustomFunctions.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste 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 Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 
00030 #ifndef UBLASCUSTOMFUNCTIONS_HPP_
00031 #define UBLASCUSTOMFUNCTIONS_HPP_
00032 
00033 #include <boost/numeric/ublas/matrix.hpp>
00034 #include <boost/numeric/ublas/vector.hpp>
00035 
00036 #include <boost/numeric/ublas/matrix_proxy.hpp>
00037 #include <boost/numeric/ublas/io.hpp>
00038 #include <boost/numeric/ublas/matrix_expression.hpp>
00039 
00040 #include "petscblaslapack.h"
00041 //Promote universal LAPACK name if it's an old version of PETSc
00042 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00043 #define LAPACKgeev_ LAgeev_
00044 #endif
00045 
00046 #include <cfloat>
00047 #define TINY DBL_EPSILON
00048 
00049 #include "Exception.hpp"
00050 
00051 
00052 
00053 using namespace boost::numeric::ublas;
00061 template<class T>
00062 T Determinant(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM)
00063 {
00064     using namespace boost::numeric::ublas;
00065 
00066     return rM(0,0);
00067 }
00071 template<class T>
00072 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM, const unsigned missrow, const unsigned misscol)
00073 {
00074     using namespace boost::numeric::ublas;
00075 
00076     assert(missrow==0);
00077     assert(misscol==0);
00078     return 1.0;
00079 }
00080 
00081 template<class T>
00082 T Determinant(const boost::numeric::ublas::c_matrix<T,2,2>& rM)
00083 {
00084     using namespace boost::numeric::ublas;
00085 #define SMALL_POW(x, a)
00086 #define SMALL_POW(x, a)
00087 #define SMALL_POW(x, a)
00088 
00089     return rM(0,0)*rM(1,1) - rM(1,0)*rM(0,1);
00090 }
00091 
00095 template<class T>
00096 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 2>& rM, const unsigned missrow, const unsigned misscol)
00097 {
00098     using namespace boost::numeric::ublas;
00099 
00100     assert(missrow < 2);
00101     assert(misscol < 2);
00102 
00103     unsigned row = (missrow==1) ? 0 : 1;
00104     unsigned col = (misscol==1) ? 0 : 1;
00105     return rM(row,col);
00106 }
00107 
00108 template<class T>
00109 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM, const unsigned missrow, const unsigned misscol)
00110 {
00111     using namespace boost::numeric::ublas;
00112 
00113     assert(missrow < 2);
00114     assert(misscol < 1);
00115 
00116     unsigned row = (missrow==1) ? 0 : 1;
00117     unsigned col = (misscol==1) ? 0 : 1;
00118     return rM(row,col);
00119 }
00120 
00121 template<class T>
00122 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM)
00123 {
00124     using namespace boost::numeric::ublas;
00125 
00126     return    rM(0,0) * (rM(1,1)*rM(2,2) - rM(1,2)*rM(2,1))
00127             - rM(0,1) * (rM(1,0)*rM(2,2) - rM(1,2)*rM(2,0))
00128             + rM(0,2) * (rM(1,0)*rM(2,1) - rM(1,1)*rM(2,0));
00129 }
00130 
00136 template<class T>
00137 T Determinant(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM)
00138 {
00139     using namespace boost::numeric::ublas;
00140 
00141     return   std::sqrt(rM(0,0) * rM(0,0) + rM(1,0) * rM(1,0));
00142 }
00143 
00149 template<class T>
00150 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM)
00151 {
00152     using namespace boost::numeric::ublas;
00153 
00154     return std::sqrt(rM(0,0)*rM(0,0) + rM(1,0)*rM(1,0) + rM(2,0)*rM(2,0));
00155 }
00156 
00162 template<class T>
00163 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM)
00164 {
00165     using namespace boost::numeric::ublas;
00166 
00167     c_matrix<T,2,2> product = prod(trans(rM), rM);
00168 
00169     return std::sqrt(Determinant(product));
00170 }
00171 
00179 template<class T>
00180 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 0>& rM)
00181 {
00182     NEVER_REACHED;
00183 }
00184 
00192 template<class T>
00193 T Determinant(const boost::numeric::ublas::c_matrix<T, 2, 0>& rM)
00194 {
00195     NEVER_REACHED;
00196 }
00197 
00205 template<class T>
00206 T Determinant(const boost::numeric::ublas::c_matrix<T, 1, 0>& rM)
00207 {
00208     NEVER_REACHED;
00209 }
00210 
00214 template<class T>
00215 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 0>& rM, const unsigned missrow, const unsigned misscol)
00216 {
00217     NEVER_REACHED;
00218 }
00219 
00223 template<class T>
00224 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 0>& rM, const unsigned missrow, const unsigned misscol)
00225 {
00226     NEVER_REACHED;
00227 }
00228 
00232 template<class T>
00233 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 1, 0>& rM, const unsigned missrow, const unsigned misscol)
00234 {
00235     NEVER_REACHED;
00236 }
00237 
00241 template<class T>
00242 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM, const unsigned missrow, const unsigned misscol)
00243 {
00244     using namespace boost::numeric::ublas;
00245 
00246     assert(missrow < 3);
00247     //assert(misscol < 2);
00248 
00249     unsigned lorow = (missrow==0) ? 1 : 0;
00250     unsigned hirow = (missrow==2) ? 1 : 2;
00251     unsigned locol = (misscol==0) ? 1 : 0;
00252     unsigned hicol = (misscol==2) ? 1 : 2;
00253     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00254 }
00255 
00259 template<class T>
00260 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM, const unsigned missrow, const unsigned misscol)
00261 {
00262     using namespace boost::numeric::ublas;
00263 
00264     assert(missrow < 3);
00265     assert(misscol < 1);
00266 
00267     unsigned lorow = (missrow==0) ? 1 : 0;
00268     unsigned hirow = (missrow==2) ? 1 : 2;
00269     unsigned locol = (misscol==0) ? 1 : 0;
00270     unsigned hicol = (misscol==2) ? 1 : 2;
00271     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00272 }
00273 
00277 template<class T>
00278 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM, const unsigned missrow, const unsigned misscol)
00279 {
00280     using namespace boost::numeric::ublas;
00281 
00282     assert(missrow < 3);
00283     assert(misscol < 3);
00284 
00285     unsigned lorow = (missrow==0) ? 1 : 0;
00286     unsigned hirow = (missrow==2) ? 1 : 2;
00287     unsigned locol = (misscol==0) ? 1 : 0;
00288     unsigned hicol = (misscol==2) ? 1 : 2;
00289     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00290 }
00291 
00298 template<class T>
00299 boost::numeric::ublas::c_matrix<T, 1, 1> Inverse(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM)
00300 {
00301     using namespace boost::numeric::ublas;
00302 
00303     c_matrix<T,1,1> inverse;
00304     T det = Determinant(rM);
00305     assert( fabs(det) > TINY ); // else it is a singular matrix
00306     inverse(0,0) =  1.0/det;
00307     return inverse;
00308 }
00309 
00310 template<class T>
00311 boost::numeric::ublas::c_matrix<T, 2, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM)
00312 {
00313     using namespace boost::numeric::ublas;
00314 
00315     c_matrix<T, 2, 3> inverse;
00316 
00317     //
00318     // calculate (T'T)^-1, where T'T = (a b)
00319     //                                 (c d)
00320 
00321     T a = rM(0,0)*rM(0,0) + rM(1,0)*rM(1,0) + rM(2,0)*rM(2,0);
00322     T b = rM(0,0)*rM(0,1) + rM(1,0)*rM(1,1) + rM(2,0)*rM(2,1);
00323     T c = b;
00324     T d = rM(0,1)*rM(0,1) + rM(1,1)*rM(1,1) + rM(2,1)*rM(2,1);
00325 
00326     T det = a*d - b*c;
00327 
00328     T a_inv =  d/det;
00329     T b_inv = -b/det;
00330     T c_inv = -c/det;
00331     T d_inv =  a/det;
00332 
00333     inverse(0,0) = a_inv*rM(0,0) + b_inv*rM(0,1);
00334     inverse(1,0) = c_inv*rM(0,0) + d_inv*rM(0,1);
00335     inverse(0,1) = a_inv*rM(1,0) + b_inv*rM(1,1);
00336     inverse(1,1) = c_inv*rM(1,0) + d_inv*rM(1,1);
00337     inverse(0,2) = a_inv*rM(2,0) + b_inv*rM(2,1);
00338     inverse(1,2) = c_inv*rM(2,0) + d_inv*rM(2,1);
00339 
00340     return inverse;
00341 }
00342 
00343 template<class T>
00344 boost::numeric::ublas::c_matrix<T, 2, 2> Inverse(const boost::numeric::ublas::c_matrix<T, 2, 2>& rM)
00345 {
00346     using namespace boost::numeric::ublas;
00347 
00348     c_matrix<T, 2, 2> inverse;
00349     T det = Determinant(rM);
00350 
00351     assert( fabs(det) > TINY ); // else it is a singular matrix
00352     inverse(0,0)  =  rM(1,1)/det;
00353     inverse(0,1)  = -rM(0,1)/det;
00354     inverse(1,0)  = -rM(1,0)/det;
00355     inverse(1,1)  =  rM(0,0)/det;
00356     return inverse;
00357 }
00358 
00359 template<class T>
00360 boost::numeric::ublas::c_matrix<T, 3, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM)
00361 {
00362     using namespace boost::numeric::ublas;
00363 
00364     c_matrix<T, 3, 3> inverse;
00365     T det = Determinant(rM);
00366     assert( fabs(det) > TINY ); // else it is a singular matrix
00367 
00368     inverse(0,0) =  (rM(1,1)*rM(2,2) - rM(1,2)*rM(2,1))/det;
00369     inverse(1,0) = -(rM(1,0)*rM(2,2) - rM(1,2)*rM(2,0))/det;
00370     inverse(2,0) =  (rM(1,0)*rM(2,1) - rM(1,1)*rM(2,0))/det;
00371     inverse(0,1) = -(rM(0,1)*rM(2,2) - rM(0,2)*rM(2,1))/det;
00372     inverse(1,1) =  (rM(0,0)*rM(2,2) - rM(0,2)*rM(2,0))/det;
00373     inverse(2,1) = -(rM(0,0)*rM(2,1) - rM(0,1)*rM(2,0))/det;
00374     inverse(0,2) =  (rM(0,1)*rM(1,2) - rM(0,2)*rM(1,1))/det;
00375     inverse(1,2) = -(rM(0,0)*rM(1,2) - rM(0,2)*rM(1,0))/det;
00376     inverse(2,2) =  (rM(0,0)*rM(1,1) - rM(0,1)*rM(1,0))/det;
00377 
00378     return inverse;
00379 }
00380 
00386 template<class T>
00387 boost::numeric::ublas::c_matrix<T, 1, 2> Inverse(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM)
00388 {
00389     using namespace boost::numeric::ublas;
00390 
00391     c_matrix<T, 1, 2> inverse;
00392     T det = Determinant(rM);
00393 
00394     inverse(0,0) = rM(0,0)/det/det;
00395     inverse(0,1) = rM(1,0)/det/det;
00396 
00397     return inverse;
00398 }
00399 
00405 template<class T>
00406 boost::numeric::ublas::c_matrix<T, 1, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM)
00407 {
00408     using namespace boost::numeric::ublas;
00409 
00410     c_matrix<T, 1, 3> inverse;
00411     T det = Determinant(rM);
00412 
00413     inverse(0,0) = rM(0,0)/det/det;
00414     inverse(0,1) = rM(1,0)/det/det;
00415     inverse(0,2) = rM(2,0)/det/det;
00416 
00417     return inverse;
00418 }
00419 
00420 template<class T>
00421 c_vector<T, 3> VectorProduct(const c_vector<T, 3>& rA, const c_vector<T, 3>& rB)
00422 {
00426 
00427     c_vector<T, 3> result;
00428 
00429     double x1 = rA(0);
00430     double y1 = rA(1);
00431     double z1 = rA(2);
00432     double x2 = rB(0);
00433     double y2 = rB(1);
00434     double z2 = rB(2);
00435 
00436     result(0) = y1*z2 - z1*y2;
00437     result(1) = z1*x2 - x1*z2;
00438     result(2) = x1*y2 - y1*x2;
00439 
00440     return result;
00441 }
00442 
00443 template<class T>
00444 T Trace(const c_matrix<T, 1, 1>& rM)
00445 {
00446     return rM(0,0);
00447 }
00448 
00449 template<class T>
00450 T Trace(const c_matrix<T, 2, 2>& rM)
00451 {
00452     return rM(0,0) + rM(1,1);
00453 }
00454 
00455 template<class T>
00456 T Trace(const c_matrix<T, 3, 3>& rM)
00457 {
00458     return rM(0,0) + rM(1,1) + rM(2,2);
00459 }
00460 
00461 template<class T>
00462 T Trace(const c_matrix<T, 4, 4>& rM)
00463 {
00464     return rM(0,0) + rM(1,1) + rM(2,2) + rM(3,3);
00465 }
00466 
00472 template<class T>
00473 T SecondInvariant(const c_matrix<T, 3, 3>& rM)
00474 {
00475     return    rM(0,0)*rM(1,1) + rM(1,1)*rM(2,2) + rM(2,2)*rM(0,0)
00476             - rM(1,0)*rM(1,0) - rM(2,1)*rM(2,1) - rM(2,0)*rM(2,0);
00477 }
00478 
00483 template<class T>
00484 T SecondInvariant(const c_matrix<T, 2, 2>& rM)
00485 {
00486     return Determinant(rM);
00487 }
00488 
00492 c_vector<double, 1> Create_c_vector(double x);
00493 
00494 c_vector<double, 2> Create_c_vector(double x, double y);
00495 
00496 c_vector<double, 3> Create_c_vector(double x, double y, double z);
00497 
00506 c_vector<double,3> CalculateEigenvectorForSmallestNonzeroEigenvalue(c_matrix<double, 3, 3>& rA);
00507 
00514 double SmallPow(double x, unsigned exponent);
00515 
00516 
00517 #endif /*UBLASCUSTOMFUNCTIONS_HPP_*/
00518 

Generated by  doxygen 1.6.2