ConstantPressureVolumeQuad.cpp

Go to the documentation of this file.
00001 /* ****************************************************************** **
00002 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00003 **          Pacific Earthquake Engineering Research Center            **
00004 **                                                                    **
00005 **                                                                    **
00006 ** (C) Copyright 1999, The Regents of the University of California    **
00007 ** All Rights Reserved.                                               **
00008 **                                                                    **
00009 ** Commercial use of this program without express permission of the   **
00010 ** University of California, Berkeley, is strictly prohibited.  See   **
00011 ** file 'COPYRIGHT'  in main directory for information on usage and   **
00012 ** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
00013 **                                                                    **
00014 ** Developed by:                                                      **
00015 **   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
00016 **   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
00017 **   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
00018 **                                                                    **
00019 ** ****************************************************************** */
00020                                                                         
00021 // $Revision: 1.17 $
00022 // $Date: 2006/08/04 19:07:15 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/element/fourNodeQuad/ConstantPressureVolumeQuad.cpp,v $
00024 
00025 // Ed "C++" Love
00026 //
00027 // Constant Presssure/Volume Four Node Quadrilateral
00028 // Plane Strain (NOT PLANE STRESS)
00029 
00030 
00031 #include <stdio.h> 
00032 #include <stdlib.h> 
00033 #include <math.h> 
00034 
00035 #include <ID.h> 
00036 #include <Vector.h>
00037 #include <Matrix.h>
00038 #include <Element.h>
00039 #include <Node.h>
00040 #include <NDMaterial.h>
00041 #include <Domain.h>
00042 #include <ErrorHandler.h>
00043 #include <ConstantPressureVolumeQuad.h>
00044 #include <Renderer.h>
00045 #include <ElementResponse.h>
00046 #include <Channel.h>
00047 #include <FEM_ObjectBroker.h>
00048 
00049 //static data
00050 double ConstantPressureVolumeQuad::matrixData[64];
00051 Matrix ConstantPressureVolumeQuad :: stiff(matrixData,8,8)   ;
00052 Vector ConstantPressureVolumeQuad :: resid(8)     ;
00053 Matrix ConstantPressureVolumeQuad :: mass(8,8)    ;
00054 Matrix ConstantPressureVolumeQuad :: damping(8,8) ;
00055  
00056 //volume-pressure constants
00057 double ConstantPressureVolumeQuad :: one3  = 1.0 / 3.0 ;
00058 double ConstantPressureVolumeQuad :: two3  = 2.0 / 3.0 ;
00059 double ConstantPressureVolumeQuad :: four3 = 4.0 / 3.0 ;
00060 double ConstantPressureVolumeQuad :: one9  = 1.0 / 9.0 ;
00061     
00062 //quadrature data
00063 double ConstantPressureVolumeQuad :: root3 = sqrt(3.0) ;
00064 double ConstantPressureVolumeQuad :: one_over_root3 = 1.0 / root3 ;
00065 
00066 double ConstantPressureVolumeQuad :: sg[] = { -one_over_root3,  
00067                                                one_over_root3, 
00068                                                one_over_root3, 
00069                                               -one_over_root3 } ;
00070 
00071 double ConstantPressureVolumeQuad :: tg[] = { -one_over_root3, 
00072                                               -one_over_root3, 
00073                                                one_over_root3,  
00074                                                one_over_root3 } ;
00075 
00076 double ConstantPressureVolumeQuad :: wg[] = { 1.0, 1.0, 1.0, 1.0 } ;
00077   
00078 
00079 //null constructor
00080 ConstantPressureVolumeQuad :: ConstantPressureVolumeQuad( ) :
00081 Element( 0, ELE_TAG_ConstantPressureVolumeQuad ),
00082 connectedExternalNodes(4), load(0)
00083 { 
00084   for (int i=0; i<9; i++)
00085     materialPointers[i] = 0;
00086 }
00087 
00088 
00089 //full constructor
00090 ConstantPressureVolumeQuad :: ConstantPressureVolumeQuad( 
00091                             int tag, 
00092                             int node1,
00093                             int node2,
00094                             int node3,
00095                             int node4,
00096                             NDMaterial &theMaterial ) :
00097 Element( tag, ELE_TAG_ConstantPressureVolumeQuad ),
00098 connectedExternalNodes(4), load(0)
00099 {
00100   connectedExternalNodes(0) = node1 ;
00101   connectedExternalNodes(1) = node2 ;
00102   connectedExternalNodes(2) = node3 ;
00103   connectedExternalNodes(3) = node4 ;
00104 
00105   int i ;
00106   for ( i = 0 ;  i < 4; i++ ) {
00107 
00108       materialPointers[i] = theMaterial.getCopy("AxiSymmetric2D") ;
00109 
00110       if (materialPointers[i] == 0) {
00111         opserr << "ConstantPressureVolumeQuad::constructor - failed to get a material of type: AxiSymmetric2D\n";
00112         exit(-1);
00113       } //end if
00114       
00115   } //end for i 
00116 
00117 }
00118 
00119 
00120 //destructor 
00121 ConstantPressureVolumeQuad :: ~ConstantPressureVolumeQuad( )
00122 {
00123   int i ;
00124   for ( i = 0 ;  i < 4; i++ ) {
00125 
00126     delete materialPointers[i] ;
00127     materialPointers[i] = 0 ; 
00128 
00129     nodePointers[i] = 0 ;
00130   } //end for i
00131 
00132   if (load != 0)
00133     delete load;
00134 }
00135 
00136 
00137 //set domain
00138 void ConstantPressureVolumeQuad :: setDomain( Domain *theDomain ) 
00139 {  
00140   int i ;
00141   for ( i = 0;  i < 4; i++ ) {
00142 
00143      nodePointers[i] = theDomain->getNode( connectedExternalNodes(i)  ) ;
00144 
00145      if ( nodePointers[i] != 0 ) {
00146          const Vector &coor = nodePointers[i]->getCrds( ) ;
00147 
00148          xl[0][i] = coor(0) ;
00149          xl[1][i] = coor(1) ; 
00150      } // end if 
00151 
00152   } //end for i 
00153   
00154   this->DomainComponent::setDomain(theDomain);
00155 }
00156 
00157 
00158 //get the number of external nodes
00159 int ConstantPressureVolumeQuad :: getNumExternalNodes( ) const
00160 {
00161   return 4 ;
00162 } 
00163 
00164 
00165 //return connected external nodes
00166 const ID& ConstantPressureVolumeQuad :: getExternalNodes( ) 
00167 {
00168   return connectedExternalNodes ;
00169 } 
00170 
00171 
00172 Node **
00173 ConstantPressureVolumeQuad::getNodePtrs(void) 
00174 {
00175   return nodePointers;
00176 } 
00177 
00178 
00179 //return number of dofs
00180 int ConstantPressureVolumeQuad :: getNumDOF( ) 
00181 {
00182   return 8 ;
00183 }
00184 
00185 
00186 //commit state
00187 int ConstantPressureVolumeQuad :: commitState( )
00188 {
00189   int success = 0 ;
00190 
00191   // call element commitState to do any base class stuff
00192   if ((success = this->Element::commitState()) != 0) {
00193     opserr << "ConstantPressureVolumeQuad::commitState () - failed in base class";
00194   }    
00195 
00196   for (int i = 0; i < 4; i++ ) 
00197     success += materialPointers[i]->commitState( ) ;
00198   
00199   return success ;
00200 }
00201  
00202 
00203 
00204 //revert to last commit 
00205 int ConstantPressureVolumeQuad :: revertToLastCommit( ) 
00206 {
00207   int i ;
00208   int success = 0 ;
00209 
00210   for ( i = 0; i < 4; i++ ) 
00211     success += materialPointers[i]->revertToLastCommit( ) ;
00212   
00213   return success ;
00214 }
00215     
00216 
00217 //revert to start 
00218 int ConstantPressureVolumeQuad :: revertToStart( ) 
00219 {
00220   int i ;
00221   int success = 0 ;
00222 
00223   for ( i = 0; i < 4; i++ ) 
00224     success += materialPointers[i]->revertToStart( ) ;
00225   
00226   return success ;
00227 }
00228 
00229 int 
00230 ConstantPressureVolumeQuad :: update( ) 
00231 {
00232   // strains ordered  00, 11, 22, 01  
00233   //            i.e.  11, 22, 33, 12 
00234   //
00235   //            strain(0) =   eps_00
00236   //            strain(1) =   eps_11
00237   //            strain(2) =   eps_22
00238   //            strain(3) = 2*eps_01
00239   //
00240   //  same ordering for stresses but no 2 
00241 
00242   int i,  k, l;
00243   int node ;
00244   int success = 0;
00245   
00246   static double tmp_shp[3][4] ; //shape functions
00247 
00248   static double shp[3][4][4] ; //shape functions at each gauss point
00249 
00250   static double vol_avg_shp[3][4] ; // volume averaged shape functions
00251 
00252   double xsj ;  // determinant jacaobian matrix 
00253 
00254   static Matrix sx(2,2) ; // inverse jacobian matrix 
00255 
00256   double dvol[4] ; //volume elements
00257 
00258   double volume = 0.0 ; //volume of element
00259 
00260   double theta = 0.0 ; //average volume change (trace of strain) 
00261 
00262   static Vector strain(4) ; //strain in vector form 
00263 
00264   double trace = 0.0 ; //trace of the strain 
00265 
00266   static Vector one(4) ; //rank 2 identity as a vector
00267   
00268   //one vector
00269   one(0) = 1.0 ;
00270   one(1) = 1.0 ;
00271   one(2) = 1.0 ;
00272   one(3) = 0.0 ;
00273 
00274 
00275   //zero stuff
00276   volume = 0.0 ;
00277 
00278   for ( k = 0; k < 3; k++ ){
00279     for ( l = 0; l < 4; l++ ) 
00280         vol_avg_shp[k][l] = 0.0 ; 
00281   } //end for k
00282 
00283 
00284   //gauss loop to compute volume averaged shape functions
00285 
00286   for ( i = 0; i < 4; i++ ){
00287     
00288     shape2d( sg[i], tg[i], xl, tmp_shp, xsj, sx ) ;
00289 
00290     dvol[i] = wg[i] * xsj ;  // multiply by radius for axisymmetry 
00291 
00292     volume += dvol[i] ;
00293 
00294     for ( k = 0; k < 3; k++ ){
00295       for ( l = 0; l < 4; l++ ) {
00296 
00297         shp[k][l][i] = tmp_shp[k][l] ;
00298 
00299         vol_avg_shp[k][l] += tmp_shp[k][l] * dvol[i] ;
00300 
00301       } // end for l
00302     } //end for k
00303 
00304   } //end for i 
00305 
00306 
00307   //compute volume averaged shape functions
00308   for ( k = 0; k < 3; k++ ){
00309     for ( l = 0; l < 4; l++ ) 
00310         vol_avg_shp[k][l] /= volume ; 
00311   } //end for k
00312 
00313 
00314   //compute theta
00315   theta = 0.0 ;
00316   for ( i = 0; i < 4; i++ ) {
00317 
00318     strain.Zero( ) ;
00319 
00320     //node loop to compute strain
00321     for ( node = 0; node < 4; node++ ) {
00322 
00323       const Vector &ul = nodePointers[node]->getTrialDisp( ) ;
00324 
00325       strain(0) += shp[0][node][i] * ul(0) ;
00326 
00327       strain(1) += shp[1][node][i] * ul(1) ;
00328 
00329       strain(2) = 0.0 ;  // not zero for axisymmetry
00330 
00331     } // end for node
00332 
00333     trace  =  strain(0) + strain(1) + strain(2) ;
00334 
00335     theta +=  trace * dvol[i] ;
00336 
00337   } // end for i
00338   theta /= volume ;
00339 
00340 
00341   //compute strain in materials
00342   for ( i = 0; i < 4; i++ ) {
00343 
00344     strain.Zero( ) ;
00345 
00346     //node loop to compute strain
00347     for ( node = 0; node < 4; node++ ) {
00348 
00349       const Vector &ul = nodePointers[node]->getTrialDisp( ) ;
00350 
00351       strain(0) += shp[0][node][i] * ul(0) ;
00352 
00353       strain(1) += shp[1][node][i] * ul(1) ;
00354 
00355       strain(2) = 0.0 ; // not zero for axisymmetry
00356 
00357       strain(3) +=  shp[1][node][i] * ul(0)     
00358                   + shp[0][node][i] * ul(1) ; 
00359 
00360     } // end for node
00361 
00362     trace = strain(0) + strain(1) + strain(2) ;
00363 
00364     //strain -= (one3*trace)*one ;
00365     strain.addVector(1.0,  one, -one3*trace ) ;
00366 
00367     //strain += (one3*theta)*one ;
00368     strain.addVector(1.0,  one, one3*theta ) ;
00369 
00370     success += materialPointers[i]->setTrialStrain( strain ) ;
00371 
00372   } // end for i
00373 
00374   return success;
00375 }
00376 
00377 //print out element data
00378 void ConstantPressureVolumeQuad :: Print( OPS_Stream &s, int flag )
00379 {
00380   s << endln ;
00381   s << "Four Node Quad -- Mixed Pressure/Volume -- Plane Strain \n" ;
00382   s << "Element Number " << this->getTag() << endln ;
00383   s << "Node 1 : " << connectedExternalNodes(0) << endln ;
00384   s << "Node 2 : " << connectedExternalNodes(1) << endln ;
00385   s << "Node 3 : " << connectedExternalNodes(2) << endln ;
00386   s << "Node 4 : " << connectedExternalNodes(3) << endln ;
00387   s << "Material Information : \n " ;
00388 
00389   materialPointers[0]->Print( s, flag ) ;
00390 
00391   s << endln ;
00392 }
00393 
00394 //return stiffness matrix 
00395 const Matrix& ConstantPressureVolumeQuad :: getTangentStiff( ) 
00396 {
00397   int tang_flag = 1 ; //get the tangent 
00398 
00399   //do tangent and residual here
00400   formResidAndTangent( tang_flag ) ;  
00401 
00402   return stiff ;
00403 }    
00404 
00405 const Matrix& ConstantPressureVolumeQuad :: getInitialStiff( ) 
00406 {
00407   int i,  j,  k, l, p, q ;
00408   int jj, kk ;
00409   
00410   static double tmp_shp[3][4] ; //shape functions
00411 
00412   static double shp[3][4][4] ; //shape functions at each gauss point
00413 
00414   static double vol_avg_shp[3][4] ; // volume averaged shape functions
00415 
00416   double xsj ;  // determinant jacaobian matrix 
00417 
00418   static Matrix sx(2,2) ; // inverse jacobian matrix 
00419 
00420   double dvol[4] ; //volume elements
00421 
00422   double volume = 0.0 ; //volume of element
00423 
00424   double pressure = 0.0 ; //constitutive pressure  
00425 
00426   static Vector strain(4) ; //strain in vector form 
00427 
00428   // static Vector sigBar(4) ; //stress in vector form
00429   static Vector sig(4) ; //mixed stress in vector form
00430 
00431   double trace = 0.0 ; //trace of the strain 
00432 
00433   static Matrix BJtran(2,4) ; 
00434   static Matrix BK(4,2) ;
00435 
00436   static Matrix littleBJtran(2,1) ;
00437   static Matrix littleBK(1,2) ; 
00438 
00439   static Matrix stiffJK(2,2) ; //nodeJ-nodeK 2x2 stiffness
00440   static Vector residJ(2) ; //nodeJ residual 
00441   
00442   static Vector one(4) ; //rank 2 identity as a vector
00443   
00444   static Matrix Pdev(4,4) ; //deviator projector
00445 
00446   //  static Matrix dd(4,4) ;  //material tangent
00447 
00448   static Matrix ddPdev(4,4) ;
00449   static Matrix PdevDD(4,4) ;
00450 
00451   static double Pdev_dd_Pdev_data[16];
00452   static double Pdev_dd_one_data[4]; 
00453   static double one_dd_Pdev_data[4];
00454   static Matrix Pdev_dd_Pdev(Pdev_dd_Pdev_data, 4, 4);
00455   static Matrix Pdev_dd_one(Pdev_dd_one_data, 4, 1); 
00456   static Matrix one_dd_Pdev(one_dd_Pdev_data, 1,4) ;
00457 
00458   double bulk ;
00459   static Matrix BJtranD(2,4) ;
00460   static Matrix BJtranDone(2,1) ;
00461 
00462   static Matrix littleBJoneD(2,4) ;
00463   static Matrix littleBJtranBulk(2,1) ;
00464   
00465   //zero stiffness and residual 
00466   stiff.Zero();
00467 
00468   //one vector
00469   one(0) = 1.0 ;
00470   one(1) = 1.0 ;
00471   one(2) = 1.0 ;
00472   one(3) = 0.0 ;
00473 
00474   //Pdev matrix
00475   Pdev.Zero( ) ;
00476 
00477   Pdev(0,0) =  two3 ;
00478   Pdev(0,1) = -one3 ;
00479   Pdev(0,2) = -one3 ;
00480 
00481   Pdev(1,0) = -one3 ;
00482   Pdev(1,1) =  two3 ;
00483   Pdev(1,2) = -one3 ;
00484 
00485   Pdev(2,0) = -one3 ;
00486   Pdev(2,1) = -one3 ;
00487   Pdev(2,2) =  two3 ;
00488 
00489   Pdev(3,3) = 1.0 ;
00490 
00491   //zero stuff
00492   volume = 0.0 ;
00493 
00494   for ( k = 0; k < 3; k++ ){
00495     for ( l = 0; l < 4; l++ ) 
00496         vol_avg_shp[k][l] = 0.0 ; 
00497   } //end for k
00498 
00499 
00500   //gauss loop to compute volume averaged shape functions
00501 
00502   for ( i = 0; i < 4; i++ ){
00503     
00504     shape2d( sg[i], tg[i], xl, tmp_shp, xsj, sx ) ;
00505 
00506     dvol[i] = wg[i] * xsj ;  // multiply by radius for axisymmetry 
00507 
00508     volume += dvol[i] ;
00509 
00510     for ( k = 0; k < 3; k++ ){
00511       for ( l = 0; l < 4; l++ ) {
00512 
00513         shp[k][l][i] = tmp_shp[k][l] ;
00514 
00515         vol_avg_shp[k][l] += tmp_shp[k][l] * dvol[i] ;
00516 
00517       } // end for l
00518     } //end for k
00519 
00520   } //end for i 
00521 
00522 
00523   //compute volume averaged shape functions
00524   for ( k = 0; k < 3; k++ ){
00525     for ( l = 0; l < 4; l++ ) 
00526         vol_avg_shp[k][l] /= volume ; 
00527   } //end for k
00528 
00529   //residual and tangent calculations gauss loop
00530   for ( i = 0; i < 4; i++ ) {
00531 
00532     static Matrix dd(4,4);
00533 
00534     dd = materialPointers[i]->getInitialTangent( ) ;
00535 
00536     dd *= dvol[i] ;
00537     
00538     //Pdev_dd_Pdev = Pdev * dd * Pdev ;
00539     Pdev_dd_Pdev.addMatrixTripleProduct(0.0,
00540                                         Pdev,
00541                                         dd,
00542                                         1.0) ;
00543       
00544     //Pdev_dd_one  = one3 * ( Pdev * dd * oneMatrix ) ;
00545     PdevDD.addMatrixProduct(0.0, Pdev, dd, 1.0) ;
00546     Pdev_dd_one(0,0) = one3 * (PdevDD(0,0) + PdevDD(0,1) + PdevDD(0,2));
00547     Pdev_dd_one(1,0) = one3 * (PdevDD(1,0) + PdevDD(1,1) + PdevDD(1,2));
00548     Pdev_dd_one(2,0) = one3 * (PdevDD(2,0) + PdevDD(2,1) + PdevDD(2,2));
00549     Pdev_dd_one(3,0) = one3 * (PdevDD(3,0) + PdevDD(3,1) + PdevDD(3,2));
00550     
00551     //one_dd_Pdev  = one3 * ( oneTran * dd * Pdev ) ;
00552     ddPdev.addMatrixProduct(0.0, dd, Pdev, 1.0) ;
00553     one_dd_Pdev(0,0) = one3 * (ddPdev(0,0) + ddPdev(1,0) + ddPdev(2,0));
00554     one_dd_Pdev(0,1) = one3 * (ddPdev(0,1) + ddPdev(1,1) + ddPdev(2,1));
00555     one_dd_Pdev(0,2) = one3 * (ddPdev(0,2) + ddPdev(1,2) + ddPdev(2,2));
00556     one_dd_Pdev(0,3) = one3 * (ddPdev(0,3) + ddPdev(1,3) + ddPdev(2,3));
00557     
00558     bulk = one9 * ( dd(0,0) + dd(0,1) + dd(0,2)  
00559                     + dd(1,0) + dd(1,1) + dd(1,2) 
00560                     + dd(2,0) + dd(2,1) + dd(2,2) ) ;
00561     
00562     jj = 0 ;
00563     for ( j = 0; j < 4; j++ ) {
00564       
00565       double BJ00 = shp[0][j][i];
00566       double BJ11 = shp[1][j][i]; 
00567       double BJ30 = shp[1][j][i];
00568       double BJ31 = shp[0][j][i];
00569       
00570       BJtran.Zero( );
00571       BJtran(0,0) = shp[0][j][i] ;
00572       BJtran(1,1) = shp[1][j][i] ; 
00573       
00574       // BJ(2,0) for axi-symmetry 
00575       
00576       BJtran(0,3) = shp[1][j][i]  ;
00577       BJtran(1,3) = shp[0][j][i]  ;
00578       
00579       //compute residual 
00580       
00581       double ltBJ00 = vol_avg_shp[0][j] ;
00582       double ltBJ01 = vol_avg_shp[1][j] ;
00583       
00584       //BJtranD          =  BJtran * Pdev_dd_Pdev ;
00585       // BJtranD.addMatrixProduct(0.0,  BJtran, Pdev_dd_Pdev, 1.0);
00586       
00587       //littleBJoneD     =  littleBJtran * one_dd_Pdev ;
00588       // littleBJoneD.addMatrixProduct(0.0,  littleBJtran, one_dd_Pdev, 1.0);
00589       
00590       static double Adata[8];
00591       static Matrix A(Adata, 2, 4);
00592       
00593       // A = BJtranD;
00594       // A += littleBJoneD;
00595       
00596       for (int colA = 0, loc = 0, colPdev = 0; colA<4; colA++, colPdev += 4) {
00597         double data3colA = Pdev_dd_Pdev_data[3+colPdev];
00598         Adata[loc++] = BJ00*Pdev_dd_Pdev_data[colPdev] + BJ30*data3colA + ltBJ00*one_dd_Pdev_data[colA];
00599         Adata[loc++] = BJ11*Pdev_dd_Pdev_data[1+colPdev] + BJ31*data3colA + ltBJ01*one_dd_Pdev_data[colA];
00600       }
00601       
00602       //BJtranDone       =  BJtran * Pdev_dd_one ;
00603       // BJtranDone.addMatrixProduct(0.0,  BJtran, Pdev_dd_one, 1.0);
00604       
00605       //littleBJtranBulk =  bulk * littleBJtran ;
00606       // littleBJtranBulk = littleBJtran ;
00607       // littleBJtranBulk *= bulk ;
00608       
00609       double B1, B2;
00610       // B1 = BJtranDone(0,0) + littleBJtranBulk(0,0);
00611       // B2 = BJtranDone(1,0) + littleBJtranBulk(1,0);
00612       
00613       B1 = BJ00*Pdev_dd_one_data[0] + BJ30*Pdev_dd_one_data[3] + ltBJ00 *bulk;
00614       B2 = BJ11*Pdev_dd_one_data[1] + BJ31*Pdev_dd_one_data[3] + ltBJ01 *bulk;
00615       
00616       int colkk, colkkP1;
00617       for ( k = 0, kk=0, colkk =0, colkkP1 =8; 
00618             k < 4; 
00619             k++, kk += 2, colkk += 16, colkkP1 += 16 ) {
00620         
00621         double BK00 = shp[0][k][i];
00622         double BK11 = shp[1][k][i];
00623         double BK30 = shp[1][k][i];
00624         double BK31 = shp[0][k][i];
00625         
00626         double littleBK00 = vol_avg_shp[0][k];
00627         double littleBK01 = vol_avg_shp[1][k];
00628 
00629         //compute stiffness matrix
00630         
00631         stiff( jj,   kk   ) += Adata[0]*BK00 + Adata[6]*BK30 + B1 * littleBK00;
00632         stiff( jj+1, kk   ) += Adata[1]*BK00 + Adata[7]*BK30 + B2 * littleBK00;
00633         stiff( jj,   kk+1 ) += Adata[2]*BK11 + Adata[6]*BK31 + B1 * littleBK01;
00634         stiff( jj+1, kk+1 ) += Adata[3]*BK11 + Adata[7]*BK31 + B2 * littleBK01;
00635         
00636       } // end for k
00637       
00638       jj += 2 ;
00639     } // end for j 
00640   } //end for i
00641 
00642   return stiff ;
00643 }    
00644 
00645 //return mass matrix
00646 const Matrix& ConstantPressureVolumeQuad :: getMass( ) 
00647 {
00648   int tangFlag = 1 ;
00649 
00650   formInertiaTerms( tangFlag ) ;
00651   return mass ;
00652 } 
00653 
00654 
00655 
00656 void ConstantPressureVolumeQuad :: zeroLoad( )
00657 {
00658   if (load != 0)
00659     load->Zero();
00660 
00661   return ;
00662 }
00663 
00664 int 
00665 ConstantPressureVolumeQuad::addLoad(ElementalLoad *theLoad, double loadFactor)
00666 {
00667   opserr << "ConstantPressureVolumeQuad::addLoad - load type unknown for ele with tag: " << this->getTag() << endln;
00668   return -1;
00669 }
00670 
00671 int
00672 ConstantPressureVolumeQuad::addInertiaLoadToUnbalance(const Vector &accel)
00673 {
00674   static const int numberGauss = 9 ;
00675   static const int numberNodes = 9 ;
00676   static const int ndf = 2 ; 
00677 
00678   int i;
00679 
00680   // check to see if have mass
00681   int haveRho = 0;
00682   for (i = 0; i < numberGauss; i++) {
00683     if (materialPointers[i]->getRho() != 0.0)
00684       haveRho = 1;
00685   }
00686 
00687   if (haveRho == 0)
00688     return 0;
00689 
00690   // Compute mass matrix
00691   int tangFlag = 1 ;
00692   formInertiaTerms( tangFlag ) ;
00693 
00694   // store computed RV fro nodes in resid vector
00695   int count = 0;
00696 
00697   for (i=0; i<numberNodes; i++) {
00698     const Vector &Raccel = nodePointers[i]->getRV(accel);
00699     for (int j=0; j<ndf; j++)
00700       resid(count++) = Raccel(i);
00701   }
00702 
00703   // create the load vector if one does not exist
00704   if (load == 0) 
00705     load = new Vector(numberNodes*ndf);
00706 
00707   // add -M * RV(accel) to the load vector
00708   load->addMatrixVector(1.0, mass, resid, -1.0);
00709   
00710   return 0;
00711 }
00712 
00713 
00714 //get residual
00715 const Vector& ConstantPressureVolumeQuad :: getResistingForce( ) 
00716 {
00717   int tang_flag = 0 ; //don't get the tangent
00718 
00719   formResidAndTangent( tang_flag ) ;
00720 
00721   // subtract external loads 
00722   if (load != 0)
00723     resid -= *load;
00724 
00725   return resid ;   
00726 }
00727 
00728 
00729 //get residual with inertia terms
00730 const Vector& ConstantPressureVolumeQuad :: getResistingForceIncInertia( )
00731 {
00732   int tang_flag = 0 ; //don't get the tangent
00733 
00734   static Vector res(8);
00735 
00736   //do tangent and residual here 
00737   formResidAndTangent( tang_flag ) ;
00738 
00739   //inertia terms
00740   formInertiaTerms( tang_flag ) ;
00741   res = resid;
00742 
00743   // subtract external loads 
00744   if (load != 0)
00745     res -= *load;
00746 
00747   // add the damping forces if rayleigh damping
00748   if (alphaM != 0.0 || betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00749     res += this->getRayleighDampingForces();
00750 
00751   return res ;
00752 }
00753 
00754 //*****************************************************************************
00755 //form inertia terms
00756 
00757 void   ConstantPressureVolumeQuad::formInertiaTerms( int tangFlag ) 
00758 {
00759 
00760   static const int ndm = 2 ;
00761 
00762   static const int ndf = 2 ; 
00763 
00764   static const int numberNodes = 4 ;
00765 
00766   static const int numberGauss = 4 ;
00767 
00768   static const int nShape = 3 ;
00769 
00770   static const int massIndex = nShape - 1 ;
00771 
00772   double xsj ;  // determinant jacaobian matrix 
00773 
00774   double dvol ; //volume element
00775 
00776   static double shp[nShape][numberNodes] ;  //shape functions at a gauss point
00777 
00778   static Vector momentum(ndf) ;
00779 
00780   static Matrix sx(ndm,ndm) ;
00781 
00782   int i, j, k, p ;
00783   int jj, kk ;
00784 
00785   double temp, rho, massJK ;
00786 
00787 
00788   //zero mass 
00789   mass.Zero( ) ;
00790 
00791   //gauss loop 
00792   for ( i = 0; i < numberGauss; i++ ) {
00793 
00794     //get shape functions    
00795     shape2d( sg[i], tg[i], xl, shp, xsj, sx ) ;
00796     
00797     //volume element
00798     dvol = wg[i] * xsj ;
00799 
00800     //node loop to compute acceleration
00801     momentum.Zero( ) ;
00802     for ( j = 0; j < numberNodes; j++ ) 
00803       //momentum += shp[massIndex][j] * ( nodePointers[j]->getTrialAccel()  ) ; 
00804       momentum.addVector( 1.0,
00805                           nodePointers[j]->getTrialAccel(),
00806                           shp[massIndex][j] ) ;
00807 
00808     //density
00809     rho = materialPointers[i]->getRho() ;
00810 
00811     //multiply acceleration by density to form momentum
00812     momentum *= rho ;
00813 
00814 
00815     //residual and tangent calculations node loops
00816     jj = 0 ;
00817     for ( j = 0; j < numberNodes; j++ ) {
00818 
00819       temp = shp[massIndex][j] * dvol ;
00820 
00821       if ( tangFlag == 1 ) {
00822 
00823          //multiply by density
00824          temp *= rho ;
00825 
00826          //node-node mass
00827          kk = 0 ;
00828          for ( k = 0; k < numberNodes; k++ ) {
00829 
00830             massJK = temp * shp[massIndex][k] ;
00831 
00832             for ( p = 0; p < ndf; p++ )  
00833               mass( jj+p, kk+p ) += massJK ;
00834             
00835             kk += ndf ;
00836           } // end for k loop
00837 
00838       } // end if tang_flag 
00839 
00840       else
00841         for ( p = 0; p < ndf; p++ )
00842           resid( jj+p ) += ( temp * momentum(p) )  ;
00843 
00844       jj += ndf ;
00845 
00846     } // end for j loop
00847 
00848 
00849   } //end for i gauss loop 
00850 
00851 
00852 
00853 }
00854 
00855 //*********************************************************************
00856 
00857 //form residual and tangent
00858 void ConstantPressureVolumeQuad ::  formResidAndTangent( int tang_flag ) 
00859 {
00860   // strains ordered  00, 11, 22, 01  
00861   //            i.e.  11, 22, 33, 12 
00862   //
00863   //            strain(0) =   eps_00
00864   //            strain(1) =   eps_11
00865   //            strain(2) =   eps_22
00866   //            strain(3) = 2*eps_01
00867   //
00868   //  same ordering for stresses but no 2 
00869 
00870   int i,  j,  k, l, p, q ;
00871   int jj, kk ;
00872   
00873   static double tmp_shp[3][4] ; //shape functions
00874 
00875   static double shp[3][4][4] ; //shape functions at each gauss point
00876 
00877   static double vol_avg_shp[3][4] ; // volume averaged shape functions
00878 
00879   double xsj ;  // determinant jacaobian matrix 
00880 
00881   static Matrix sx(2,2) ; // inverse jacobian matrix 
00882 
00883   double dvol[4] ; //volume elements
00884 
00885   double volume = 0.0 ; //volume of element
00886 
00887   double pressure = 0.0 ; //constitutive pressure  
00888 
00889   static Vector strain(4) ; //strain in vector form 
00890 
00891   // static Vector sigBar(4) ; //stress in vector form
00892   static Vector sig(4) ; //mixed stress in vector form
00893 
00894   double trace = 0.0 ; //trace of the strain 
00895 
00896   static Matrix BJtran(2,4) ; 
00897   static Matrix BK(4,2) ;
00898 
00899   static Matrix littleBJtran(2,1) ;
00900   static Matrix littleBK(1,2) ; 
00901 
00902   static Matrix stiffJK(2,2) ; //nodeJ-nodeK 2x2 stiffness
00903   static Vector residJ(2) ; //nodeJ residual 
00904   
00905   static Vector one(4) ; //rank 2 identity as a vector
00906   
00907   static Matrix Pdev(4,4) ; //deviator projector
00908 
00909   //  static Matrix dd(4,4) ;  //material tangent
00910 
00911   static Matrix ddPdev(4,4) ;
00912   static Matrix PdevDD(4,4) ;
00913 
00914   static double Pdev_dd_Pdev_data[16];
00915   static double Pdev_dd_one_data[4]; 
00916   static double one_dd_Pdev_data[4];
00917   static Matrix Pdev_dd_Pdev(Pdev_dd_Pdev_data, 4, 4);
00918   static Matrix Pdev_dd_one(Pdev_dd_one_data, 4, 1); 
00919   static Matrix one_dd_Pdev(one_dd_Pdev_data, 1,4) ;
00920 
00921   double bulk ;
00922   static Matrix BJtranD(2,4) ;
00923   static Matrix BJtranDone(2,1) ;
00924 
00925   static Matrix littleBJoneD(2,4) ;
00926   static Matrix littleBJtranBulk(2,1) ;
00927   
00928   //zero stiffness and residual 
00929   if ( tang_flag == 1 ) 
00930     stiff.Zero();
00931   else
00932     resid.Zero();
00933 
00934   //one vector
00935   one(0) = 1.0 ;
00936   one(1) = 1.0 ;
00937   one(2) = 1.0 ;
00938   one(3) = 0.0 ;
00939 
00940   //Pdev matrix
00941   Pdev.Zero( ) ;
00942 
00943   Pdev(0,0) =  two3 ;
00944   Pdev(0,1) = -one3 ;
00945   Pdev(0,2) = -one3 ;
00946 
00947   Pdev(1,0) = -one3 ;
00948   Pdev(1,1) =  two3 ;
00949   Pdev(1,2) = -one3 ;
00950 
00951   Pdev(2,0) = -one3 ;
00952   Pdev(2,1) = -one3 ;
00953   Pdev(2,2) =  two3 ;
00954 
00955   Pdev(3,3) = 1.0 ;
00956 
00957   //zero stuff
00958   volume = 0.0 ;
00959 
00960   for ( k = 0; k < 3; k++ ){
00961     for ( l = 0; l < 4; l++ ) 
00962         vol_avg_shp[k][l] = 0.0 ; 
00963   } //end for k
00964 
00965 
00966   //gauss loop to compute volume averaged shape functions
00967 
00968   for ( i = 0; i < 4; i++ ){
00969     
00970     shape2d( sg[i], tg[i], xl, tmp_shp, xsj, sx ) ;
00971 
00972     dvol[i] = wg[i] * xsj ;  // multiply by radius for axisymmetry 
00973 
00974     volume += dvol[i] ;
00975 
00976     for ( k = 0; k < 3; k++ ){
00977       for ( l = 0; l < 4; l++ ) {
00978 
00979         shp[k][l][i] = tmp_shp[k][l] ;
00980 
00981         vol_avg_shp[k][l] += tmp_shp[k][l] * dvol[i] ;
00982 
00983       } // end for l
00984     } //end for k
00985 
00986   } //end for i 
00987 
00988 
00989   //compute volume averaged shape functions
00990   for ( k = 0; k < 3; k++ ){
00991     for ( l = 0; l < 4; l++ ) 
00992         vol_avg_shp[k][l] /= volume ; 
00993   } //end for k
00994 
00995   //compute pressure if residual calculation
00996   if (tang_flag != 1) {
00997     pressure = 0.0 ;
00998     for ( i = 0; i < 4; i++ ) {
00999 
01000       const Vector &sigBar = materialPointers[i]->getStress( ) ;
01001 
01002       pressure +=  one3 * ( sigBar(0) + sigBar(1) + sigBar(2) ) * dvol[i] ;
01003       
01004     } // end for i
01005 
01006     pressure /= volume ;
01007   } // end if != tang_flag
01008 
01009   //residual and tangent calculations gauss loop
01010   
01011   for ( i = 0; i < 4; i++ ) {
01012 
01013     if ( tang_flag == 1 ) {    // compute matrices for stiffness calculation
01014       
01015       static Matrix dd(4,4);
01016       dd = materialPointers[i]->getTangent( ) ;
01017       
01018       dd *= dvol[i] ;
01019       
01020       //Pdev_dd_Pdev = Pdev * dd * Pdev ;
01021       Pdev_dd_Pdev.addMatrixTripleProduct(0.0,
01022                                           Pdev,
01023                                           dd,
01024                                           1.0) ;
01025       
01026       //Pdev_dd_one  = one3 * ( Pdev * dd * oneMatrix ) ;
01027       PdevDD.addMatrixProduct(0.0, Pdev, dd, 1.0) ;
01028       Pdev_dd_one(0,0) = one3 * (PdevDD(0,0) + PdevDD(0,1) + PdevDD(0,2));
01029       Pdev_dd_one(1,0) = one3 * (PdevDD(1,0) + PdevDD(1,1) + PdevDD(1,2));
01030       Pdev_dd_one(2,0) = one3 * (PdevDD(2,0) + PdevDD(2,1) + PdevDD(2,2));
01031       Pdev_dd_one(3,0) = one3 * (PdevDD(3,0) + PdevDD(3,1) + PdevDD(3,2));
01032       
01033       //one_dd_Pdev  = one3 * ( oneTran * dd * Pdev ) ;
01034       ddPdev.addMatrixProduct(0.0, dd, Pdev, 1.0) ;
01035       one_dd_Pdev(0,0) = one3 * (ddPdev(0,0) + ddPdev(1,0) + ddPdev(2,0));
01036       one_dd_Pdev(0,1) = one3 * (ddPdev(0,1) + ddPdev(1,1) + ddPdev(2,1));
01037       one_dd_Pdev(0,2) = one3 * (ddPdev(0,2) + ddPdev(1,2) + ddPdev(2,2));
01038       one_dd_Pdev(0,3) = one3 * (ddPdev(0,3) + ddPdev(1,3) + ddPdev(2,3));
01039       
01040       bulk = one9 * ( dd(0,0) + dd(0,1) + dd(0,2)  
01041                       + dd(1,0) + dd(1,1) + dd(1,2) 
01042                       + dd(2,0) + dd(2,1) + dd(2,2) ) ;
01043       
01044     } else { // compute stress for residual calculation
01045       //stress for equilibrium
01046       const Vector &sigBar = materialPointers[i]->getStress( ) ; 
01047       trace = sigBar(0) + sigBar(1) + sigBar(2) ;
01048       sig  = sigBar ;
01049 
01050       //sig -= (one3*trace)*one ;
01051       sig.addVector(1.0,  one, -one3*trace ) ;
01052       sig.addVector(1.0,  one, pressure ) ;
01053       
01054       //multilply by volume elements and compute 
01055       sig *= dvol[i] ;
01056     }
01057         
01058     //residual and tangent loop over nodes
01059     jj = 0 ;
01060     for ( j = 0; j < 4; j++ ) {
01061 
01062       /********** expanding for efficiency the matrix operations that use these
01063       BJ.Zero( );
01064       BJ(0,0) = shp[0][j][i] ;
01065       BJ(1,1) = shp[1][j][i] ; 
01066 
01067       // BJ(2,0) for axi-symmetry 
01068 
01069       BJ(3,0) = shp[1][j][i]  ;
01070       BJ(3,1) = shp[0][j][i]  ;
01071 
01072       littleBJ(0,0) = vol_avg_shp[0][j] ;
01073       littleBJ(0,1) = vol_avg_shp[1][j] ;
01074 
01075       // BJtran = this->transpose( 4, 2, BJ ) ;
01076       for (p=0; p<2; p++) {
01077         for (q=0; q<4; q++) 
01078           BJtran(p,q) = BJ(q,p) ;
01079       }//end for p
01080 
01081       for (p=0; p<2; p++) {
01082         for (q=0; q<1; q++) 
01083           littleBJtran(p,q) = littleBJ(q,p) ;
01084       }//end for p
01085 
01086       **********************************************************************/
01087 
01088 
01089       double BJ00 = shp[0][j][i];
01090       double BJ11 = shp[1][j][i]; 
01091       double BJ30 = shp[1][j][i];
01092       double BJ31 = shp[0][j][i];
01093 
01094       BJtran.Zero( );
01095       BJtran(0,0) = shp[0][j][i] ;
01096       BJtran(1,1) = shp[1][j][i] ; 
01097 
01098       // BJ(2,0) for axi-symmetry 
01099 
01100       BJtran(0,3) = shp[1][j][i]  ;
01101       BJtran(1,3) = shp[0][j][i]  ;
01102 
01103       //compute residual 
01104 
01105       if ( tang_flag == 1 ) { //stiffness matrix
01106 
01107         double ltBJ00 = vol_avg_shp[0][j] ;
01108         double ltBJ01 = vol_avg_shp[1][j] ;
01109 
01110         //BJtranD          =  BJtran * Pdev_dd_Pdev ;
01111         // BJtranD.addMatrixProduct(0.0,  BJtran, Pdev_dd_Pdev, 1.0);
01112 
01113         //littleBJoneD     =  littleBJtran * one_dd_Pdev ;
01114         // littleBJoneD.addMatrixProduct(0.0,  littleBJtran, one_dd_Pdev, 1.0);
01115 
01116         static double Adata[8];
01117         static Matrix A(Adata, 2, 4);
01118 
01119         // A = BJtranD;
01120         // A += littleBJoneD;
01121 
01122         for (int colA = 0, loc = 0, colPdev = 0; colA<4; colA++, colPdev += 4) {
01123           double data3colA = Pdev_dd_Pdev_data[3+colPdev];
01124           Adata[loc++] = BJ00*Pdev_dd_Pdev_data[colPdev] + BJ30*data3colA + ltBJ00*one_dd_Pdev_data[colA];
01125           Adata[loc++] = BJ11*Pdev_dd_Pdev_data[1+colPdev] + BJ31*data3colA + ltBJ01*one_dd_Pdev_data[colA];
01126         }
01127 
01128         //BJtranDone       =  BJtran * Pdev_dd_one ;
01129         // BJtranDone.addMatrixProduct(0.0,  BJtran, Pdev_dd_one, 1.0);
01130 
01131         //littleBJtranBulk =  bulk * littleBJtran ;
01132         // littleBJtranBulk = littleBJtran ;
01133         // littleBJtranBulk *= bulk ;
01134 
01135         double B1, B2;
01136         // B1 = BJtranDone(0,0) + littleBJtranBulk(0,0);
01137         // B2 = BJtranDone(1,0) + littleBJtranBulk(1,0);
01138 
01139         B1 = BJ00*Pdev_dd_one_data[0] + BJ30*Pdev_dd_one_data[3] + ltBJ00 *bulk;
01140         B2 = BJ11*Pdev_dd_one_data[1] + BJ31*Pdev_dd_one_data[3] + ltBJ01 *bulk;
01141 
01142         int colkk, colkkP1;
01143         for ( k = 0, kk=0, colkk =0, colkkP1 =8; 
01144               k < 4; 
01145               k++, kk += 2, colkk += 16, colkkP1 += 16 ) {
01146 
01147           /**************************************************************
01148            REPLACING THESE LINES WITH THE 4 BELOW COMMENT FOR EFFICIENCY
01149            BK.Zero( );
01150            BK(0,0) = shp[0][k][i];
01151            BK(1,1) = shp[1][k][i];
01152            
01153            // BK(2,0) for axi-symmetry 
01154            
01155            BK(3,0) = shp[1][k][i];
01156            BK(3,1) = shp[0][k][i];
01157           **************************************************************/
01158 
01159           double BK00 = shp[0][k][i];
01160           double BK11 = shp[1][k][i];
01161           double BK30 = shp[1][k][i];
01162           double BK31 = shp[0][k][i];
01163 
01164           double littleBK00 = vol_avg_shp[0][k];
01165           double littleBK01 = vol_avg_shp[1][k];
01166 
01167           //compute stiffness matrix
01168         
01169           // stiffJK =  ( BJtranD + littleBJoneD ) * BK
01170           //        +  ( BJtranDone + littleBJtranBulk ) * littleBK ; 
01171 
01172           /**************************************************************
01173             REPLACING THESE LINES WITH THE 4 BELOW COMMENT FOR EFFICIENCY
01174           //stiffJK.addMatrixProduct(0.0, A, BK, 1.0);
01175 
01176           //stiff( jj,   kk   ) += stiffJK(0,0) + B1 * littleBK00;
01177           //stiff( jj+1, kk   ) += stiffJK(1,0) + B2 * littleBK00;
01178           //stiff( jj,   kk+1 ) += stiffJK(0,1) + B1 * littleBK01;
01179           //stiff( jj+1, kk+1 ) += stiffJK(1,1) + B2 * littleBK01;        
01180           ***************************************************************/
01181 
01182           // matrixData[  colkk +   jj] += Adata[0]*BK00 + Adata[6]*BK30 + B1 * littleBK00;
01183           // matrixData[  colkk + jj+1] += Adata[1]*BK00 + Adata[7]*BK30 + B2 * littleBK00;
01184           // matrixData[colkkP1 +   jj] += Adata[2]*BK11 + Adata[6]*BK31 + B1 * littleBK01;
01185           // matrixData[colkkP1 + jj+1] += Adata[3]*BK11 + Adata[7]*BK31 + B2 * littleBK01;
01186           stiff( jj,   kk   ) += Adata[0]*BK00 + Adata[6]*BK30 + B1 * littleBK00;
01187           stiff( jj+1, kk   ) += Adata[1]*BK00 + Adata[7]*BK30 + B2 * littleBK00;
01188           stiff( jj,   kk+1 ) += Adata[2]*BK11 + Adata[6]*BK31 + B1 * littleBK01;
01189           stiff( jj+1, kk+1 ) += Adata[3]*BK11 + Adata[7]*BK31 + B2 * littleBK01;
01190 
01191         } // end for k
01192 
01193       } else { // residual calculation
01194         
01195         //residJ = BJtran * sig; 
01196         residJ.addMatrixVector(0.0,  BJtran, sig, 1.0);
01197         resid( jj   ) += residJ(0);
01198         resid( jj+1 ) += residJ(1);
01199       }
01200       
01201       jj += 2 ;
01202     } // end for j 
01203 
01204   } //end for i
01205 
01206   
01207   return ;
01208 }
01209 
01210 
01211 //shape function routine for four node quads
01212 void ConstantPressureVolumeQuad :: shape2d( double ss, double tt, 
01213                                             const double x[2][4], 
01214                                             double shp[3][4], 
01215                                             double &xsj, 
01216                                             Matrix &sx ) 
01217 { 
01218 
01219   int i, j, k ;
01220 
01221   double temp ;
01222      
01223   static const double s[] = { -0.5,  0.5, 0.5, -0.5 } ;
01224   static const double t[] = { -0.5, -0.5, 0.5,  0.5 } ;
01225 
01226   static double xs[2][2];
01227 
01228   //  static Matrix xs(2,2) ;
01229 
01230   for ( i = 0; i < 4; i++ ) {
01231       shp[2][i] = ( 0.5 + s[i]*ss )*( 0.5 + t[i]*tt ) ;
01232       shp[0][i] = s[i] * ( 0.5 + t[i]*tt ) ;
01233       shp[1][i] = t[i] * ( 0.5 + s[i]*ss ) ;
01234   } // end for i
01235 
01236   
01237   // Construct jacobian and its inverse
01238   
01239   for ( i = 0; i < 2; i++ ) {
01240     for ( j = 0; j < 2; j++ ) {
01241 
01242       double value = 0;
01243       for ( k = 0; k < 4; k++ )
01244         value +=  x[i][k] * shp[j][k] ;
01245       // xs(i,j) +=  x[i][k] * shp[j][k] ;
01246       xs[i][j] = value;
01247       
01248     } //end for j
01249   }  // end for i 
01250 
01251   xsj = xs[0][0]*xs[1][1] - xs[0][1]*xs[1][0] ;
01252 
01253   sx(0,0) =  xs[1][1] / xsj ;
01254   sx(1,1) =  xs[0][0] / xsj ;
01255   sx(0,1) = -xs[0][1] / xsj ; 
01256   sx(1,0) = -xs[1][0] / xsj ; 
01257 
01258   //form global derivatives 
01259   
01260   for ( i = 0; i < 4; i++ ) {
01261     temp      = shp[0][i]*sx(0,0) + shp[1][i]*sx(1,0) ;
01262     shp[1][i] = shp[0][i]*sx(0,1) + shp[1][i]*sx(1,1) ;
01263     shp[0][i] = temp ;
01264   } // end for i
01265 
01266   return ;
01267 }
01268         
01269 //***********************************************************************
01270 
01271 int
01272 ConstantPressureVolumeQuad::displaySelf(Renderer &theViewer, int displayMode, float fact)
01273 {
01274     // first determine the end points of the quad based on
01275     // the display factor (a measure of the distorted image)
01276     // store this information in 4 3d vectors v1 through v4
01277     const Vector &end1Crd = nodePointers[0]->getCrds();
01278     const Vector &end2Crd = nodePointers[1]->getCrds(); 
01279     const Vector &end3Crd = nodePointers[2]->getCrds(); 
01280     const Vector &end4Crd = nodePointers[3]->getCrds(); 
01281 
01282     static Matrix coords(4,3) ;
01283     static Vector values(4) ;
01284 
01285     coords.Zero( ) ;
01286 
01287     values(0) = 1 ;
01288     values(1) = 1 ;
01289     values(2) = 1 ;
01290     values(3) = 1 ;
01291 
01292 
01293     if (displayMode >= 0) {    
01294       
01295       const Vector &end1Disp = nodePointers[0]->getDisp();
01296       const Vector &end2Disp = nodePointers[1]->getDisp();
01297       const Vector &end3Disp = nodePointers[2]->getDisp();
01298       const Vector &end4Disp = nodePointers[3]->getDisp();
01299 
01300       for (int i = 0; i < 2; i++) {
01301         coords(0,i) = end1Crd(i) + end1Disp(i)*fact;
01302         coords(1,i) = end2Crd(i) + end2Disp(i)*fact;    
01303         coords(2,i) = end3Crd(i) + end3Disp(i)*fact;    
01304         coords(3,i) = end4Crd(i) + end4Disp(i)*fact;    
01305       }
01306     } else {
01307       int mode = displayMode  *  -1;
01308       const Matrix &eigen1 = nodePointers[0]->getEigenvectors();
01309       const Matrix &eigen2 = nodePointers[1]->getEigenvectors();
01310       const Matrix &eigen3 = nodePointers[2]->getEigenvectors();
01311       const Matrix &eigen4 = nodePointers[3]->getEigenvectors();
01312       if (eigen1.noCols() >= mode) {
01313         for (int i = 0; i < 2; i++) {
01314           coords(0,i) = end1Crd(i) + eigen1(i,mode-1)*fact;
01315           coords(1,i) = end2Crd(i) + eigen2(i,mode-1)*fact;
01316           coords(2,i) = end3Crd(i) + eigen3(i,mode-1)*fact;
01317           coords(3,i) = end4Crd(i) + eigen4(i,mode-1)*fact;
01318         }    
01319       } else {
01320         for (int i = 0; i < 2; i++) {
01321           coords(0,i) = end1Crd(i);
01322           coords(1,i) = end2Crd(i);
01323           coords(2,i) = end3Crd(i);
01324           coords(3,i) = end4Crd(i);
01325         }    
01326       }
01327     }
01328 
01329     //opserr << coords;
01330     int error = 0;
01331 
01332     error += theViewer.drawPolygon (coords, values);
01333 
01334     return error;
01335 }
01336 
01337 
01338 Response*
01339 ConstantPressureVolumeQuad::setResponse(const char **argv, int argc, 
01340                                         Information &eleInfo, OPS_Stream &output)
01341 {
01342   Response *theResponse =0;
01343 
01344   output.tag("ElementOutput");
01345   output.attr("eleType","ConstantPressureVolumeQuad");
01346   output.attr("eleTag",this->getTag());
01347   output.attr("node1",connectedExternalNodes[0]);
01348   output.attr("node2",connectedExternalNodes[1]);
01349   output.attr("node3",connectedExternalNodes[2]);
01350   output.attr("node4",connectedExternalNodes[3]);
01351 
01352   char dataOut[10];
01353   if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0) {
01354     
01355     for (int i=1; i<=4; i++) {
01356       sprintf(dataOut,"P1_%d",i);
01357       output.tag("ResponseType",dataOut);
01358       sprintf(dataOut,"P2_%d",i);
01359       output.tag("ResponseType",dataOut);
01360     }
01361     
01362     theResponse =  new ElementResponse(this, 1, resid);
01363   }   else if (strcmp(argv[0],"material") == 0 || strcmp(argv[0],"integrPoint") == 0) {
01364     int pointNum = atoi(argv[1]);
01365     if (pointNum > 0 && pointNum <= 4) {
01366 
01367       output.tag("GaussPoint");
01368       output.attr("number",pointNum);
01369       output.attr("eta",sg[pointNum-1]);
01370       output.attr("neta",tg[pointNum-1]);
01371 
01372       theResponse =  materialPointers[pointNum-1]->setResponse(&argv[2], argc-2, eleInfo, output);
01373       
01374       output.endTag();
01375 
01376   } else if (strcmp(argv[0],"stresses") ==0) {
01377 
01378       for (int i=0; i<4; i++) {
01379         output.tag("GaussPoint");
01380         output.attr("number",i+1);
01381         output.attr("eta",sg[i]);
01382         output.attr("neta",tg[i]);
01383 
01384         output.tag("NdMaterialOutput");
01385         output.attr("classType", materialPointers[i]->getClassTag());
01386         output.attr("tag", materialPointers[i]->getTag());
01387 
01388         output.tag("ResponseType","UnknownStress");
01389         output.tag("ResponseType","UnknownStress");
01390         output.tag("ResponseType","UnknownStress");
01391         output.tag("ResponseType","UnknownStress");
01392 
01393         output.endTag(); // GaussPoint
01394         output.endTag(); // NdMaterialOutput
01395       }
01396 
01397       theResponse =  new ElementResponse(this, 3, Vector(16));
01398     }
01399   }
01400         
01401   output.endTag(); // ElementOutput
01402 
01403   return theResponse;
01404 }
01405 
01406 int 
01407 ConstantPressureVolumeQuad::getResponse(int responseID, Information &eleInfo)
01408 {
01409   if (responseID == 1) {
01410 
01411     return eleInfo.setVector(this->getResistingForce());
01412 
01413   } else if (responseID == 3) {
01414 
01415     // Loop over the integration points
01416     static Vector stresses(16);
01417     int cnt = 0;
01418     for (int i = 0; i < 4; i++) {
01419 
01420       // Get material stress response
01421       const Vector &sigma = materialPointers[i]->getStress();
01422       stresses(cnt) = sigma(0);
01423       stresses(cnt+1) = sigma(1);
01424       stresses(cnt+2) = sigma(2);
01425       stresses(cnt+3) = sigma(2);
01426       cnt += 4;
01427     }
01428     return eleInfo.setVector(stresses);
01429         
01430   } else
01431 
01432     return -1;
01433 }
01434    
01435 //-----------------------------------------------------------------------
01436 
01437 int ConstantPressureVolumeQuad :: sendSelf (int commitTag, Channel &theChannel)
01438 {
01439   int res = 0;
01440   
01441   // note: we don't check for dataTag == 0 for Element
01442   // objects as that is taken care of in a commit by the Domain
01443   // object - don't want to have to do the check if sending data
01444   int dataTag = this->getDbTag();
01445   
01446 
01447   // Now quad sends the ids of its materials
01448   int matDbTag;
01449   
01450   static ID idData(13);
01451   
01452   int i;
01453   for (i = 0; i < 4; i++) {
01454     idData(i) = materialPointers[i]->getClassTag();
01455     matDbTag = materialPointers[i]->getDbTag();
01456     // NOTE: we do have to ensure that the material has a database
01457     // tag if we are sending to a database channel.
01458     if (matDbTag == 0) {
01459       matDbTag = theChannel.getDbTag();
01460                         if (matDbTag != 0)
01461                           materialPointers[i]->setDbTag(matDbTag);
01462     }
01463     idData(i+4) = matDbTag;
01464   }
01465   
01466   idData(8) = this->getTag();
01467   idData(9) = connectedExternalNodes(0);
01468   idData(10) = connectedExternalNodes(1);
01469   idData(11) = connectedExternalNodes(2);
01470   idData(12) = connectedExternalNodes(3);
01471 
01472   res += theChannel.sendID(dataTag, commitTag, idData);
01473   if (res < 0) {
01474     opserr << "WARNING ConstantPressureVolumeQuad::sendSelf() - " << this->getTag() << " failed to send ID\n"; 
01475                             
01476     return res;
01477   }
01478 
01479   // Finally, quad asks its material objects to send themselves
01480   for (i = 0; i < 4; i++) {
01481     res += materialPointers[i]->sendSelf(commitTag, theChannel);
01482     if (res < 0) {
01483       opserr << "WARNING ConstantPressureVolumeQuad::sendSelf() - " << this->getTag() << "failed to send its Material\n";
01484       return res;
01485     }
01486   }
01487   return res;
01488 }
01489     
01490 int 
01491 ConstantPressureVolumeQuad :: recvSelf (int commitTag, 
01492                                         Channel &theChannel, 
01493                                         FEM_ObjectBroker &theBroker)
01494 {
01495   int res = 0;
01496   
01497   int dataTag = this->getDbTag();
01498 
01499   static ID idData(13);
01500   // Quad now receives the tags of its four external nodes
01501   res += theChannel.recvID(dataTag, commitTag, idData);
01502   if (res < 0) {
01503     opserr << "WARNING ConstantPressureVolumeQuad::recvSelf() - " << this->getTag() << " failed to receive ID\n";
01504     return res;
01505   }
01506 
01507   this->setTag(idData(8));
01508   connectedExternalNodes(0) = idData(9);
01509   connectedExternalNodes(1) = idData(10);
01510   connectedExternalNodes(2) = idData(11);
01511   connectedExternalNodes(3) = idData(12);
01512 
01513   int i;
01514 
01515   if (materialPointers[0] == 0) {
01516     for (i = 0; i < 4; i++) {
01517       int matClassTag = idData(i);
01518       int matDbTag = idData(i+4);
01519       // Allocate new material with the sent class tag
01520       materialPointers[i] = theBroker.getNewNDMaterial(matClassTag);
01521       if (materialPointers[i] == 0) {
01522         opserr << "ConstantPressureVolumeQuad::recvSelf() - " <<
01523           "Broker could not create NDMaterial of class type" << matClassTag << endln;
01524         return -1;
01525       }
01526       // Now receive materials into the newly allocated space
01527       materialPointers[i]->setDbTag(matDbTag);
01528       res += materialPointers[i]->recvSelf(commitTag, theChannel, theBroker);
01529       if (res < 0) {
01530         opserr << "NLBeamColumn3d::recvSelf() - material " << 
01531           i << "failed to recv itself\n";
01532         return res;
01533       }
01534     }
01535   }
01536   // Number of materials is the same, receive materials into current space
01537   else {
01538     for (i = 0; i < 4; i++) {
01539       int matClassTag = idData(i);
01540       int matDbTag = idData(i+4);
01541       // Check that material is of the right type; if not,
01542       // delete it and create a new one of the right type
01543       if (materialPointers[i]->getClassTag() != matClassTag) {
01544         delete materialPointers[i];
01545         materialPointers[i] = theBroker.getNewNDMaterial(matClassTag);
01546         if (materialPointers[i] == 0) {
01547           opserr << "ConstantPressureVolumeQuad::recvSelf() - " << 
01548             "Broker could not create NDMaterial of class type" << matClassTag << endln;
01549         exit(-1);
01550         }
01551       }
01552       // Receive the material
01553       materialPointers[i]->setDbTag(matDbTag);
01554       res += materialPointers[i]->recvSelf(commitTag, theChannel, theBroker);
01555       if (res < 0) {
01556         opserr << "ConstantPressureVolumeQuad::recvSelf() - material  " << i <<
01557           "failed to recv itself\n";
01558         return res;
01559       }
01560     }
01561   }
01562   
01563   return res;
01564 }
01565 

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