Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

ConstantPressureVolumeQuad.cpp

Go to the documentation of this file.
00001 // Ed "C++" Love
00002 // Do not ask Prashant about this code.  He has no clue. 
00003 //
00004 // Constant Presssure/Volume Four Node Quadrilateral
00005 // Plane Strain (NOT PLANE STRESS)
00006 //
00007 
00008 #include <iostream.h>
00009 #include <stdio.h> 
00010 #include <stdlib.h> 
00011 #include <math.h> 
00012 
00013 #include <ID.h> 
00014 #include <Vector.h>
00015 #include <Matrix.h>
00016 #include <Element.h>
00017 #include <Node.h>
00018 #include <NDMaterial.h>
00019 #include <Domain.h>
00020 #include <ErrorHandler.h>
00021 #include <ConstantPressureVolumeQuad.h>
00022 
00023 //static data
00024 Matrix ConstantPressureVolumeQuad :: stiff(8,8)   ;
00025 Vector ConstantPressureVolumeQuad :: resid(8)     ;
00026 Matrix ConstantPressureVolumeQuad :: mass(8,8)    ;
00027 Matrix ConstantPressureVolumeQuad :: damping(8,8) ;
00028  
00029 //volume-pressure constants
00030 double ConstantPressureVolumeQuad :: one3  = 1.0 / 3.0 ;
00031 double ConstantPressureVolumeQuad :: two3  = 2.0 / 3.0 ;
00032 double ConstantPressureVolumeQuad :: four3 = 4.0 / 3.0 ;
00033 double ConstantPressureVolumeQuad :: one9  = 1.0 / 9.0 ;
00034     
00035 //quadrature data
00036 double ConstantPressureVolumeQuad :: root3 = sqrt(3.0) ;
00037 double ConstantPressureVolumeQuad :: one_over_root3 = 1.0 / root3 ;
00038 
00039 double ConstantPressureVolumeQuad :: sg[] = { -one_over_root3,  
00040             one_over_root3, 
00041             one_over_root3, 
00042            -one_over_root3 } ;
00043 
00044 double ConstantPressureVolumeQuad :: tg[] = { -one_over_root3, 
00045                                               -one_over_root3, 
00046                                                one_over_root3,  
00047                                                one_over_root3 } ;
00048 
00049 double ConstantPressureVolumeQuad :: wg[] = { 1.0, 1.0, 1.0, 1.0 } ;
00050   
00051 
00052 //null constructor
00053 ConstantPressureVolumeQuad :: ConstantPressureVolumeQuad( ) :
00054 Element( 0, ELE_TAG_ConstantPressureVolumeQuad ),
00055 connectedExternalNodes(4) 
00056 { 
00057   return ; 
00058 }
00059 
00060 
00061 //full constructor
00062 ConstantPressureVolumeQuad :: ConstantPressureVolumeQuad( 
00063                             int tag, 
00064                        int node1,
00065        int node2,
00066        int node3,
00067        int node4,
00068        NDMaterial &theMaterial ) :
00069 Element( tag, ELE_TAG_ConstantPressureVolumeQuad ),
00070 connectedExternalNodes(4) 
00071 {
00072   connectedExternalNodes(0) = node1 ;
00073   connectedExternalNodes(1) = node2 ;
00074   connectedExternalNodes(2) = node3 ;
00075   connectedExternalNodes(3) = node4 ;
00076 
00077   int i ;
00078   for ( i = 0 ;  i < 4; i++ ) {
00079 
00080       materialPointers[i] = theMaterial.getCopy("AxiSymmetric2D") ;
00081 
00082       if (materialPointers[i] == 0) {
00083 
00084    g3ErrorHandler->fatal("ConstantPressureVolumeQuad::constructor %s",
00085     "- failed to get a material of type: AxiSymmetric2D");
00086       } //end if
00087       
00088   } //end for i 
00089 
00090 }
00091 
00092 
00093 //destructor 
00094 ConstantPressureVolumeQuad :: ~ConstantPressureVolumeQuad( )
00095 {
00096   int i ;
00097   for ( i = 0 ;  i < 4; i++ ) {
00098 
00099     delete materialPointers[i] ;
00100     materialPointers[i] = 0 ; 
00101 
00102     nodePointers[i] = 0 ;
00103   } //end for i
00104 
00105 }
00106 
00107 
00108 //set domain
00109 void ConstantPressureVolumeQuad :: setDomain( Domain *theDomain ) 
00110 {  
00111   int i ;
00112   for ( i = 0;  i < 4; i++ ) {
00113 
00114      nodePointers[i] = theDomain->getNode( connectedExternalNodes(i)  ) ;
00115 
00116      if ( nodePointers[i] != 0 ) {
00117   const Vector &coor = nodePointers[i]->getCrds( ) ;
00118 
00119   xl[0][i] = coor(0) ;
00120   xl[1][i] = coor(1) ; 
00121      } // end if 
00122 
00123   } //end for i 
00124   
00125   this->DomainComponent::setDomain(theDomain);
00126 }
00127 
00128 
00129 //get the number of external nodes
00130 int ConstantPressureVolumeQuad :: getNumExternalNodes( ) const
00131 {
00132   return 4 ;
00133 } 
00134  
00135 
00136 //return connected external nodes
00137 const ID& ConstantPressureVolumeQuad :: getExternalNodes( ) 
00138 {
00139   return connectedExternalNodes ;
00140 } 
00141 
00142 
00143 //return number of dofs
00144 int ConstantPressureVolumeQuad :: getNumDOF( ) 
00145 {
00146   return 8 ;
00147 }
00148 
00149 
00150 //commit state
00151 int ConstantPressureVolumeQuad :: commitState( )
00152 {
00153   int i ;
00154   int success = 0 ;
00155 
00156   for ( i = 0; i < 4; i++ ) 
00157     success += materialPointers[i]->commitState( ) ;
00158   
00159   return success ;
00160 }
00161  
00162 
00163 
00164 //revert to last commit 
00165 int ConstantPressureVolumeQuad :: revertToLastCommit( ) 
00166 {
00167   int i ;
00168   int success = 0 ;
00169 
00170   for ( i = 0; i < 4; i++ ) 
00171     success += materialPointers[i]->revertToLastCommit( ) ;
00172   
00173   return success ;
00174 }
00175     
00176 
00177 //revert to start 
00178 int ConstantPressureVolumeQuad :: revertToStart( ) 
00179 {
00180   int i ;
00181   int success = 0 ;
00182 
00183   for ( i = 0; i < 4; i++ ) 
00184     success += materialPointers[i]->revertToStart( ) ;
00185   
00186   return success ;
00187 }
00188 
00189 //print out element data
00190 void ConstantPressureVolumeQuad :: Print( ostream &s, int flag )
00191 {
00192   s << '\n' ;
00193   s << "Four Node Quad -- Mixed Pressure/Volume -- Plane Strain \n" ;
00194   s << "Node 1 : " << connectedExternalNodes(0) << '\n' ;
00195   s << "Node 2 : " << connectedExternalNodes(1) << '\n' ;
00196   s << "Node 3 : " << connectedExternalNodes(2) << '\n' ;
00197   s << "Node 4 : " << connectedExternalNodes(3) << '\n' ;
00198   s << "Material Information : \n " ;
00199 
00200   materialPointers[0]->Print( s, flag ) ;
00201 
00202   s << endl ;
00203 }
00204 
00205 //return stiffness matrix 
00206 const Matrix& ConstantPressureVolumeQuad :: getTangentStiff( ) 
00207 {
00208   int tang_flag = 1 ; //get the tangent 
00209 
00210   //do tangent and residual here
00211   formResidAndTangent( tang_flag ) ;  
00212 
00213   return stiff ;
00214 }    
00215 
00216 
00217 //return secant matrix 
00218 const Matrix& ConstantPressureVolumeQuad :: getSecantStiff( ) 
00219 {
00220    int tang_flag = 1 ; //get the tangent
00221 
00222   //do tangent and residual here
00223   formResidAndTangent( tang_flag ) ;  
00224     
00225   return stiff ;
00226 }
00227     
00228 
00229 //return damping matrix because frank is a dumb ass 
00230 const Matrix& ConstantPressureVolumeQuad :: getDamp( ) 
00231 {
00232   //not supported
00233   return damping ;
00234 }    
00235 
00236 
00237 //return mass matrix
00238 const Matrix& ConstantPressureVolumeQuad :: getMass( ) 
00239 {
00240   //not supported
00241   return mass ;
00242 } 
00243 
00244 
00245 //zero the load -- what load?
00246 void ConstantPressureVolumeQuad :: zeroLoad( )
00247 {
00248   return ;
00249 }
00250 
00251 //add load -- what load?
00252 int  ConstantPressureVolumeQuad :: addLoad( const Vector &addP )
00253 {
00254   return -1 ;
00255 }
00256 
00257 
00258 //get residual
00259 const Vector& ConstantPressureVolumeQuad :: getResistingForce( ) 
00260 {
00261   int tang_flag = 0 ; //don't get the tangent
00262 
00263   formResidAndTangent( tang_flag ) ;
00264 
00265   return resid ;   
00266 }
00267 
00268 
00269 //get residual with inertia terms
00270 const Vector& ConstantPressureVolumeQuad :: getResistingForceIncInertia( )
00271 {
00272   int tang_flag = 0 ; //don't get the tangent
00273 
00274   //do tangent and residual here 
00275   formResidAndTangent( tang_flag ) ;
00276 
00277   return resid ;
00278 }
00279 
00280 
00281 //-----------------------------------------------------------------------
00282 
00283 //form residual and tangent
00284 void ConstantPressureVolumeQuad ::  formResidAndTangent( int tang_flag ) 
00285 {
00286   // strains ordered  00, 11, 22, 01  
00287   //            i.e.  11, 22, 33, 12 
00288   //
00289   //            strain(0) =   eps_00
00290   //            strain(1) =   eps_11
00291   //            strain(2) =   eps_22
00292   //            strain(3) = 2*eps_01
00293   //
00294   //  same ordering for stresses but no 2 
00295 
00296   int i,  j,  k, l ;
00297   int ii, jj, kk ;
00298   int node ;
00299   int success ;
00300   
00301   double tmp_shp[3][4] ; //shape functions
00302 
00303   double     shp[3][4][4] ; //shape functions at each gauss point
00304 
00305   double vol_avg_shp[3][4] ; // volume averaged shape functions
00306 
00307   double xsj ;  // determinant jacaobian matrix 
00308 
00309   static Matrix sx(2,2) ; // inverse jacobian matrix 
00310 
00311   double dvol[4] ; //volume elements
00312 
00313   double volume = 0.0 ; //volume of element
00314 
00315   double theta = 0.0 ; //average volume change (trace of strain) 
00316 
00317   double pressure = 0.0 ; //constitutive pressure  
00318 
00319   static Vector strain(4) ; //strain in vector form 
00320 
00321   static Vector sigBar(4) ; //stress in vector form
00322   static Vector sig(4) ; //mixed stress in vector form
00323 
00324   double trace = 0.0 ; //trace of the strain 
00325 
00326   static Matrix BJ(4,2) ; //strain-displacement matrices
00327   static Matrix BJtran(2,4) ; 
00328   static Matrix BK(4,2) ;
00329 
00330   static Matrix littleBJ(1,2) ; //volume strain-displacement matrices
00331   static Matrix littleBJtran(2,1) ;
00332   static Matrix littleBK(1,2) ; 
00333 
00334   static Matrix stiffJK(2,2) ; //nodeJ-nodeK 2x2 stiffness
00335   static Vector residJ(2) ; //nodeJ residual 
00336   
00337   static Vector one(4) ; //rank 2 identity as a vector
00338   static Matrix oneMatrix(4,1) ;
00339   static Matrix oneTran(1,4) ;
00340   
00341   static Matrix Pdev(4,4) ; //deviator projector
00342 
00343   static Matrix dd(4,4) ;  //material tangent
00344 
00345   static Matrix Pdev_dd_Pdev(4,4) ;
00346   static Matrix Pdev_dd_one(4,1) ; 
00347   static Matrix one_dd_Pdev(1,4) ;
00348   double bulk ;
00349   static Matrix BJtranD(2,4) ;
00350   static Matrix BJtranDone(2,1) ;
00351   static Matrix littleBJoneD(2,4) ;
00352   static Matrix littleBJtranBulk(2,1) ;
00353   
00354   //zero stiffness and residual 
00355   stiff.Zero( ) ;
00356   resid.Zero( ) ;
00357 
00358   //one vector
00359   one(0) = 1.0 ;
00360   one(1) = 1.0 ;
00361   one(2) = 1.0 ;
00362   one(3) = 0.0 ;
00363 
00364   //one matrix
00365   oneMatrix(0,0) = 1.0 ;
00366   oneMatrix(1,0) = 1.0 ;
00367   oneMatrix(2,0) = 1.0 ;
00368   oneMatrix(3,0) = 0.0 ;
00369   oneTran = this->transpose( 4, 1, oneMatrix ) ;
00370 
00371   //Pdev matrix
00372   Pdev.Zero( ) ;
00373 
00374   Pdev(0,0) =  two3 ;
00375   Pdev(0,1) = -one3 ;
00376   Pdev(0,2) = -one3 ;
00377 
00378   Pdev(1,0) = -one3 ;
00379   Pdev(1,1) =  two3 ;
00380   Pdev(1,2) = -one3 ;
00381 
00382   Pdev(2,0) = -one3 ;
00383   Pdev(2,1) = -one3 ;
00384   Pdev(2,2) =  two3 ;
00385 
00386   Pdev(3,3) = 1.0 ;
00387 
00388 
00389   //zero stuff
00390   volume = 0.0 ;
00391 
00392   for ( k = 0; k < 3; k++ ){
00393     for ( l = 0; l < 4; l++ ) 
00394         vol_avg_shp[k][l] = 0.0 ; 
00395   } //end for k
00396 
00397 
00398   //gauss loop to compute volume averaged shape functions
00399 
00400   for ( i = 0; i < 4; i++ ){
00401     
00402     shape2d( sg[i], tg[i], xl, tmp_shp, xsj, sx ) ;
00403 
00404     dvol[i] = wg[i] * xsj ;  // multiply by radius for axisymmetry 
00405 
00406     volume += dvol[i] ;
00407 
00408     for ( k = 0; k < 3; k++ ){
00409       for ( l = 0; l < 4; l++ ) {
00410 
00411  shp[k][l][i] = tmp_shp[k][l] ;
00412 
00413         vol_avg_shp[k][l] += tmp_shp[k][l] * dvol[i] ;
00414 
00415       } // end for l
00416     } //end for k
00417 
00418   } //end for i 
00419 
00420 
00421   //compute volume averaged shape functions
00422   for ( k = 0; k < 3; k++ ){
00423     for ( l = 0; l < 4; l++ ) 
00424         vol_avg_shp[k][l] /= volume ; 
00425   } //end for k
00426 
00427 
00428   //compute theta
00429   theta = 0.0 ;
00430   for ( i = 0; i < 4; i++ ) {
00431 
00432     strain.Zero( ) ;
00433 
00434     //node loop to compute strain
00435     for ( node = 0; node < 4; node++ ) {
00436 
00437       const Vector &ul = nodePointers[node]->getTrialDisp( ) ;
00438 
00439       strain(0) += shp[0][node][i] * ul(0) ;
00440 
00441       strain(1) += shp[1][node][i] * ul(1) ;
00442 
00443       strain(2) = 0.0 ;  // not zero for axisymmetry
00444 
00445 
00446     } // end for node
00447 
00448     trace  =  strain(0) + strain(1) + strain(2) ;
00449 
00450     theta +=  trace * dvol[i] ;
00451 
00452   } // end for i
00453   theta /= volume ;
00454 
00455 
00456   //compute pressure
00457   pressure = 0.0 ;
00458   for ( i = 0; i < 4; i++ ) {
00459 
00460     strain.Zero( ) ;
00461 
00462     //node loop to compute strain
00463     for ( node = 0; node < 4; node++ ) {
00464 
00465       const Vector &ul = nodePointers[node]->getTrialDisp( ) ;
00466 
00467       strain(0) += shp[0][node][i] * ul(0) ;
00468 
00469       strain(1) += shp[1][node][i] * ul(1) ;
00470 
00471       strain(2) = 0.0 ; // not zero for axisymmetry
00472 
00473       strain(3) +=  shp[1][node][i] * ul(0)  
00474            + shp[0][node][i] * ul(1) ; 
00475 
00476     } // end for node
00477 
00478     trace = strain(0) + strain(1) + strain(2) ;
00479 
00480     strain -= (one3*trace)*one ;
00481     strain += (one3*theta)*one ;
00482     
00483     success = materialPointers[i]->setTrialStrain( strain ) ;
00484 
00485     const Vector &sigBar = materialPointers[i]->getStress( ) ;
00486 
00487     pressure +=  one3 * ( sigBar(0) + sigBar(1) + sigBar(2) ) * dvol[i] ;
00488 
00489   } // end for i
00490   pressure /= volume ;
00491 
00492 
00493   //residual and tangent calculations gauss loop
00494 
00495   for ( i = 0; i < 4; i++ ) {
00496 
00497     const Vector &sigBar = materialPointers[i]->getStress( ) ;
00498 
00499     //stress for equilibrium
00500 
00501     trace = sigBar(0) + sigBar(1) + sigBar(2) ;
00502 
00503     sig  = sigBar ;
00504     sig -= (one3*trace)*one ;
00505     sig += pressure*one ;
00506 
00507     //multilply by volume elements and compute 
00508     // matrices for stiffness calculation
00509 
00510     sig *= dvol[i] ;
00511 
00512     if ( tang_flag == 1 ) {
00513 
00514  const Matrix &ddBar  = materialPointers[i]->getTangent( ) ;
00515  
00516  dd = ddBar * dvol[i] ;
00517         
00518  Pdev_dd_Pdev = Pdev * dd * Pdev ;
00519 
00520  Pdev_dd_one  = one3 * ( Pdev * dd * oneMatrix ) ;
00521  
00522  one_dd_Pdev  = one3 * ( oneTran * dd * Pdev ) ;
00523 
00524  bulk = one9 * (   dd(0,0) + dd(0,1) + dd(0,2)  
00525                  + dd(1,0) + dd(1,1) + dd(1,2) 
00526                  + dd(2,0) + dd(2,1) + dd(2,2) ) ;
00527 
00528     } //end if tang_flag
00529     
00530 
00531     //residual and tangent loop over nodes
00532     
00533     jj = 0 ;
00534     for ( j = 0; j < 4; j++ ) {
00535       
00536       BJ.Zero( );
00537       BJ(0,0) = shp[0][j][i] ;
00538       BJ(1,1) = shp[1][j][i] ; 
00539 
00540       // BJ(2,0) for axi-symmetry 
00541 
00542       BJ(3,0) = shp[1][j][i]  ;
00543       BJ(3,1) = shp[0][j][i]  ;
00544 
00545 
00546       littleBJ(0,0) = vol_avg_shp[0][j] ;
00547       littleBJ(0,1) = vol_avg_shp[1][j] ;
00548 
00549       BJtran = this->transpose( 4, 2, BJ ) ;
00550 
00551       littleBJtran = this->transpose( 1, 2, littleBJ ) ;
00552 
00553       //compute residual 
00554 
00555       residJ = BJtran * sig ; 
00556 
00557       resid( jj   ) += residJ(0) ;
00558       resid( jj+1 ) += residJ(1) ;
00559 
00560       if ( tang_flag == 1 ) { //stiffness matrix
00561 
00562    BJtranD          =  BJtran * Pdev_dd_Pdev ;
00563    BJtranDone       =  BJtran * Pdev_dd_one ;
00564    littleBJoneD     =  littleBJtran * one_dd_Pdev ;
00565    littleBJtranBulk =  bulk * littleBJtran ;
00566    
00567     kk = 0 ;
00568    for ( k = 0; k < 4; k++ ) {
00569 
00570        BK.Zero( );
00571        BK(0,0) = shp[0][k][i] ;
00572        BK(1,1) = shp[1][k][i] ;
00573 
00574        // BK(2,0) for axi-symmetry 
00575 
00576        BK(3,0) = shp[1][k][i] ;
00577        BK(3,1) = shp[0][k][i] ;
00578 
00579 
00580        littleBK(0,0) = vol_avg_shp[0][k] ;
00581        littleBK(0,1) = vol_avg_shp[1][k] ;
00582 
00583        //compute stiffness matrix
00584         
00585        stiffJK =  ( BJtranD + littleBJoneD ) * BK
00586                       +  ( BJtranDone + littleBJtranBulk ) * littleBK ; 
00587 
00588        stiff( jj,   kk   ) += stiffJK(0,0) ;
00589        stiff( jj+1, kk   ) += stiffJK(1,0) ;
00590        stiff( jj,   kk+1 ) += stiffJK(0,1) ;
00591        stiff( jj+1, kk+1 ) += stiffJK(1,1) ;
00592 
00593        kk += 2 ;
00594    } // end for k
00595 
00596       } // end if tang_flag 
00597 
00598       
00599       jj += 2 ;
00600     } // end for j 
00601 
00602   } //end for i
00603 
00604   
00605   return ;
00606 }
00607 
00608 
00609 //----------------------------------------------------------------------
00610 
00611 Matrix ConstantPressureVolumeQuad :: transpose( int dim1, 
00612       int dim2, 
00613       const Matrix &M ) 
00614 {
00615   int i ;
00616   int j ;
00617 
00618   Matrix Mtran( dim2, dim1 ) ;
00619 
00620   for ( i = 0; i < dim1; i++ ) {
00621 
00622     for ( j = 0; j < dim2; j++ ) 
00623       Mtran(j,i) = M(i,j) ;
00624 
00625   } // end for i
00626 
00627   return Mtran ;
00628 }
00629 
00630 //---------------------------------------------------------------------
00631 
00632 //shape function routine for four node quads
00633 void ConstantPressureVolumeQuad :: shape2d( double ss, double tt, 
00634                               const double x[2][4], 
00635                               double shp[3][4], 
00636                               double &xsj, 
00637                               Matrix &sx ) 
00638 { 
00639 
00640   int i, j, k ;
00641 
00642   double temp ;
00643      
00644   static const double s[] = { -0.5,  0.5, 0.5, -0.5 } ;
00645   static const double t[] = { -0.5, -0.5, 0.5,  0.5 } ;
00646 
00647   static Matrix xs(2,2) ;
00648 
00649   for ( i = 0; i < 4; i++ ) {
00650       shp[2][i] = ( 0.5 + s[i]*ss )*( 0.5 + t[i]*tt ) ;
00651       shp[0][i] = s[i] * ( 0.5 + t[i]*tt ) ;
00652       shp[1][i] = t[i] * ( 0.5 + s[i]*ss ) ;
00653   } // end for i
00654 
00655   
00656   // Construct jacobian and its inverse
00657   
00658   xs.Zero( ) ;
00659   for ( i = 0; i < 2; i++ ) {
00660     for ( j = 0; j < 2; j++ ) {
00661 
00662       for ( k = 0; k < 4; k++ )
00663    xs(i,j) +=  x[i][k] * shp[j][k] ;
00664 
00665     } //end for j
00666   }  // end for i 
00667 
00668   xsj = xs(0,0)*xs(1,1) - xs(0,1)*xs(1,0) ;
00669 
00670   sx(0,0) =  xs(1,1) / xsj ;
00671   sx(1,1) =  xs(0,0) / xsj ;
00672   sx(0,1) = -xs(0,1) / xsj ; 
00673   sx(1,0) = -xs(1,0) / xsj ; 
00674 
00675 
00676   //form global derivatives 
00677   
00678   for ( i = 0; i < 4; i++ ) {
00679     temp      = shp[0][i]*sx(0,0) + shp[1][i]*sx(1,0) ;
00680     shp[1][i] = shp[0][i]*sx(0,1) + shp[1][i]*sx(1,1) ;
00681     shp[0][i] = temp ;
00682   } // end for i
00683 
00684   return ;
00685 }
00686     
00687 //-----------------------------------------------------------------------
00688 
00689 int ConstantPressureVolumeQuad :: sendSelf (int commitTag, Channel &theChannel)
00690 {
00691     return -1;
00692 }
00693     
00694 int ConstantPressureVolumeQuad :: recvSelf (int commitTag, 
00695      Channel &theChannel, 
00696      FEM_ObjectBroker &theBroker)
00697 {
00698     return -1;
00699 }
00700 
Copyright Contact Us