BJmath_tst.cpp

Go 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 

Generated on Mon Oct 23 15:05:24 2006 for OpenSees by doxygen 1.5.0