UblasCustomFunctions.hpp

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
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 #ifndef UBLASCUSTOMFUNCTIONS_HPP_
00030 #define UBLASCUSTOMFUNCTIONS_HPP_
00031 
00038 #include <boost/numeric/ublas/matrix.hpp>
00039 #include <boost/numeric/ublas/vector.hpp>
00040 
00041 #include <boost/numeric/ublas/matrix_proxy.hpp>
00042 #include <boost/numeric/ublas/io.hpp>
00043 #include <boost/numeric/ublas/matrix_expression.hpp>
00044 
00045 #include "petsc.h"
00046 #include "petscblaslapack.h"
00047 //Promote universal LAPACK name if it's an old version of PETSc
00048 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00049 #define LAPACKgeev_ LAgeev_
00050 #endif
00051 
00052 #include "Exception.hpp"
00053 #include "MathsCustomFunctions.hpp"
00054 
00055 using namespace boost::numeric::ublas;
00056 
00057 // COMMON DETERMINANTS - SQUARE
00058 
00065 template<class T>
00066 T Determinant(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM)
00067 {
00068     using namespace boost::numeric::ublas;
00069 
00070     return rM(0,0);
00071 }
00072 
00079 template<class T>
00080 T Determinant(const boost::numeric::ublas::c_matrix<T,2,2>& rM)
00081 {
00082     using namespace boost::numeric::ublas;
00083 
00084     return rM(0,0)*rM(1,1) - rM(1,0)*rM(0,1);
00085 }
00086 
00093 template<class T>
00094 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM)
00095 {
00096     using namespace boost::numeric::ublas;
00097 
00098     return    rM(0,0) * (rM(1,1)*rM(2,2) - rM(1,2)*rM(2,1))
00099             - rM(0,1) * (rM(1,0)*rM(2,2) - rM(1,2)*rM(2,0))
00100             + rM(0,2) * (rM(1,0)*rM(2,1) - rM(1,1)*rM(2,0));
00101 }
00102 
00103 // COMMON GENERALIZED DETERMINANTS - NOT SQUARE
00104 
00112 template<class T>
00113 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM)
00114 {
00115     using namespace boost::numeric::ublas;
00116     c_matrix<T,2,2> product = prod(trans(rM), rM);
00117     return std::sqrt(Determinant(product));
00118 }
00119 
00127 template<class T>
00128 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM)
00129 {
00130     using namespace boost::numeric::ublas;
00131     return std::sqrt(rM(0,0)*rM(0,0) + rM(1,0)*rM(1,0) + rM(2,0)*rM(2,0));
00132 }
00133 
00141 template<class T>
00142 T Determinant(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM)
00143 {
00144     using namespace boost::numeric::ublas;
00145     return   std::sqrt(rM(0,0) * rM(0,0) + rM(1,0) * rM(1,0));
00146 }
00147 
00153 template<class T>
00154 T Determinant(const boost::numeric::ublas::c_matrix<T, 3, 0>& rM)
00155 {
00156     NEVER_REACHED;
00157 }
00158 
00164 template<class T>
00165 T Determinant(const boost::numeric::ublas::c_matrix<T, 2, 0>& rM)
00166 {
00167     NEVER_REACHED;
00168 }
00169 
00175 template<class T>
00176 T Determinant(const boost::numeric::ublas::c_matrix<T, 1, 0>& rM)
00177 {
00178     NEVER_REACHED;
00179 }
00180 
00181 // COMMON SUBDETERMINANTS - SQUARE
00182 
00192 template<class T>
00193 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM, const unsigned missrow, const unsigned misscol)
00194 {
00195     using namespace boost::numeric::ublas;
00196 
00197     assert(missrow == 0);
00198     assert(misscol == 0);
00199     return 1.0;
00200 }
00201 
00210 template<class T>
00211 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 2>& rM, const unsigned missrow, const unsigned misscol)
00212 {
00213     using namespace boost::numeric::ublas;
00214 
00215     assert(missrow < 2);
00216     assert(misscol < 2);
00217 
00218     unsigned row = (missrow==1) ? 0 : 1;
00219     unsigned col = (misscol==1) ? 0 : 1;
00220     return rM(row,col);
00221 }
00222 
00231 template<class T>
00232 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM, const unsigned missrow, const unsigned misscol)
00233 {
00234     using namespace boost::numeric::ublas;
00235 
00236     assert(missrow < 3);
00237     assert(misscol < 3);
00238 
00239     unsigned lorow = (missrow==0) ? 1 : 0;
00240     unsigned hirow = (missrow==2) ? 1 : 2;
00241     unsigned locol = (misscol==0) ? 1 : 0;
00242     unsigned hicol = (misscol==2) ? 1 : 2;
00243     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00244 }
00245 
00246 // COMMON SUBDETERMINANTS - NOT SQUARE
00247 
00256 template<class T>
00257 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM, const unsigned missrow, const unsigned misscol)
00258 {
00259     using namespace boost::numeric::ublas;
00260 
00261     assert(missrow < 3);
00262     //assert(misscol < 2); //Don't assert this since it is used
00263 
00264     unsigned lorow = (missrow==0) ? 1 : 0;
00265     unsigned hirow = (missrow==2) ? 1 : 2;
00266     unsigned locol = (misscol==0) ? 1 : 0;
00267     unsigned hicol = (misscol==2) ? 1 : 2;
00268     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00269 }
00270 
00279 template<class T>
00280 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM, const unsigned missrow, const unsigned misscol)
00281 {
00282     using namespace boost::numeric::ublas;
00283 
00284     assert(missrow < 3);
00285     assert(misscol < 1);
00286 
00287     unsigned lorow = (missrow==0) ? 1 : 0;
00288     unsigned hirow = (missrow==2) ? 1 : 2;
00289     unsigned locol = (misscol==0) ? 1 : 0;
00290     unsigned hicol = (misscol==2) ? 1 : 2;
00291     return rM(lorow,locol)*rM(hirow,hicol) - rM(lorow,hicol)*rM(hirow,locol);
00292 }
00293 
00302 template<class T>
00303 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM, const unsigned missrow, const unsigned misscol)
00304 {
00305     using namespace boost::numeric::ublas;
00306 
00307     assert(missrow < 2);
00308     assert(misscol < 1);
00309 
00310     unsigned row = (missrow==1) ? 0 : 1;
00311     unsigned col = (misscol==1) ? 0 : 1;
00312     return rM(row,col);
00313 }
00314 
00315 #if defined(__xlC__)
00316 /* IBM compiler doesn't support zero-sized arrays*/
00317 #else //#if defined(__xlC__)
00318 
00326 template<class T>
00327 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 3, 0>& rM, const unsigned missrow, const unsigned misscol)
00328 {
00329     NEVER_REACHED;
00330 }
00331 
00340 template<class T>
00341 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 2, 0>& rM, const unsigned missrow, const unsigned misscol)
00342 {
00343     NEVER_REACHED;
00344 }
00345 
00354 template<class T>
00355 T SubDeterminant(const boost::numeric::ublas::c_matrix<T, 1, 0>& rM, const unsigned missrow, const unsigned misscol)
00356 {
00357     NEVER_REACHED;
00358 }
00359 #endif //#if defined(__xlC__)
00360 
00361 // COMMON INVERSES - SQUARE
00362 
00370 template<class T>
00371 boost::numeric::ublas::c_matrix<T, 1, 1> Inverse(const boost::numeric::ublas::c_matrix<T, 1, 1>& rM)
00372 {
00373     using namespace boost::numeric::ublas;
00374 
00375     c_matrix<T,1,1> inverse;
00376     T det = Determinant(rM);
00377     assert(fabs(det) > DBL_EPSILON); // else it is a singular matrix
00378     inverse(0,0) =  1.0/det;
00379     return inverse;
00380 }
00381 
00389 template<class T>
00390 boost::numeric::ublas::c_matrix<T, 2, 2> Inverse(const boost::numeric::ublas::c_matrix<T, 2, 2>& rM)
00391 {
00392     using namespace boost::numeric::ublas;
00393 
00394     c_matrix<T, 2, 2> inverse;
00395     T det = Determinant(rM);
00396 
00397     assert( fabs(det) > DBL_EPSILON ); // else it is a singular matrix
00398     inverse(0,0)  =  rM(1,1)/det;
00399     inverse(0,1)  = -rM(0,1)/det;
00400     inverse(1,0)  = -rM(1,0)/det;
00401     inverse(1,1)  =  rM(0,0)/det;
00402     return inverse;
00403 }
00404 
00412 template<class T>
00413 boost::numeric::ublas::c_matrix<T, 3, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 3>& rM)
00414 {
00415     using namespace boost::numeric::ublas;
00416 
00417     c_matrix<T, 3, 3> inverse;
00418     T det = Determinant(rM);
00419     assert(fabs(det) > DBL_EPSILON); // else it is a singular matrix
00420 
00421     inverse(0,0) =  (rM(1,1)*rM(2,2) - rM(1,2)*rM(2,1))/det;
00422     inverse(1,0) = -(rM(1,0)*rM(2,2) - rM(1,2)*rM(2,0))/det;
00423     inverse(2,0) =  (rM(1,0)*rM(2,1) - rM(1,1)*rM(2,0))/det;
00424     inverse(0,1) = -(rM(0,1)*rM(2,2) - rM(0,2)*rM(2,1))/det;
00425     inverse(1,1) =  (rM(0,0)*rM(2,2) - rM(0,2)*rM(2,0))/det;
00426     inverse(2,1) = -(rM(0,0)*rM(2,1) - rM(0,1)*rM(2,0))/det;
00427     inverse(0,2) =  (rM(0,1)*rM(1,2) - rM(0,2)*rM(1,1))/det;
00428     inverse(1,2) = -(rM(0,0)*rM(1,2) - rM(0,2)*rM(1,0))/det;
00429     inverse(2,2) =  (rM(0,0)*rM(1,1) - rM(0,1)*rM(1,0))/det;
00430 
00431     return inverse;
00432 }
00433 
00434 // COMMON PSEUDO-INVERSES - NOT SQUARE
00435 
00443 template<class T>
00444 boost::numeric::ublas::c_matrix<T, 2, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 2>& rM)
00445 {
00446     using namespace boost::numeric::ublas;
00447 
00448     c_matrix<T, 2, 3> inverse;
00449 
00450     //
00451     // calculate (T'T)^-1, where T'T = (a b)
00452     //                                 (c d)
00453 
00454     T a = rM(0,0)*rM(0,0) + rM(1,0)*rM(1,0) + rM(2,0)*rM(2,0);
00455     T b = rM(0,0)*rM(0,1) + rM(1,0)*rM(1,1) + rM(2,0)*rM(2,1);
00456     T c = b;
00457     T d = rM(0,1)*rM(0,1) + rM(1,1)*rM(1,1) + rM(2,1)*rM(2,1);
00458 
00459     T det = a*d - b*c;
00460 
00461     T a_inv =  d/det;
00462     T b_inv = -b/det;
00463     T c_inv = -c/det;
00464     T d_inv =  a/det;
00465 
00466     inverse(0,0) = a_inv*rM(0,0) + b_inv*rM(0,1);
00467     inverse(1,0) = c_inv*rM(0,0) + d_inv*rM(0,1);
00468     inverse(0,1) = a_inv*rM(1,0) + b_inv*rM(1,1);
00469     inverse(1,1) = c_inv*rM(1,0) + d_inv*rM(1,1);
00470     inverse(0,2) = a_inv*rM(2,0) + b_inv*rM(2,1);
00471     inverse(1,2) = c_inv*rM(2,0) + d_inv*rM(2,1);
00472 
00473     return inverse;
00474 }
00475 
00483 template<class T>
00484 boost::numeric::ublas::c_matrix<T, 1, 2> Inverse(const boost::numeric::ublas::c_matrix<T, 2, 1>& rM)
00485 {
00486     using namespace boost::numeric::ublas;
00487 
00488     c_matrix<T, 1, 2> inverse;
00489     T det = Determinant(rM);
00490 
00491     inverse(0,0) = rM(0,0)/det/det;
00492     inverse(0,1) = rM(1,0)/det/det;
00493 
00494     return inverse;
00495 }
00496 
00504 template<class T>
00505 boost::numeric::ublas::c_matrix<T, 1, 3> Inverse(const boost::numeric::ublas::c_matrix<T, 3, 1>& rM)
00506 {
00507     using namespace boost::numeric::ublas;
00508 
00509     c_matrix<T, 1, 3> inverse;
00510     T det = Determinant(rM);
00511 
00512     inverse(0,0) = rM(0,0)/det/det;
00513     inverse(0,1) = rM(1,0)/det/det;
00514     inverse(0,2) = rM(2,0)/det/det;
00515 
00516     return inverse;
00517 }
00518 
00519 // COMMON MATRIX TRACES
00520 
00527 template<class T>
00528 T Trace(const c_matrix<T, 1, 1>& rM)
00529 {
00530     return rM(0,0);
00531 }
00532 
00539 template<class T>
00540 T Trace(const c_matrix<T, 2, 2>& rM)
00541 {
00542     return rM(0,0) + rM(1,1);
00543 }
00544 
00551 template<class T>
00552 T Trace(const c_matrix<T, 3, 3>& rM)
00553 {
00554     return rM(0,0) + rM(1,1) + rM(2,2);
00555 }
00556 
00563 template<class T>
00564 T Trace(const c_matrix<T, 4, 4>& rM)
00565 {
00566     return rM(0,0) + rM(1,1) + rM(2,2) + rM(3,3);
00567 }
00568 
00569 // OTHER MATRIX FUNCTIONS (INVARIANTS, EIGENVECTORS)
00570 
00579 template<class T>
00580 T SecondInvariant(const c_matrix<T, 3, 3>& rM)
00581 {
00582     return    rM(0,0)*rM(1,1) + rM(1,1)*rM(2,2) + rM(2,2)*rM(0,0)
00583             - rM(1,0)*rM(1,0) - rM(2,1)*rM(2,1) - rM(2,0)*rM(2,0);
00584 }
00585 
00593 template<class T>
00594 T SecondInvariant(const c_matrix<T, 2, 2>& rM)
00595 {
00596     return Determinant(rM);
00597 }
00598 
00608 c_vector<double,3> CalculateEigenvectorForSmallestNonzeroEigenvalue(c_matrix<double, 3, 3>& rA);
00609 
00610 //COMMON VECTOR FUNCTIONS
00611 
00619 template<class T>
00620 c_vector<T, 3> VectorProduct(const c_vector<T, 3>& rA, const c_vector<T, 3>& rB)
00621 {
00622 
00623     c_vector<T, 3> result;
00624 
00625     double x1 = rA(0);
00626     double y1 = rA(1);
00627     double z1 = rA(2);
00628     double x2 = rB(0);
00629     double y2 = rB(1);
00630     double z2 = rB(2);
00631 
00632     result(0) = y1*z2 - z1*y2;
00633     result(1) = z1*x2 - x1*z2;
00634     result(2) = x1*y2 - y1*x2;
00635 
00636     return result;
00637 }
00638 
00645 c_vector<double, 1> Create_c_vector(double x);
00646 
00654 c_vector<double, 2> Create_c_vector(double x, double y);
00655 
00664 c_vector<double, 3> Create_c_vector(double x, double y, double z);
00665 
00666 #endif /*UBLASCUSTOMFUNCTIONS_HPP_*/
Generated on Thu Dec 22 13:00:07 2011 for Chaste by  doxygen 1.6.3