UblasCustomFunctions.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
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_MINOR == 2) //Old API
00043 #define LAPACKgeev_ LAgeev_
00044 #endif
00045 
00046 //#include <iostream>
00047 //#include <fstream>
00048 //#include <vector>
00049 
00050 #include <cfloat>
00051 #define TINY DBL_EPSILON
00052 
00053 #include "Exception.hpp"
00054 
00055 using namespace boost::numeric::ublas;
00063 template<class T>
00064 T Determinant(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM)
00065 {
00066     using namespace boost::numeric::ublas;
00067 
00068     return rM(0,0);
00069 }
00073 template<class T>
00074 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM, const unsigned missrow, const unsigned misscol)
00075 {
00076     using namespace boost::numeric::ublas;
00077 
00078     assert(missrow==0);
00079     assert(misscol==0);
00080     return 1.0;
00081 }
00082 
00083 template<class T>
00084 T Determinant(const boost::numeric::ublas::c_matrix<T,2,2>& rM)
00085 {
00086     using namespace boost::numeric::ublas;
00087 
00088     return rM(0,0)*rM(1,1) - rM(1,0)*rM(0,1);
00089 }
00090 
00094 template<class T>
00095 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 2>& rM, const unsigned missrow, const unsigned misscol)
00096 {
00097     using namespace boost::numeric::ublas;
00098 
00099     assert(missrow < 2);
00100     assert(misscol < 2);
00101 
00102     unsigned row = (missrow==1) ? 0 : 1;
00103     unsigned col = (misscol==1) ? 0 : 1;
00104     return rM(row,col);
00105 }
00106 
00107 template<class T>
00108 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM, const unsigned missrow, const unsigned misscol)
00109 {
00110     using namespace boost::numeric::ublas;
00111 
00112     assert(missrow < 2);
00113     assert(misscol < 1);
00114 
00115     unsigned row = (missrow==1) ? 0 : 1;
00116     unsigned col = (misscol==1) ? 0 : 1;
00117     return rM(row,col);
00118 }
00119 
00120 template<class T>
00121 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM)
00122 {
00123     using namespace boost::numeric::ublas;
00124 
00125     return    rM(0,0) * (rM(1,1)*rM(2,2) - rM(1,2)*rM(2,1))
00126             - rM(0,1) * (rM(1,0)*rM(2,2) - rM(1,2)*rM(2,0))
00127             + rM(0,2) * (rM(1,0)*rM(2,1) - rM(1,1)*rM(2,0));
00128 }
00129 
00135 template<class T>
00136 T Determinant(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM)
00137 {
00138     using namespace boost::numeric::ublas;
00139 
00140     return   std::sqrt(rM(0,0) * rM(0,0) + rM(1,0) * rM(1,0));
00141 }
00142 
00148 template<class T>
00149 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM)
00150 {
00151     using namespace boost::numeric::ublas;
00152 
00153     return std::sqrt(rM(0,0)*rM(0,0) + rM(1,0)*rM(1,0) + rM(2,0)*rM(2,0));
00154 }
00155 
00161 template<class T>
00162 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM)
00163 {
00164     using namespace boost::numeric::ublas;
00165     
00166     c_matrix<T,2,2> product = prod(trans(rM), rM);
00167     
00168     return std::sqrt(Determinant(product));
00169 }
00170 
00178 template<class T>
00179 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 0>& rM)
00180 {
00181     NEVER_REACHED;
00182 }
00183 
00191 template<class T>
00192 T Determinant(const boost::numeric::ublas::c_matrix<T, 2, 0>& rM)
00193 {
00194     NEVER_REACHED;
00195 }
00196 
00204 template<class T>
00205 T Determinant(const boost::numeric::ublas::c_matrix<T, 1, 0>& rM)
00206 {
00207     NEVER_REACHED;
00208 }
00209 
00213 template<class T>
00214 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 0>& rM, const unsigned missrow, const unsigned misscol)
00215 {
00216     NEVER_REACHED;
00217 }
00218 
00222 template<class T>
00223 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 0>& rM, const unsigned missrow, const unsigned misscol)
00224 {
00225     NEVER_REACHED;
00226 }
00227 
00231 template<class T>
00232 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 1, 0>& rM, const unsigned missrow, const unsigned misscol)
00233 {
00234     NEVER_REACHED;
00235 }
00236 
00240 template<class T>
00241 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM, const unsigned missrow, const unsigned misscol)
00242 {
00243     using namespace boost::numeric::ublas;
00244 
00245     assert(missrow < 3);
00246     //assert(misscol < 2);
00247 
00248     unsigned lorow = (missrow==0) ? 1 : 0;
00249     unsigned hirow = (missrow==2) ? 1 : 2;
00250     unsigned locol = (misscol==0) ? 1 : 0;
00251     unsigned hicol = (misscol==2) ? 1 : 2;
00252     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00253 }
00254 
00258 template<class T>
00259 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM, const unsigned missrow, const unsigned misscol)
00260 {
00261     using namespace boost::numeric::ublas;
00262 
00263     assert(missrow < 3);
00264     assert(misscol < 1);
00265 
00266     unsigned lorow = (missrow==0) ? 1 : 0;
00267     unsigned hirow = (missrow==2) ? 1 : 2;
00268     unsigned locol = (misscol==0) ? 1 : 0;
00269     unsigned hicol = (misscol==2) ? 1 : 2;
00270     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00271 }
00272 
00276 template<class T>
00277 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM, const unsigned missrow, const unsigned misscol)
00278 {
00279     using namespace boost::numeric::ublas;
00280 
00281     assert(missrow < 3);
00282     assert(misscol < 3);
00283 
00284     unsigned lorow = (missrow==0) ? 1 : 0;
00285     unsigned hirow = (missrow==2) ? 1 : 2;
00286     unsigned locol = (misscol==0) ? 1 : 0;
00287     unsigned hicol = (misscol==2) ? 1 : 2;
00288     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00289 }
00290 
00297 template<class T>
00298 boost::numeric::ublas::c_matrix<T, 1, 1> Inverse(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM)
00299 {
00300     using namespace boost::numeric::ublas;
00301 
00302     c_matrix<T,1,1> inverse;
00303     T det = Determinant(rM);
00304     assert( fabs(det) > TINY ); // else it is a singular matrix
00305     inverse(0,0) =  1.0/det;
00306     return inverse;
00307 }
00308 
00309 template<class T>
00310 boost::numeric::ublas::c_matrix<T, 2, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM)
00311 {
00312     using namespace boost::numeric::ublas;
00313     
00314     c_matrix<T, 2, 3> inverse;
00315     
00316     //
00317     // calculate (T'T)^-1, where T'T = (a b) 
00318     //                                 (c d)
00319 
00320     T a = rM(0,0)*rM(0,0) + rM(1,0)*rM(1,0) + rM(2,0)*rM(2,0);
00321     T b = rM(0,0)*rM(0,1) + rM(1,0)*rM(1,1) + rM(2,0)*rM(2,1);
00322     T c = b;
00323     T d = rM(0,1)*rM(0,1) + rM(1,1)*rM(1,1) + rM(2,1)*rM(2,1);
00324     
00325     T det = a*d - b*c;
00326     
00327     T a_inv =  d/det;
00328     T b_inv = -b/det;
00329     T c_inv = -c/det;
00330     T d_inv =  a/det;
00331     
00332     inverse(0,0) = a_inv*rM(0,0) + b_inv*rM(0,1);
00333     inverse(1,0) = c_inv*rM(0,0) + d_inv*rM(0,1);
00334     inverse(0,1) = a_inv*rM(1,0) + b_inv*rM(1,1);
00335     inverse(1,1) = c_inv*rM(1,0) + d_inv*rM(1,1);
00336     inverse(0,2) = a_inv*rM(2,0) + b_inv*rM(2,1);
00337     inverse(1,2) = c_inv*rM(2,0) + d_inv*rM(2,1);
00338     
00339     return inverse;    
00340 }
00341 
00342 template<class T>
00343 boost::numeric::ublas::c_matrix<T, 2, 2> Inverse(const boost::numeric::ublas::c_matrix<T, 2, 2>& rM)
00344 {
00345     using namespace boost::numeric::ublas;
00346 
00347     c_matrix<T, 2, 2> inverse;
00348     T det = Determinant(rM);
00349 
00350     assert( fabs(det) > TINY ); // else it is a singular matrix
00351     inverse(0,0)  =  rM(1,1)/det;
00352     inverse(0,1)  = -rM(0,1)/det;
00353     inverse(1,0)  = -rM(1,0)/det;
00354     inverse(1,1)  =  rM(0,0)/det;
00355     return inverse;
00356 }
00357 
00358 template<class T>
00359 boost::numeric::ublas::c_matrix<T, 3, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM)
00360 {
00361     using namespace boost::numeric::ublas;
00362 
00363     c_matrix<T, 3, 3> inverse;
00364     T det = Determinant(rM);
00365     assert( fabs(det) > TINY ); // else it is a singular matrix
00366 
00367     inverse(0,0) =  (rM(1,1)*rM(2,2) - rM(1,2)*rM(2,1))/det;
00368     inverse(1,0) = -(rM(1,0)*rM(2,2) - rM(1,2)*rM(2,0))/det;
00369     inverse(2,0) =  (rM(1,0)*rM(2,1) - rM(1,1)*rM(2,0))/det;
00370     inverse(0,1) = -(rM(0,1)*rM(2,2) - rM(0,2)*rM(2,1))/det;
00371     inverse(1,1) =  (rM(0,0)*rM(2,2) - rM(0,2)*rM(2,0))/det;
00372     inverse(2,1) = -(rM(0,0)*rM(2,1) - rM(0,1)*rM(2,0))/det;
00373     inverse(0,2) =  (rM(0,1)*rM(1,2) - rM(0,2)*rM(1,1))/det;
00374     inverse(1,2) = -(rM(0,0)*rM(1,2) - rM(0,2)*rM(1,0))/det;
00375     inverse(2,2) =  (rM(0,0)*rM(1,1) - rM(0,1)*rM(1,0))/det;
00376 
00377     return inverse;
00378 }
00379 
00385 template<class T>
00386 boost::numeric::ublas::c_matrix<T, 1, 2> Inverse(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM)
00387 {
00388     using namespace boost::numeric::ublas;
00389 
00390     c_matrix<T, 1, 2> inverse;
00391     T det = Determinant(rM);
00392 
00393     inverse(0,0) = rM(0,0)/det/det;
00394     inverse(0,1) = rM(1,0)/det/det;
00395     
00396     return inverse;
00397 }
00398 
00404 template<class T>
00405 boost::numeric::ublas::c_matrix<T, 1, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM)
00406 {
00407     using namespace boost::numeric::ublas;
00408 
00409     c_matrix<T, 1, 3> inverse;
00410     T det = Determinant(rM);
00411 
00412     inverse(0,0) = rM(0,0)/det/det;
00413     inverse(0,1) = rM(1,0)/det/det;
00414     inverse(0,2) = rM(2,0)/det/det;
00415     
00416     return inverse;
00417 }
00418 
00419 template<class T>
00420 c_vector<T, 3> VectorProduct(const c_vector<T, 3>& rA, const c_vector<T, 3>& rB)
00421 {
00425 
00426     c_vector<T, 3> result;
00427 
00428     double x1 = rA(0);
00429     double y1 = rA(1);
00430     double z1 = rA(2);
00431     double x2 = rB(0);
00432     double y2 = rB(1);
00433     double z2 = rB(2);
00434 
00435     result(0) = y1*z2 - z1*y2;
00436     result(1) = z1*x2 - x1*z2;
00437     result(2) = x1*y2 - y1*x2;
00438 
00439     return result;
00440 }
00441 
00442 template<class T>
00443 T Trace(const c_matrix<T, 1, 1>& rM)
00444 {
00445     return rM(0,0);
00446 }
00447 
00448 template<class T>
00449 T Trace(const c_matrix<T, 2, 2>& rM)
00450 {
00451     return rM(0,0) + rM(1,1);
00452 }
00453 
00454 template<class T>
00455 T Trace(const c_matrix<T, 3, 3>& rM)
00456 {
00457     return rM(0,0) + rM(1,1) + rM(2,2);
00458 }
00459 
00460 template<class T>
00461 T Trace(const c_matrix<T, 4, 4>& rM)
00462 {
00463     return rM(0,0) + rM(1,1) + rM(2,2) + rM(3,3);
00464 }
00465 
00471 template<class T>
00472 T SecondInvariant(const c_matrix<T, 3, 3>& rM)
00473 {
00474     return    rM(0,0)*rM(1,1) + rM(1,1)*rM(2,2) + rM(2,2)*rM(0,0)
00475             - rM(1,0)*rM(1,0) - rM(2,1)*rM(2,1) - rM(2,0)*rM(2,0);
00476 }
00477 
00482 template<class T>
00483 T SecondInvariant(const c_matrix<T, 2, 2>& rM)
00484 {
00485     return Determinant(rM);
00486 }
00487 
00491 c_vector<double, 1> Create_c_vector(double x);
00492 
00493 c_vector<double, 2> Create_c_vector(double x, double y);
00494 
00495 c_vector<double, 3> Create_c_vector(double x, double y, double z);
00496 
00505 c_vector<double,3> CalculateEigenvectorForSmallestNonzeroEigenvalue(c_matrix<double, 3, 3>& rA);
00506 
00507 #endif /*UBLASCUSTOMFUNCTIONS_HPP_*/
00508 

Generated on Tue Aug 4 16:10:22 2009 for Chaste by  doxygen 1.5.5