Chaste Release::3.1
UblasCustomFunctions.hpp
Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (c) 2005-2012, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #ifndef UBLASCUSTOMFUNCTIONS_HPP_
00037 #define UBLASCUSTOMFUNCTIONS_HPP_
00038 
00045 #include <boost/numeric/ublas/matrix.hpp>
00046 #include <boost/numeric/ublas/vector.hpp>
00047 
00048 #include <boost/numeric/ublas/matrix_proxy.hpp>
00049 #include <boost/numeric/ublas/io.hpp>
00050 #include <boost/numeric/ublas/matrix_expression.hpp>
00051 
00052 #include "petsc.h"
00053 #include "petscblaslapack.h"
00054 //Promote universal LAPACK name if it's an old version of PETSc
00055 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00056 #define LAPACKgeev_ LAgeev_
00057 #endif
00058 
00059 #include "Exception.hpp"
00060 #include "MathsCustomFunctions.hpp"
00061 
00062 using namespace boost::numeric::ublas;
00063 
00064 // COMMON DETERMINANTS - SQUARE
00065 
00072 template<class T>
00073 T Determinant(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM)
00074 {
00075     using namespace boost::numeric::ublas;
00076 
00077     return rM(0,0);
00078 }
00079 
00086 template<class T>
00087 T Determinant(const boost::numeric::ublas::c_matrix<T,2,2>& rM)
00088 {
00089     using namespace boost::numeric::ublas;
00090 
00091     return rM(0,0)*rM(1,1) - rM(1,0)*rM(0,1);
00092 }
00093 
00100 template<class T>
00101 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM)
00102 {
00103     using namespace boost::numeric::ublas;
00104 
00105     return    rM(0,0) * (rM(1,1)*rM(2,2) - rM(1,2)*rM(2,1))
00106             - rM(0,1) * (rM(1,0)*rM(2,2) - rM(1,2)*rM(2,0))
00107             + rM(0,2) * (rM(1,0)*rM(2,1) - rM(1,1)*rM(2,0));
00108 }
00109 
00110 // COMMON GENERALIZED DETERMINANTS - NOT SQUARE
00111 
00119 template<class T>
00120 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM)
00121 {
00122     using namespace boost::numeric::ublas;
00123     c_matrix<T,2,2> product = prod(trans(rM), rM);
00124     return std::sqrt(Determinant(product));
00125 }
00126 
00134 template<class T>
00135 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM)
00136 {
00137     using namespace boost::numeric::ublas;
00138     return std::sqrt(rM(0,0)*rM(0,0) + rM(1,0)*rM(1,0) + rM(2,0)*rM(2,0));
00139 }
00140 
00148 template<class T>
00149 T Determinant(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM)
00150 {
00151     using namespace boost::numeric::ublas;
00152     return   std::sqrt(rM(0,0) * rM(0,0) + rM(1,0) * rM(1,0));
00153 }
00154 
00160 template<class T>
00161 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 0>& rM)
00162 {
00163     NEVER_REACHED;
00164 }
00165 
00171 template<class T>
00172 T Determinant(const boost::numeric::ublas::c_matrix<T, 2, 0>& rM)
00173 {
00174     NEVER_REACHED;
00175 }
00176 
00182 template<class T>
00183 T Determinant(const boost::numeric::ublas::c_matrix<T, 1, 0>& rM)
00184 {
00185     NEVER_REACHED;
00186 }
00187 
00188 // COMMON SUBDETERMINANTS - SQUARE
00189 
00199 template<class T>
00200 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM, const unsigned missrow, const unsigned misscol)
00201 {
00202     using namespace boost::numeric::ublas;
00203 
00204     assert(missrow == 0);
00205     assert(misscol == 0);
00206     return 1.0;
00207 }
00208 
00217 template<class T>
00218 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 2>& rM, const unsigned missrow, const unsigned misscol)
00219 {
00220     using namespace boost::numeric::ublas;
00221 
00222     assert(missrow < 2);
00223     assert(misscol < 2);
00224 
00225     unsigned row = (missrow==1) ? 0 : 1;
00226     unsigned col = (misscol==1) ? 0 : 1;
00227     return rM(row,col);
00228 }
00229 
00238 template<class T>
00239 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM, const unsigned missrow, const unsigned misscol)
00240 {
00241     using namespace boost::numeric::ublas;
00242 
00243     assert(missrow < 3);
00244     assert(misscol < 3);
00245 
00246     unsigned lorow = (missrow==0) ? 1 : 0;
00247     unsigned hirow = (missrow==2) ? 1 : 2;
00248     unsigned locol = (misscol==0) ? 1 : 0;
00249     unsigned hicol = (misscol==2) ? 1 : 2;
00250     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00251 }
00252 
00253 // COMMON SUBDETERMINANTS - NOT SQUARE
00254 
00263 template<class T>
00264 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM, const unsigned missrow, const unsigned misscol)
00265 {
00266     using namespace boost::numeric::ublas;
00267 
00268     assert(missrow < 3);
00269     //assert(misscol < 2); //Don't assert this since it is used
00270 
00271     unsigned lorow = (missrow==0) ? 1 : 0;
00272     unsigned hirow = (missrow==2) ? 1 : 2;
00273     unsigned locol = (misscol==0) ? 1 : 0;
00274     unsigned hicol = (misscol==2) ? 1 : 2;
00275     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00276 }
00277 
00286 template<class T>
00287 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM, const unsigned missrow, const unsigned misscol)
00288 {
00289     using namespace boost::numeric::ublas;
00290 
00291     assert(missrow < 3);
00292     assert(misscol < 1);
00293 
00294     unsigned lorow = (missrow==0) ? 1 : 0;
00295     unsigned hirow = (missrow==2) ? 1 : 2;
00296     unsigned locol = (misscol==0) ? 1 : 0;
00297     unsigned hicol = (misscol==2) ? 1 : 2;
00298     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00299 }
00300 
00309 template<class T>
00310 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM, const unsigned missrow, const unsigned misscol)
00311 {
00312     using namespace boost::numeric::ublas;
00313 
00314     assert(missrow < 2);
00315     assert(misscol < 1);
00316 
00317     unsigned row = (missrow==1) ? 0 : 1;
00318     unsigned col = (misscol==1) ? 0 : 1;
00319     return rM(row,col);
00320 }
00321 
00322 #if defined(__xlC__)
00323 /* IBM compiler doesn't support zero-sized arrays*/
00324 #else //#if defined(__xlC__)
00325 
00333 template<class T>
00334 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 0>& rM, const unsigned missrow, const unsigned misscol)
00335 {
00336     NEVER_REACHED;
00337 }
00338 
00347 template<class T>
00348 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 0>& rM, const unsigned missrow, const unsigned misscol)
00349 {
00350     NEVER_REACHED;
00351 }
00352 
00361 template<class T>
00362 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 1, 0>& rM, const unsigned missrow, const unsigned misscol)
00363 {
00364     NEVER_REACHED;
00365 }
00366 #endif //#if defined(__xlC__)
00367 
00368 // COMMON INVERSES - SQUARE
00369 
00377 template<class T>
00378 boost::numeric::ublas::c_matrix<T, 1, 1> Inverse(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM)
00379 {
00380     using namespace boost::numeric::ublas;
00381 
00382     c_matrix<T,1,1> inverse;
00383     T det = Determinant(rM);
00384     assert(fabs(det) > DBL_EPSILON); // else it is a singular matrix
00385     inverse(0,0) =  1.0/det;
00386     return inverse;
00387 }
00388 
00396 template<class T>
00397 boost::numeric::ublas::c_matrix<T, 2, 2> Inverse(const boost::numeric::ublas::c_matrix<T, 2, 2>& rM)
00398 {
00399     using namespace boost::numeric::ublas;
00400 
00401     c_matrix<T, 2, 2> inverse;
00402     T det = Determinant(rM);
00403 
00404     assert( fabs(det) > DBL_EPSILON ); // else it is a singular matrix
00405     inverse(0,0)  =  rM(1,1)/det;
00406     inverse(0,1)  = -rM(0,1)/det;
00407     inverse(1,0)  = -rM(1,0)/det;
00408     inverse(1,1)  =  rM(0,0)/det;
00409     return inverse;
00410 }
00411 
00419 template<class T>
00420 boost::numeric::ublas::c_matrix<T, 3, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM)
00421 {
00422     using namespace boost::numeric::ublas;
00423 
00424     c_matrix<T, 3, 3> inverse;
00425     T det = Determinant(rM);
00426     assert(fabs(det) > DBL_EPSILON); // else it is a singular matrix
00427 
00428     inverse(0,0) =  (rM(1,1)*rM(2,2) - rM(1,2)*rM(2,1))/det;
00429     inverse(1,0) = -(rM(1,0)*rM(2,2) - rM(1,2)*rM(2,0))/det;
00430     inverse(2,0) =  (rM(1,0)*rM(2,1) - rM(1,1)*rM(2,0))/det;
00431     inverse(0,1) = -(rM(0,1)*rM(2,2) - rM(0,2)*rM(2,1))/det;
00432     inverse(1,1) =  (rM(0,0)*rM(2,2) - rM(0,2)*rM(2,0))/det;
00433     inverse(2,1) = -(rM(0,0)*rM(2,1) - rM(0,1)*rM(2,0))/det;
00434     inverse(0,2) =  (rM(0,1)*rM(1,2) - rM(0,2)*rM(1,1))/det;
00435     inverse(1,2) = -(rM(0,0)*rM(1,2) - rM(0,2)*rM(1,0))/det;
00436     inverse(2,2) =  (rM(0,0)*rM(1,1) - rM(0,1)*rM(1,0))/det;
00437 
00438     return inverse;
00439 }
00440 
00441 // COMMON PSEUDO-INVERSES - NOT SQUARE
00442 
00450 template<class T>
00451 boost::numeric::ublas::c_matrix<T, 2, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM)
00452 {
00453     using namespace boost::numeric::ublas;
00454 
00455     c_matrix<T, 2, 3> inverse;
00456 
00457     //
00458     // calculate (T'T)^-1, where T'T = (a b)
00459     //                                 (c d)
00460 
00461     T a = rM(0,0)*rM(0,0) + rM(1,0)*rM(1,0) + rM(2,0)*rM(2,0);
00462     T b = rM(0,0)*rM(0,1) + rM(1,0)*rM(1,1) + rM(2,0)*rM(2,1);
00463     T c = b;
00464     T d = rM(0,1)*rM(0,1) + rM(1,1)*rM(1,1) + rM(2,1)*rM(2,1);
00465 
00466     T det = a*d - b*c;
00467 
00468     T a_inv =  d/det;
00469     T b_inv = -b/det;
00470     T c_inv = -c/det;
00471     T d_inv =  a/det;
00472 
00473     inverse(0,0) = a_inv*rM(0,0) + b_inv*rM(0,1);
00474     inverse(1,0) = c_inv*rM(0,0) + d_inv*rM(0,1);
00475     inverse(0,1) = a_inv*rM(1,0) + b_inv*rM(1,1);
00476     inverse(1,1) = c_inv*rM(1,0) + d_inv*rM(1,1);
00477     inverse(0,2) = a_inv*rM(2,0) + b_inv*rM(2,1);
00478     inverse(1,2) = c_inv*rM(2,0) + d_inv*rM(2,1);
00479 
00480     return inverse;
00481 }
00482 
00490 template<class T>
00491 boost::numeric::ublas::c_matrix<T, 1, 2> Inverse(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM)
00492 {
00493     using namespace boost::numeric::ublas;
00494 
00495     c_matrix<T, 1, 2> inverse;
00496     T det = Determinant(rM);
00497 
00498     inverse(0,0) = rM(0,0)/det/det;
00499     inverse(0,1) = rM(1,0)/det/det;
00500 
00501     return inverse;
00502 }
00503 
00511 template<class T>
00512 boost::numeric::ublas::c_matrix<T, 1, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM)
00513 {
00514     using namespace boost::numeric::ublas;
00515 
00516     c_matrix<T, 1, 3> inverse;
00517     T det = Determinant(rM);
00518 
00519     inverse(0,0) = rM(0,0)/det/det;
00520     inverse(0,1) = rM(1,0)/det/det;
00521     inverse(0,2) = rM(2,0)/det/det;
00522 
00523     return inverse;
00524 }
00525 
00526 // COMMON MATRIX TRACES
00527 
00534 template<class T>
00535 T Trace(const c_matrix<T, 1, 1>& rM)
00536 {
00537     return rM(0,0);
00538 }
00539 
00546 template<class T>
00547 T Trace(const c_matrix<T, 2, 2>& rM)
00548 {
00549     return rM(0,0) + rM(1,1);
00550 }
00551 
00558 template<class T>
00559 T Trace(const c_matrix<T, 3, 3>& rM)
00560 {
00561     return rM(0,0) + rM(1,1) + rM(2,2);
00562 }
00563 
00570 template<class T>
00571 T Trace(const c_matrix<T, 4, 4>& rM)
00572 {
00573     return rM(0,0) + rM(1,1) + rM(2,2) + rM(3,3);
00574 }
00575 
00576 // OTHER MATRIX FUNCTIONS (INVARIANTS, EIGENVECTORS)
00577 
00586 template<class T>
00587 T SecondInvariant(const c_matrix<T, 3, 3>& rM)
00588 {
00589     return    rM(0,0)*rM(1,1) + rM(1,1)*rM(2,2) + rM(2,2)*rM(0,0)
00590             - rM(1,0)*rM(1,0) - rM(2,1)*rM(2,1) - rM(2,0)*rM(2,0);
00591 }
00592 
00600 template<class T>
00601 T SecondInvariant(const c_matrix<T, 2, 2>& rM)
00602 {
00603     return Determinant(rM);
00604 }
00605 
00615 c_vector<double,3> CalculateEigenvectorForSmallestNonzeroEigenvalue(c_matrix<double, 3, 3>& rA);
00616 
00617 //COMMON VECTOR FUNCTIONS
00618 
00626 template<class T>
00627 c_vector<T, 3> VectorProduct(const c_vector<T, 3>& rA, const c_vector<T, 3>& rB)
00628 {
00629 
00630     c_vector<T, 3> result;
00631 
00632     double x1 = rA(0);
00633     double y1 = rA(1);
00634     double z1 = rA(2);
00635     double x2 = rB(0);
00636     double y2 = rB(1);
00637     double z2 = rB(2);
00638 
00639     result(0) = y1*z2 - z1*y2;
00640     result(1) = z1*x2 - x1*z2;
00641     result(2) = x1*y2 - y1*x2;
00642 
00643     return result;
00644 }
00645 
00652 c_vector<double, 1> Create_c_vector(double x);
00653 
00661 c_vector<double, 2> Create_c_vector(double x, double y);
00662 
00671 c_vector<double, 3> Create_c_vector(double x, double y, double z);
00672 
00673 #endif /*UBLASCUSTOMFUNCTIONS_HPP_*/