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