math_tst.cppGo to the documentation of this file.00001 // $Revision: 1.6 $ 00002 // $Date: 2005/04/03 17:14:53 $ 00003 // $Source: /usr/local/cvs/OpenSees/SRC/nDarray/math_tst.cpp,v $ 00004 00005 00007 //################################################################################ 00008 //# COPY-YES (C): :-)) # 00009 //# PROJECT: Object Oriented Finite Element Program # 00010 //# PURPOSE: # 00011 //# CLASS: # 00012 //# # 00013 //# VERSION: # 00014 //# LANGUAGE: C++.ver >= 2.0 # 00015 //# TARGET OS: DOS || UNIX || . . . # 00016 //# DESIGNER(S): Boris Jeremic # 00017 //# PROGRAMMER(S): Boris Jeremic # 00018 //# # 00019 //# # 00020 //# DATE: November '92 # 00021 //# UPDATE HISTORY: August 11 '93 additional tests # 00022 //# December 21 '93 additional tests # 00023 //# December 29 '93 additional tests # 00024 //# October '94 additional tests # 00025 //# August 2000 additional tests # 00026 //# # 00027 //# # 00028 //# # 00029 //################################################################################ 00030 //*/ 00031 #include "time.h" 00032 #include "limits.h" 00033 #include "math.h" 00034 #include "float.h" 00035 // nDarray tools 00036 #include "BJtensor.h" 00037 #include "stresst.h" 00038 #include "straint.h" 00039 #include "BJvector.h" 00040 #include "BJmatrix.h" 00041 00042 00043 #include <Tensor.h> 00044 //#include <G3Globals.h> 00045 //#include <ConsoleErrorHandler.h> 00046 //ErrorHandler *g3ErrorHandler; 00047 00048 int main(int argc, char *argv[]) 00049 { 00050 // g3ErrorHandler = new ConsoleErrorHandler(); 00051 00052 if (argc != 2) 00053 { 00054 puts("\a\n usage: math_tst matrix_file_name\n"); 00055 exit( 1 ); 00056 } 00057 ::printf("\n\n------------- MACHINE (CPU) DEPENDENT THINGS --------------\n\n"); 00058 00059 // defining machine epsilon for different built in data types supported by C++ 00060 float float_eps = f_macheps(); // or use float.h values FLT_EPSILON 00061 double double_eps = d_macheps(); // or use float.h values DBL_EPSILON 00062 long double long_double_eps = ld_macheps(); // or use float.h values LDBL_EPSILON 00063 00064 ::printf("\n float macheps = %.20e \n",float_eps); 00065 ::printf(" double macheps = %.20e \n",double_eps); 00066 ::printf(" long double macheps = %.20Le \n\n\n",long_double_eps); 00067 00068 00069 // Usual tolerance is defined as square root of machine epsilon 00070 float sqrt_f_eps = sqrt(f_macheps()); 00071 double sqrt_d_eps = sqrt(d_macheps()); 00072 long double sqrt_ld_eps = sqrt(ld_macheps()); 00073 00074 ::printf("\n sqrt float macheps = %.20e \n",sqrt_f_eps); 00075 ::printf(" sqrt double macheps = %.20e \n",sqrt_d_eps); 00076 ::printf(" sqrt long double macheps = %.20Le \n",sqrt_ld_eps); 00077 00078 00079 00080 ::printf("\n\n---------------- MATRIX -----------------\n\n"); 00081 00082 // New data type MATRIX is defined in such a way that it can be regarded 00083 // as concrete data type. 00084 // default constructor: 00085 BJmatrix matrix1; 00086 matrix1.print("m1","matrix1"); 00087 00088 static double initvalue[] = {1.0, 2.0, 00089 3.0, 4.0}; 00090 // constructor with matrix initialization 00091 BJmatrix matrix2(2,2,initvalue); 00092 matrix2.print("m2","matrix2"); 00093 00094 // unit matrix initialization ( third order ) 00095 BJmatrix matrix3("I",3); 00096 matrix3.print("m3","matrix3"); 00097 00098 // matrix initialization from the file that is in predefined format! 00099 BJmatrix m(argv[1]); 00100 m.print("m","m is"); 00101 //==== 00102 // matrix assignment 00103 BJmatrix first_matrix = m; 00104 first_matrix.print("fm","first_matrix is"); 00105 00106 00107 // --------------------------------- 00108 ::printf("\n\n--------EIGENVECTORS and EIGENVALUES-----------\n"); 00109 static double symm_initvalue[] = {1.0, 0.0, 00110 0.0, 0.0}; 00111 // constructor with matrix initialization 00112 BJmatrix sym_matrix(2,2,symm_initvalue); 00113 sym_matrix.print("m","Sym_matrix"); 00114 00115 // Eigenvalues 00116 BJvector eval = sym_matrix.eigenvalues(); 00117 eval.print("ev","Eigenvalues of sym_matrix"); 00118 // Eigenvectors 00119 BJmatrix evect = sym_matrix.eigenvectors(); 00120 evect.print("ev","Eigenvectors of sym_matrix"); 00121 00122 // matrix to file "test.$$$" 00123 m.write_standard("test.$$$", "this is a test"); 00124 00125 // equivalence of two matrices ( within tolerance sqrt(macheps) ) 00126 if ( first_matrix == m ) ::printf("\n first_matrix == m TRUE \n"); 00127 else ::printf("\a\n first_matrix == m NOTTRUE \n"); 00128 00129 // matrix addition 00130 BJmatrix m2 =m+m; 00131 m2.print("m2","\nm+m = \n"); 00132 00133 // equivalence of two matrices ( within tolerance sqrt(macheps) ) 00134 if ( m2 == m ) ::printf("\a\n m2 == m TRUE \n"); 00135 else ::printf("\n m2 == m NOTTRUE \n"); 00136 00137 // matrix substraction 00138 BJmatrix m3 =m-m; 00139 m3.print("m3","\nm-m = \n"); 00140 00141 // matrix multiplication 00142 BJmatrix m4 = m*m; 00143 m4.print("m4","\n m*m = \n"); 00144 00145 // matrix transposition 00146 BJmatrix mtran = m.transpose(); 00147 mtran.print("mt","transpose of m is"); 00148 00149 // determinant of matrix 00150 00151 printf("determinant = %6.6f \n",m.determinant()); 00152 00153 // exit(0); 00154 // matrix inversion 00155 BJmatrix minv = m.inverse(); 00156 minv.print("mi","inverse of m is"); 00157 // check matrix inversion 00158 ( m * minv ).print("1"," m * m.inverse() "); 00159 00160 // minima, maxima, mean and variance values for matrix: 00161 printf("min = %6.6f \n", m.mmin() ); 00162 printf("max = %6.6f \n", m.mmax() ); 00163 printf("mean = %6.6f \n", m.mean() ); 00164 printf("variance = %6.6f \n", m.variance() ); 00165 00166 //====//===printf("\n\n----------------- SKY MATRIX ----------------------\n\n"); 00167 //====//=== 00168 //====//===// skymatrix as defined by K.J. Bathe in "FE procedures in Engineering Analysis" 00169 //====//===// The example is from that book too! 00170 //====//=== 00171 //====//===int maxa[] = { 1, 2, 4, 6, 8, 13}; 00172 //====//===double a[] = {2.0, 3.0, -2.0, 5.0, -2.0, 10.0, -3.0, 10.0, 4.0, 0.0, 0.0, -1.0}; 00173 //====//===double rhs[] = { 0.0, 1.0, 0.0, 0.0, 0.0 }; 00174 //====//=== 00175 //====//===// skymatrix constructor 00176 //====//=== skymatrix first( 5, maxa, a); 00177 //====//=== 00178 //====//===// simple print functions: 00179 //====//=== first.full_print("\nfirst Sparse Skyline Matrix as FULL :\n "); 00180 //====//=== first.lower_print("\nfirst Sparse Skyline Matrix :\n "); 00181 //====//=== first.upper_print("\nfirst Sparse Skyline Matrix :\n "); 00182 //====//=== 00183 //====//===// skymatrix assignment 00184 //====//=== skymatrix second = first; 00185 //====//=== second.full_print("\nsecond Sparse Skyline Matrix as FULL :\n "); 00186 //====//=== 00187 //====//===// skymatrix third; // not defined ! 00188 //====//===// assignments: 00189 //====//=== skymatrix third = second = first; 00190 //====//=== 00191 //====//===// LDL factorization ( see K.J. Bathe's book! ) 00192 //====//=== first = first.v_ldl_factorize(); 00193 //====//=== 00194 //====//===// simple print functions: 00195 //====//=== first.lower_print("\n lower first but factorized :\n "); 00196 //====//=== first.full_print("\nfirst but factorized Sparse Skyline Matrix as FULL :\n "); 00197 //====//=== first.upper_print("\n upper first but factorized :\n "); 00198 //====//=== 00199 //====//===// right hand side reduction ( see K.J. Bathe's book! ) ( vetor of unknowns is rhs ) 00200 //====//=== first.d_reduce_r_h_s_l_v( rhs ); 00201 //====//=== int i=0; 00202 //====//=== for( i=0 ; i<5 ; i++ ) 00203 //====//=== { 00204 //====//=== printf("intermediate_rhs[%d] = %8.4f\n",i, rhs[i]); 00205 //====//=== } 00206 //====//=== 00207 //====//===// backsubstitution 00208 //====//=== first.d_back_substitute ( rhs ); 00209 //====//=== for( i=0 ; i<5 ; i++ ) 00210 //====//=== { 00211 //====//=== printf("solution_rhs[%d] = %8.4f\n",i, rhs[i]); 00212 //====//=== } 00213 //====//=== 00214 //====//===// minima, maxima and mean values for skymatrix: 00215 //====//=== printf("min = %6.6f \n", first.mmin() ); 00216 //====//=== printf("max = %6.6f \n", first.mmax() ); 00217 //====//=== printf("mean = %6.6f \n", first.mean() ); 00218 //====//===// 00219 //====//===// 00220 //====//=== 00221 //====//===printf("\n\n----------------- PROFILE MATRIX ----------------------\n"); 00222 //====//===printf("----------------- EXAMPLE 1 ----------------------\n\n"); 00223 //====//=== 00224 //====//===// profilematrix as defined by O.C. Zienkiewicz and R.L. Taylor 00225 //====//===// in "The FEM - fourth edition" 00226 //====//===// The example is from: K.J. Bathe: "FE procedures in Engineering Analysis" 00227 //====//=== 00228 //====//===int jp[] = { 0, 1, 2, 3, 7}; 00229 //====//===double au[] = { -2.0, -2.0, -3.0, -1.0, 0.0, 0.0, 4.0}; 00230 //====//===double ad[] = { 2.0, 3.0, 5.0, 10.0, 10.0 }; 00231 //====//===double* al = au; 00232 //====//===double b[] = { 0.0, 1.0, 0.0, 0.0, 0.0 }; 00233 //====//=== 00234 //====//===// profile matrix constructor 00235 //====//=== profilematrix first_profile( 5, jp, 'S', au, al, ad); 00236 //====//=== 00237 //====//===// simple print function 00238 //====//=== first_profile.full_print("\nfirst_profile Sparse Profile Matrix as FULL :\n "); 00239 //====//=== 00240 //====//===// asignment operetor 00241 //====//=== profilematrix second_profile = first_profile; 00242 //====//=== second_profile.full_print("\nsecond_profile Sparse Profile Matrix as FULL :\n "); 00243 //====//=== 00244 //====//===// triangularization ( Crout's method ); see: O.C. Zienkiewicz and R.L. Taylor: 00245 //====//===// "The FEM - fourth edition" 00246 //====//=== first_profile = first_profile.datri(); 00247 //====//=== first_profile.full_print("\nfirst but factorized Sparse Profile Matrix as FULL :\n "); 00248 //====//=== ::printf("\n\n"); 00249 //====//=== 00250 //====//===// right hand side reduction and backsubstitution ( vector of unknowns is b ) 00251 //====//=== first_profile.dasol(b); 00252 //====//=== for( i=0 ; i<5 ; i++ ) 00253 //====//=== { 00254 //====//=== printf("solution_b[%d] = %8.4f\n",i, b[i]); 00255 //====//=== } 00256 //====//=== 00257 //====//=== printf("\n\nmin = %6.6f \n", first_profile.mmin() ); 00258 //====//=== printf("max = %6.6f \n", first_profile.mmax() ); 00259 //====//=== printf("mean = %6.6f \n", first_profile.mean() ); 00260 //====//=== 00261 //====//=== 00262 //====//===printf("\n----------------- EXAMPLE 2 ----------------------\n\n"); 00263 //====//=== 00264 //====//===// The example is from: O.C. Zienkiewicz and R.L. Taylor: 00265 //====//===// "The FEM - fourth edition" 00266 //====//===int jp2[] = { 0, 1, 3}; 00267 //====//===double au2[] = { 2.0, 1.0, 2.0}; 00268 //====//===double ad2[] = { 4.0, 4.0, 4.0}; 00269 //====//===double* al2 = au2; 00270 //====//===double b2[] = { 0.0, 0.0, 1.0 }; 00271 //====//=== 00272 //====//===// profile matrix constructor 00273 //====//=== profilematrix first_profile2( 3, jp2, 'S', au2, al2, ad2); 00274 //====//=== 00275 //====//===// simple print function 00276 //====//=== first_profile2.full_print("\nfirst_profile Sparse Profile Matrix as FULL :\n "); 00277 //====//=== 00278 //====//===// asignment operetor 00279 //====//=== profilematrix second_profile2 = first_profile2; 00280 //====//=== second_profile2.full_print("\nsecond_profile Sparse Profile Matrix as FULL :\n "); 00281 //====//=== 00282 //====//===// triangularization ( Crout's method ); see: O.C. Zienkiewicz and R.L. Taylor: 00283 //====//===// "The FEM - fourth edition" 00284 //====//=== profilematrix first_profile2TRI = first_profile2.datri(); 00285 //====//=== first_profile2TRI.full_print("\nfirst but factorized Sparse Profile Matrix as FULL :\n "); 00286 //====//=== ::printf("\n\n"); 00287 //====//=== 00288 //====//===// right hand side reduction and backsubstitution ( vector of unknowns is b2 ) 00289 //====//=== first_profile2TRI.dasol( b2 ); 00290 //====//=== for( i=0 ; i<3 ; i++ ) 00291 //====//=== { 00292 //====//=== printf("solution_b[%d] = %8.4f\n",i, b2[i]); 00293 //====//=== } 00294 //====//=== 00295 //====//=== printf("\n\nmin = %6.6f \n", first_profile2.mmin() ); 00296 //====//=== printf("max = %6.6f \n", first_profile2.mmax() ); 00297 //====//=== printf("mean = %6.6f \n", first_profile2.mean() ); 00298 //====//=== 00299 //====//=== 00300 //====//===printf("\n----------------- EXAMPLE 3 ----------------------\n\n"); 00301 //====//=== 00302 //====//===// The main advantage of profile solver as described in 00303 //====//===// O.C. Zienkiewicz and R.L. Taylor: "The FEM - fourth edition" 00304 //====//===// is that it supports nonsymetric matrices stored in profile format. 00305 //====//=== 00306 //====//===int jp3[] = { 0, 1, 3}; 00307 //====//===double au3[] = { 2.0, 3.0, 2.0}; 00308 //====//===double ad3[] = { 4.0, 4.0, 4.0}; 00309 //====//===double al3[] = { 2.0, 1.0, 2.0}; 00310 //====//===double b3[] = { 1.0, 1.0, 1.0 }; 00311 //====//=== 00312 //====//===// nonsymetric profile matrix constructor 00313 //====//=== profilematrix first_profile3( 3, jp3, 'N', au3, al3, ad3); 00314 //====//=== 00315 //====//===// print out 00316 //====//=== first_profile3.full_print("\nfirst_profile Sparse Profile Matrix as FULL :\n "); 00317 //====//=== 00318 //====//===// triangularization ( Crout's method ); see: O.C. Zienkiewicz and R.L. Taylor: 00319 //====//===// "The FEM - fourth edition" 00320 //====//=== profilematrix first_profile3TRI = first_profile3.datri(); 00321 //====//=== first_profile3TRI.full_print("\nfirst but factorized \ 00322 //====//=== Sparse Profile Matrix as FULL :\n "); 00323 //====//=== ::printf("\n\n"); 00324 //====//=== 00325 //====//===// right hand side reduction and backsubstitution ( vector of unknowns is b3 ) 00326 //====//=== first_profile3TRI.dasol( b3 ); 00327 //====//=== for( i=0 ; i<3 ; i++ ) 00328 //====//=== { 00329 //====//=== printf("solution_b[%d] = %8.4f\n",i, b3 00330 //====//=== [i]); 00331 //====//=== } 00332 //====//=== 00333 //====//=== printf("\n\nmin = %6.6f \n", first_profile3.mmin() ); 00334 //====//=== printf("max = %6.6f \n", first_profile3.mmax() ); 00335 //====//=== printf("mean = %6.6f \n", first_profile3.mean() ); 00336 //====//=== 00337 //====//=== 00338 //====printf("\n\n------------ VECTOR -------------------\n\n"); 00339 00340 static double vect1[] = {2.0, 3.0, -2.0, 5.0, -2.0}; 00341 static double vect2[] = {1.0, 1.0, 1.0, 1.0, 1.0}; 00342 00343 // vector constructor 00344 BJvector first_vector( 5, vect1); 00345 first_vector.print("f","\n\nfirst_vector vector\n"); 00346 00347 // vector constructor 00348 BJvector second_vector ( 5, vect2); 00349 second_vector.print("s","\n\nsecond_vector vector\n"); 00350 00351 // default constructor for vector 00352 BJvector third_vector; 00353 // vector assignment 00354 third_vector = first_vector + second_vector; 00355 third_vector.print("t","\nfirst_vector + second_vector = \n"); 00356 00357 BJvector dot_product = first_vector.transpose() * second_vector; 00358 // vector dot product; 00359 // dot_product = first_vector.transpose() * second_vector; 00360 //==== dot_product.print("d","\nfirst_vector * second_vector \n"); 00361 //==== 00362 00363 printf("\n\n------------VECTOR AND MATRIX -----------------\n\n"); 00364 static double vect3[] = {1.0, 2.0, 3.0, 4.0, 5.0}; 00365 00366 //default construcotrs 00367 BJmatrix res1; 00368 BJmatrix res2; 00369 00370 // matrix constructor 00371 BJmatrix vect_as_matrix(5, 1, vect3); 00372 BJvector vect(5, vect3); 00373 00374 first_matrix.print("f","\n first matrix"); 00375 00376 // vector and matrix are quite similar ! 00377 vect_as_matrix.print("vm","\n vector as matrix"); 00378 vect.print("v","\n vector"); 00379 00380 // this should give the same answer! ( vector multiplication with matrix 00381 res1 = vect_as_matrix.transpose() * first_matrix; 00382 res2 = vect.transpose() * first_matrix; 00383 00384 res1.print("r1","\n result"); 00385 res2.print("r2","\n result"); 00386 00387 00388 00389 ::printf("\n\n----------------- TENSOR --------------------\n\n"); 00390 00391 Tensor t0(); 00392 Tensor *ta = new Tensor; 00393 00394 // tensor default construcotr 00395 tensor t1; 00396 t1.print("t1","\n tensor t1"); 00397 00398 static double t2values[] = { 1,2,3, 00399 4,5,6, 00400 7,8,9 }; 00401 // tensor constructor with values assignments ( order 2 ; like matrix ) 00402 tensor t2( 2, def_dim_2, t2values); 00403 t2.print("t2","\ntensor t2 (2nd-order with values assignement)"); 00404 00405 fprintf(stderr,"rank of t2: %d ", t2.rank()); 00406 for (int ii=1; ii<=t2.rank(); ii++) { 00407 fprintf(stderr,"dimension of t2 in %d is %d ", ii, t2.dim(ii)); 00408 } 00409 00410 00411 tensor tst( 2, def_dim_2, t2values); 00412 // t2 = t2*2.0; 00413 // t2.print("t2x2","\ntensor t2 x 2.0"); 00414 t2.print("t2","\noriginal tensor t2 "); 00415 tst.print("tst","\ntst "); 00416 00417 tensor t2xt2 = t2("ij")*t2("jk"); 00418 t2xt2.print("t2xt2","\ntensor t2 x t2"); 00419 00420 tensor t2xtst = t2("ij")*tst("jk"); 00421 t2xtst.print("t2xtst","\ntensor t2 x tst"); 00422 // exit(0); 00423 t2.print("t2","\noriginal tensor t2 "); 00424 00425 // tensor constructor with 0.0 assignment ( order 4 ; 4D array ) 00426 tensor ZERO(4,def_dim_4,0.0); 00427 ZERO.print("z","\ntensor ZERO (4-th order with value assignment)"); 00428 00429 static double t4val[] = 00430 { 11.100, 12.300, 13.100, 15.230, 16.450, 14.450, 17.450, 18.657, 19.340, 00431 110.020, 111.000, 112.030, 114.034, 115.043, 113.450, 116.670, 117.009, 118.060, 00432 128.400, 129.500, 130.060, 132.560, 133.000, 131.680, 134.100, 135.030, 136.700, 00433 119.003, 120.400, 121.004, 123.045, 124.023, 122.546, 125.023, 126.043, 127.000, 00434 137.500, 138.600, 139.000, 141.067, 142.230, 140.120, 143.250, 144.030, 145.900, 00435 146.060, 147.700, 148.990, 150.870, 151.000, 149.780, 152.310, 153.200, 154.700, 00436 164.050, 165.900, 166.003, 168.450, 169.023, 167.067, 170.500, 171.567, 172.500, 00437 155.070, 156.800, 157.067, 159.000, 160.230, 158.234, 161.470, 162.234, 163.800, 00438 173.090, 174.030, 175.340, 177.060, 178.500, 176.000, 179.070, 180.088, 181.200}; 00439 00440 // tensor constructor with values assignment ( order 4 ; 4D array ) 00441 tensor t4(4, def_dim_4, t4val); 00442 t4.print("t4","\ntensor t4 (4th-order with values assignment)"); 00443 00444 // Some relevant notes from the Dec. 96 Draft (as pointed out by KAI folks): 00445 // 00446 // "A binary operator shall be implemented either by a non-static member 00447 // function (_class.mfct_) with one parameter or by a non-member function 00448 // with two parameters. Thus, for any binary operator @, x@y can be 00449 // interpreted as either x.operator@(y) or operator@(x,y)." [13.5.2] 00450 // 00451 // "The order of evaluation of arguments [of a function call] is 00452 // unspecified." [5.2.2 paragraph 9] 00453 // 00454 // 00455 // SO THAT IS WHY I NEED THIS temp 00456 // It is not evident which operator will be called up first: operator() or operator* . 00457 // 00458 //% //////////////////////////////////////////////////////////////////////// 00459 // testing the multi products using indicial notation: 00460 tensor tst1; 00461 tensor temp = t2("ij") * t4("ijkl"); 00462 tst1 = temp("kl") * t4("klpq") * t2("pq"); 00463 tst1.print("tst1","\ntensor tst1 = t2(\"ij\")*t4(\"ijkl\")*t4(\"klpq\")*t2(\"pq\");"); 00464 00465 00466 // testing inverse function for 4. order tensor. Inverse for 4. order tensor 00467 // is done by converting that tensor to matrix, inverting that matrix 00468 // and finally converting matrix back to tensor 00469 tensor t4inv_2 = t4.inverse_2(); 00470 t4inv_2.print("t4i","\ntensor t4 inverted_2"); 00471 tensor unity_2 = t4("ijkl")*t4inv_2("klpq"); 00472 unity_2.print("uno2","\ntensor unity_2"); 00473 00474 //.................................................................... 00475 // There are several built in tensor types. One of them is: 00476 // Levi-Civita permutation tensor 00477 tensor e("e",3,def_dim_3); 00478 e.print("e","\nLevi-Civita permutation tensor e"); 00479 00480 // The other one is: 00481 // Kronecker delta tensor 00482 tensor I2("I", 2, def_dim_2); 00483 I2.print("I2","\ntensor I2 (2nd order unit tensor: Kronecker Delta -> d_ij)"); 00484 00485 00486 00487 tensor Ipmnq = I2("pm") * I2("nq"); 00488 tensor Imnpq = I2("mn") * I2("pq"); 00489 // tensor Apqmn = alpha("pq") * I2("mn"); 00490 tensor X = Imnpq * (1.0/3.0) ;// - Apqmn * (1.0/3.0); 00491 X.print(); 00492 00493 00494 // tensor multiplications 00495 tensor I2I2 = I2("ij")*I2("ij"); 00496 I2I2.print("I2I2","\ntensor I2 * I2"); 00497 00498 // tensor multiplications ( from right) 00499 tensor I2PI = I2*PI; 00500 I2PI.print("I2PI","\ntensor I2 * PI"); 00501 00503 // tensor PII2 = PI*I2; 00504 // PII2.print("PII2","\ntensor PI * I2"); 00505 00507 // tensor mPII2 = -PII2; 00508 // mPII2.print("mPII2","\ntensor -PI * I2"); 00509 00510 // trace function 00511 double deltatrace = I2.trace(); 00512 ::printf("\ntrace of Kronecker delta is %f \n",deltatrace); 00513 00514 // determinant of 2. order tensor only! 00515 double deltadet = I2.determinant(); 00516 ::printf("\ndeterminant of Kronecker delta is %f \n",deltadet); 00517 00518 // comparison of tensor ( again within sqrt(macheps) tolerance ) 00519 tensor I2again = I2; 00520 if ( I2again == I2 ) ::printf("\n I2again == I2 TRUE (OK)\n"); 00521 else ::printf("\a\n\n\n I2again == I2 NOTTRUE \n\n\n"); 00522 00523 //.................................................................... 00524 // some of the 4. order tensor used in conituum mechanics: 00525 // the most general representation of the fourth order isotropic tensor 00526 // includes the following fourth orther unit isotropic tensors: 00527 tensor I_ijkl( 4, def_dim_4, 0.0 ); 00528 I_ijkl = I2("ij")*I2("kl"); 00529 // I_ijkl.print("ijkl","\ntensor I_ijkl = d_ij d_kl)"); 00530 tensor I_ikjl( 4, def_dim_4, 0.0 ); 00531 // I_ikjl = I2("ij")*I2("kl"); 00532 I_ikjl = I_ijkl.transpose0110(); 00533 // I_ikjl.print("ikjl","\ntensor I_ikjl) "); 00534 tensor I_ikjl_inv_2 = I_ikjl.inverse_2(); 00535 // I_ikjl_inv_2.print("I_ikjl","\ntensor I_ikjl_inverse_2)"); 00536 if ( I_ikjl == I_ikjl_inv_2 ) ::printf("\n\n I_ikjl == I_ikjl_inv_2 !\n"); 00537 else ::printf("\a\n\n I_ikjl != I_ikjl_inv_2 !\n"); 00538 00539 tensor I_iljk( 4, def_dim_4, 0.0 ); 00540 // I_ikjl = I2("ij")*I2("kl"); 00541 //.. I_iljk = I_ikjl.transpose0101(); 00542 I_iljk = I_ijkl.transpose0111(); 00543 // I_iljk.print("iljk","\ntensor I_iljk) "); 00544 // To check out this three fourth-order isotropic tensor please see 00545 // W.Michael Lai, David Rubin, Erhard Krempl 00546 // " Introduction to Continuum Mechanics" 00547 // QA808.2 00548 // ISBN 0-08-022699-X 00549 00550 //.................................................................... 00551 // Multiplications between 4. order tensors 00552 ::printf("\n\n intermultiplications \n"); 00553 // tensor I_ijkl_I_ikjl = I_ijkl("ijkl")*I_ikjl("ikjl"); 00554 tensor I_ijkl_I_ikjl = I_ijkl("ijkl")*I_ikjl("ijkl"); 00555 I_ijkl_I_ikjl.print("i","\n\n I_ijkl*I_ikjl \n"); 00556 00557 // tensor I_ijkl_I_iljk = I_ijkl("ijkl")*I_iljk("iljk"); 00558 tensor I_ijkl_I_iljk = I_ijkl("ijkl")*I_iljk("ijkl"); 00559 I_ijkl_I_iljk.print("i","\n\n I_ijkl*I_iljk \n"); 00560 00561 // tensor I_ikjl_I_iljk = I_ikjl("ikjl")*I_iljk("iljk"); 00562 tensor I_ikjl_I_iljk = I_ikjl("ijkl")*I_iljk("ijkl"); 00563 I_ikjl_I_iljk.print("i","\n\n I_ikjl*I_iljk \n"); 00564 00565 //.................................................................... 00566 // More multiplications between 4. order tensors 00567 ::printf("\n\n intermultiplications same with same \n"); 00568 tensor I_ijkl_I_ijkl = I_ijkl("ijkl")*I_ijkl("ijkl"); 00569 I_ijkl_I_ijkl.print("i","\n\n I_ijkl*I_ijkl \n"); 00570 00571 tensor I_ikjl_I_ikjl = I_ikjl("ikjl")*I_ikjl("ikjl"); 00572 I_ikjl_I_ikjl.print("i","\n\n I_ikjl*I_ikjl \n"); 00573 00574 tensor I_iljk_I_iljk = I_iljk("iljk")*I_iljk("iljk"); 00575 I_iljk_I_iljk.print("i","\n\n I_iljk*I_iljk \n"); 00576 00577 00578 // tensor additions ans scalar multiplications 00579 // symmetric part of fourth oder unit isotropic tensor 00580 tensor I4s = (I_ikjl+I_iljk)*0.5; 00581 // tensor I4s = 0.5*(I_ikjl+I_iljk); 00582 I4s.print("I4s","\n symmetric tensor I4s = (I_ikjl+I_iljk)*0.5 "); 00583 // skew-symmetric part of fourth oder unit isotropic tensor 00584 tensor I4sk = (I_ikjl-I_iljk)*0.5; 00585 I4sk.print("I4sk","\n skew-symmetric tensor I4sk = (I_ikjl-I_iljk)*0.5 "); 00586 00587 // equvalence check ( they should be different ) 00588 if ( I4s == I4sk ) ::printf("\n\n I4s == I4sk !\n"); 00589 else ::printf("\a\n\n I4s != I4sk !\n"); 00590 00591 00592 //.................................................................... 00593 // e-delta identity ( see Lubliner ( QA931 .L939 1990) page 2. 00594 // and Lai ( QA808.2 L3 1978) page 12 ) 00595 tensor ee = e("ijm")*e("klm"); 00596 ee.print("ee","\ntensor e_ijm*e_klm"); 00597 tensor id = ee - (I_ikjl - I_iljk); 00598 if ( id == ZERO ) ::printf("\n\n e-delta identity HOLDS !! \n\n"); 00599 tensor ee1 = e("ilm")*e("jlm"); 00600 ee1.print("ee1","\n\n e(\"ilm\")*e(\"jlm\") \n"); 00601 tensor ee2 = e("ijk")*e("ijk"); 00602 ee2.print("ee2","\n\n e(\"ijk\")*e(\"ijk\") \n"); 00603 00604 00605 //.................................................................... 00606 // Linear Isotropic Elasticity Tensor 00607 // building elasticity tensor 00608 double Ey = 20000; 00609 double nu = 0.2; 00610 // building stiffness tensor in one command line 00611 tensor E1 = (I_ijkl*((Ey*nu*2.0)/(2.0*(1.0+nu)*(1-2.0*nu)))) + 00612 ( (I_ikjl+I_iljk)*(Ey/(2.0*(1.0+nu)))); 00613 // building compliance tensor in one command line 00614 tensor D1= (I_ijkl * (-nu/Ey)) + ( (I_ikjl+I_iljk) * ((1.0+nu)/(2.0*Ey))); 00615 00616 00617 tensor test3 = E1("ijkl") * I2("kl"); 00618 test3.print("tst","\n\n E1(\"ijkl\") * I2(\"kl\")\n"); 00619 00620 00621 // multiplication between them 00622 tensor test = E1("ijkl")*D1("klpq"); 00623 test.print("t","\n\n\n test = E1(\"ijkl\")*D1(\"klpq\") \n"); 00624 // and this should be equal to the symmetric part of 4. order unit tensor 00625 if ( test == I4s ) ::printf("\n test == I4s TRUE ( up to sqrt(macheps())) \n"); 00626 else ::printf("\a\n\n\n test == I4s NOTTRUE ( up to sqrt(macheps())) \n\n\n"); 00627 00628 //............Different Way........................................... 00629 // Linear Isotropic Elasticity Tensor 00630 double lambda = nu * Ey / (1. + nu) / (1. - 2. * nu); 00631 double mu = Ey / (2. * (1. + nu)); 00632 ::printf("\n lambda = %.12e\n",lambda); 00633 ::printf(" mu = %.12e\n",mu); 00634 00635 ::printf("\nYoung Modulus = %.4e",Ey); 00636 ::printf("\nPoisson ratio = %.4e\n",nu); 00637 ::printf( " lambda + 2 mu = %.4e\n", (lambda + 2 * mu)); 00638 00639 // building elasticity tensor 00640 tensor E2 = (I_ijkl * lambda) + (I4s * (2. * mu)); 00641 E2.print("E2","tensor E2: elastic moduli Tensor = lambda*I2*I2+2*mu*I4s"); 00642 00643 tensor E2inv = E2.inverse(); 00644 00645 // building compliance tensor 00646 tensor D2= (I_ijkl * (-nu/Ey)) + (I4s * (1./(2.*mu))); 00647 D2.print("D2","tensor D2: compliance Tensor (I_ijkl * (-nu/Ey)) + (I4s * (1./2./mu))"); 00648 00649 if ( E2inv == D2 ) ::printf("\n E2inv == D2 TRUE \n"); 00650 else ::printf("\a\n\n\n E2inv == D2 NOTTRUE \n\n\n"); 00651 00652 if ( E1 == E2 ) ::printf("\n E1 == E2 TRUE \n"); 00653 else ::printf("\a\n\n\n E1 == E2 NOTTRUE \n\n\n"); 00654 00655 if ( D1 == D2 ) ::printf("\n D1 == D2 TRUE \n"); 00656 else ::printf("\a\n\n\n D1 == D2 NOTTRUE \n\n\n"); 00657 00658 00659 // -------------- 00660 ::printf("\n\n\n --------------------------TENSOR SCALAR MULTIPLICATION ----\n\n"); 00661 tensor EEEE1 = E2; 00662 tensor EEEE2 = EEEE1*2.0; 00663 EEEE1.print("E1","tensor EEEE1"); 00664 EEEE2.print("E2","tensor EEEE2"); 00665 00666 00667 //###printf("\n\n------------VECTOR AND SKYMATRIX -----------------\n\n"); 00668 //###// 1) use of member function full_val is of crucial importance here 00669 //###// and it enable us to use skymatrix as if it is full matrix. 00670 //###// There is however small time overhead but that can be optimized . . . 00671 //###double vect4[] = {1.0, 2.0, 3.0, 4.0, 5.0}; 00672 //### 00673 //###matrix res2; 00674 //###vector vector2(5, vect4); 00675 //###second.full_print(); 00676 //###vector2.print(); 00677 //###res2 = vector2.transpose() * second; 00678 //###res2.print(); 00679 //### 00680 //### 00681 //###printf("\n\n------------ MATRIX AND SKYMATRIX -----------------\n\n"); 00682 //###// 1) use of member function full_val is of crucial importance here 00683 //###// and it enable us to use skymatrix as if it is full matrix. 00684 //###// There is however small time overhead but that can be optimized . . . 00685 //### 00686 //###matrix big_result; 00687 //###big_result = first_matrix * second; 00688 //###big_result.print(); 00689 00690 00691 00692 00693 exit(1); 00694 // return 1; 00695 } |