Chaste Release::3.1
|
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_*/