EnhancedQuad.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.13 $
00022 // $Date: 2006/08/04 19:07:15 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/element/fourNodeQuad/EnhancedQuad.cpp,v $
00024 
00025 #include <stdio.h> 
00026 #include <stdlib.h> 
00027 #include <math.h> 
00028 
00029 #include <ID.h> 
00030 #include <Vector.h>
00031 #include <Matrix.h>
00032 #include <Element.h>
00033 #include <Node.h>
00034 #include <NDMaterial.h>
00035 #include <Domain.h>
00036 #include <ErrorHandler.h>
00037 #include <EnhancedQuad.h>
00038 #include <Renderer.h>
00039 #include <ElementResponse.h>
00040 #include <Channel.h>
00041 #include <FEM_ObjectBroker.h>
00042 
00043 
00044 //static data
00045 double  EnhancedQuad::xl[2][4] ;
00046 Matrix  EnhancedQuad::stiff(8,8) ;
00047 Vector  EnhancedQuad::resid(8) ;
00048 Matrix  EnhancedQuad::mass(8,8) ;
00049 
00050 double  EnhancedQuad::stressData[3][4] ;
00051 double  EnhancedQuad::tangentData[3][3][4] ;
00052 
00053     
00054 //quadrature data
00055 const double  EnhancedQuad::root3 = sqrt(3.0) ;
00056 const double  EnhancedQuad::one_over_root3 = 1.0 / root3 ;
00057 
00058 const double  EnhancedQuad::sg[] = { -one_over_root3,  
00059                                      one_over_root3, 
00060                                      one_over_root3, 
00061                                      -one_over_root3 } ;
00062 
00063 const double  EnhancedQuad::tg[] = { -one_over_root3, 
00064                                      -one_over_root3, 
00065                                      one_over_root3,  
00066                                      one_over_root3 } ;
00067 
00068 const double  EnhancedQuad::wg[] = { 1.0, 1.0, 1.0, 1.0 } ;
00069 
00070   
00071 
00072 //null constructor
00073 EnhancedQuad::EnhancedQuad( ) :
00074 Element( 0, ELE_TAG_EnhancedQuad ),
00075 connectedExternalNodes(4),
00076 alpha(4) , load(0), Ki(0)
00077 { 
00078   for ( int i = 0 ;  i < 4; i++ ) {
00079     materialPointers[i] = 0;
00080   }
00081 
00082   //zero enhanced parameters
00083   alpha.Zero( ) ;
00084 }
00085 
00086 
00087 //full constructor
00088 EnhancedQuad::EnhancedQuad(  int tag, 
00089                          int node1,
00090                          int node2,
00091                          int node3,
00092                          int node4,
00093                          NDMaterial &theMaterial,
00094                          const char *type ) 
00095   :
00096 Element( tag, ELE_TAG_EnhancedQuad ),
00097 connectedExternalNodes(4),
00098 alpha(4), load(0), Ki(0)
00099 {
00100 
00101   connectedExternalNodes(0) = node1 ;
00102   connectedExternalNodes(1) = node2 ;
00103   connectedExternalNodes(2) = node3 ;
00104   connectedExternalNodes(3) = node4 ;
00105 
00106   if (strcmp(type,"PlaneStrain") != 0 && strcmp(type,"PlaneStress") != 0
00107       && strcmp(type,"PlaneStrain2D") != 0 && strcmp(type,"PlaneStress2D") != 0) {
00108     opserr << "EnhancedQuad::EnhancedQuad -- improper material type " << type << " for EnhancedQuad\n";
00109     exit(-1);
00110   }
00111 
00112   int i ;
00113   for ( i = 0 ;  i < 4; i++ ) {
00114 
00115       materialPointers[i] = theMaterial.getCopy(type) ;
00116 
00117       if (materialPointers[i] == 0) {
00118         opserr << "EnhancedQuad::EnhancedQuad -- failed to get a material of type " << type << endln;
00119         exit(-1);
00120       } //end if
00121       
00122   } //end for i 
00123 
00124   //zero enhanced parameters
00125   alpha.Zero( ) ;
00126 
00127 }
00128 
00129 
00130 //destructor 
00131 EnhancedQuad::~EnhancedQuad( )
00132 {
00133   int i ;
00134   for ( i = 0 ;  i < 4; i++ ) 
00135     if (materialPointers[i] != 0)
00136       delete materialPointers[i] ;
00137 
00138   if (load != 0)
00139     delete load;
00140 
00141   if (Ki != 0)
00142     delete Ki;
00143 }
00144 
00145 
00146 //set domain
00147 void  EnhancedQuad::setDomain( Domain *theDomain ) 
00148 {  
00149 
00150   int i ;
00151 
00152   //node pointers
00153   for ( i = 0; i < 4; i++ ) 
00154      nodePointers[i] = theDomain->getNode( connectedExternalNodes(i) ) ;
00155 
00156   this->DomainComponent::setDomain(theDomain) ;
00157 }
00158 
00159 
00160 //get the number of external nodes
00161 int  EnhancedQuad::getNumExternalNodes( ) const
00162 {
00163   return 4 ;
00164 } 
00165  
00166 
00167 //return connected external nodes
00168 const ID&  EnhancedQuad::getExternalNodes( ) 
00169 {
00170   return connectedExternalNodes ;
00171 } 
00172 
00173 
00174 Node **
00175 EnhancedQuad::getNodePtrs(void) 
00176 {
00177   return nodePointers;
00178 } 
00179 
00180 //return number of dofs
00181 int  EnhancedQuad::getNumDOF( ) 
00182 {
00183   return 8 ;
00184 }
00185 
00186 
00187 //commit state
00188 int  EnhancedQuad::commitState( )
00189 {
00190   int success = 0 ;
00191 
00192   // call element commitState to do any base class stuff
00193   if ((success = this->Element::commitState()) != 0) {
00194     opserr << "EnhancedQuad::commitState () - failed in base class";
00195   }    
00196 
00197   for (int i = 0; i < 4; i++ ) 
00198     success += materialPointers[i]->commitState( ) ;
00199   
00200   return success ;
00201 }
00202  
00203 
00204 
00205 //revert to last commit 
00206 int  EnhancedQuad::revertToLastCommit( ) 
00207 {
00208   int i ;
00209   int success = 0 ;
00210 
00211   for ( i = 0; i < 4; i++ ) 
00212     success += materialPointers[i]->revertToLastCommit( ) ;
00213   
00214   return success ;
00215 }
00216     
00217 
00218 //revert to start 
00219 int  EnhancedQuad::revertToStart( ) 
00220 {
00221   int i ;
00222   int success = 0 ;
00223 
00224   //zero enhanced parameters
00225   this->alpha.Zero( ) ;
00226 
00227   for ( i = 0; i < 4; i++ ) 
00228     success += materialPointers[i]->revertToStart( ) ;
00229   
00230   return success ;
00231 }
00232 
00233 //print out element data
00234 void  EnhancedQuad::Print( OPS_Stream &s, int flag )
00235 {
00236   s << endln ;
00237   s << "Enhanced Strain Four Node Quad \n" ;
00238   s << "Element Number: " << this->getTag() << endln ;
00239   s << "Node 1 : " << connectedExternalNodes(0) << endln ;
00240   s << "Node 2 : " << connectedExternalNodes(1) << endln ;
00241   s << "Node 3 : " << connectedExternalNodes(2) << endln ;
00242   s << "Node 4 : " << connectedExternalNodes(3) << endln ;
00243 
00244   s << "Material Information : \n " ;
00245   materialPointers[0]->Print( s, flag ) ;
00246 
00247   s << endln ;
00248 }
00249 
00250 //return stiffness matrix 
00251 const Matrix&  EnhancedQuad::getTangentStiff( ) 
00252 {
00253   int tang_flag = 1 ; //get the tangent 
00254 
00255   //do tangent and residual here
00256   formResidAndTangent( tang_flag ) ;  
00257 
00258   return stiff ;
00259 }    
00260 
00261 
00262 //return secant matrix 
00263 const Matrix&  EnhancedQuad::getInitialStiff( ) 
00264 {
00265 
00266   if (Ki != 0)
00267     return *Ki;
00268 
00269   static const int ndm = 2 ;
00270 
00271   static const int ndf = 2 ; 
00272 
00273   static const int nstress = 3 ;
00274  
00275   static const int numberNodes = 4 ;
00276 
00277   static const int numberGauss = 4 ;
00278 
00279   static const int nShape = 3 ;
00280 
00281   static const int nEnhanced = 4 ;
00282   
00283   static const int nModes = 2 ;
00284 
00285   static const int numberDOF = 8 ;
00286 
00287 
00288   int i, j, k, p, q ;
00289   int jj, kk ;
00290 
00291   static double xsj[numberGauss] ;  // determinant jacaobian matrix 
00292 
00293   static double dvol[numberGauss] ; //volume element
00294 
00295   static Vector strain(nstress) ;  //strain
00296 
00297   static double shp[nShape][numberNodes] ;  //shape functions at a gauss point
00298 
00299   static double Shape[nShape][numberNodes][numberGauss] ; //all the shape functions
00300 
00301   static Vector residJ(ndf) ; //nodeJ residual 
00302 
00303   static Matrix stiffJK(ndf,ndf) ; //nodeJK stiffness 
00304 
00305   static Matrix stiffKJ(ndf,ndf) ; //nodeKJ stiffness
00306 
00307   static Vector stress(nstress) ;  //stress
00308 
00309   static Matrix dd(nstress,nstress) ;  //material tangent
00310 
00311   static Matrix J0(ndm,ndm) ; //Jacobian matrix at center of element
00312 
00313   static Matrix J0inv(ndm,ndm) ; //inverse of above
00314 
00315 
00316   static Matrix Kee(nEnhanced,nEnhanced) ;
00317 
00318   static Vector residE(nEnhanced) ;
00319 
00320   static Vector Umode(ndf) ;
00321 
00322   static Vector dalpha(nEnhanced) ;
00323 
00324   static Matrix Kue(numberDOF,nEnhanced) ;
00325 
00326   static Matrix Keu(nEnhanced,numberDOF) ;
00327 
00328   static Matrix KeeInvKeu(nEnhanced,numberDOF) ;
00329 
00330 
00331   //---------B-matrices------------------------------------
00332 
00333     static Matrix BJ(nstress,ndf) ;      // B matrix node J
00334 
00335     static Matrix BJtran(ndf,nstress) ;
00336 
00337     static Matrix BK(nstress,ndf) ;      // B matrix node k
00338 
00339     static Matrix BKtran(ndf,nstress) ;
00340 
00341     static Matrix BJtranD(ndf,nstress) ;
00342 
00343     static Matrix BKtranD(ndf,nstress) ;
00344   //-------------------------------------------------------
00345 
00346   
00347   //zero stiffness and residual 
00348   stiff.Zero( ) ;
00349 
00350   Kee.Zero( ) ;
00351   residE.Zero( ) ;
00352 
00353   Kue.Zero( ) ;
00354   Keu.Zero( ) ;
00355 
00356 
00357   //compute basis vectors and local nodal coordinates
00358   computeBasis( ) ;
00359 
00360   //compute Jacobian and inverse at center
00361   double L1 = 0.0 ;
00362   double L2 = 0.0 ;
00363   computeJacobian( L1, L2, xl, J0, J0inv ) ; 
00364 
00365   //gauss loop to compute and save shape functions 
00366   double det ;
00367   for ( i = 0; i < numberGauss; i++ ) {
00368 
00369     //get shape functions    
00370     shape2d( sg[i], tg[i], xl, shp, det ) ;
00371 
00372     //save shape functions
00373     for ( p = 0; p < nShape; p++ ) {
00374        for ( q = 0; q < numberNodes; q++ )
00375           Shape[p][q][i] = shp[p][q] ;
00376     } // end for p
00377 
00378     //save jacobian determinant
00379     xsj[i] = det ;
00380 
00381     //volume element to also be saved
00382     dvol[i] = wg[i] * det ;  
00383 
00384   } // end for i gauss loop
00385 
00386   Kee.Zero( ) ;
00387   //gauss loop
00388   for ( i = 0; i < numberGauss; i++ ) {
00389 
00390     //tangent 
00391     dd = materialPointers[i]->getInitialTangent( ) ;
00392     
00393     //multiply by volume element
00394     dd *= dvol[i] ;
00395     saveData( i, stress, dd ) ;   
00396   }
00397   Kee.Zero( ) ;
00398   for ( i = 0; i < numberGauss; i++ ) {
00399     //extract shape functions from saved array
00400     for ( p = 0; p < nShape; p++ ) {
00401       for ( q = 0; q < numberNodes; q++ )
00402         shp[p][q]  = Shape[p][q][i] ;
00403     } // end for p
00404     
00405     //enhanced residual and tangent calculations loops
00406     jj = 0 ;
00407     for ( j = 0; j < nModes; j++ ) {
00408       
00409       //compute B matrix 
00410       BJ = computeBenhanced( j, sg[i], tg[i], xsj[i], J0inv ) ; 
00411       
00412       //transpose 
00413       BJtran = transpose( BJ ) ;
00414       
00415       //BJtranD = BJtran * dd ;
00416       BJtranD.addMatrixProduct(0.0, BJtran, dd, 1.0) ;
00417       
00418       kk = 0 ;
00419       for ( k = 0; k < nModes; k++ ) {
00420         
00421         BK = computeBenhanced( k, sg[i], tg[i], xsj[i], J0inv ) ;
00422         
00423         //stiffJK =  BJtranD * BK  ;
00424         stiffJK.addMatrixProduct(0.0, BJtranD,BK,1.0) ;
00425         
00426         for ( p = 0; p < ndf; p++ )  {
00427           for ( q = 0; q < ndf; q++ )
00428             Kee( jj+p, kk+q ) += stiffJK( p, q ) ;
00429         } //end for p
00430         
00431         kk += ndf ;
00432       } // end for k loop
00433       
00434       jj += ndf ;
00435     } // end for j loop
00436   } // end for i gauss loop 
00437   
00439   for ( i = 0; i < numberGauss; i++ ) {
00440     //extract shape functions from saved array
00441     for ( p = 0; p < nShape; p++ ) {
00442        for ( q = 0; q < numberNodes; q++ )
00443           shp[p][q]  = Shape[p][q][i] ;
00444     } // end for p
00445 
00446 
00447     //recover stress and tangent from saved data
00448     getData( i, stress, dd ) ;
00449     jj = 0 ;
00450     for ( j = 0; j < numberNodes; j++ ) {
00451 
00452       BJ = computeB( j, shp ) ;
00453    
00454       //transpose 
00455       BJtran = transpose( BJ ) ;
00456 
00457       //BJtranD = BJtran * dd ;
00458       BJtranD.addMatrixProduct(0.0, BJtran, dd, 1.0) ;
00459       
00460       //node-node stiffness
00461       kk = 0 ;
00462       for ( k = 0; k < numberNodes; k++ ) {
00463         
00464         BK = computeB( k, shp ) ;
00465         
00466         //stiffJK =  BJtranD * BK  ;
00467         stiffJK.addMatrixProduct(0.0, BJtranD, BK,1.0) ;
00468         
00469         for ( p = 0; p < ndf; p++ )  {
00470           for ( q = 0; q < ndf; q++ )
00471             stiff( jj+p, kk+q ) += stiffJK( p, q ) ;
00472         } //end for p
00473         
00474         kk += ndf ;
00475       } // end for k loop
00476       
00477 
00478       //node-enhanced stiffness Kue 
00479       kk = 0 ;
00480       for ( k = 0; k < nModes; k++ ) {
00481         
00482         BK = computeBenhanced( k, sg[i], tg[i], xsj[i], J0inv ) ;
00483         
00484         //stiffJK =  BJtranD * BK  ;
00485         stiffJK.addMatrixProduct(0.0, BJtranD,BK,1.0) ;
00486         
00487         for ( p = 0; p < ndf; p++ )  {
00488           for ( q = 0; q < ndf; q++ )
00489             Kue( jj+p, kk+q ) += stiffJK( p, q ) ;
00490         } //end for p 
00491         
00492         kk += ndf ;
00493       } // end for k loop
00494 
00495       //enhanced-node stiffness Keu 
00496       kk = 0 ;
00497       for ( k = 0; k < nModes; k++ ) {
00498         
00499         BK = computeBenhanced( k, sg[i], tg[i], xsj[i], J0inv ) ;
00500         
00501         //transpose 
00502         BKtran = transpose( BK ) ;
00503         
00504         //BKtranD = BKtran * dd ;
00505         BKtranD.addMatrixProduct(0.0, BKtran,dd,1.0 ) ;
00506         
00507         //stiffKJ = (BKtran*dd)*BJ ;
00508         stiffKJ.addMatrixProduct(0.0, BKtranD,BJ,1.0) ;
00509         
00510         for ( p = 0; p < ndf; p++ )  {
00511           for ( q = 0; q < ndf; q++ )
00512             Keu( kk+p, jj+q ) += stiffKJ( p, q ) ;
00513         } //end for p  
00514         
00515         kk += ndf ;
00516       } // end for k loop
00517     
00518       jj += ndf ;
00519     } // end for j loop
00520   
00521   
00522   } //end for i gauss loop 
00523 
00524 
00525   Kee.Solve( Keu, KeeInvKeu ) ;
00526 
00527   //stiff -= ( Kue * KeeInvKeu ) ;
00528   stiff.addMatrixProduct(1.0,  Kue, KeeInvKeu, -1.0);
00529 
00530   Ki = new Matrix(stiff);
00531 
00532   return stiff;
00533 }
00534     
00535 
00536 
00537 //return mass matrix
00538 const Matrix&  EnhancedQuad::getMass( ) 
00539 {
00540 
00541   int tangFlag = 1 ;
00542 
00543   formInertiaTerms( tangFlag ) ;
00544 
00545   return mass ;
00546 
00547 } 
00548 
00549 
00550 
00551 void  EnhancedQuad::zeroLoad( )
00552 {
00553   if (load != 0)
00554     load->Zero();
00555 
00556   return ;
00557 }
00558 
00559 
00560 int 
00561 EnhancedQuad::addLoad(ElementalLoad *theLoad, double loadFactor)
00562 {
00563   opserr << "EnhancedQuad::addLoad - load type unknown for ele with tag: " << this->getTag() << endln;
00564   return -1;
00565 }
00566 
00567 int
00568 EnhancedQuad::addInertiaLoadToUnbalance(const Vector &accel)
00569 {
00570   static const int numberGauss = 4 ;
00571   static const int numberNodes = 4 ;
00572   static const int ndf = 2 ; 
00573 
00574   int i;
00575 
00576   // check to see if have mass
00577   int haveRho = 0;
00578   for (i = 0; i < numberGauss; i++) {
00579     if (materialPointers[i]->getRho() != 0.0)
00580       haveRho = 1;
00581   }
00582 
00583   if (haveRho == 0)
00584     return 0;
00585 
00586   // Compute mass matrix
00587   int tangFlag = 1 ;
00588   formInertiaTerms( tangFlag ) ;
00589 
00590   // store computed RV fro nodes in resid vector
00591   int count = 0;
00592   for (i=0; i<numberNodes; i++) {
00593     const Vector &Raccel = nodePointers[i]->getRV(accel);
00594     for (int j=0; j<ndf; j++)
00595       resid(count++) = Raccel(i);
00596   }
00597 
00598   // create the load vector if one does not exist
00599   if (load == 0) 
00600     load = new Vector(numberNodes*ndf);
00601 
00602   // add -M * RV(accel) to the load vector
00603   load->addMatrixVector(1.0, mass, resid, -1.0);
00604   
00605   return 0;
00606 }
00607 
00608 
00609 //get residual
00610 const Vector&  EnhancedQuad::getResistingForce( ) 
00611 {
00612   int tang_flag = 0 ; //don't get the tangent
00613 
00614   formResidAndTangent( tang_flag ) ;
00615 
00616   // subtract external loads 
00617   if (load != 0)
00618     resid -= *load;
00619 
00620   return resid ;   
00621 }
00622 
00623 
00624 //get residual with inertia terms
00625 const Vector&  EnhancedQuad::getResistingForceIncInertia( )
00626 {
00627   int tang_flag = 0 ; //don't get the tangent
00628 
00629   static Vector res(8);
00630 
00631   //do tangent and residual here 
00632   formResidAndTangent( tang_flag ) ;
00633 
00634   //inertia terms
00635   formInertiaTerms( tang_flag ) ;
00636 
00637   res = resid;
00638 
00639   // add the damping forces if rayleigh damping
00640   if (alphaM != 0.0 || betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00641     res += this->getRayleighDampingForces();
00642 
00643   // subtract external loads 
00644   if (load != 0)
00645     res -= *load;
00646 
00647   return res;
00648 }
00649 
00650 
00651 //*********************************************************************
00652 //form inertia terms
00653 
00654 void   EnhancedQuad::formInertiaTerms( int tangFlag ) 
00655 {
00656 
00657   static const int ndf = 2 ; 
00658 
00659   static const int numberNodes = 4 ;
00660 
00661   static const int numberGauss = 4 ;
00662 
00663   static const int nShape = 3 ;
00664 
00665   static const int massIndex = nShape - 1 ;
00666 
00667   double xsj ;  // determinant jacaobian matrix 
00668 
00669   double dvol ; //volume element
00670 
00671   static double shp[nShape][numberNodes] ;  //shape functions at a gauss point
00672 
00673   static Vector momentum(ndf) ;
00674 
00675   int i, j, k, p ;
00676   int jj, kk ;
00677 
00678   double temp, rho, massJK ;
00679 
00680 
00681   //zero mass 
00682   mass.Zero( ) ;
00683 
00684   //compute basis vectors and local nodal coordinates
00685   computeBasis( ) ;
00686 
00687   //gauss loop 
00688   for ( i = 0; i < numberGauss; i++ ) {
00689 
00690     //get shape functions    
00691     shape2d( sg[i], tg[i], xl, shp, xsj ) ;
00692     
00693     //volume element
00694     dvol = wg[i] * xsj ;
00695 
00696     //node loop to compute acceleration
00697     momentum.Zero( ) ;
00698     for ( j = 0; j < numberNodes; j++ ) 
00699       //momentum += shp[massIndex][j] * ( nodePointers[j]->getTrialAccel()  ) ; 
00700       momentum.addVector( 1.0,
00701                           nodePointers[j]->getTrialAccel(),
00702                           shp[massIndex][j] ) ;
00703 
00704     //density
00705     rho = materialPointers[i]->getRho() ;
00706 
00707     //multiply acceleration by density to form momentum
00708     momentum *= rho ;
00709 
00710 
00711     //residual and tangent calculations node loops
00712     jj = 0 ;
00713     for ( j = 0; j < numberNodes; j++ ) {
00714 
00715       temp = shp[massIndex][j] * dvol ;
00716 
00717       for ( p = 0; p < ndf; p++ )
00718         resid( jj+p ) += ( temp * momentum(p) )  ;
00719 
00720       
00721       if ( tangFlag == 1 ) {
00722 
00723          //multiply by density
00724          temp *= rho ;
00725 
00726          //node-node mass
00727          kk = 0 ;
00728          for ( k = 0; k < numberNodes; k++ ) {
00729 
00730             massJK = temp * shp[massIndex][k] ;
00731 
00732             for ( p = 0; p < ndf; p++ )  
00733               mass( jj+p, kk+p ) += massJK ;
00734             
00735             kk += ndf ;
00736           } // end for k loop
00737 
00738       } // end if tang_flag 
00739 
00740       jj += ndf ;
00741     } // end for j loop
00742   } //end for i gauss loop 
00743 }
00744 
00745 //*********************************************************************
00746 //form residual and tangent
00747 void  EnhancedQuad::formResidAndTangent( int tang_flag ) 
00748 {
00749 
00750   static const double tolerance = 1.0e-08 ;
00751 
00752   static const int nIterations = 10 ;
00753 
00754   static const int ndm = 2 ;
00755 
00756   static const int ndf = 2 ; 
00757 
00758   static const int nstress = 3 ;
00759  
00760   static const int numberNodes = 4 ;
00761 
00762   static const int numberGauss = 4 ;
00763 
00764   static const int nShape = 3 ;
00765 
00766   static const int nEnhanced = 4 ;
00767   
00768   static const int nModes = 2 ;
00769 
00770   static const int numberDOF = 8 ;
00771 
00772 
00773   int i, j, k, p, q ;
00774   int jj, kk ;
00775 
00776   int success ;
00777 
00778   static double xsj[numberGauss] ;  // determinant jacaobian matrix 
00779 
00780   static double dvol[numberGauss] ; //volume element
00781 
00782   static Vector strain(nstress) ;  //strain
00783 
00784   static double shp[nShape][numberNodes] ;  //shape functions at a gauss point
00785 
00786   static double Shape[nShape][numberNodes][numberGauss] ; //all the shape functions
00787 
00788   static Vector residJ(ndf) ; //nodeJ residual 
00789 
00790   static Matrix stiffJK(ndf,ndf) ; //nodeJK stiffness 
00791 
00792   static Matrix stiffKJ(ndf,ndf) ; //nodeKJ stiffness
00793 
00794   static Vector stress(nstress) ;  //stress
00795 
00796   static Matrix dd(nstress,nstress) ;  //material tangent
00797 
00798   static Matrix J0(ndm,ndm) ; //Jacobian matrix at center of element
00799 
00800   static Matrix J0inv(ndm,ndm) ; //inverse of above
00801 
00802 
00803   static Matrix Kee(nEnhanced,nEnhanced) ;
00804 
00805   static Vector residE(nEnhanced) ;
00806 
00807   static Vector Umode(ndf) ;
00808 
00809   static Vector dalpha(nEnhanced) ;
00810 
00811   static Matrix Kue(numberDOF,nEnhanced) ;
00812 
00813   static Matrix Keu(nEnhanced,numberDOF) ;
00814 
00815   static Matrix KeeInvKeu(nEnhanced,numberDOF) ;
00816 
00817 
00818   //---------B-matrices------------------------------------
00819 
00820     static Matrix BJ(nstress,ndf) ;      // B matrix node J
00821 
00822     static Matrix BJtran(ndf,nstress) ;
00823 
00824     static Matrix BK(nstress,ndf) ;      // B matrix node k
00825 
00826     static Matrix BKtran(ndf,nstress) ;
00827 
00828     static Matrix BJtranD(ndf,nstress) ;
00829 
00830     static Matrix BKtranD(ndf,nstress) ;
00831   //-------------------------------------------------------
00832 
00833   
00834   //zero stiffness and residual 
00835   stiff.Zero( ) ;
00836   resid.Zero( ) ;
00837 
00838   Kee.Zero( ) ;
00839   residE.Zero( ) ;
00840 
00841   Kue.Zero( ) ;
00842   Keu.Zero( ) ;
00843 
00844 
00845   //compute basis vectors and local nodal coordinates
00846   computeBasis( ) ;
00847 
00848   //compute Jacobian and inverse at center
00849   double L1 = 0.0 ;
00850   double L2 = 0.0 ;
00851   computeJacobian( L1, L2, xl, J0, J0inv ) ; 
00852 
00853 
00854   //gauss loop to compute and save shape functions 
00855   double det ;
00856   for ( i = 0; i < numberGauss; i++ ) {
00857 
00858     //get shape functions    
00859     shape2d( sg[i], tg[i], xl, shp, det ) ;
00860 
00861     //save shape functions
00862     for ( p = 0; p < nShape; p++ ) {
00863        for ( q = 0; q < numberNodes; q++ )
00864           Shape[p][q][i] = shp[p][q] ;
00865     } // end for p
00866 
00867     //save jacobian determinant
00868     xsj[i] = det ;
00869 
00870     //volume element to also be saved
00871     dvol[i] = wg[i] * det ;  
00872 
00873   } // end for i gauss loop
00874 
00875 
00876   //-------------------------------------------------------------------
00877   //newton loop to solve for enhanced strain parameters
00878 
00879   int count = 0 ;
00880   do {
00881 
00882     residE.Zero( ) ;
00883     Kee.Zero( ) ;
00884 
00885     //gauss loop
00886     for ( i = 0; i < numberGauss; i++ ) {
00887 
00888       //extract shape functions from saved array
00889       for ( p = 0; p < nShape; p++ ) {
00890         for ( q = 0; q < numberNodes; q++ )
00891           shp[p][q]  = Shape[p][q][i] ;
00892       } // end for p
00893 
00894 
00895       //zero the strain
00896       strain.Zero( ) ;
00897 
00898       // j-node loop to compute nodal strain contributions
00899       for ( j = 0; j < numberNodes; j++ )  {
00900 
00901         //compute B matrix 
00902         BJ = computeB( j, shp ) ;
00903       
00904         //nodal displacements 
00905         const Vector &ul = nodePointers[j]->getTrialDisp( ) ;
00906 
00907         //compute the strain
00908         //strain += (BJ*ul) ; 
00909         strain.addMatrixVector(1.0, BJ, ul, 1.0) ;
00910 
00911       } // end for j
00912 
00913       // j-node loop to compute enhanced strain contributions
00914       for ( j = 0; j < nModes; j++ )  {
00915 
00916         //compute B matrix 
00917         BJ = computeBenhanced( j, sg[i], tg[i], xsj[i], J0inv ) ; 
00918       
00919         //enhanced "displacements" 
00920         Umode(0) = this->alpha( 2*j     ) ;
00921         Umode(1) = this->alpha( 2*j + 1 ) ;
00922 
00923         //compute the strain
00924         //strain += (BJ*Umode) ; 
00925         strain.addMatrixVector(1.0, BJ, Umode, 1.0) ;
00926 
00927       } // end for j
00928 
00929       success = materialPointers[i]->setTrialStrain( strain ) ;
00930 
00931       //compute the stress
00932       stress = materialPointers[i]->getStress( ) ;
00933 
00934       //multiply by volume element
00935       stress  *= dvol[i] ;
00936 
00937       //tangent 
00938       dd = materialPointers[i]->getTangent( ) ;
00939 
00940       //multiply by volume element
00941       dd *= dvol[i] ;
00942 
00943       //save stress and tangent (already multiplied by volume element)
00944       saveData( i, stress, dd ) ; 
00945 
00946       //enhanced residual and tangent calculations loops
00947 
00948       jj = 0 ;
00949       for ( j = 0; j < nModes; j++ ) {
00950 
00951         //compute B matrix 
00952         BJ = computeBenhanced( j, sg[i], tg[i], xsj[i], J0inv ) ; 
00953 
00954         //transpose 
00955         BJtran = transpose( BJ ) ;
00956 
00957 
00958         //residual
00959         //residJ = (BJtran * stress) ;
00960         //residJ *= (-1.0) ;
00961         residJ.addMatrixVector(0.0, BJtran,stress,-1.0) ;
00962 
00963         //residual 
00964         for ( p = 0; p < ndf; p++ )
00965           residE( jj+p ) += residJ(p)  ;
00966 
00967 
00968         //BJtranD = BJtran * dd ;
00969         BJtranD.addMatrixProduct(0.0, BJtran,dd,1.0) ;
00970 
00971         kk = 0 ;
00972         for ( k = 0; k < nModes; k++ ) {
00973 
00974           BK = computeBenhanced( k, sg[i], tg[i], xsj[i], J0inv ) ;
00975   
00976           //stiffJK =  BJtranD * BK  ;
00977           stiffJK.addMatrixProduct(0.0, BJtranD,BK,1.0) ;
00978 
00979           for ( p = 0; p < ndf; p++ )  {
00980              for ( q = 0; q < ndf; q++ )
00981                 Kee( jj+p, kk+q ) += stiffJK( p, q ) ;
00982           } //end for p
00983 
00984             kk += ndf ;
00985           } // end for k loop
00986 
00987         jj += ndf ;
00988       } // end for j loop
00989 
00990 
00991     } // end for i gauss loop 
00992 
00993 
00994     //solve for enhanced strain parameters
00995 
00996     dalpha.Zero( ) ;
00997 
00998     Kee.Solve( residE, dalpha ) ;
00999 
01000     if (dalpha(0) > 1.0e10)  opserr << "dalpha: " << residE << dalpha;
01001 
01002     this->alpha += dalpha ;
01003 
01004     count++ ;
01005     if ( count > nIterations ) {
01006       opserr << "Exceeded " << nIterations
01007            << " iterations solving for enhanced strain parameters " << endln ;
01008       break ;
01009     } //end if 
01010 
01011 
01012     //do at least 2 iterations so saved data is good
01013   } while ( residE.Norm() > tolerance  ||  count < 2 ) ;
01014 
01015 
01016   //end enhanced strain parameters newton loop
01017   //-------------------------------------------------------------------
01018 
01019 
01020   //gauss loop 
01021   for ( i = 0; i < numberGauss; i++ ) {
01022 
01023     //extract shape functions from saved array
01024     for ( p = 0; p < nShape; p++ ) {
01025        for ( q = 0; q < numberNodes; q++ )
01026           shp[p][q]  = Shape[p][q][i] ;
01027     } // end for p
01028 
01029 
01030     //recover stress and tangent from saved data
01031     getData( i, stress, dd ) ;
01032 
01033 
01034     //residual and tangent calculations node loops
01035 
01036     jj = 0 ;
01037     for ( j = 0; j < numberNodes; j++ ) {
01038 
01039       BJ = computeB( j, shp ) ;
01040    
01041       //transpose 
01042       BJtran = transpose( BJ ) ;
01043 
01044       //residual
01045       //residJ = BJtran * stress ;
01046       residJ.addMatrixVector(0.0, BJtran,stress,1.0) ;
01047 
01048       for ( p = 0; p < ndf; p++ )
01049         resid( jj+p ) += residJ(p)  ;
01050 
01051 
01052       if ( tang_flag == 1 ) {
01053 
01054         //BJtranD = BJtran * dd ;
01055         BJtranD.addMatrixProduct(0.0, BJtran,dd,1.0) ;
01056 
01057          //node-node stiffness
01058          kk = 0 ;
01059          for ( k = 0; k < numberNodes; k++ ) {
01060 
01061             BK = computeB( k, shp ) ;
01062   
01063             //stiffJK =  BJtranD * BK  ;
01064             stiffJK.addMatrixProduct(0.0, BJtranD,BK,1.0) ;
01065 
01066             for ( p = 0; p < ndf; p++ )  {
01067                for ( q = 0; q < ndf; q++ )
01068                   stiff( jj+p, kk+q ) += stiffJK( p, q ) ;
01069             } //end for p
01070 
01071             kk += ndf ;
01072           } // end for k loop
01073 
01074 
01075          //node-enhanced stiffness Kue 
01076          kk = 0 ;
01077          for ( k = 0; k < nModes; k++ ) {
01078 
01079             BK = computeBenhanced( k, sg[i], tg[i], xsj[i], J0inv ) ;
01080   
01081             //stiffJK =  BJtranD * BK  ;
01082             stiffJK.addMatrixProduct(0.0, BJtranD,BK,1.0) ;
01083            
01084             for ( p = 0; p < ndf; p++ )  {
01085                for ( q = 0; q < ndf; q++ )
01086                   Kue( jj+p, kk+q ) += stiffJK( p, q ) ;
01087             } //end for p 
01088 
01089             kk += ndf ;
01090           } // end for k loop
01091 
01092 
01093          //enhanced-node stiffness Keu 
01094          kk = 0 ;
01095          for ( k = 0; k < nModes; k++ ) {
01096 
01097             BK = computeBenhanced( k, sg[i], tg[i], xsj[i], J0inv ) ;
01098 
01099             //transpose 
01100             BKtran = transpose( BK ) ;
01101             
01102             //BKtranD = BKtran * dd ;
01103             BKtranD.addMatrixProduct(0.0, BKtran,dd,1.0 ) ;
01104 
01105             //stiffKJ = (BKtran*dd)*BJ ;
01106             stiffKJ.addMatrixProduct(0.0, BKtranD,BJ,1.0) ;
01107 
01108             for ( p = 0; p < ndf; p++ )  {
01109                for ( q = 0; q < ndf; q++ )
01110                   Keu( kk+p, jj+q ) += stiffKJ( p, q ) ;
01111             } //end for p  
01112 
01113             kk += ndf ;
01114           } // end for k loop
01115 
01116 
01117 
01118       } // end if tang_flag 
01119 
01120       jj += ndf ;
01121     } // end for j loop
01122 
01123 
01124   } //end for i gauss loop 
01125 
01126 
01127   //static condensation of enhanced parameters
01128 
01129   if ( tang_flag == 1 ) {
01130     
01131      Kee.Solve( Keu, KeeInvKeu ) ;
01132 
01133      //stiff -= ( Kue * KeeInvKeu ) ;
01134      stiff.addMatrixProduct(1.0,  Kue,KeeInvKeu,-1.0 ) ;
01135 
01136   } //end if 
01137 
01138   return ;
01139 }
01140 
01141 
01142 
01143 
01144 
01145 int  
01146 EnhancedQuad::update(void) 
01147 {
01148   return 0;
01149 }
01150   
01151 
01152 //************************************************************************
01153 void   
01154 EnhancedQuad::saveData(int gp, 
01155                        const Vector &stress,
01156                        const Matrix &tangent ) 
01157 {
01158 
01159   int i, j ;
01160 
01161   //save stress
01162   for ( i=0; i<3; i++ )
01163     stressData[i][gp] = stress(i) ;
01164 
01165   //save tangent
01166   for ( i=0; i<3; i++ ) {
01167     for (j=0; j<3; j++ ) 
01168       tangentData[i][j][gp] = tangent(i,j) ;
01169   } //end for i
01170 
01171   return ;
01172 }
01173 
01174 
01175 //************************************************************************
01176 //recover stress and tangent data
01177 
01178 void  EnhancedQuad::getData( int gp,
01179                              Vector &stress,
01180                              Matrix &tangent ) 
01181 {
01182 
01183   int i, j ;
01184 
01185   //get stress
01186   for ( i=0; i<3; i++ )
01187     stress(i) = stressData[i][gp] ;
01188 
01189   //get tangent
01190   for ( i=0; i<3; i++ ) {
01191     for ( j=0; j<3; j++ ) 
01192       tangent(i,j) = tangentData[i][j][gp] ;
01193   } //end for i
01194 
01195   return ;
01196 
01197 }
01198 
01199 //************************************************************************
01200 //compute local coordinates and basis
01201 
01202 void   EnhancedQuad::computeBasis( ) 
01203 {
01204   //nodal coordinates 
01205 
01206   int i ;
01207   for ( i = 0; i < 4; i++ ) {
01208 
01209        const Vector &coorI = nodePointers[i]->getCrds( ) ;
01210 
01211        xl[0][i] = coorI(0) ;
01212        xl[1][i] = coorI(1) ;
01213 
01214   }  //end for i 
01215 
01216 }
01217 
01218 //*************************************************************************
01219 //compute B matrix
01220 
01221 const Matrix&
01222 EnhancedQuad::computeB( int node, const double shp[3][4] ) 
01223 {
01224 
01225   static Matrix B(3,2) ;
01226 
01227 //---B Matrix in standard {1,2,3} mechanics notation---------------
01228 //
01229 //                -             -
01230 //               | +N,1      0   | 
01231 // B    =        |   0     +N,2  |    (3x2)
01232 //               | +N,2    +N,1  |
01233 //                -             -  
01234 //
01235 //-------------------------------------------------------------------
01236 
01237   B.Zero( ) ;
01238 
01239   B(0,0) = shp[0][node] ;
01240   B(1,1) = shp[1][node] ;
01241   B(2,0) = shp[1][node] ;
01242   B(2,1) = shp[0][node] ;
01243 
01244   return B ;
01245 
01246 }
01247 
01248 //***********************************************************************
01249 //compute enhanced strain B-matrices
01250 
01251 const Matrix&   
01252 EnhancedQuad::computeBenhanced( int node, 
01253                                          double L1,
01254                                          double L2,
01255                                          double j, 
01256                                          const Matrix &Jinv )
01257 {
01258   static Matrix B(3,2) ;
01259 
01260   static double JinvTran[2][2] ;
01261 
01262   static double shape[2] ;
01263 
01264   static double parameter ;
01265 
01266 
01267   //compute JinvTran
01268   JinvTran[0][0] = Jinv(0,0) ;
01269   JinvTran[1][1] = Jinv(1,1) ;
01270   JinvTran[0][1] = Jinv(1,0) ;
01271   JinvTran[1][0] = Jinv(0,1) ;      //residual 
01272 
01273 
01274 
01275   if ( node == 0 ) {
01276 
01277     //first column of JinvTran 
01278     shape[0] = JinvTran[0][0] ;
01279     shape[1] = JinvTran[1][0] ;
01280 
01281     parameter = L1 / j ;
01282 
01283   }
01284   else if ( node == 1 ) {
01285 
01286     //second column of JinvTran 
01287     shape[0] = JinvTran[0][1] ;
01288     shape[1] = JinvTran[1][1] ;
01289 
01290     parameter = L2 / j ;
01291 
01292   } //end if 
01293 
01294   shape[0] *= parameter ;
01295   shape[1] *= parameter ; 
01296 
01297 
01298   B.Zero( ) ;
01299 
01300   B(0,0) = shape[0] ;
01301   B(1,1) = shape[1] ;
01302   B(2,0) = shape[1] ;
01303   B(2,1) = shape[0] ;
01304   
01305   return B ;
01306 
01307 }
01308 
01309 //***********************************************************************
01310 //compute Jacobian matrix and inverse at point {L1,L2} 
01311 
01312 void   EnhancedQuad::computeJacobian( double L1, double L2,
01313                                       const double x[2][4], 
01314                                       Matrix &JJ, 
01315                                       Matrix &JJinv )
01316 {
01317   int i, j, k ;
01318      
01319   static const double s[] = { -0.5,  0.5, 0.5, -0.5 } ;
01320   static const double t[] = { -0.5, -0.5, 0.5,  0.5 } ;
01321 
01322   static double shp[2][4] ;
01323 
01324   double ss = L1 ;
01325   double tt = L2 ;
01326 
01327   for ( i = 0; i < 4; i++ ) {
01328       shp[0][i] = s[i] * ( 0.5 + t[i]*tt ) ;
01329       shp[1][i] = t[i] * ( 0.5 + s[i]*ss ) ;
01330   } // end for i
01331 
01332   
01333   // Construct jacobian and its inverse
01334   
01335   JJ.Zero( ) ;
01336   for ( i = 0; i < 2; i++ ) {
01337     for ( j = 0; j < 2; j++ ) {
01338 
01339       for ( k = 0; k < 4; k++ )
01340           JJ(i,j) +=  x[i][k] * shp[j][k] ;
01341 
01342     } //end for j
01343   }  // end for i 
01344 
01345   double xsj = JJ(0,0)*JJ(1,1) - JJ(0,1)*JJ(1,0) ;
01346 
01347   //inverse jacobian
01348   double jinv = 1.0 / xsj ;
01349   JJinv(0,0) =  JJ(1,1) * jinv ;
01350   JJinv(1,1) =  JJ(0,0) * jinv ;
01351   JJinv(0,1) = -JJ(0,1) * jinv ;
01352   JJinv(1,0) = -JJ(1,0) * jinv ;
01353 
01354   return ;
01355 
01356 }
01357 
01358 //************************************************************************
01359 //shape function routine for four node quads
01360 
01361 void  EnhancedQuad::shape2d( double ss, double tt, 
01362                            const double x[2][4], 
01363                            double shp[3][4], 
01364                            double &xsj            )
01365 
01366 { 
01367 
01368   int i, j, k ;
01369 
01370   double temp ;
01371      
01372   static const double s[] = { -0.5,  0.5, 0.5, -0.5 } ;
01373   static const double t[] = { -0.5, -0.5, 0.5,  0.5 } ;
01374 
01375   static Matrix xs(2,2) ;
01376   static Matrix sx(2,2) ;
01377 
01378   for ( i = 0; i < 4; i++ ) {
01379       shp[2][i] = ( 0.5 + s[i]*ss )*( 0.5 + t[i]*tt ) ;
01380       shp[0][i] = s[i] * ( 0.5 + t[i]*tt ) ;
01381       shp[1][i] = t[i] * ( 0.5 + s[i]*ss ) ;
01382   } // end for i
01383 
01384   
01385   // Construct jacobian and its inverse
01386   
01387   xs.Zero( ) ;
01388   for ( i = 0; i < 2; i++ ) {
01389     for ( j = 0; j < 2; j++ ) {
01390 
01391       for ( k = 0; k < 4; k++ )
01392           xs(i,j) +=  x[i][k] * shp[j][k] ;
01393 
01394     } //end for j
01395   }  // end for i 
01396 
01397   xsj = xs(0,0)*xs(1,1) - xs(0,1)*xs(1,0) ;
01398 
01399   //inverse jacobian
01400   //inverse jacobian
01401   double jinv = 1.0 / xsj ;
01402   sx(0,0) =  xs(1,1) * jinv ;
01403   sx(1,1) =  xs(0,0) * jinv ;
01404   sx(0,1) = -xs(0,1) * jinv ;
01405   sx(1,0) = -xs(1,0) * jinv ;
01406 
01407 
01408   //form global derivatives 
01409   
01410   for ( i = 0; i < 4; i++ ) {
01411     temp      = shp[0][i]*sx(0,0) + shp[1][i]*sx(1,0) ;
01412     shp[1][i] = shp[0][i]*sx(0,1) + shp[1][i]*sx(1,1) ;
01413     shp[0][i] = temp ;
01414   } // end for i
01415 
01416   return ;
01417 }
01418            
01419 //**********************************************************************
01420 
01421 const Matrix&
01422 EnhancedQuad::transpose( const Matrix &M ) 
01423 {
01424   int i ;
01425   int j ;
01426 
01427   //we're always transposing 3x2 matrices for this element,
01428   //so always return a 2x3 .
01429 
01430   static int dim1 = 2 ;
01431   static int dim2 = 3 ;
01432   static Matrix Mtran(dim1,dim2) ;
01433 
01434   for ( i = 0; i < dim1; i++ ) {
01435      for ( j = 0; j < dim2; j++ ) 
01436          Mtran(i,j) = M(j,i) ;
01437   } // end for i
01438 
01439   return Mtran ;
01440 }
01441 
01442 //**********************************************************************
01443 
01444 Response*
01445 EnhancedQuad::setResponse(const char **argv, int argc, 
01446                           Information &eleInfo, OPS_Stream &output)
01447 {
01448   Response *theResponse =0;
01449 
01450   output.tag("ElementOutput");
01451   output.attr("eleType","EnhancedQuad");
01452   output.attr("eleTag",this->getTag());
01453   output.attr("node1",connectedExternalNodes[0]);
01454   output.attr("node2",connectedExternalNodes[1]);
01455   output.attr("node3",connectedExternalNodes[2]);
01456   output.attr("node4",connectedExternalNodes[3]);
01457 
01458   char dataOut[10];
01459   if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0) {
01460     
01461     for (int i=1; i<=4; i++) {
01462       sprintf(dataOut,"P1_%d",i);
01463       output.tag("ResponseType",dataOut);
01464       sprintf(dataOut,"P2_%d",i);
01465       output.tag("ResponseType",dataOut);
01466     }
01467     
01468     theResponse =  new ElementResponse(this, 1, resid);
01469   }   else if (strcmp(argv[0],"material") == 0 || strcmp(argv[0],"integrPoint") == 0) {
01470     int pointNum = atoi(argv[1]);
01471     if (pointNum > 0 && pointNum <= 4) {
01472 
01473       output.tag("GaussPoint");
01474       output.attr("number",pointNum);
01475       output.attr("eta",sg[pointNum-1]);
01476       output.attr("neta",tg[pointNum-1]);
01477 
01478       theResponse =  materialPointers[pointNum-1]->setResponse(&argv[2], argc-2, eleInfo, output);
01479       
01480       output.endTag();
01481 
01482   } else if (strcmp(argv[0],"stresses") ==0) {
01483 
01484       for (int i=0; i<4; i++) {
01485         output.tag("GaussPoint");
01486         output.attr("number",i+1);
01487         output.attr("eta",sg[i]);
01488         output.attr("neta",tg[i]);
01489 
01490         output.tag("NdMaterialOutput");
01491         output.attr("classType", materialPointers[i]->getClassTag());
01492         output.attr("tag", materialPointers[i]->getTag());
01493 
01494         output.tag("ResponseType","sigma11");
01495         output.tag("ResponseType","sigma22");
01496         output.tag("ResponseType","sigma12");
01497 
01498         output.endTag(); // GaussPoint
01499         output.endTag(); // NdMaterialOutput
01500       }
01501 
01502       theResponse =  new ElementResponse(this, 3, Vector(12));
01503     }
01504   }
01505         
01506   output.endTag(); // ElementOutput
01507 
01508   return theResponse;
01509 }
01510 
01511 int 
01512 EnhancedQuad::getResponse(int responseID, Information &eleInfo)
01513 {
01514   if (responseID == 1) {
01515 
01516     return eleInfo.setVector(this->getResistingForce());
01517 
01518   } else if (responseID == 3) {
01519 
01520     // Loop over the integration points
01521     static Vector stresses(12);
01522     int cnt = 0;
01523     for (int i = 0; i < 4; i++) {
01524 
01525       // Get material stress response
01526       const Vector &sigma = materialPointers[i]->getStress();
01527       stresses(cnt) = sigma(0);
01528       stresses(cnt+1) = sigma(1);
01529       stresses(cnt+2) = sigma(2);
01530       cnt += 3;
01531     }
01532     return eleInfo.setVector(resid);
01533         
01534   } else
01535 
01536     return -1;
01537 }
01538 
01539 
01540 
01541 int  EnhancedQuad::sendSelf (int commitTag, Channel &theChannel)
01542 {
01543   int res = 0;
01544   
01545   // note: we don't check for dataTag == 0 for Element
01546   // objects as that is taken care of in a commit by the Domain
01547   // object - don't want to have to do the check if sending data
01548   int dataTag = this->getDbTag();
01549   
01550   // Quad packs its data into a Vector and sends this to theChannel
01551   // along with its dbTag and the commitTag passed in the arguments
01552 
01553   // Now quad sends the ids of its materials
01554   int matDbTag;
01555   
01556   static ID idData(13);
01557 
01558   idData(12) = this->getTag();
01559   
01560   int i;
01561   for (i = 0; i < 4; i++) {
01562     idData(i) = materialPointers[i]->getClassTag();
01563     matDbTag = materialPointers[i]->getDbTag();
01564     // NOTE: we do have to ensure that the material has a database
01565     // tag if we are sending to a database channel.
01566     if (matDbTag == 0) {
01567       matDbTag = theChannel.getDbTag();
01568                         if (matDbTag != 0)
01569                           materialPointers[i]->setDbTag(matDbTag);
01570     }
01571     idData(i+4) = matDbTag;
01572   }
01573   
01574   idData(8) = connectedExternalNodes(0);
01575   idData(9) = connectedExternalNodes(1);
01576   idData(10) = connectedExternalNodes(2);
01577   idData(11) = connectedExternalNodes(3);
01578 
01579   res += theChannel.sendID(dataTag, commitTag, idData);
01580   if (res < 0) {
01581     opserr << "WARNING EnhancedQuad::sendSelf() - " << this->getTag() << " failed to send ID\n";
01582     return res;
01583   }
01584 
01585 
01586   res += theChannel.sendVector(dataTag, commitTag, alpha);
01587   if (res < 0) {
01588     opserr << "WARNING EnhancedQuad::sendSelf() - " << this->getTag() << " failed to send ID\n";
01589     return res;
01590   }
01591 
01592   // Finally, quad asks its material objects to send themselves
01593   for (i = 0; i < 4; i++) {
01594     res += materialPointers[i]->sendSelf(commitTag, theChannel);
01595     if (res < 0) {
01596       opserr << "WARNING EnhancedQuad::sendSelf() - " << this->getTag() << " failed to send its Material\n";
01597       return res;
01598     }
01599   }
01600   
01601   return res;
01602 }
01603     
01604 int  EnhancedQuad::recvSelf (int commitTag, 
01605                        Channel &theChannel, 
01606                        FEM_ObjectBroker &theBroker)
01607 {
01608   int res = 0;
01609   
01610   int dataTag = this->getDbTag();
01611 
01612   static ID idData(13);
01613   // Quad now receives the tags of its four external nodes
01614   res += theChannel.recvID(dataTag, commitTag, idData);
01615   if (res < 0) {
01616     opserr << "WARNING EnhancedQuad::recvSelf() - " << this->getTag() << " failed to receive ID\n";
01617     return res;
01618   }
01619 
01620   this->setTag(idData(12));
01621 
01622   connectedExternalNodes(0) = idData(8);
01623   connectedExternalNodes(1) = idData(9);
01624   connectedExternalNodes(2) = idData(10);
01625   connectedExternalNodes(3) = idData(11);
01626   
01627 
01628   res += theChannel.recvVector(dataTag, commitTag, alpha);
01629   if (res < 0) {
01630     opserr << "WARNING EnhancedQuad::sendSelf() - " << this->getTag() << " failed to send ID\n";
01631     return res;
01632   }
01633 
01634   int i;
01635 
01636   if (materialPointers[0] == 0) {
01637     for (i = 0; i < 4; i++) {
01638       int matClassTag = idData(i);
01639       int matDbTag = idData(i+4);
01640       // Allocate new material with the sent class tag
01641       materialPointers[i] = theBroker.getNewNDMaterial(matClassTag);
01642       if (materialPointers[i] == 0) {
01643         opserr << "EnhancedQuad::recvSelf() - Broker could not create NDMaterial of class type " << matClassTag << endln;
01644         return -1;
01645       }
01646       // Now receive materials into the newly allocated space
01647       materialPointers[i]->setDbTag(matDbTag);
01648       res += materialPointers[i]->recvSelf(commitTag, theChannel, theBroker);
01649       if (res < 0) {
01650         opserr << "NLBeamColumn3d::recvSelf() - material " << i << "failed to recv itself\n";
01651         return res;
01652       }
01653     }
01654   }
01655 
01656   // materials exist , ensure materials of correct type and recvSelf on them
01657   else {
01658     for (i = 0; i < 4; i++) {
01659       int matClassTag = idData(i);
01660       int matDbTag = idData(i+4);
01661       // Check that material is of the right type; if not,
01662       // delete it and create a new one of the right type
01663       if (materialPointers[i]->getClassTag() != matClassTag) {
01664         delete materialPointers[i];
01665         materialPointers[i] = theBroker.getNewNDMaterial(matClassTag);
01666         if (materialPointers[i] == 0) {
01667           opserr << "EnhancedQuad::recvSelf() - Broker could not create NDMaterial of class type" << matClassTag << endln;
01668           exit(-1);
01669         }
01670       materialPointers[i]->setDbTag(matDbTag);
01671       }
01672       // Receive the material
01673 
01674       res += materialPointers[i]->recvSelf(commitTag, theChannel, theBroker);
01675       if (res < 0) {
01676         opserr << "EnhancedQuad::recvSelf() - material " << i << "failed to recv itself\n";
01677         return res;
01678       }
01679     }
01680   }
01681 
01682   return res;
01683 }
01684 //**************************************************************************
01685 
01686 int
01687 EnhancedQuad::displaySelf(Renderer &theViewer, int displayMode, float fact)
01688 {
01689     // first set the quantity to be displayed at the nodes;
01690     // if displayMode is 1 through 3 we will plot material stresses otherwise 0.0
01691 
01692     static Vector values(4) ;
01693 
01694     for (int j=0; j<4; j++)
01695       values(j) = 0.0;
01696 
01697     // until someone projects the stress to the nodes will display the stress 
01698     // at the guass points at the nodes .. could also just display the average!
01699     if (displayMode < 4 && displayMode > 0) {
01700         for (int i=0; i<4; i++) {
01701           const Vector &stress = materialPointers[i]->getStress();
01702           values(i) = stress(displayMode-1);
01703         }
01704     }
01705 
01706     // now determine the end points of the quad based on
01707     // the display factor (a measure of the distorted image)
01708     // store this information in 4 3d vectors v1 through v4
01709 
01710     const Vector &end1Crd = nodePointers[0]->getCrds();
01711     const Vector &end2Crd = nodePointers[1]->getCrds(); 
01712     const Vector &end3Crd = nodePointers[2]->getCrds(); 
01713     const Vector &end4Crd = nodePointers[3]->getCrds(); 
01714 
01715     static Matrix coords(4,3) ;
01716 
01717     if (displayMode >= 0) {    
01718       
01719       const Vector &end1Disp = nodePointers[0]->getDisp();
01720       const Vector &end2Disp = nodePointers[1]->getDisp();
01721       const Vector &end3Disp = nodePointers[2]->getDisp();
01722       const Vector &end4Disp = nodePointers[3]->getDisp();
01723       
01724       for (int i = 0; i < 2; i++) {
01725         coords(0,i) = end1Crd(i) + end1Disp(i)*fact;
01726         coords(1,i) = end2Crd(i) + end2Disp(i)*fact;    
01727         coords(2,i) = end3Crd(i) + end3Disp(i)*fact;    
01728         coords(3,i) = end4Crd(i) + end4Disp(i)*fact;    
01729       }
01730     } else {
01731       int mode = displayMode  *  -1;
01732       const Matrix &eigen1 = nodePointers[0]->getEigenvectors();
01733       const Matrix &eigen2 = nodePointers[1]->getEigenvectors();
01734       const Matrix &eigen3 = nodePointers[2]->getEigenvectors();
01735       const Matrix &eigen4 = nodePointers[3]->getEigenvectors();
01736       if (eigen1.noCols() >= mode) {
01737         for (int i = 0; i < 2; i++) {
01738           coords(0,i) = end1Crd(i) + eigen1(i,mode-1)*fact;
01739           coords(1,i) = end2Crd(i) + eigen2(i,mode-1)*fact;
01740           coords(2,i) = end3Crd(i) + eigen3(i,mode-1)*fact;
01741           coords(3,i) = end4Crd(i) + eigen4(i,mode-1)*fact;
01742         }    
01743       } else {
01744         for (int i = 0; i < 2; i++) {
01745           coords(0,i) = end1Crd(i);
01746           coords(1,i) = end2Crd(i);
01747           coords(2,i) = end3Crd(i);
01748           coords(3,i) = end4Crd(i);
01749         }    
01750       }
01751     }
01752 
01753     int error = 0;
01754 
01755     // finally we draw the element using drawPolygon
01756     error += theViewer.drawPolygon (coords, values);
01757 
01758     return error;
01759 }
01760 

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