![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand * 00004 * Copyright (C) 2009 Sergio Galindo * 00005 * * 00006 * This program is free software: you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation, either version 3 of the License, or * 00009 * any later version. * 00010 * * 00011 * This program is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00014 * GNU General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License * 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00018 ************************************************************************/ 00019 00020 #ifndef MECHSYS_MATVEC_H 00021 #define MECHSYS_MATVEC_H 00022 00023 // Std Lib 00024 #include <iostream> 00025 #include <sstream> // for istringstream, ostringstream 00026 #include <cstring> // for strcmp 00027 #include <cmath> // for sqrt, pow 00028 #include <algorithm> // for min, max 00029 00030 // Blitz++ 00031 #include <blitz/tinyvec-et.h> 00032 #include <blitz/tinymat.h> 00033 00034 // GSL 00035 #include <gsl/gsl_math.h> 00036 #include <gsl/gsl_eigen.h> 00037 00038 // Tensors 00039 #ifdef HAS_TENSORS 00040 #include <tensors/tensoperators.h> 00041 #include <tensors/tensor1.h> 00042 #include <tensors/tensor2.h> 00043 #include <tensors/tensor3.h> 00044 #include <tensors/tensor4.h> 00045 typedef TensorsLib::Tensor1<double,3> Ten1_t; 00046 typedef TensorsLib::Tensor2<double,3> Ten2_t; 00047 typedef TensorsLib::Tensor3<double,3> Ten3_t; 00048 typedef TensorsLib::Tensor4<double,3> Ten4_t; 00049 #endif 00050 00051 // MechSys 00052 #include <mechsys/util/fatal.h> 00053 #include <mechsys/util/util.h> 00054 #include <mechsys/util/array.h> 00055 00056 // LAPACK 00057 extern "C" 00058 { 00059 // DGETRF - compute an LU factorization of a general M-by-N matrix A using partial pivoting with row interchanges 00060 void dgetrf_(const int* m, const int* n, double* a, const int* lda, int* ipiv, int* info); 00061 00062 // DGETRI - compute the inverse of a matrix using the LU factorization computed by DGETRF 00063 void dgetri_(const int* n, double* a, const int* lda, int* ipiv, double* work, const int* lwork, int* info); 00064 00065 // DGESVD - computes the singular value decomposition of a real M-by-N matrix A, optionally computing the left and/or right singular vectors 00066 void dgesvd_(const char* jobu, const char* jobvt, const int* M, const int* N, double* A, const int* lda, double* S, double* U, const int* ldu, double* VT, const int* ldvt, double* work,const int* lwork, const int* info); 00067 00068 // DGESV - double-general-solver 00069 void dgesv_(int *Np, int *NRHSp, double *A, int *LDAp, int *IPIVp, double *B, int *LDBp, int *INFOp); 00070 } 00071 00072 00074 00075 00076 #ifdef USE_MTL4 00077 00078 // Boost/MTL4 00079 #include <boost/numeric/mtl/mtl.hpp> 00080 00082 typedef mtl::dense2D<double, mtl::matrix::parameters<mtl::tag::col_major> > Mat_t; 00083 00085 typedef mtl::dense_vector<double> Vec_t; 00086 00087 #else 00088 00089 #include <mechsys/linalg/vector.h> 00090 #include <mechsys/linalg/matrix.h> 00091 #include <mechsys/linalg/laexpr.h> 00092 00093 typedef LinAlg::Vector<double> Vec_t; 00094 typedef LinAlg::Matrix<double> Mat_t; 00095 00096 inline double dot (Vec_t const & V, Vec_t const & W) { return LinAlg::Dot(V,W); } 00097 inline size_t size (Vec_t const & V) { return V.Size(); } 00098 inline void set_to_zero (Vec_t & V) { V.SetValues(0.0); } 00099 inline void set_to_zero (Mat_t & M) { M.SetValues(0.0); } 00100 inline size_t num_rows (Vec_t const & V) { return V.Size(); } 00101 inline size_t num_rows (Mat_t const & M) { return M.Rows(); } 00102 inline size_t num_cols (Mat_t const & M) { return M.Cols(); } 00103 00104 #endif 00105 00107 inline String PrintVector (Vec_t const & V, char const * Fmt="%13g", Array<long> const * SkipR=NULL, double Tol=1.0e-13) 00108 { 00109 int m = size(V); 00110 String lin; 00111 for (int i=0; i<m; ++i) 00112 { 00113 bool skip_row = false; 00114 if (SkipR!=NULL) skip_row = (SkipR->Find(i)<0 ? false : true); 00115 if (!skip_row) 00116 { 00117 double val = (fabs(V(i))<Tol ? 0.0 : V(i)); 00118 String buf; buf.Printf(Fmt,val); 00119 lin.append(buf); 00120 } 00121 } 00122 lin.append("\n"); 00123 return lin; 00124 } 00125 00127 inline String PrintMatrix (Mat_t const & M, char const * Fmt="%13g", Array<long> const * SkipRC=NULL, double Tol=1.0e-13, bool NumPy=false) 00128 { 00129 int m = M.num_rows(); 00130 int n = M.num_cols(); 00131 String lin; 00132 if (NumPy) lin.append("matrix([["); 00133 for (int i=0; i<m; ++i) 00134 { 00135 bool skip_row = false; 00136 if (SkipRC!=NULL) skip_row = (SkipRC->Find(i)<0 ? false : true); 00137 if (!skip_row) 00138 { 00139 if (NumPy && i!=0) lin.append(" ["); 00140 for (int j=0; j<n; ++j) 00141 { 00142 bool skip_col = false; 00143 if (SkipRC!=NULL) skip_col = (SkipRC->Find(j)<0 ? false : true); 00144 if (!skip_col) 00145 { 00146 double val = (fabs(M(i,j))<Tol ? 0.0 : M(i,j)); 00147 String buf; buf.Printf(Fmt,val); 00148 lin.append(buf); 00149 if (NumPy && j!=n-1) lin.append(","); 00150 } 00151 } 00152 if (NumPy && i!=m-1) lin.append("],"); 00153 if (NumPy && i==m-1) lin.append("]])"); 00154 else lin.append("\n"); 00155 } 00156 } 00157 return lin; 00158 } 00159 00161 inline void WriteSMAT (Mat_t const & M, char const * FileKey, double Tol=1.0e-14) 00162 { 00163 // find the number of really non-zero values 00164 size_t m = num_rows(M); 00165 size_t n = num_cols(M); 00166 size_t nz = 0; 00167 for (size_t i=0; i<m; ++i) 00168 for (size_t j=0; j<n; ++j) 00169 { 00170 if (fabs(M(i,j))>Tol) nz++; 00171 } 00172 00173 // output 00174 std::ostringstream oss; 00175 char buf[256]; 00176 sprintf(buf, "%zd %zd %zd\n", m, n, nz); 00177 oss << buf; 00178 for (size_t i=0; i<m; ++i) 00179 for (size_t j=0; j<n; ++j) 00180 { 00181 if (fabs(M(i,j))>Tol) 00182 { 00183 sprintf(buf, " %zd %zd %.17g\n", i, j, M(i,j)); 00184 oss << buf; 00185 } 00186 } 00187 00188 // write to file 00189 String fn(FileKey); fn.append(".smat"); 00190 std::ofstream of(fn.CStr(), std::ios::out); 00191 of << oss.str(); 00192 of.close(); 00193 printf("File <%s%s%s> written\n",TERM_CLR_BLUE_H, fn.CStr(), TERM_RST); 00194 } 00195 00197 inline double CompareVectors (Vec_t const & A, Vec_t const & B) 00198 { 00199 size_t m = size(A); 00200 if (m!=size(B)) throw new Fatal("matvec.h:CompareVectors: vectors A_%d and B_%d must have the same size",m,size(B)); 00201 double error = 0.0; 00202 for (size_t i=0; i<m; ++i) 00203 error += fabs(A(i)-B(i)); 00204 return error; 00205 } 00206 00208 inline double CompareMatrices (Mat_t const & A, Mat_t const & B) 00209 { 00210 size_t m = A.num_rows(); 00211 size_t n = A.num_cols(); 00212 if ((m!=B.num_rows()) || (n!=B.num_cols())) throw new Fatal("matvec.h:CompareMatrices: matrices A_%dx%d and B_%dx%d must have the same number of rows and columns",m,n,B.num_rows(),B.num_cols()); 00213 double error = 0.0; 00214 for (size_t i=0; i<m; ++i) 00215 for (size_t j=0; j<n; ++j) 00216 error += fabs(A(i,j)-B(i,j)); 00217 return error; 00218 } 00219 00221 inline double CheckDiagonal (Mat_t const & M, bool CheckUnitDiag=false) 00222 { 00223 size_t m = M.num_rows(); 00224 size_t n = M.num_cols(); 00225 double error = 0.0; 00226 for (size_t i=0; i<m; ++i) 00227 for (size_t j=0; j<n; ++j) 00228 { 00229 if ((i==j) && CheckUnitDiag) error += fabs(M(i,j)-1.0); 00230 if (i!=j) error += fabs(M(i,j)); 00231 } 00232 return error; 00233 } 00234 00236 inline double Det (Mat_t const & M) 00237 { 00238 int m = M.num_rows(); 00239 int n = M.num_cols(); 00240 if (m==1) 00241 { 00242 double res = 0; 00243 for (int i=0; i<n; i++) res += M(0,i)*M(0,i); 00244 return sqrt(res); 00245 } 00246 else if (m==2 && n==2) 00247 { 00248 return M(0,0)*M(1,1) - M(1,0)*M(0,1); 00249 } 00250 /* 00251 else if (m==2 && n==3) 00252 { 00253 double d1 = M(0,0)*M(1,1) - M(0,1)*M(1,0); 00254 double d2 = M(0,1)*M(1,2) - M(0,2)*M(1,1); 00255 double d3 = M(0,2)*M(1,0) - M(0,0)*M(1,2); 00256 return sqrt(d1*d1 + d2*d2 + d3*d3); 00257 } 00258 */ 00259 else if (m==3 && n==3) 00260 { 00261 return M(0,0)*(M(1,1)*M(2,2) - M(1,2)*M(2,1)) 00262 - M(0,1)*(M(1,0)*M(2,2) - M(1,2)*M(2,0)) 00263 + M(0,2)*(M(1,0)*M(2,1) - M(1,1)*M(2,0)); 00264 } 00265 else if (m==n) 00266 { 00267 // factorization 00268 int info = 0; 00269 int * ipiv = new int [m]; 00270 Mat_t Mcpy(M); 00271 dgetrf_(&m, // M 00272 &m, // N 00273 Mcpy.data, // double * A 00274 &m, // LDA 00275 ipiv, // Pivot indices 00276 &info); // INFO 00277 if (info!=0) throw new Fatal ("matvec.h::Det: LAPACK: LU factorization failed"); 00278 00279 // determinant 00280 double det = 1.0; 00281 for (int i=0; i<m; ++i) 00282 { 00283 if (ipiv[i]!=(i+1)) det = -det * Mcpy(i,i); 00284 else det = det * Mcpy(i,i); 00285 } 00286 00287 // end 00288 delete [] ipiv; 00289 return det; 00290 } 00291 else throw new Fatal("matvec.h:Det: Method is not implemented for (%d x %d) matrices yet",m,n); 00292 } 00293 00295 inline void Identity (size_t NRows, Mat_t & I) 00296 { 00297 I.change_dim (NRows,NRows); 00298 for (size_t i=0; i<NRows; ++i) 00299 for (size_t j=0; j<NRows; ++j) 00300 { 00301 if (i==j) I(i,j) = 1.0; 00302 else I(i,j) = 0.0; 00303 } 00304 } 00305 00307 inline void Svd (Mat_t const & M, Mat_t & U, Vec_t & S, Mat_t & Vt) 00308 { 00309 int info = 0; 00310 char job = 'A'; 00311 int m = M.num_rows(); 00312 int n = M.num_cols(); 00313 int min_mn = (m<n ? m : n); 00314 int max_mn = (m>n ? m : n); 00315 int lwork = 2.0*std::max(3*min_mn+max_mn, 5*min_mn); 00316 00317 U. change_dim (m, m); 00318 Vt.change_dim (n, n); // trans(V) 00319 S. change_dim (min_mn); 00320 00321 double * work = new double [lwork]; // Work 00322 00323 // decomposition 00324 Mat_t tmp(M); 00325 dgesvd_(&job, // JOBU 00326 &job, // JOBVT 00327 &m, // M 00328 &n, // N 00329 tmp.data, // A 00330 &m, // LDA 00331 S.data, // S 00332 U.data, // U 00333 &m, // LDU 00334 Vt.data, // VT 00335 &n, // LDVT 00336 work, // WORK 00337 &lwork, // LWORK 00338 &info); // INFO 00339 if (info!=0) throw new Fatal ("matvec::Svd: LAPACK: Decomposition failed"); 00340 00341 delete [] work; 00342 } 00343 00345 inline void Inv (Mat_t const & M, Mat_t & Mi, double Tol=1.0e-10) 00346 { 00347 int m = M.num_rows(); 00348 int n = M.num_cols(); 00349 Mi.change_dim(m,n); 00350 if (m==2 && n==2) 00351 { 00352 double det = Det(M); 00353 if (fabs(det)<Tol) throw new Fatal("matvec.h:Inv: Cannot calculate inverse due to zero determinant. det = %g",det); 00354 00355 Mi(0,0) = M(1,1) / det; 00356 Mi(0,1) = -M(0,1) / det; 00357 00358 Mi(1,0) = -M(1,0) / det; 00359 Mi(1,1) = M(0,0) / det; 00360 } 00361 else if (m==3 && n==3) 00362 { 00363 double det = Det(M); 00364 if (fabs(det)<Tol) throw new Fatal("matvec.h:Inv: Cannot calculate inverse due to zero determinant. det = %g",det); 00365 00366 Mi(0,0) = (M(1,1)*M(2,2) - M(1,2)*M(2,1)) / det; 00367 Mi(0,1) = (M(0,2)*M(2,1) - M(0,1)*M(2,2)) / det; 00368 Mi(0,2) = (M(0,1)*M(1,2) - M(0,2)*M(1,1)) / det; 00369 00370 Mi(1,0) = (M(1,2)*M(2,0) - M(1,0)*M(2,2)) / det; 00371 Mi(1,1) = (M(0,0)*M(2,2) - M(0,2)*M(2,0)) / det; 00372 Mi(1,2) = (M(0,2)*M(1,0) - M(0,0)*M(1,2)) / det; 00373 00374 Mi(2,0) = (M(1,0)*M(2,1) - M(1,1)*M(2,0)) / det; 00375 Mi(2,1) = (M(0,1)*M(2,0) - M(0,0)*M(2,1)) / det; 00376 Mi(2,2) = (M(0,0)*M(1,1) - M(0,1)*M(1,0)) / det; 00377 } 00378 else if (m==n) // square 00379 { 00380 int info = 0; 00381 int * ipiv = new int [m]; 00382 00383 // factorization 00384 Mi = M; 00385 dgetrf_(&m, // M 00386 &m, // N 00387 Mi.data, // double * A 00388 &m, // LDA 00389 ipiv, // Pivot indices 00390 &info); // INFO 00391 if (info!=0) throw new Fatal ("matvec.h::Inv: LAPACK: LU factorization failed"); 00392 00393 int NB = 4; // Optimal blocksize ? 00394 int lwork = m*NB; // Dimension of work >= max(1,m), optimal=m*NB 00395 double * work = new double [lwork]; // Work 00396 00397 // inversion 00398 dgetri_(&m, // N 00399 Mi.data, // double * A 00400 &m, // LDA 00401 ipiv, // Pivot indices 00402 work, // work 00403 &lwork, // dimension of work 00404 &info); // INFO 00405 if (info!=0) throw new Fatal ("matvec::Inv: LAPACK: Inversion failed"); 00406 00407 delete [] ipiv; 00408 delete [] work; 00409 } 00410 else // generalized (pseudo) inverse 00411 { 00412 Mat_t U; Vec_t S; Mat_t Vt; 00413 Svd(M, U, S, Vt); 00414 Mat_t Di(m,n); 00415 set_to_zero(Di); 00416 for (size_t i=0; i<size(S); ++i) 00417 { 00418 if (S(i)>Tol) Di(i,i) = 1.0/S(i); 00419 } 00420 Mat_t tmp(U*Di*Vt); 00421 Mi.change_dim(n,m); 00422 Mi = trans(tmp); 00423 } 00424 } 00425 00427 inline void Sol (Mat_t & M, Vec_t & X) 00428 { 00429 int m = M.num_rows(); 00430 int n = M.num_cols(); 00431 int mv = size(X); 00432 if (m!=n) throw new Fatal("Sol: Matrix must be square"); 00433 if (m!=mv) throw new Fatal("Sol: Vector X must have the same number of rows of matrix M"); 00434 00435 int info = 0; 00436 int nrhs = 1; // vector X has 1 column 00437 int * ipiv = new int [m]; 00438 dgesv_(&m, // A(m,m) 00439 &nrhs, // {X}(m,1) (RHS: Right Hand Side) 00440 M.data, // double * A 00441 &m, // LDA 00442 ipiv, // Pivot Indices 00443 X.data, // double * Y 00444 &m, // LDY 00445 &info); // info 00446 delete [] ipiv; 00447 00448 if (info!=0) 00449 { 00450 throw new Fatal ("Sol: Linear solver (DGESV) failed (singular matrix?)"); 00451 } 00452 } 00453 00455 inline void Sol (Mat_t const & M, Vec_t const & B, Vec_t & X) 00456 { 00457 Mat_t m(M); 00458 X = B; 00459 Sol (m, X); 00460 } 00461 00463 inline double Norm (Vec_t const & V) 00464 { 00465 return sqrt(dot(V,V)); 00466 } 00467 00469 inline void Dyad (Vec_t const & A, Vec_t const & B, Mat_t & M) 00470 { 00471 M.change_dim(size(A),size(B)); 00472 for (size_t i=0; i<size(A); ++i) 00473 for (size_t j=0; j<size(B); ++j) 00474 M(i,j) = A(i) * B(j); 00475 } 00476 00478 inline void Mult (Vec_t const & A, Mat_t const & M, Vec_t & B) 00479 { 00480 B.change_dim (M.num_cols()); 00481 set_to_zero (B); 00482 for (size_t i=0; i<M.num_rows(); ++i) 00483 for (size_t j=0; j<M.num_cols(); ++j) 00484 B(j) += A(i)*M(i,j); 00485 } 00486 00488 inline void Vec2ColMat (Vec_t const & V, Mat_t & M) 00489 { 00490 M.change_dim (size(V),1); 00491 for (size_t i=0; i<size(V); ++i) M(i,0) = V(i); 00492 } 00493 00495 inline void Eig (Mat_t & M, Vec_t & L, Mat_t * Q=NULL, bool Qtrans=false) 00496 { 00497 // calculate 00498 size_t nrow = num_rows (M); 00499 size_t ncol = num_cols (M); 00500 if (nrow!=ncol) throw new Fatal("Eig: Matrix (%zdx%zd) must be square", nrow,ncol); 00501 00502 // eigenvalues 00503 L.change_dim (nrow); 00504 gsl_vector eval = {nrow, 1, L.data, NULL, 0}; // size, stride, data, block, owner 00505 00506 // solve 00507 gsl_matrix_view m = gsl_matrix_view_array (M.data, nrow, nrow); 00508 if (Q==NULL) 00509 { 00510 gsl_eigen_symm_workspace * w = gsl_eigen_symm_alloc (nrow); 00511 gsl_eigen_symm (&m.matrix, &eval, w); 00512 gsl_eigen_symm_free (w); 00513 } 00514 else 00515 { 00516 Q->change_dim (nrow, nrow); 00517 gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc (nrow); 00518 if (Qtrans) 00519 { 00520 gsl_matrix_view q = gsl_matrix_view_array (Q->data, nrow, nrow); 00521 gsl_eigen_symmv (&m.matrix, &eval, &q.matrix, w); 00522 } 00523 else 00524 { 00525 gsl_matrix * q = gsl_matrix_alloc (nrow, nrow); 00526 gsl_eigen_symmv (&m.matrix, &eval, q, w); 00527 for (size_t j=0; j<ncol; ++j) 00528 { 00529 gsl_vector_view evec_j = gsl_matrix_column (q, j); 00530 for (size_t i=0; i<nrow; ++i) (*Q)(i,j) = gsl_vector_get (&evec_j.vector, i); 00531 } 00532 gsl_matrix_free (q); 00533 } 00534 gsl_eigen_symmv_free (w); 00535 } 00536 } 00537 00538 00540 00541 00543 typedef blitz::TinyMatrix<double,3,3> Mat3_t; 00544 00546 typedef blitz::TinyVector<double,3> Vec3_t; 00547 typedef blitz::TinyVector<size_t,3> iVec3_t; 00548 typedef blitz::TinyVector<bool,3> bVec3_t; 00549 00551 inline String PrintVector (Vec3_t const & V, char const * Fmt="%13g", double Tol=1.0e-13) 00552 { 00553 int m = 3; 00554 String lin; 00555 for (int i=0; i<m; ++i) 00556 { 00557 double val = (fabs(V(i))<Tol ? 0.0 : V(i)); 00558 String buf; buf.Printf(Fmt,val); 00559 lin.append(buf); 00560 } 00561 lin.append("\n"); 00562 return lin; 00563 } 00564 00566 inline String PrintMatrix (Mat3_t const & M, char const * Fmt="%13g", double Tol=1.0e-13) 00567 { 00568 int m = 3; 00569 int n = 3; 00570 String lin; 00571 for (int i=0; i<m; ++i) 00572 { 00573 for (int j=0; j<n; ++j) 00574 { 00575 double val = (fabs(M(i,j))<Tol ? 0.0 : M(i,j)); 00576 String buf; buf.Printf(Fmt,val); 00577 lin.append(buf); 00578 } 00579 lin.append("\n"); 00580 } 00581 return lin; 00582 } 00583 00585 inline double CompareVectors (Vec3_t const & A, Vec3_t const & B) 00586 { 00587 double error = 0.0; 00588 for (size_t i=0; i<3; ++i) 00589 error += fabs(A(i)-B(i)); 00590 return error; 00591 } 00592 00594 inline double CompareMatrices (Mat3_t const & A, Mat3_t const & B) 00595 { 00596 double error = 0.0; 00597 for (size_t i=0; i<3; ++i) 00598 for (size_t j=0; j<3; ++j) 00599 error += fabs(A(i,j)-B(i,j)); 00600 return error; 00601 } 00602 00604 inline void Trans (Mat3_t const & M, Mat3_t & Mt) 00605 { 00606 Mt(0,0)=M(0,0); Mt(0,1)=M(1,0); Mt(0,2)=M(2,0); 00607 Mt(1,0)=M(0,1); Mt(1,1)=M(1,1); Mt(1,2)=M(2,1); 00608 Mt(2,0)=M(0,2); Mt(2,1)=M(1,2); Mt(2,2)=M(2,2); 00609 } 00610 00612 inline double Det (Mat3_t const & M) 00613 { 00614 double det = M(0,0)*(M(1,1)*M(2,2) - M(1,2)*M(2,1)) 00615 - M(0,1)*(M(1,0)*M(2,2) - M(1,2)*M(2,0)) 00616 + M(0,2)*(M(1,0)*M(2,1) - M(1,1)*M(2,0)); 00617 return det; 00618 } 00619 00621 inline void Identity (Mat3_t & I) 00622 { 00623 I = 1.0, 0.0, 0.0, 00624 0.0, 1.0, 0.0, 00625 0.0, 0.0, 1.0; 00626 } 00627 00629 inline void Inv (Mat3_t const & M, Mat3_t & Mi, double Tol=1.0e-10) 00630 { 00631 double det = M(0,0)*(M(1,1)*M(2,2) - M(1,2)*M(2,1)) 00632 - M(0,1)*(M(1,0)*M(2,2) - M(1,2)*M(2,0)) 00633 + M(0,2)*(M(1,0)*M(2,1) - M(1,1)*M(2,0)); 00634 00635 if (fabs(det)<Tol) 00636 { 00637 std::ostringstream oss; 00638 oss << PrintMatrix(M); 00639 throw new Fatal("matvec.h::Inv: 3x3 matrix inversion failed with null (%g) determinat. M =\n%s",Tol,oss.str().c_str()); 00640 } 00641 00642 Mi(0,0)=(M(1,1)*M(2,2)-M(1,2)*M(2,1))/det; Mi(0,1)=(M(0,2)*M(2,1)-M(0,1)*M(2,2))/det; Mi(0,2)=(M(0,1)*M(1,2)-M(0,2)*M(1,1))/det; 00643 Mi(1,0)=(M(1,2)*M(2,0)-M(1,0)*M(2,2))/det; Mi(1,1)=(M(0,0)*M(2,2)-M(0,2)*M(2,0))/det; Mi(1,2)=(M(0,2)*M(1,0)-M(0,0)*M(1,2))/det; 00644 Mi(2,0)=(M(1,0)*M(2,1)-M(1,1)*M(2,0))/det; Mi(2,1)=(M(0,1)*M(2,0)-M(0,0)*M(2,1))/det; Mi(2,2)=(M(0,0)*M(1,1)-M(0,1)*M(1,0))/det; 00645 } 00646 00648 inline void Sol (Mat3_t const & M, Vec3_t const & B, Vec3_t & X, double Tol=1.0e-10) 00649 { 00650 // determinant 00651 double det = M(0,0)*(M(1,1)*M(2,2) - M(1,2)*M(2,1)) 00652 - M(0,1)*(M(1,0)*M(2,2) - M(1,2)*M(2,0)) 00653 + M(0,2)*(M(1,0)*M(2,1) - M(1,1)*M(2,0)); 00654 if (fabs(det)<Tol) throw new Fatal("matvec.h:Sol: Cannot calculate inverse due to zero determinant. det = %g",det); 00655 00656 // inverse matrix 00657 Mat3_t Mi; 00658 Mi(0,0) = (M(1,1)*M(2,2) - M(1,2)*M(2,1)) / det; 00659 Mi(0,1) = (M(0,2)*M(2,1) - M(0,1)*M(2,2)) / det; 00660 Mi(0,2) = (M(0,1)*M(1,2) - M(0,2)*M(1,1)) / det; 00661 00662 Mi(1,0) = (M(1,2)*M(2,0) - M(1,0)*M(2,2)) / det; 00663 Mi(1,1) = (M(0,0)*M(2,2) - M(0,2)*M(2,0)) / det; 00664 Mi(1,2) = (M(0,2)*M(1,0) - M(0,0)*M(1,2)) / det; 00665 00666 Mi(2,0) = (M(1,0)*M(2,1) - M(1,1)*M(2,0)) / det; 00667 Mi(2,1) = (M(0,1)*M(2,0) - M(0,0)*M(2,1)) / det; 00668 Mi(2,2) = (M(0,0)*M(1,1) - M(0,1)*M(1,0)) / det; 00669 00670 // solve system 00671 X(0) = Mi(0,0)*B(0) + Mi(0,1)*B(1) + Mi(0,2)*B(2); 00672 X(1) = Mi(1,0)*B(0) + Mi(1,1)*B(1) + Mi(1,2)*B(2); 00673 X(2) = Mi(2,0)*B(0) + Mi(2,1)*B(1) + Mi(2,2)*B(2); 00674 } 00675 00677 inline void Eig (Mat3_t & M, Vec3_t & L) 00678 { 00679 // calculate 00680 gsl_matrix_view m = gsl_matrix_view_array (M.data(), 3, 3); 00681 gsl_vector * eval = gsl_vector_alloc (3); 00682 gsl_eigen_symm_workspace * w = gsl_eigen_symm_alloc (3); 00683 gsl_eigen_symm (&m.matrix, eval, w); 00684 00685 // eigenvalues 00686 L = gsl_vector_get(eval,0), gsl_vector_get(eval,1), gsl_vector_get(eval,2); 00687 00688 // clean up 00689 gsl_eigen_symm_free (w); 00690 gsl_vector_free (eval); 00691 } 00692 00694 inline void Eig (Mat3_t & M, Vec3_t & L, Vec3_t & V0, Vec3_t & V1, Vec3_t & V2, bool SortAsc=false, bool SortDesc=false) 00695 { 00696 // calculate 00697 gsl_matrix_view m = gsl_matrix_view_array (M.data(), 3, 3); 00698 gsl_vector * eval = gsl_vector_alloc (3); 00699 gsl_matrix * evec = gsl_matrix_alloc (3, 3); 00700 gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc (3); 00701 gsl_eigen_symmv (&m.matrix, eval, evec, w); 00702 00703 // sort 00704 if (SortAsc) gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_VAL_ASC); 00705 if (SortDesc) gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_VAL_DESC); 00706 00707 // eigenvalues 00708 L = gsl_vector_get(eval,0), gsl_vector_get(eval,1), gsl_vector_get(eval,2); 00709 00710 // eigenvectors 00711 gsl_vector_view ev = gsl_matrix_column (evec,0); 00712 V0 = gsl_vector_get (&ev.vector,0), gsl_vector_get(&ev.vector,1), gsl_vector_get(&ev.vector,2); 00713 ev = gsl_matrix_column (evec,1); 00714 V1 = gsl_vector_get (&ev.vector,0), gsl_vector_get(&ev.vector,1), gsl_vector_get(&ev.vector,2); 00715 ev = gsl_matrix_column (evec,2); 00716 V2 = gsl_vector_get (&ev.vector,0), gsl_vector_get(&ev.vector,1), gsl_vector_get(&ev.vector,2); 00717 00718 // clean up 00719 gsl_eigen_symmv_free (w); 00720 gsl_vector_free (eval); 00721 gsl_matrix_free (evec); 00722 } 00723 00725 inline double Norm (Vec3_t const & V) 00726 { 00727 return sqrt(blitz::dot(V,V)); 00728 } 00729 00731 inline void Dyad (Vec3_t const & A, Vec3_t const & B, Mat3_t & M) 00732 { 00733 M(0,0)=A(0)*B(0); M(0,1)=A(0)*B(1); M(0,2)=A(0)*B(2); 00734 M(1,0)=A(1)*B(0); M(1,1)=A(1)*B(1); M(1,2)=A(1)*B(2); 00735 M(2,0)=A(2)*B(0); M(2,1)=A(2)*B(1); M(2,2)=A(2)*B(2); 00736 } 00737 00739 inline void Dyad (double s, Vec3_t const & A, Vec3_t const & B, Mat3_t & M) 00740 { 00741 M(0,0)=s*A(0)*B(0); M(0,1)=s*A(0)*B(1); M(0,2)=s*A(0)*B(2); 00742 M(1,0)=s*A(1)*B(0); M(1,1)=s*A(1)*B(1); M(1,2)=s*A(1)*B(2); 00743 M(2,0)=s*A(2)*B(0); M(2,1)=s*A(2)*B(1); M(2,2)=s*A(2)*B(2); 00744 } 00745 00747 inline void Mult (Vec3_t const & A, Mat3_t const & M, Vec3_t & B) 00748 { 00749 B(0) = A(0)*M(0,0) + A(1)*M(1,0) + A(2)*M(2,0); 00750 B(1) = A(0)*M(0,1) + A(1)*M(1,1) + A(2)*M(2,1); 00751 B(2) = A(0)*M(0,2) + A(1)*M(1,2) + A(2)*M(2,2); 00752 } 00753 00755 inline void Mult (Mat3_t const & A, Mat3_t const & B, Mat3_t & M) 00756 { 00757 M(0,0)=A(0,2)*B(2,0)+A(0,1)*B(1,0)+A(0,0)*B(0,0); M(0,1)=A(0,2)*B(2,1)+A(0,1)*B(1,1)+A(0,0)*B(0,1); M(0,2)=A(0,2)*B(2,2)+A(0,1)*B(1,2)+A(0,0)*B(0,2); 00758 M(1,0)=A(1,2)*B(2,0)+B(1,0)*A(1,1)+B(0,0)*A(1,0); M(1,1)=A(1,2)*B(2,1)+A(1,1)*B(1,1)+B(0,1)*A(1,0); M(1,2)=A(1,2)*B(2,2)+A(1,1)*B(1,2)+B(0,2)*A(1,0); 00759 M(2,0)=A(2,2)*B(2,0)+B(1,0)*A(2,1)+B(0,0)*A(2,0); M(2,1)=B(2,1)*A(2,2)+B(1,1)*A(2,1)+B(0,1)*A(2,0); M(2,2)=A(2,2)*B(2,2)+B(1,2)*A(2,1)+B(0,2)*A(2,0); 00760 } 00761 00763 inline void set_to_zero (Vec3_t & V) 00764 { 00765 V = 0.0, 0.0, 0.0; 00766 } 00767 00769 inline void set_to_zero (Mat3_t & M) 00770 { 00771 M = 0.0, 0.0, 0.0, 00772 0.0, 0.0, 0.0, 00773 0.0, 0.0, 0.0; 00774 } 00775 00776 // Constants 00777 namespace OrthoSys 00778 { 00779 Vec3_t O; 00780 Vec3_t e0,e1,e2; 00781 Mat3_t I; 00782 00783 int __init_ortho_sys() 00784 { 00785 O = 0.0, 0.0, 0.0; 00786 e0 = 1.0, 0.0, 0.0; 00787 e1 = 0.0, 1.0, 0.0; 00788 e2 = 0.0, 0.0, 1.0; 00789 I = 1.0, 0.0, 0.0, 00790 0.0, 1.0, 0.0, 00791 0.0, 0.0, 1.0; 00792 return 0.0; 00793 } 00794 00795 int __dummy_init_ortho_sys = __init_ortho_sys(); 00796 } 00797 00798 #ifdef USE_BOOST_PYTHON 00799 inline Vec3_t Tup2Vec3 (BPy::tuple const & T3) 00800 { 00801 return Vec3_t(BPy::extract<double>(T3[0])(), BPy::extract<double>(T3[1])(), BPy::extract<double>(T3[2])()); 00802 } 00803 #endif 00804 00805 00807 00808 00810 inline void Ten2Mat (Vec_t const & Ten, Mat3_t & Mat) 00811 { 00812 // matrix of tensor 00813 size_t ncp = size(Ten); 00814 if (ncp==4) 00815 { 00816 Mat = Ten(0), Ten(3)/Util::SQ2, 0.0, 00817 Ten(3)/Util::SQ2, Ten(1), 0.0, 00818 0.0, 0.0, Ten(2); 00819 } 00820 else if (ncp==6) 00821 { 00822 Mat = Ten(0), Ten(3)/Util::SQ2, Ten(5)/Util::SQ2, 00823 Ten(3)/Util::SQ2, Ten(1), Ten(4)/Util::SQ2, 00824 Ten(5)/Util::SQ2, Ten(4)/Util::SQ2, Ten(2); 00825 00826 } 00827 else throw new Fatal("matvec.h::Ten2Mat: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 00828 } 00829 00831 inline void Ten2Mat (Vec_t const & Ten, Mat_t & Mat) 00832 { 00833 // matrix of tensor 00834 Mat.change_dim (3,3); 00835 size_t ncp = size(Ten); 00836 if (ncp==4) 00837 { 00838 Mat = Ten(0), Ten(3)/Util::SQ2, 0.0, 00839 Ten(3)/Util::SQ2, Ten(1), 0.0, 00840 0.0, 0.0, Ten(2); 00841 } 00842 else if (ncp==6) 00843 { 00844 Mat = Ten(0), Ten(3)/Util::SQ2, Ten(5)/Util::SQ2, 00845 Ten(3)/Util::SQ2, Ten(1), Ten(4)/Util::SQ2, 00846 Ten(5)/Util::SQ2, Ten(4)/Util::SQ2, Ten(2); 00847 00848 } 00849 else throw new Fatal("matvec.h::Ten2Mat: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 00850 } 00851 00853 inline void Mat2Ten (Mat3_t const & Mat, Vec_t & Ten, size_t NumComponents, bool CheckSymmetry=true, double Tol=1.0e-10) 00854 { 00855 if (CheckSymmetry) 00856 { 00857 if (fabs(Mat(0,1)-Mat(1,0))>Tol) throw new Fatal("matvec.h::Mat2Ten: Matrix is not symmetric"); 00858 if (fabs(Mat(1,2)-Mat(2,1))>Tol) throw new Fatal("matvec.h::Mat2Ten: Matrix is not symmetric"); 00859 if (fabs(Mat(2,0)-Mat(0,2))>Tol) throw new Fatal("matvec.h::Mat2Ten: Matrix is not symmetric"); 00860 } 00861 00862 // tensor from matrix 00863 Ten.change_dim (NumComponents); 00864 if (NumComponents==4) 00865 { 00866 Ten = Mat(0,0), Mat(1,1), Mat(2,2), Util::SQ2*Mat(0,1); 00867 } 00868 else if (NumComponents==6) 00869 { 00870 Ten = Mat(0,0), Mat(1,1), Mat(2,2), Util::SQ2*Mat(0,1), Util::SQ2*Mat(1,2), Util::SQ2*Mat(2,0); 00871 } 00872 else throw new Fatal("matvec.h::Mat2Ten: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 00873 } 00874 00875 #ifdef HAS_TENSORS 00876 00878 inline void Vec2Tensor (Vec_t const & V, Ten1_t & Vec) 00879 { 00880 if (size(V)!=3) throw new Fatal("matvec.h::Ten1Tensor: Vector (Vec_t) must have size equal to 3"); 00881 Vec = V(0), V(1), V(2); 00882 } 00883 00885 inline void Vec2Tensor (Vec3_t const & V, Ten1_t & Vec) 00886 { 00887 Vec = V(0), V(1), V(2); 00888 } 00889 00891 inline void Tensor2Vec (Ten1_t const & V, Vec_t & Vec) 00892 { 00893 Vec.change_dim (3); 00894 Vec = V[0], V[1], V[2]; 00895 } 00896 00898 inline void Tensor2Vec (Ten1_t const & V, Vec3_t & Vec) 00899 { 00900 Vec = V[0], V[1], V[2]; 00901 } 00902 00904 inline void Tensor2Mat (Ten2_t const & T, Mat3_t & M) 00905 { 00906 M = T[0][0], T[0][1], T[0][2], 00907 T[1][0], T[1][1], T[1][2], 00908 T[2][0], T[2][1], T[2][2]; 00909 } 00910 00912 inline void Mat2Tensor (Mat3_t const & M, Ten2_t & T) 00913 { 00914 T = M(0,0), M(0,1), M(0,2), 00915 M(1,0), M(1,1), M(1,2), 00916 M(2,0), M(2,1), M(2,2); 00917 } 00918 00920 inline void Ten2Tensor (Vec_t const & Ten, Ten2_t & T) 00921 { 00922 size_t ncp = size(Ten); 00923 if (ncp==4) 00924 { 00925 T = Ten(0), Ten(3)/Util::SQ2, 0.0, 00926 Ten(3)/Util::SQ2, Ten(1), 0.0, 00927 0.0, 0.0, Ten(2); 00928 } 00929 else if (ncp==6) 00930 { 00931 T = Ten(0), Ten(3)/Util::SQ2, Ten(5)/Util::SQ2, 00932 Ten(3)/Util::SQ2, Ten(1), Ten(4)/Util::SQ2, 00933 Ten(5)/Util::SQ2, Ten(4)/Util::SQ2, Ten(2); 00934 } 00935 else throw new Fatal("matvec.h::Ten2Tensor: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation. NumComponents==%d is invalid",ncp); 00936 } 00937 00939 inline void Tensor2Ten (Ten2_t const & T, Vec_t & Ten, size_t NumComponents, bool CheckSymmetry=true, double Tol=1.0e-10) 00940 { 00941 if (CheckSymmetry) 00942 { 00943 bool error = false; 00944 if (fabs(T[0][1]-T[1][0])>Tol) error = true; 00945 if (fabs(T[1][2]-T[2][1])>Tol) error = true; 00946 if (fabs(T[2][0]-T[0][2])>Tol) error = true; 00947 if (error) 00948 { 00949 Mat3_t mT; 00950 Tensor2Mat (T, mT); 00951 std::ostringstream oss; 00952 oss << "T = \n" << PrintMatrix(mT); 00953 throw new Fatal("matvec.h::Tensor2Ten: Tensor is not symmetric\n%s",oss.str().c_str()); 00954 } 00955 } 00956 00957 Ten.change_dim (NumComponents); 00958 if (NumComponents==4) 00959 { 00960 Ten = T[0][0], T[1][1], T[2][2], T[0][1]*Util::SQ2; 00961 } 00962 else if (NumComponents==6) 00963 { 00964 Ten = T[0][0], T[1][1], T[2][2], T[0][1]*Util::SQ2, T[1][2]*Util::SQ2, T[2][0]*Util::SQ2; 00965 } 00966 else throw new Fatal("matvec.h::Tensor2Ten: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation. NumComponents==%d is invalid",NumComponents); 00967 } 00968 00970 inline void Tensor2Ten (Ten4_t const & T, Mat_t & Ten, size_t NumComponents, bool CheckSymmetry=true, double Tol=1.0e-10) 00971 { 00972 if (!(NumComponents==4 || NumComponents==6)) throw new Fatal("matvec.h::Tensor2Ten: This method is only available for 4th order symmetric tensors with either 4x4 or 6x6 components according to Mandel's representation. NumComponents==%d is invalid",NumComponents); 00973 Ten.change_dim (NumComponents,NumComponents); 00974 for (size_t i=0; i<3; ++i) 00975 for (size_t j=0; j<3; ++j) 00976 for (size_t k=0; k<3; ++k) 00977 for (size_t l=0; l<3; ++l) 00978 { 00979 if (CheckSymmetry) 00980 { 00981 if (fabs(T[i][j][k][l] - T[i][j][l][k])>Tol) throw new Fatal("matvec.h::Tensor2Ten: 4ht order Tensor is not super symmetric: ijkl != ijlk"); 00982 if (fabs(T[i][j][k][l] - T[j][i][k][l])>Tol) throw new Fatal("matvec.h::Tensor2Ten: 4ht order Tensor is not super symmetric: ijkl != jikl"); 00983 if (fabs(T[i][j][k][l] - T[k][l][i][j])>Tol) throw new Fatal("matvec.h::Tensor2Ten: 4ht order Tensor is not super symmetric: ijkl != klij"); 00984 } 00985 size_t I = TensorsLib::Tensor4ToMandel_i[i][j][k][l]; 00986 size_t J = TensorsLib::Tensor4ToMandel_j[i][j][k][l]; 00987 double a = (k==l ? 1.0 : Util::SQ2); 00988 double b = (i==j ? 1.0 : Util::SQ2); 00989 if (I<NumComponents && J<NumComponents) Ten(I,J) = T[i][j][k][l]*a*b; 00990 } 00991 } 00992 00993 #endif 00994 00995 00997 00998 01000 inline void UnitVecDeriv (Vec_t const & n, Vec_t & nu, Mat_t & dnudn, double Tol=1.0e-8) 01001 { 01002 double norm_n = Norm(n); 01003 Mat_t I; 01004 Identity (size(n), I); 01005 if (norm_n>Tol) 01006 { 01007 nu = n / norm_n; 01008 Mat_t nu_dy_nu; 01009 Dyad (nu, nu, nu_dy_nu); 01010 dnudn = I/norm_n - nu_dy_nu/norm_n; 01011 } 01012 else 01013 { 01014 nu = 1./Util::SQ3, 1./Util::SQ3, 1./Util::SQ3; 01015 dnudn = I; 01016 } 01017 } 01018 01020 inline void UnitVecDeriv (Vec3_t const & n, Vec3_t & nu, Mat3_t & dnudn, double Tol=1.0e-8) 01021 { 01022 double norm_n = Norm(n); 01023 if (norm_n>Tol) 01024 { 01025 double s = 1.0/norm_n; 01026 nu = n / norm_n; 01027 dnudn(0,0)=s-s*nu(0)*nu(0); dnudn(0,1)= -s*nu(0)*nu(1); dnudn(0,2)= -s*nu(0)*nu(2); 01028 dnudn(1,0)= -s*nu(1)*nu(0); dnudn(1,1)=s-s*nu(1)*nu(1); dnudn(1,2)= -s*nu(1)*nu(2); 01029 dnudn(2,0)= -s*nu(2)*nu(0); dnudn(2,1)= -s*nu(2)*nu(1); dnudn(2,2)=s-s*nu(2)*nu(2); 01030 } 01031 else 01032 { 01033 nu = 1./Util::SQ3, 1./Util::SQ3, 1./Util::SQ3; 01034 dnudn = 1.0, 0.0, 0.0, 01035 0.0, 1.0, 0.0, 01036 0.0, 0.0, 1.0; 01037 } 01038 } 01039 01040 #ifdef HAS_TENSORS 01041 01043 inline void UnitVecDeriv (Vec3_t const & n, Vec3_t & nu, Ten2_t & dnudn, double Tol=1.0e-8) 01044 { 01045 double norm_n = Norm(n); 01046 if (norm_n>Tol) 01047 { 01048 double s = 1.0/norm_n; 01049 nu = n / norm_n; 01050 dnudn[0][0]=s-s*nu(0)*nu(0); dnudn[0][1]= -s*nu(0)*nu(1); dnudn[0][2]= -s*nu(0)*nu(2); 01051 dnudn[1][0]= -s*nu(1)*nu(0); dnudn[1][1]=s-s*nu(1)*nu(1); dnudn[1][2]= -s*nu(1)*nu(2); 01052 dnudn[2][0]= -s*nu(2)*nu(0); dnudn[2][1]= -s*nu(2)*nu(1); dnudn[2][2]=s-s*nu(2)*nu(2); 01053 } 01054 else 01055 { 01056 nu = 1./Util::SQ3, 1./Util::SQ3, 1./Util::SQ3; 01057 dnudn = 1.0, 0.0, 0.0, 01058 0.0, 1.0, 0.0, 01059 0.0, 0.0, 1.0; 01060 } 01061 } 01062 01063 #endif 01064 01065 01067 01068 01069 // Assymmetric 3D tensor 01070 typedef blitz::TinyVector<double,9> ATensor2; 01071 01073 inline void Sym (double a, ATensor2 const & T, size_t NCp, Vec_t & S) 01074 { 01075 S.change_dim (NCp); 01076 if (NCp==4) 01077 { 01078 S(0) = a*T(0); 01079 S(1) = a*T(1); 01080 S(2) = a*T(2); 01081 S(3) = a*0.5*(T(3)+T(6))*Util::SQ2; 01082 } 01083 else if (NCp==6) 01084 { 01085 S(0) = a*T(0); 01086 S(1) = a*T(1); 01087 S(2) = a*T(2); 01088 S(3) = a*0.5*(T(3)+T(6))*Util::SQ2; 01089 S(4) = a*0.5*(T(4)+T(7))*Util::SQ2; 01090 S(5) = a*0.5*(T(5)+T(8))*Util::SQ2; 01091 } 01092 else throw new Fatal("matvec.h::Sym: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation. NCp=%zd is invalid",NCp); 01093 } 01094 01096 inline void Dot (ATensor2 const & A, ATensor2 const & B, ATensor2 & C) 01097 { 01098 C(0) = A(0)*B(0)+A(3)*B(6)+A(5)*B(8); 01099 C(3) = A(0)*B(3)+A(3)*B(1)+A(5)*B(7); 01100 C(5) = A(0)*B(5)+A(3)*B(4)+A(5)*B(2); 01101 C(6) = A(6)*B(0)+A(1)*B(6)+A(4)*B(8); 01102 C(1) = A(6)*B(3)+A(1)*B(1)+A(4)*B(7); 01103 C(4) = A(6)*B(5)+A(1)*B(4)+A(4)*B(2); 01104 C(8) = A(8)*B(0)+A(7)*B(6)+A(2)*B(8); 01105 C(7) = A(8)*B(3)+A(7)*B(1)+A(2)*B(7); 01106 C(2) = A(8)*B(5)+A(7)*B(4)+A(2)*B(2); 01107 } 01108 01110 inline void AddSkewTimesOp1 (ATensor2 const & L, Vec_t const & S, Vec_t & R, double Tol=1.0e-14) 01111 { 01112 size_t ncp = size(R); 01113 if (ncp==4) 01114 { 01115 R(0) += -(Util::SQ2*S(3)*L(6)-Util::SQ2*L(3)*S(3))/2.0; 01116 R(1) += (Util::SQ2*S(3)*L(6)-Util::SQ2*L(3)*S(3))/2.0; 01117 R(2) += 0.0; 01118 R(3) += -((S(1)-S(0))*L(6)+(S(0)-S(1))*L(3))/Util::SQ2; 01119 double R4 = (Util::SQ2*S(3)*L(8)+(2*S(1)-2*S(2))*L(7)-Util::SQ2*S(3)*L(5)+(2*S(2)-2*S(1))*L(4))/(2.0*Util::SQ2); 01120 double R5 = -((2*S(2)-2*S(0))*L(8)-Util::SQ2*S(3)*L(7)+(2*S(0)-2*S(2))*L(5)+Util::SQ2*S(3)*L(4))/(2.0*Util::SQ2); 01121 if (fabs(R4)>Tol) throw new Fatal("matvec.h::SkewTimesOp1: R4=%g is not zero => Tensor cannot be represented by 4 components only",R4); 01122 if (fabs(R5)>Tol) throw new Fatal("matvec.h::SkewTimesOp1: R5=%g is not zero => Tensor cannot be represented by 5 components only",R5); 01123 } 01124 else if (ncp==6) 01125 { 01126 R(0) += -(Util::SQ2*S(5)*L(8)+Util::SQ2*S(3)*L(6)-Util::SQ2*L(5)*S(5)-Util::SQ2*L(3)*S(3))/2.0; 01127 R(1) += -(Util::SQ2*S(4)*L(7)-Util::SQ2*S(3)*L(6)-Util::SQ2*L(4)*S(4)+Util::SQ2*L(3)*S(3))/2.0; 01128 R(2) += (Util::SQ2*S(5)*L(8)+Util::SQ2*S(4)*L(7)-Util::SQ2*L(5)*S(5)-Util::SQ2*L(4)*S(4))/2.0; 01129 R(3) += -(Util::SQ2*S(4)*L(8)+Util::SQ2*S(5)*L(7)+(2*S(1)-2*S(0))*L(6)-Util::SQ2*L(4)*S(5)-Util::SQ2*S(4)*L(5)+(2*S(0)-2*S(1))*L(3))/(2.0*Util::SQ2); 01130 R(4) += (Util::SQ2*S(3)*L(8)+(2*S(1)-2*S(2))*L(7)+Util::SQ2*S(5)*L(6)-Util::SQ2*L(3)*S(5)-Util::SQ2*S(3)*L(5)+(2*S(2)-2*S(1))*L(4))/(2.0*Util::SQ2); 01131 R(5) += -((2*S(2)-2*S(0))*L(8)-Util::SQ2*S(3)*L(7)+Util::SQ2*S(4)*L(6)+(2*S(0)-2*S(2))*L(5)-Util::SQ2*L(3)*S(4)+Util::SQ2*S(3)*L(4))/(2.0*Util::SQ2); 01132 } 01133 else throw new Fatal("matvec.h::SkewTimesOp1: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation. NCp=%zd is invalid",ncp); 01134 } 01135 01137 inline double Det (ATensor2 const & F) 01138 { 01139 return -F(3)*(F(2)*F(6)-F(4)*F(8)) + F(5)*(F(6)*F(7)-F(1)*F(8)) + F(0)*(F(1)*F(2)-F(4)*F(7)); 01140 } 01141 01143 inline void CalcLCauchyGreen (ATensor2 const & F, size_t NCp, Vec_t & b, double Tol=1.0e-14) 01144 { 01145 b.change_dim (NCp); 01146 if (NCp==4) 01147 { 01148 b(0) = pow(F(5),2.0)+pow(F(3),2.0)+pow(F(0),2.0); 01149 b(1) = pow(F(6),2.0)+pow(F(4),2.0)+pow(F(1),2.0); 01150 b(2) = pow(F(8),2.0)+pow(F(7),2.0)+pow(F(2),2.0); 01151 b(3) = Util::SQ2*F(0)*F(6)+Util::SQ2*F(4)*F(5)+Util::SQ2*F(1)*F(3); 01152 double b4 = Util::SQ2*F(6)*F(8)+Util::SQ2*F(1)*F(7)+Util::SQ2*F(2)*F(4); 01153 double b5 = Util::SQ2*F(0)*F(8)+Util::SQ2*F(3)*F(7)+Util::SQ2*F(2)*F(5); 01154 if (fabs(b4)>Tol) throw new Fatal("matvec.h::CalcLCauchyGreen: b4=%g is not zero => Tensor cannot be represented by 4 components only",b4); 01155 if (fabs(b5)>Tol) throw new Fatal("matvec.h::CalcLCauchyGreen: b5=%g is not zero => Tensor cannot be represented by 5 components only",b5); 01156 } 01157 else if (NCp==6) 01158 { 01159 b(0) = pow(F(5),2.0)+pow(F(3),2.0)+pow(F(0),2.0); 01160 b(1) = pow(F(6),2.0)+pow(F(4),2.0)+pow(F(1),2.0); 01161 b(2) = pow(F(8),2.0)+pow(F(7),2.0)+pow(F(2),2.0); 01162 b(3) = Util::SQ2*F(0)*F(6)+Util::SQ2*F(4)*F(5)+Util::SQ2*F(1)*F(3); 01163 b(4) = Util::SQ2*F(6)*F(8)+Util::SQ2*F(1)*F(7)+Util::SQ2*F(2)*F(4); 01164 b(5) = Util::SQ2*F(0)*F(8)+Util::SQ2*F(3)*F(7)+Util::SQ2*F(2)*F(5); 01165 } 01166 else throw new Fatal("matvec.h::CalcLCauchyGreen: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation. NCp=%zd is invalid",NCp); 01167 } 01168 01169 01171 inline void Mult (Vec_t const & Sig, Vec3_t const & n, Vec3_t & t) 01172 { 01173 size_t ncp = size(Sig); 01174 if (ncp==4) 01175 { 01176 t(0) = Sig(0)*n(0) + Sig(3)*n(1)/Util::SQ2; 01177 t(1) = Sig(3)*n(0)/Util::SQ2 + Sig(1)*n(1); 01178 t(2) = + Sig(2)*n(2); 01179 } 01180 else if (ncp==6) 01181 { 01182 t(0) = Sig(0)*n(0) + Sig(3)*n(1)/Util::SQ2 + Sig(5)*n(2)/Util::SQ2; 01183 t(1) = Sig(3)*n(0)/Util::SQ2 + Sig(1)*n(1) + Sig(4)*n(2)/Util::SQ2; 01184 t(2) = Sig(5)*n(0)/Util::SQ2 + Sig(4)*n(1)/Util::SQ2 + Sig(2)*n(2); 01185 } 01186 else throw new Fatal("matvec.h::Mult: (Cauchy) This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 01187 } 01188 01190 inline void Dev (Vec_t const & Ten, Vec_t & DevTen) 01191 { 01192 double coef = (Ten(0)+Ten(1)+Ten(2))/3.0; 01193 DevTen = Ten; 01194 DevTen(0) -= coef; 01195 DevTen(1) -= coef; 01196 DevTen(2) -= coef; 01197 } 01198 01200 inline double Tra (Vec_t const & Ten) 01201 { 01202 return Ten(0)+Ten(1)+Ten(2); 01203 } 01204 01206 inline void Pow2 (Vec_t const & Ten, Vec_t & Ten2) 01207 { 01208 size_t ncp = size(Ten); 01209 Ten2.change_dim (ncp); 01210 if (ncp==4) 01211 { 01212 Ten2 = Ten(0)*Ten(0) + Ten(3)*Ten(3)/2.0, 01213 Ten(1)*Ten(1) + Ten(3)*Ten(3)/2.0, 01214 Ten(2)*Ten(2), 01215 Ten(0)*Ten(3) + Ten(1)*Ten(3); 01216 } 01217 else if (ncp==6) 01218 { 01219 Ten2 = Ten(0)*Ten(0) + Ten(3)*Ten(3)/2.0 + Ten(5)*Ten(5)/2.0, 01220 Ten(3)*Ten(3)/2.0 + Ten(1)*Ten(1) + Ten(4)*Ten(4)/2.0, 01221 Ten(5)*Ten(5)/2.0 + Ten(4)*Ten(4)/2.0 + Ten(2)*Ten(2), 01222 Ten(0)*Ten(3) + Ten(3)*Ten(1) + Ten(5)*Ten(4)/Util::SQ2, 01223 Ten(3)*Ten(5)/Util::SQ2 + Ten(1)*Ten(4) + Ten(4)*Ten(2), 01224 Ten(0)*Ten(5) + Ten(3)*Ten(4)/Util::SQ2 + Ten(5)*Ten(2); 01225 } 01226 else throw new Fatal("matvec.h::Pow2: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 01227 } 01228 01230 inline double Det (Vec_t const & Ten) 01231 { 01232 size_t ncp = size(Ten); 01233 if (ncp==4) 01234 { 01235 return Ten(0)*Ten(1)*Ten(2) 01236 - Ten(2)*Ten(3)*Ten(3)/2.0; 01237 } 01238 else if (ncp==6) 01239 { 01240 return Ten(0)*Ten(1)*Ten(2) 01241 + Ten(3)*Ten(4)*Ten(5)/Util::SQ2 01242 - Ten(0)*Ten(4)*Ten(4)/2.0 01243 - Ten(1)*Ten(5)*Ten(5)/2.0 01244 - Ten(2)*Ten(3)*Ten(3)/2.0; 01245 } 01246 else throw new Fatal("matvec.h::Det: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 01247 } 01248 01250 inline void Inv (Vec_t const & T, Vec_t & Ti, double Tol=1.0e-10) 01251 { 01252 size_t ncp = size(T); 01253 Ti.change_dim (ncp); 01254 if (ncp==4) 01255 { 01256 double det = T(0)*T(1)*T(2) 01257 - T(2)*T(3)*T(3)/2.0; 01258 01259 if (fabs(det)<Tol) 01260 { 01261 std::ostringstream oss; oss<<PrintVector(T); 01262 throw new Fatal("matvec.h::Inv: inverse of 2nd order symmetric tensor failed with null (%g) determinat.\n T =%s",Tol,oss.str().c_str()); 01263 } 01264 01265 Ti(0) = T(1)*T(2)/det; 01266 Ti(1) = T(0)*T(2)/det; 01267 Ti(2) = (T(0)*T(1) - T(3)*T(3)/2.0)/det; 01268 Ti(3) = -T(2)*T(3)/det; 01269 01270 } 01271 else if (ncp==6) 01272 { 01273 double det = T(0)*T(1)*T(2) 01274 + T(3)*T(4)*T(5)/Util::SQ2 01275 - T(0)*T(4)*T(4)/2.0 01276 - T(1)*T(5)*T(5)/2.0 01277 - T(2)*T(3)*T(3)/2.0; 01278 01279 if (fabs(det)<Tol) 01280 { 01281 std::ostringstream oss; oss<<PrintVector(T); 01282 throw new Fatal("matvec.h::Inv: inverse of 2nd order symmetric tensor failed with null (%g) determinat.\n T =%s",Tol,oss.str().c_str()); 01283 } 01284 01285 Ti(0) = (T(1)*T(2) - T(4)*T(4)/2.0)/det; 01286 Ti(1) = (T(0)*T(2) - T(5)*T(5)/2.0)/det; 01287 Ti(2) = (T(0)*T(1) - T(3)*T(3)/2.0)/det; 01288 Ti(3) = (T(4)*T(5)/Util::SQ2 - T(2)*T(3))/det; 01289 Ti(4) = (T(3)*T(5)/Util::SQ2 - T(0)*T(4))/det; 01290 Ti(5) = (T(3)*T(4)/Util::SQ2 - T(1)*T(5))/det; 01291 } 01292 else throw new Fatal("matvec.h::Inv: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 01293 } 01294 01296 inline void CharInvs (Vec_t const & Ten, double & I1, double & I2, double & I3) 01297 { 01298 I1 = Ten(0) + Ten(1) + Ten(2); 01299 I2 = Ten(0)*Ten(1) + Ten(1)*Ten(2) + Ten(2)*Ten(0) - Ten(3)*Ten(3)/2.0; 01300 I3 = Ten(0)*Ten(1)*Ten(2) - Ten(2)*Ten(3)*Ten(3)/2.0; 01301 size_t ncp = size(Ten); 01302 if (ncp>4) 01303 { 01304 I2 += (-Ten(4)*Ten(4)/2.0 - Ten(5)*Ten(5)/2.0); 01305 I3 += (Ten(3)*Ten(4)*Ten(5)/Util::SQ2 - Ten(0)*Ten(4)*Ten(4)/2.0 - Ten(1)*Ten(5)*Ten(5)/2.0); 01306 } 01307 } 01308 01310 inline void CharInvs (Vec_t const & Ten, double & I1, double & I2, double & I3, Vec_t & dI1dTen, Vec_t & dI2dTen, Vec_t & dI3dTen) 01311 { 01312 I1 = Ten(0) + Ten(1) + Ten(2); 01313 I2 = Ten(0)*Ten(1) + Ten(1)*Ten(2) + Ten(2)*Ten(0) - Ten(3)*Ten(3)/2.0; 01314 I3 = Ten(0)*Ten(1)*Ten(2) - Ten(2)*Ten(3)*Ten(3)/2.0; 01315 size_t ncp = size(Ten); 01316 dI1dTen.change_dim (ncp); 01317 dI2dTen.change_dim (ncp); 01318 dI3dTen.change_dim (ncp); 01319 if (ncp>4) 01320 { 01321 I2 += (-Ten(4)*Ten(4)/2.0 - Ten(5)*Ten(5)/2.0); 01322 I3 += (Ten(3)*Ten(4)*Ten(5)/Util::SQ2 - Ten(0)*Ten(4)*Ten(4)/2.0 - Ten(1)*Ten(5)*Ten(5)/2.0); 01323 dI1dTen = 1.0, 1.0, 1.0, 0.0, 0.0, 0.0; 01324 } 01325 else dI1dTen = 1.0, 1.0, 1.0, 0.0; 01326 Vec_t Ten2(ncp); 01327 Pow2 (Ten, Ten2); 01328 dI2dTen = I1*dI1dTen - Ten; 01329 dI3dTen = Ten2 - I1*Ten + I2*dI1dTen; 01330 } 01331 01333 inline void DerivInv (Vec_t const & A, Vec_t & Ai, Mat_t & dInvA_dA, double Tol=1.0e-10) 01334 { 01335 Inv (A, Ai, Tol); 01336 size_t ncp = size(A); 01337 dInvA_dA.change_dim (ncp,ncp); 01338 if (ncp==4) throw new Fatal("matvec.h: DerivInv: This method doesn't work for ncp==4"); 01339 else if (ncp==6) 01340 { 01341 double s = Util::SQ2; 01342 dInvA_dA = 01343 -Ai(0)*Ai(0) , -Ai(3)*Ai(3)/2. , -Ai(5)*Ai(5)/2. , -Ai(0)*Ai(3) , -(Ai(3)*Ai(5))/s , -Ai(0)*Ai(5) , 01344 -Ai(3)*Ai(3)/2. , -Ai(1)*Ai(1) , -Ai(4)*Ai(4)/2. , -Ai(1)*Ai(3) , -Ai(1)*Ai(4) , -(Ai(3)*Ai(4))/s , 01345 -Ai(5)*Ai(5)/2. , -Ai(4)*Ai(4)/2. , -Ai(2)*Ai(2) , -(Ai(4)*Ai(5))/s , -Ai(2)*Ai(4) , -Ai(2)*Ai(5) , 01346 -Ai(0)*Ai(3) , -Ai(1)*Ai(3) , -(Ai(4)*Ai(5))/s , -Ai(3)*Ai(3)/2.-Ai(0)*Ai(1) , -(Ai(1)*Ai(5))/s-(Ai(3)*Ai(4))/2. , -(Ai(3)*Ai(5))/2.-(Ai(0)*Ai(4))/s , 01347 -(Ai(3)*Ai(5))/s , -Ai(1)*Ai(4) , -Ai(2)*Ai(4) , -(Ai(1)*Ai(5))/s-(Ai(3)*Ai(4))/2. , -Ai(4)*Ai(4)/2.-Ai(1)*Ai(2) , -(Ai(4)*Ai(5))/2.-(Ai(2)*Ai(3))/s , 01348 -Ai(0)*Ai(5) , -(Ai(3)*Ai(4))/s , -Ai(2)*Ai(5) , -(Ai(3)*Ai(5))/2.-(Ai(0)*Ai(4))/s , -(Ai(4)*Ai(5))/2.-(Ai(2)*Ai(3))/s , -Ai(5)*Ai(5)/2.-Ai(0)*Ai(2) ; 01349 } 01350 else throw new Fatal("matvec.h::DerivInv: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 01351 } 01352 01354 inline void Eig (Vec_t const & Ten, Vec3_t & L, Vec3_t & V0, Vec3_t & V1, Vec3_t & V2, bool SortAsc=false, bool SortDesc=false) 01355 { 01356 Mat3_t M; 01357 Ten2Mat (Ten, M); 01358 Eig (M, L, V0, V1, V2, SortAsc, SortDesc); 01359 } 01360 01362 inline void EigenProj (Vec_t const & Ten, Vec3_t & L, Vec3_t & v0, Vec3_t & v1, Vec3_t & v2, Vec_t & P0, Vec_t & P1, Vec_t & P2, bool SortAsc=false, bool SortDesc=false) 01363 { 01364 // matrix of tensor 01365 Mat3_t ten; 01366 Ten2Mat (Ten, ten); 01367 01368 // eigen-values and vectors 01369 Eig (ten, L, v0, v1, v2, SortAsc, SortDesc); 01370 01371 // eigen-projectors 01372 size_t ncp = size(Ten); 01373 P0.change_dim (ncp); 01374 P1.change_dim (ncp); 01375 P2.change_dim (ncp); 01376 if (ncp==4) 01377 { 01378 P0 = v0(0)*v0(0), v0(1)*v0(1), v0(2)*v0(2), v0(0)*v0(1)*Util::SQ2; 01379 P1 = v1(0)*v1(0), v1(1)*v1(1), v1(2)*v1(2), v1(0)*v1(1)*Util::SQ2; 01380 P2 = v2(0)*v2(0), v2(1)*v2(1), v2(2)*v2(2), v2(0)*v2(1)*Util::SQ2; 01381 } 01382 else 01383 { 01384 P0 = v0(0)*v0(0), v0(1)*v0(1), v0(2)*v0(2), v0(0)*v0(1)*Util::SQ2, v0(1)*v0(2)*Util::SQ2, v0(2)*v0(0)*Util::SQ2; 01385 P1 = v1(0)*v1(0), v1(1)*v1(1), v1(2)*v1(2), v1(0)*v1(1)*Util::SQ2, v1(1)*v1(2)*Util::SQ2, v1(2)*v1(0)*Util::SQ2; 01386 P2 = v2(0)*v2(0), v2(1)*v2(1), v2(2)*v2(2), v2(0)*v2(1)*Util::SQ2, v2(1)*v2(2)*Util::SQ2, v2(2)*v2(0)*Util::SQ2; 01387 } 01388 } 01389 01391 inline void EigenProjAnalytic (Vec_t const & Ten, Vec3_t & L, Vec_t & P0, Vec_t & P1, Vec_t & P2) 01392 { 01393 // identity tensor 01394 size_t ncp = size(Ten); 01395 Vec_t I(ncp); 01396 set_to_zero(I); 01397 I(0)=1.0; I(1)=1.0; I(2)=1.0; 01398 01399 // characteristics invariants 01400 double I1,I2,I3; 01401 CharInvs (Ten,I1,I2,I3); 01402 01403 // inverse tensor 01404 Vec_t Ti; 01405 Inv (Ten, Ti); 01406 01407 // eigen-values/projectors 01408 P0.change_dim (ncp); 01409 P1.change_dim (ncp); 01410 P2.change_dim (ncp); 01411 Vec_t * P[3] = {&P0, &P1, &P2}; // all three eigen projectors 01412 double alpha = 2.0*sqrt(I1*I1-3.0*I2); 01413 double theta = acos((2.0*I1*I1*I1-9.0*I1*I2+27.0*I3)/(2.0*pow(I1*I1-3.0*I2,3.0/2.0))); 01414 //std::cout << "I1 = " << I1 << ", I2 = " << I2 << ", I3 = " << I3 << ", I1*I1-3*I2 = " << I1*I1-3.0*I2 << std::endl; 01415 //std::cout << "alpha = " << alpha << ", theta = " << theta << std::endl; 01416 for (size_t k=0; k<3; ++k) 01417 { 01418 L(k) = (I1+alpha*cos((theta+2.0*Util::PI*(1.0+k))/3.0))/3.0; 01419 if (fabs(L(k))<1.0e-14) throw new Fatal("matvec.h:EigenProjAnalytic: L(%d)=%g must be non-zero",k,L(k)); 01420 double coef = L(k)/(2.0*L(k)*L(k)-L(k)*I1+I3/L(k)); 01421 (*P[k]) = coef*(Ten+(L(k)-I1)*I+(I3/L(k))*Ti); 01422 } 01423 } 01424 01426 inline void Calc_I (size_t NCp, Vec_t & I) 01427 { 01428 I.change_dim(NCp); 01429 if (NCp==4) I = 1.0, 1.0, 1.0, 0.0; 01430 else if (NCp==6) I = 1.0, 1.0, 1.0, 0.0, 0.0, 0.0; 01431 else throw new Fatal("matvec.h::Calc_I: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 01432 } 01433 01435 inline void Calc_IIsym (size_t NCp, Mat_t & IIsym) 01436 { 01437 IIsym.change_dim(NCp,NCp); 01438 if (NCp==4) 01439 { 01440 IIsym = 1.0, 0.0, 0.0, 0.0, 01441 0.0, 1.0, 0.0, 0.0, 01442 0.0, 0.0, 1.0, 0.0, 01443 0.0, 0.0, 0.0, 1.0; 01444 } 01445 else if (NCp==6) 01446 { 01447 IIsym = 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 01448 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 01449 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 01450 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 01451 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 01452 0.0, 0.0, 0.0, 0.0, 0.0, 1.0; 01453 } 01454 else throw new Fatal("matvec.h::Calc_IIsym: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 01455 } 01456 01458 inline void Calc_IdyI (size_t NCp, Mat_t & IdyI) 01459 { 01460 IdyI.change_dim(NCp,NCp); 01461 if (NCp==4) 01462 { 01463 IdyI = 1.0, 1.0, 1.0, 0.0, 01464 1.0, 1.0, 1.0, 0.0, 01465 1.0, 1.0, 1.0, 0.0, 01466 0.0, 0.0, 0.0, 0.0; 01467 } 01468 else if (NCp==6) 01469 { 01470 IdyI = 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 01471 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 01472 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 01473 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 01474 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 01475 0.0, 0.0, 0.0, 0.0, 0.0, 0.0; 01476 } 01477 else throw new Fatal("matvec.h::Calc_IdyI: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 01478 } 01479 01481 inline void Calc_Psd (size_t NCp, Mat_t & Psd) 01482 { 01483 Psd.change_dim(NCp,NCp); 01484 if (NCp==4) 01485 { 01486 Psd = 2.0/3.0, -1.0/3.0, -1.0/3.0, 0.0, 01487 -1.0/3.0, 2.0/3.0, -1.0/3.0, 0.0, 01488 -1.0/3.0, -1.0/3.0, 2.0/3.0, 0.0, 01489 0.0, 0.0, 0.0, 1.0; 01490 } 01491 else if (NCp==6) 01492 { 01493 Psd = 2.0/3.0, -1.0/3.0, -1.0/3.0, 0.0, 0.0, 0.0, 01494 -1.0/3.0, 2.0/3.0, -1.0/3.0, 0.0, 0.0, 0.0, 01495 -1.0/3.0, -1.0/3.0, 2.0/3.0, 0.0, 0.0, 0.0, 01496 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 01497 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 01498 0.0, 0.0, 0.0, 0.0, 0.0, 1.0; 01499 } 01500 else throw new Fatal("matvec.h::Calc_Psd: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 01501 } 01502 01504 inline void Calc_Piso (size_t NCp, Mat_t & Piso) 01505 { 01506 Piso.change_dim(NCp,NCp); 01507 if (NCp==4) 01508 { 01509 Piso = 1.0/3.0, 1.0/3.0, 1.0/3.0, 0.0, 01510 1.0/3.0, 1.0/3.0, 1.0/3.0, 0.0, 01511 1.0/3.0, 1.0/3.0, 1.0/3.0, 0.0, 01512 0.0, 0.0, 0.0, 0.0; 01513 } 01514 else if (NCp==6) 01515 { 01516 Piso = 1.0/3.0, 1.0/3.0, 1.0/3.0, 0.0, 0.0, 0.0, 01517 1.0/3.0, 1.0/3.0, 1.0/3.0, 0.0, 0.0, 0.0, 01518 1.0/3.0, 1.0/3.0, 1.0/3.0, 0.0, 0.0, 0.0, 01519 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 01520 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 01521 0.0, 0.0, 0.0, 0.0, 0.0, 0.0; 01522 } 01523 else throw new Fatal("matvec.h::Calc_Piso: This method is only available for 2nd order symmetric tensors with either 4 or 6 components according to Mandel's representation"); 01524 } 01525 01527 inline void EigenProjDerivs (Vec_t const & A, Vec3_t & L, Vec3_t & v0, Vec3_t & v1, Vec3_t & v2, 01528 Vec_t & P0, Vec_t & P1, Vec_t & P2, 01529 Mat_t & dP0dA, Mat_t & dP1dA, Mat_t & dP2dA, 01530 double Pertubation=1.0e-7, double Tol=1.0e-14, bool SortAsc=false, bool SortDesc=false) 01531 { 01532 // eigenprojectors 01533 EigenProj (A, L, v0, v1, v2, P0, P1, P2, SortAsc, SortDesc); 01534 01535 // check eigenvalues 01536 if (fabs(L(0))<Tol) throw new Fatal("matvec.h::EigenProjDerivs: Principal values cannot be zero (Tol=%g).\n L = [%g, %g, %g]",Tol,L(0),L(1),L(2)); 01537 if (fabs(L(1))<Tol) throw new Fatal("matvec.h::EigenProjDerivs: Principal values cannot be zero (Tol=%g).\n L = [%g, %g, %g]",Tol,L(0),L(1),L(2)); 01538 if (fabs(L(2))<Tol) throw new Fatal("matvec.h::EigenProjDerivs: Principal values cannot be zero (Tol=%g).\n L = [%g, %g, %g]",Tol,L(0),L(1),L(2)); 01539 01540 // apply pertubation 01541 bool pert[3] = { false, false, false }; 01542 if (fabs(L(0)-L(1))<Pertubation) { L(0)+=Pertubation; L(1)-=Pertubation; pert[0]=true; } 01543 if (fabs(L(1)-L(2))<Pertubation) { L(1)+=Pertubation; L(2)-=Pertubation; pert[1]=true; } 01544 if (fabs(L(2)-L(0))<Pertubation) { L(2)+=Pertubation; L(0)-=Pertubation; pert[2]=true; } 01545 01546 // characteristic invariants 01547 double I1 = L(0)+L(1)+L(2); 01548 double I3 = L(0)*L(1)*L(2); 01549 double a[3] = {2.*L(0)*L(0)-I1*L(0)+I3/L(0), 01550 2.*L(1)*L(1)-I1*L(1)+I3/L(1), 01551 2.*L(2)*L(2)-I1*L(2)+I3/L(2)}; 01552 01553 // check alphas 01554 if (fabs(a[0])<Tol) throw new Fatal("matvec.h::EigenProjDerivs: Alpha0 cannot be zero (Tol=%g).\n L = [%g, %g, %g]\n I1,I3 = [%g, %g, %g]\n Alphas = [%g, %g, %g]",Tol,L(0),L(1),L(2), I1,I3, a[0],a[1],a[2]); 01555 if (fabs(a[1])<Tol) throw new Fatal("matvec.h::EigenProjDerivs: Alpha1 cannot be zero (Tol=%g).\n L = [%g, %g, %g]\n I1,I3 = [%g, %g, %g]\n Alphas = [%g, %g, %g]",Tol,L(0),L(1),L(2), I1,I3, a[0],a[1],a[2]); 01556 if (fabs(a[1])<Tol) throw new Fatal("matvec.h::EigenProjDerivs: Alpha2 cannot be zero (Tol=%g).\n L = [%g, %g, %g]\n I1,I3 = [%g, %g, %g]\n Alphas = [%g, %g, %g]",Tol,L(0),L(1),L(2), I1,I3, a[0],a[1],a[2]); 01557 01558 // inverse tensor and derivative of inverse 01559 size_t ncp = size(A); 01560 Vec_t Ai; 01561 Mat_t dInvAdA, IIsym; 01562 DerivInv (A, Ai, dInvAdA, Tol); 01563 Calc_IIsym (ncp, IIsym); 01564 01565 // dyadic between projectors 01566 Array<Mat_t> PdyP(3); 01567 Dyad (P0,P0, PdyP[0]); 01568 Dyad (P1,P1, PdyP[1]); 01569 Dyad (P2,P2, PdyP[2]); 01570 01571 // constants 01572 double c[3][3] = {{I3/(a[0]*L(0)*L(0))-L(0)/a[0], I3/(a[0]*L(1)*L(1))-L(0)/a[0], I3/(a[0]*L(2)*L(2))-L(0)/a[0]}, 01573 {I3/(a[1]*L(0)*L(0))-L(1)/a[1], I3/(a[1]*L(1)*L(1))-L(1)/a[1], I3/(a[1]*L(2)*L(2))-L(1)/a[1]}, 01574 {I3/(a[2]*L(0)*L(0))-L(2)/a[2], I3/(a[2]*L(1)*L(1))-L(2)/a[2], I3/(a[2]*L(2)*L(2))-L(2)/a[2]}}; 01575 01576 // derivative of projector 01577 dP0dA.change_dim (ncp,ncp); 01578 dP1dA.change_dim (ncp,ncp); 01579 dP2dA.change_dim (ncp,ncp); 01580 dP0dA = (L(0)/a[0])*IIsym + (I3/a[0])*dInvAdA + c[0][0]*PdyP[0] + c[0][1]*PdyP[1] + c[0][2]*PdyP[2]; 01581 dP1dA = (L(1)/a[1])*IIsym + (I3/a[1])*dInvAdA + c[1][0]*PdyP[0] + c[1][1]*PdyP[1] + c[1][2]*PdyP[2]; 01582 dP2dA = (L(2)/a[2])*IIsym + (I3/a[2])*dInvAdA + c[2][0]*PdyP[0] + c[2][1]*PdyP[1] + c[2][2]*PdyP[2]; 01583 01584 // remove pertubation 01585 if (pert[0]) { L(0)-=Pertubation; L(1)+=Pertubation; } 01586 if (pert[1]) { L(1)-=Pertubation; L(2)+=Pertubation; } 01587 if (pert[2]) { L(2)-=Pertubation; L(0)+=Pertubation; } 01588 } 01589 01591 #ifdef HAS_TENSORS 01592 inline void EigenVecDerivs (Vec3_t const & L, Ten1_t const & v0, Ten1_t const & v1, Ten1_t const & v2, 01593 Ten3_t & dv0dSig, Ten3_t & dv1dSig, Ten3_t & dv2dSig, 01594 double Pertubation=1.0e-7, double Tol=1.0e-10) 01595 { 01596 // check eigenvalues 01597 if (fabs(L(0))<Tol) throw new Fatal("matvec.h::EigenVecDerivs: Principal values cannot be zero (Tol=%g).\n L = [%g, %g, %g]",Tol,L(0),L(1),L(2)); 01598 if (fabs(L(1))<Tol) throw new Fatal("matvec.h::EigenVecDerivs: Principal values cannot be zero (Tol=%g).\n L = [%g, %g, %g]",Tol,L(0),L(1),L(2)); 01599 if (fabs(L(2))<Tol) throw new Fatal("matvec.h::EigenVecDerivs: Principal values cannot be zero (Tol=%g).\n L = [%g, %g, %g]",Tol,L(0),L(1),L(2)); 01600 01601 // apply pertubation 01602 Vec3_t l(L); 01603 if (fabs(l(0)-l(1))<Pertubation) { l(0)+=Pertubation; l(1)-=Pertubation; } 01604 if (fabs(l(1)-l(2))<Pertubation) { l(1)+=Pertubation; l(2)-=Pertubation; } 01605 if (fabs(l(2)-l(0))<Pertubation) { l(2)+=Pertubation; l(0)-=Pertubation; } 01606 01607 // derivatives 01608 double a0 = 0.5/(l(0)-l(1)); double b0 = 0.5/(l(0)-l(2)); 01609 double a1 = 0.5/(l(1)-l(2)); double b1 = 0.5/(l(1)-l(0)); 01610 double a2 = 0.5/(l(2)-l(0)); double b2 = 0.5/(l(2)-l(1)); 01611 dv0dSig = ((v1&v0&v1) + (v1&v1&v0))*a0 + ((v2&v0&v2) + (v2&v2&v0))*b0; 01612 dv1dSig = ((v2&v1&v2) + (v2&v2&v1))*a1 + ((v0&v1&v0) + (v0&v0&v1))*b1; 01613 dv2dSig = ((v0&v2&v0) + (v0&v0&v2))*a2 + ((v1&v2&v1) + (v1&v1&v2))*b2; 01614 } 01615 #endif 01616 01617 01619 01620 01621 // Cambridge invariants 01622 inline double Calc_pcam (Vec_t const & Sig) { return -(Sig(0)+Sig(1)+Sig(2))/3.0; } 01623 inline double Calc_ev (Vec_t const & Eps) { return Eps(0)+Eps(1)+Eps(2); } 01624 inline double Calc_qcam (Vec_t const & Sig) { double m = (size(Sig)>4 ? pow(Sig(4),2.0)+pow(Sig(5),2.0) : 0.0); return sqrt(pow(Sig(0)-Sig(1),2.0) + pow(Sig(1)-Sig(2),2.0) + pow(Sig(2)-Sig(0),2.0) + 3.0*(pow(Sig(3),2.0)+m))/sqrt(2.0); } 01625 inline double Calc_ed (Vec_t const & Eps) { double m = (size(Eps)>4 ? pow(Eps(4),2.0)+pow(Eps(5),2.0) : 0.0); return sqrt(pow(Eps(0)-Eps(1),2.0) + pow(Eps(1)-Eps(2),2.0) + pow(Eps(2)-Eps(0),2.0) + 3.0*(pow(Eps(3),2.0)+m))*(sqrt(2.0)/3.0); } 01626 01627 // Octahedral invariants 01628 inline double Calc_poct (Vec_t const & Sig) { return -(Sig(0)+Sig(1)+Sig(2))/sqrt(3.0); } 01629 inline double Calc_evoct (Vec_t const & Eps) { return (Eps(0)+Eps(1)+Eps(2))/sqrt(3.0); } 01630 inline double Calc_qoct (Vec_t const & Sig) { double m = (size(Sig)>4 ? pow(Sig(4),2.0)+pow(Sig(5),2.0) : 0.0); return sqrt(pow(Sig(0)-Sig(1),2.0) + pow(Sig(1)-Sig(2),2.0) + pow(Sig(2)-Sig(0),2.0) + 3.0*(pow(Sig(3),2.0)+m))/sqrt(3.0); } 01631 inline double Calc_edoct (Vec_t const & Eps) { double m = (size(Eps)>4 ? pow(Eps(4),2.0)+pow(Eps(5),2.0) : 0.0); return sqrt(pow(Eps(0)-Eps(1),2.0) + pow(Eps(1)-Eps(2),2.0) + pow(Eps(2)-Eps(0),2.0) + 3.0*(pow(Eps(3),2.0)+m))/sqrt(3.0); } 01632 01633 // Octahedral invariants of Sig. */ 01634 inline void Calc_pqoct (Vec_t const & Sig, double & p, double & q) { p = Calc_poct(Sig); q = Calc_qoct(Sig); } 01635 01636 01638 inline void OctInvs (Vec_t const & Sig, double & p, double & q, double & t, double qTol=1.0e-8) 01639 { 01640 size_t ncp = size(Sig); 01641 Vec_t s; 01642 Dev (Sig, s); 01643 double m = (ncp>4 ? pow(Sig(4),2.0)+pow(Sig(5),2.0) : 0.0); 01644 p = -(Sig(0)+Sig(1)+Sig(2))/Util::SQ3; 01645 q = sqrt(pow(Sig(0)-Sig(1),2.0) + pow(Sig(1)-Sig(2),2.0) + pow(Sig(2)-Sig(0),2.0) + 3.0*(pow(Sig(3),2.0)+m))/sqrt(3.0); 01646 t = 0.0; 01647 if (q>qTol) 01648 { 01649 double det_s = Det(s); 01650 t = -3.0*Util::SQ6*det_s/(q*q*q); 01651 if (t<=-1.0) t = -1.0; 01652 if (t>= 1.0) t = 1.0; 01653 } 01654 } 01655 01657 inline void OctInvs (Vec_t const & Sig, double & p, double & q, Vec_t & s, double qTol=1.0e-8, bool ApplyPertub=false) 01658 { 01659 q = Calc_qoct (Sig); 01660 if (q>qTol || !ApplyPertub) 01661 { 01662 p = Calc_poct (Sig); 01663 Dev (Sig, s); 01664 } 01665 else 01666 { 01667 Vec_t sig(Sig); 01668 if (sig(3)<0.0) sig(3) -= qTol*Util::SQ2; 01669 else sig(3) += qTol*Util::SQ2; 01670 q = Calc_qoct (sig); 01671 p = Calc_poct (sig); 01672 Dev (sig, s); 01673 if (q<=qTol) 01674 { 01675 std::ostringstream oss; 01676 oss << "Sig = " << PrintVector(Sig); 01677 oss << "sig = " << PrintVector(sig); 01678 throw new Fatal("matvec.h::OctInvs: __internal_error__ Pertubation for q<=qTol failed (q=%g, qTol=%g)\n%s",q,qTol,oss.str().c_str()); 01679 } 01680 } 01681 } 01682 01684 inline void OctInvs (Vec_t const & Sig, double & p, double & q, double & t, double & th, Vec_t & s, double qTol=1.0e-8, Vec_t * dthdSig=NULL, bool ApplyPertub=false) 01685 { 01686 OctInvs (Sig, p, q, s, qTol, ApplyPertub); 01687 t = 0.0; 01688 th = asin(t)/3.0; 01689 double q3 = pow(q,3.0); 01690 if (q3>qTol) 01691 { 01692 double det_s = Det(s); 01693 t = -3.0*Util::SQ6*det_s/q3; 01694 if (t<=-1.0) t = -1.0; 01695 if (t>= 1.0) t = 1.0; 01696 th = asin(t)/3.0; 01697 if (dthdSig!=NULL) 01698 { 01699 Vec_t ss, devss; 01700 Pow2 (s, ss); 01701 Dev (ss, devss); 01702 if (t>-0.999 && t<0.999) (*dthdSig) = (-1.0/(q*q*cos(3.0*th)))*(t*s + (Util::SQ6/q)*devss); 01703 else set_to_zero ((*dthdSig)); 01704 } 01705 } 01706 else if (dthdSig!=NULL) set_to_zero ((*dthdSig)); 01707 } 01708 01710 inline void OctInvs (Vec3_t const & L, double & p, double & q, double & t, double qTol=1.0e-8) 01711 { 01712 p = -(L(0)+L(1)+L(2))/Util::SQ3; 01713 q = sqrt(pow(L(0)-L(1),2.0) + pow(L(1)-L(2),2.0) + pow(L(2)-L(0),2.0))/sqrt(3.0); 01714 t = 0.0; 01715 if (q>qTol) 01716 { 01717 Vec3_t S((2.*L(0)-L(1)-L(2))/3., 01718 (2.*L(1)-L(2)-L(0))/3., 01719 (2.*L(2)-L(0)-L(1))/3.); 01720 t = -3.0*Util::SQ6*S(0)*S(1)*S(2)/pow(q,3.0); 01721 if (t<=-1.0) t = -1.0; 01722 if (t>= 1.0) t = 1.0; 01723 } 01724 } 01725 01727 inline void OctInvs (Vec3_t const & L, double & p, double & q, double & t, Vec3_t & dpdL, Vec3_t & dqdL, Vec3_t & dtdL, double qTol=1.0e-8) 01728 { 01729 Vec3_t one(1.0,1.0,1.0), s; 01730 p = -(L(0)+L(1)+L(2))/Util::SQ3; 01731 q = sqrt(pow(L(0)-L(1),2.0) + pow(L(1)-L(2),2.0) + pow(L(2)-L(0),2.0))/sqrt(3.0); 01732 t = 0.0; 01733 s = L - ((L(0)+L(1)+L(2))/3.0)*one; 01734 dpdL = (-1.0/Util::SQ3)*one; 01735 dqdL = 0.0, 0.0, 0.0; 01736 if (q>qTol) 01737 { 01738 double q3 = q*q*q; 01739 double q5 = q3*q*q; 01740 double l = (L(0)-L(1))*(L(1)-L(2))*(L(2)-L(0)); 01741 Vec3_t B(L(2)-L(1), L(0)-L(2), L(1)-L(0)); 01742 t = -3.0*Util::SQ6*s(0)*s(1)*s(2)/q3; 01743 dqdL = (1.0/q)*s; 01744 dtdL = (-Util::SQ6*l/q5)*B; 01745 if (t<=-1.0) t = -1.0; 01746 if (t>= 1.0) t = 1.0; 01747 } 01748 } 01749 01751 inline void pqth2L (double p, double q, double th, Vec3_t & L, char const * Type="oct") 01752 { 01753 if (strcmp(Type,"cam")==0) 01754 { 01755 L(0) = -p + 2.0*q*sin(th-2.0*Util::PI/3.0)/3.0; 01756 L(1) = -p + 2.0*q*sin(th) /3.0; 01757 L(2) = -p + 2.0*q*sin(th+2.0*Util::PI/3.0)/3.0; 01758 } 01759 else if (strcmp(Type,"oct")==0) // oct 01760 { 01761 L(0) = -p/Util::SQ3 + 2.0*q*sin(th-2.0*Util::PI/3.0)/Util::SQ6; 01762 L(1) = -p/Util::SQ3 + 2.0*q*sin(th) /Util::SQ6; 01763 L(2) = -p/Util::SQ3 + 2.0*q*sin(th+2.0*Util::PI/3.0)/Util::SQ6; 01764 } 01765 else throw new Fatal("pqTh2L: Method is not available for invariant Type==%s",Type); 01766 } 01767 01768 inline void OctDerivs (Vec3_t const & L, double & p, double & q, double & t, Mat3_t & dpqthdL, double qTol=1.0e-8) 01769 { 01770 OctInvs (L, p,q,t, qTol); 01771 if (q>qTol) 01772 { 01773 01774 Vec3_t S((2.*L(0)-L(1)-L(2))/3., 01775 (2.*L(1)-L(2)-L(0))/3., 01776 (2.*L(2)-L(0)-L(1))/3.); 01777 Vec3_t devSS((2.*S(1)*S(2) - S(2)*S(0) - S(0)*S(1))/3., 01778 (2.*S(2)*S(0) - S(1)*S(2) - S(0)*S(1))/3., 01779 (2.*S(0)*S(1) - S(1)*S(2) - S(2)*S(0))/3.); 01780 double th = asin(t)/3.0; 01781 double c = -1.0/(pow(q,3.0)*cos(3.0*th)); 01782 dpqthdL = -1./Util::SQ3, -1./Util::SQ3, -1./Util::SQ3, 01783 S(0)/q, S(1)/q, S(2)/q, 01784 c*Util::SQ6*devSS(0)+c*q*t*S(0), c*Util::SQ6*devSS(1)+c*q*t*S(1), c*Util::SQ6*devSS(2)+c*q*t*S(2); 01785 } 01786 else 01787 { 01788 dpqthdL = -1./Util::SQ3, -1./Util::SQ3, -1./Util::SQ3, 01789 0., 0., 0., 01790 0., 0., 0.; 01791 } 01792 } 01793 01794 inline void InvOctDerivs (Vec3_t const & Lsorted, double & p, double & q, double & t, Mat3_t & dLdpqth, double qTol=1.0e-8) 01795 { 01796 OctInvs (Lsorted, p,q,t, qTol); 01797 double th = asin(t)/3.0; 01798 dLdpqth = -1./Util::SQ3, (2.*sin(th-(2.*Util::PI)/3.))/Util::SQ6, (2.*q*cos(th-(2.*Util::PI)/3.))/Util::SQ6, 01799 -1./Util::SQ3, (2.*sin(th) )/Util::SQ6, (2.*q*cos(th) )/Util::SQ6, 01800 -1./Util::SQ3, (2.*sin(th+(2.*Util::PI)/3.))/Util::SQ6, (2.*q*cos(th+(2.*Util::PI)/3.))/Util::SQ6; 01801 } 01802 01803 #ifdef USE_BOOST_PYTHON 01804 inline BPy::tuple Pypqth2L (double p, double q, double th, BPy::str const & Type) 01805 { 01806 Vec3_t l; 01807 pqth2L (p, q, th, l, BPy::extract<char const *>(Type)()); 01808 return BPy::make_tuple (l(0), l(1), l(2)); 01809 } 01810 #endif 01811 01812 01814 01815 01817 inline double Phi2M (double Phi, char const * Type="oct") 01818 { 01819 double sphi = sin(Phi*Util::PI/180.0); 01820 if (strcmp(Type,"oct")==0) return 2.0*Util::SQ2*sphi/(3.0-sphi); 01821 else if (strcmp(Type,"cam")==0) return 6.0*sphi/(3.0-sphi); 01822 else if (strcmp(Type,"smp")==0) 01823 { 01824 double eta = 2.0*Util::SQ2*sphi/(3.0-sphi); 01825 double c = sqrt((2.0+Util::SQ2*eta-2.0*eta*eta)/(3.0*Util::SQ3*(Util::SQ2*eta+2.0))); 01826 double a = sqrt((2.0*eta+Util::SQ2)/Util::SQ6); 01827 double b = sqrt((Util::SQ2-eta)/Util::SQ6); 01828 return sqrt((eta*eta+1.0)/(c*c*pow(a+2.0*b,2.0))-1.0); 01829 } 01830 else throw new Fatal("Phi2M: Method is not available for invariant Type==%s",Type); 01831 } 01832 01834 inline double M2Phi (double M, char const * Type="oct") 01835 { 01836 double sphi; 01837 if (strcmp(Type,"oct")==0) sphi = 3.0*M/(M+2.0*Util::SQ2); 01838 else if (strcmp(Type,"cam")==0) sphi = 3.0*M/(M+6.0); 01839 else throw new Fatal("M2Phi: Method is not available for invariant Type==%s",Type); 01840 return asin(sphi)*180.0/Util::PI; 01841 } 01842 01844 inline double Calc_K (double E, double nu) { return E/(3.0*(1.0-2.0*nu)); } 01845 01847 inline double Calc_G (double E, double nu) { return E/(2.0*(1.0+nu)); } 01848 01850 inline double Calc_lam (double E, double nu) { return E*nu/((1.0+nu)*(1.0-2.0*nu)); } 01851 01853 inline double Calc_G_ (double K, double nu) { return 3.0*(1.0-2.0*nu)*K/(2.0*(1.0+nu)); } 01854 01856 inline double Calc_E (double K, double G) { return 9.0*K*G/(3.0*K+G); } 01857 01859 inline double Calc_E_ (double K, double nu) { return 3.0*K*(1.0-2.0*nu); } 01860 01862 inline double Calc_nu (double K, double G) { return (3.0*K-2.0*G)/(6.0*K+2.0*G); } 01863 01864 01866 01867 01868 #ifdef USE_BOOST_PYTHON 01869 01870 inline void Vec2List (Vec3_t const & V, BPy::list & L) 01871 { 01872 for (size_t i=0; i<3; ++i) L.append(V(i)); 01873 } 01874 01875 inline void Vec2List (Vec_t const & V, BPy::list & L) 01876 { 01877 for (size_t i=0; i<size(V); ++i) L.append(V(i)); 01878 } 01879 01880 inline void List2Vec (BPy::list const & L, Vec_t & V) 01881 { 01882 size_t m = BPy::len(L); 01883 if (m>0) 01884 { 01885 V.change_dim (m); 01886 for (size_t i=0; i<m; ++i) V(i) = BPy::extract<double>(L[i])(); 01887 } 01888 } 01889 01890 inline void Mat2List (Mat_t const & M, BPy::list & L) 01891 { 01892 size_t m = num_rows(M); 01893 size_t n = num_cols(M); 01894 for (size_t i=0; i<m; ++i) 01895 { 01896 BPy::list row; 01897 for (size_t j=0; j<n; ++j) row.append(M(i,j)); 01898 L.append(row); 01899 } 01900 } 01901 01902 inline void List2Mat (BPy::list const & L, Mat_t & M) 01903 { 01904 size_t m = BPy::len(L); 01905 if (m>0) 01906 { 01907 size_t n = BPy::len(BPy::extract<BPy::list>(L[0])()); 01908 M.change_dim (m,n); 01909 for (size_t i=0; i<m; ++i) 01910 { 01911 BPy::list const & row = BPy::extract<BPy::list>(L[i])(); 01912 for (size_t j=0; j<n; ++j) M(i,j) = BPy::extract<double>(row[j])(); 01913 } 01914 } 01915 } 01916 01917 inline void PyEigenProjAnalytic (BPy::list const & Ten, BPy::list & L, BPy::list & P0, BPy::list & P1, BPy::list & P2) 01918 { 01919 Vec3_t l; 01920 Vec_t ten, p0, p1, p2; 01921 List2Vec (Ten, ten); 01922 EigenProjAnalytic (ten, l, p0, p1, p2); 01923 Vec2List (l, L); 01924 Vec2List (p0, P0); 01925 Vec2List (p1, P1); 01926 Vec2List (p2, P2); 01927 } 01928 01929 #endif 01930 01931 #endif // MECHSYS_MATVEC_H