math_tst.cpp

Go 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 }

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