FourNodeQuad.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.27 $
00022 // $Date: 2006/09/05 21:11:21 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/element/fourNodeQuad/FourNodeQuad.cpp,v $
00024 
00025 // Written: MHS
00026 // Created: Feb 2000
00027 // Revised: Dec 2000 for efficiency
00028 //
00029 // Description: This file contains the class definition for FourNodeQuad.
00030 
00031 #include <FourNodeQuad.h>
00032 #include <Node.h>
00033 #include <NDMaterial.h>
00034 #include <Matrix.h>
00035 #include <Vector.h>
00036 #include <ID.h>
00037 #include <Renderer.h>
00038 #include <Domain.h>
00039 #include <string.h>
00040 #include <Information.h>
00041 #include <Parameter.h>
00042 #include <Channel.h>
00043 #include <FEM_ObjectBroker.h>
00044 #include <ElementResponse.h>
00045 
00046 
00047 double FourNodeQuad::matrixData[64];
00048 Matrix FourNodeQuad::K(matrixData, 8, 8);
00049 Vector FourNodeQuad::P(8);
00050 double FourNodeQuad::shp[3][4];
00051 double FourNodeQuad::pts[4][2];
00052 double FourNodeQuad::wts[4];
00053 
00054 FourNodeQuad::FourNodeQuad(int tag, int nd1, int nd2, int nd3, int nd4,
00055                            NDMaterial &m, const char *type, double t,
00056                            double p, double r, double b1, double b2)
00057 :Element (tag, ELE_TAG_FourNodeQuad), 
00058   theMaterial(0), connectedExternalNodes(4), 
00059   Q(8), pressureLoad(8), thickness(t), rho(r), pressure(p), Ki(0)
00060 {
00061         pts[0][0] = -0.5773502691896258;
00062         pts[0][1] = -0.5773502691896258;
00063         pts[1][0] =  0.5773502691896258;
00064         pts[1][1] = -0.5773502691896258;
00065         pts[2][0] =  0.5773502691896258;
00066         pts[2][1] =  0.5773502691896258;
00067         pts[3][0] = -0.5773502691896258;
00068         pts[3][1] =  0.5773502691896258;
00069 
00070         wts[0] = 1.0;
00071         wts[1] = 1.0;
00072         wts[2] = 1.0;
00073         wts[3] = 1.0;
00074 
00075         if (strcmp(type,"PlaneStrain") != 0 && strcmp(type,"PlaneStress") != 0
00076             && strcmp(type,"PlaneStrain2D") != 0 && strcmp(type,"PlaneStress2D") != 0) {
00077           opserr << "FourNodeQuad::FourNodeQuad -- improper material type: " << type << "for FourNodeQuad\n";
00078           exit(-1);
00079         }
00080 
00081         // Body forces
00082         b[0] = b1;
00083         b[1] = b2;
00084 
00085     // Allocate arrays of pointers to NDMaterials
00086     theMaterial = new NDMaterial *[4];
00087     
00088     if (theMaterial == 0) {
00089       opserr << "FourNodeQuad::FourNodeQuad - failed allocate material model pointer\n";
00090       exit(-1);
00091     }
00092 
00093         int i;
00094     for (i = 0; i < 4; i++) {
00095       
00096       // Get copies of the material model for each integration point
00097       theMaterial[i] = m.getCopy(type);
00098                         
00099       // Check allocation
00100       if (theMaterial[i] == 0) {
00101         opserr << "FourNodeQuad::FourNodeQuad -- failed to get a copy of material model\n";
00102         exit(-1);
00103       }
00104     }
00105 
00106     // Set connected external node IDs
00107     connectedExternalNodes(0) = nd1;
00108     connectedExternalNodes(1) = nd2;
00109     connectedExternalNodes(2) = nd3;
00110     connectedExternalNodes(3) = nd4;
00111     
00112     for (i=0; i<4; i++)
00113       theNodes[i] = 0;
00114 }
00115 
00116 FourNodeQuad::FourNodeQuad()
00117 :Element (0,ELE_TAG_FourNodeQuad),
00118   theMaterial(0), connectedExternalNodes(4), 
00119  Q(8), pressureLoad(8), thickness(0.0), rho(0.0), pressure(0.0), Ki(0)
00120 {
00121   pts[0][0] = -0.577350269189626;
00122   pts[0][1] = -0.577350269189626;
00123   pts[1][0] =  0.577350269189626;
00124   pts[1][1] = -0.577350269189626;
00125   pts[2][0] =  0.577350269189626;
00126   pts[2][1] =  0.577350269189626;
00127   pts[3][0] = -0.577350269189626;
00128   pts[3][1] =  0.577350269189626;
00129   
00130   wts[0] = 1.0;
00131   wts[1] = 1.0;
00132   wts[2] = 1.0;
00133   wts[3] = 1.0;
00134 
00135     for (int i=0; i<4; i++)
00136       theNodes[i] = 0;
00137 }
00138 
00139 FourNodeQuad::~FourNodeQuad()
00140 {    
00141   for (int i = 0; i < 4; i++) {
00142     if (theMaterial[i])
00143       delete theMaterial[i];
00144   }
00145 
00146   // Delete the array of pointers to NDMaterial pointer arrays
00147   if (theMaterial)
00148     delete [] theMaterial;
00149 
00150   if (Ki != 0)
00151     delete Ki;
00152 }
00153 
00154 int
00155 FourNodeQuad::getNumExternalNodes() const
00156 {
00157     return 4;
00158 }
00159 
00160 const ID&
00161 FourNodeQuad::getExternalNodes()
00162 {
00163     return connectedExternalNodes;
00164 }
00165 
00166 
00167 Node **
00168 FourNodeQuad::getNodePtrs(void) 
00169 {
00170   return theNodes;
00171 }
00172 
00173 int
00174 FourNodeQuad::getNumDOF()
00175 {
00176     return 8;
00177 }
00178 
00179 void
00180 FourNodeQuad::setDomain(Domain *theDomain)
00181 {
00182         // Check Domain is not null - invoked when object removed from a domain
00183     if (theDomain == 0) {
00184         theNodes[0] = 0;
00185         theNodes[1] = 0;
00186         theNodes[2] = 0;
00187         theNodes[3] = 0;
00188         return;
00189     }
00190 
00191     int Nd1 = connectedExternalNodes(0);
00192     int Nd2 = connectedExternalNodes(1);
00193     int Nd3 = connectedExternalNodes(2);
00194     int Nd4 = connectedExternalNodes(3);
00195 
00196     theNodes[0] = theDomain->getNode(Nd1);
00197     theNodes[1] = theDomain->getNode(Nd2);
00198     theNodes[2] = theDomain->getNode(Nd3);
00199     theNodes[3] = theDomain->getNode(Nd4);
00200 
00201     if (theNodes[0] == 0 || theNodes[1] == 0 || theNodes[2] == 0 || theNodes[3] == 0) {
00202         //opserr << "FATAL ERROR FourNodeQuad (tag: %d), node not found in domain",
00203         //      this->getTag());
00204         
00205         return;
00206     }
00207 
00208     int dofNd1 = theNodes[0]->getNumberDOF();
00209     int dofNd2 = theNodes[1]->getNumberDOF();
00210     int dofNd3 = theNodes[2]->getNumberDOF();
00211     int dofNd4 = theNodes[3]->getNumberDOF();
00212     
00213     if (dofNd1 != 2 || dofNd2 != 2 || dofNd3 != 2 || dofNd4 != 2) {
00214         //opserr << "FATAL ERROR FourNodeQuad (tag: %d), has differing number of DOFs at its nodes",
00215         //      this->getTag());
00216         
00217         return;
00218     }
00219     this->DomainComponent::setDomain(theDomain);
00220 
00221     // Compute consistent nodal loads due to pressure
00222     this->setPressureLoadAtNodes();
00223 }
00224 
00225 int
00226 FourNodeQuad::commitState()
00227 {
00228     int retVal = 0;
00229 
00230     // call element commitState to do any base class stuff
00231     if ((retVal = this->Element::commitState()) != 0) {
00232       opserr << "FourNodeQuad::commitState () - failed in base class";
00233     }    
00234 
00235     // Loop over the integration points and commit the material states
00236     for (int i = 0; i < 4; i++)
00237       retVal += theMaterial[i]->commitState();
00238 
00239     return retVal;
00240 }
00241 
00242 int
00243 FourNodeQuad::revertToLastCommit()
00244 {
00245     int retVal = 0;
00246 
00247     // Loop over the integration points and revert to last committed state
00248     for (int i = 0; i < 4; i++)
00249                 retVal += theMaterial[i]->revertToLastCommit();
00250 
00251     return retVal;
00252 }
00253 
00254 int
00255 FourNodeQuad::revertToStart()
00256 {
00257     int retVal = 0;
00258 
00259     // Loop over the integration points and revert states to start
00260     for (int i = 0; i < 4; i++)
00261                 retVal += theMaterial[i]->revertToStart();
00262 
00263     return retVal;
00264 }
00265 
00266 
00267 int
00268 FourNodeQuad::update()
00269 {
00270         const Vector &disp1 = theNodes[0]->getTrialDisp();
00271         const Vector &disp2 = theNodes[1]->getTrialDisp();
00272         const Vector &disp3 = theNodes[2]->getTrialDisp();
00273         const Vector &disp4 = theNodes[3]->getTrialDisp();
00274         
00275         static double u[2][4];
00276 
00277         u[0][0] = disp1(0);
00278         u[1][0] = disp1(1);
00279         u[0][1] = disp2(0);
00280         u[1][1] = disp2(1);
00281         u[0][2] = disp3(0);
00282         u[1][2] = disp3(1);
00283         u[0][3] = disp4(0);
00284         u[1][3] = disp4(1);
00285 
00286         static Vector eps(3);
00287 
00288         int ret = 0;
00289 
00290         // Loop over the integration points
00291         for (int i = 0; i < 4; i++) {
00292 
00293                 // Determine Jacobian for this integration point
00294                 this->shapeFunction(pts[i][0], pts[i][1]);
00295 
00296                 // Interpolate strains
00297                 //eps = B*u;
00298                 //eps.addMatrixVector(0.0, B, u, 1.0);
00299                 eps.Zero();
00300                 for (int beta = 0; beta < 4; beta++) {
00301                         eps(0) += shp[0][beta]*u[0][beta];
00302                         eps(1) += shp[1][beta]*u[1][beta];
00303                         eps(2) += shp[0][beta]*u[1][beta] + shp[1][beta]*u[0][beta];
00304                 }
00305 
00306                 // Set the material strain
00307                 ret += theMaterial[i]->setTrialStrain(eps);
00308         }
00309 
00310         return ret;
00311 }
00312 
00313 
00314 const Matrix&
00315 FourNodeQuad::getTangentStiff()
00316 {
00317 
00318         K.Zero();
00319 
00320         double dvol;
00321         double DB[3][2];
00322 
00323         // Loop over the integration points
00324         for (int i = 0; i < 4; i++) {
00325 
00326           // Determine Jacobian for this integration point
00327           dvol = this->shapeFunction(pts[i][0], pts[i][1]);
00328           dvol *= (thickness*wts[i]);
00329           
00330           // Get the material tangent
00331           const Matrix &D = theMaterial[i]->getTangent();
00332           
00333           // Perform numerical integration
00334           //K = K + (B^ D * B) * intWt(i)*intWt(j) * detJ;
00335           //K.addMatrixTripleProduct(1.0, B, D, intWt(i)*intWt(j)*detJ);
00336           
00337           double D00 = D(0,0); double D01 = D(0,1); double D02 = D(0,2);
00338           double D10 = D(1,0); double D11 = D(1,1); double D12 = D(1,2);
00339           double D20 = D(2,0); double D21 = D(2,1); double D22 = D(2,2);
00340 
00341           //      for (int beta = 0, ib = 0, colIb =0, colIbP1 = 8; 
00342           //   beta < 4; 
00343           //   beta++, ib += 2, colIb += 16, colIbP1 += 16) {
00344             
00345           for (int alpha = 0, ia = 0; alpha < 4; alpha++, ia += 2) {
00346             for (int beta = 0, ib = 0; beta < 4; beta++, ib += 2) {
00347               
00348               DB[0][0] = dvol * (D00 * shp[0][beta] + D02 * shp[1][beta]);
00349               DB[1][0] = dvol * (D10 * shp[0][beta] + D12 * shp[1][beta]);
00350               DB[2][0] = dvol * (D20 * shp[0][beta] + D22 * shp[1][beta]);
00351               DB[0][1] = dvol * (D01 * shp[1][beta] + D02 * shp[0][beta]);
00352               DB[1][1] = dvol * (D11 * shp[1][beta] + D12 * shp[0][beta]);
00353               DB[2][1] = dvol * (D21 * shp[1][beta] + D22 * shp[0][beta]);
00354               
00355 
00356               K(ia,ib) += shp[0][alpha]*DB[0][0] + shp[1][alpha]*DB[2][0];
00357               K(ia,ib+1) += shp[0][alpha]*DB[0][1] + shp[1][alpha]*DB[2][1];
00358               K(ia+1,ib) += shp[1][alpha]*DB[1][0] + shp[0][alpha]*DB[2][0];
00359               K(ia+1,ib+1) += shp[1][alpha]*DB[1][1] + shp[0][alpha]*DB[2][1];
00360               //              matrixData[colIb   +   ia] += shp[0][alpha]*DB[0][0] + shp[1][alpha]*DB[2][0];
00361               //matrixData[colIbP1 +   ia] += shp[0][alpha]*DB[0][1] + shp[1][alpha]*DB[2][1];
00362               //matrixData[colIb   + ia+1] += shp[1][alpha]*DB[1][0] + shp[0][alpha]*DB[2][0];
00363               //matrixData[colIbP1 + ia+1] += shp[1][alpha]*DB[1][1] + shp[0][alpha]*DB[2][1];
00364               
00365             }
00366           }
00367         }
00368         
00369         return K;
00370 }
00371 
00372 
00373 const Matrix&
00374 FourNodeQuad::getInitialStiff()
00375 {
00376   if (Ki != 0)
00377     return *Ki;
00378 
00379   K.Zero();
00380   
00381   double dvol;
00382   double DB[3][2];
00383   
00384   // Loop over the integration points
00385   for (int i = 0; i < 4; i++) {
00386     
00387     // Determine Jacobian for this integration point
00388     dvol = this->shapeFunction(pts[i][0], pts[i][1]);
00389     dvol *= (thickness*wts[i]);
00390     
00391     // Get the material tangent
00392     const Matrix &D = theMaterial[i]->getInitialTangent();
00393 
00394     double D00 = D(0,0); double D01 = D(0,1); double D02 = D(0,2);
00395     double D10 = D(1,0); double D11 = D(1,1); double D12 = D(1,2);
00396     double D20 = D(2,0); double D21 = D(2,1); double D22 = D(2,2);
00397     
00398     // Perform numerical integration
00399     //K = K + (B^ D * B) * intWt(i)*intWt(j) * detJ;
00400     //K.addMatrixTripleProduct(1.0, B, D, intWt(i)*intWt(j)*detJ);
00401     for (int beta = 0, ib = 0, colIb =0, colIbP1 = 8; 
00402          beta < 4; 
00403          beta++, ib += 2, colIb += 16, colIbP1 += 16) {
00404       
00405       for (int alpha = 0, ia = 0; alpha < 4; alpha++, ia += 2) {
00406         
00407         DB[0][0] = dvol * (D00 * shp[0][beta] + D02 * shp[1][beta]);
00408         DB[1][0] = dvol * (D10 * shp[0][beta] + D12 * shp[1][beta]);
00409         DB[2][0] = dvol * (D20 * shp[0][beta] + D22 * shp[1][beta]);
00410         DB[0][1] = dvol * (D01 * shp[1][beta] + D02 * shp[0][beta]);
00411         DB[1][1] = dvol * (D11 * shp[1][beta] + D12 * shp[0][beta]);
00412         DB[2][1] = dvol * (D21 * shp[1][beta] + D22 * shp[0][beta]);
00413         
00414         matrixData[colIb   +   ia] += shp[0][alpha]*DB[0][0] + shp[1][alpha]*DB[2][0];
00415         matrixData[colIbP1 +   ia] += shp[0][alpha]*DB[0][1] + shp[1][alpha]*DB[2][1];
00416         matrixData[colIb   + ia+1] += shp[1][alpha]*DB[1][0] + shp[0][alpha]*DB[2][0];
00417         matrixData[colIbP1 + ia+1] += shp[1][alpha]*DB[1][1] + shp[0][alpha]*DB[2][1];
00418       }
00419     }
00420   }
00421 
00422   Ki = new Matrix(K);
00423   return K;
00424 }
00425 
00426 const Matrix&
00427 FourNodeQuad::getMass()
00428 {
00429         K.Zero();
00430 
00431         int i;
00432         static double rhoi[4];
00433         double sum = this->rho;
00434         for (i = 0; i < 4; i++) {
00435           rhoi[i] = theMaterial[i]->getRho();
00436           sum += rhoi[i];
00437         }
00438 
00439         if (sum == 0.0)
00440           return K;
00441 
00442         double rhodvol, Nrho;
00443 
00444         // Compute a lumped mass matrix
00445         for (i = 0; i < 4; i++) {
00446 
00447                 // Determine Jacobian for this integration point
00448                 rhodvol = this->shapeFunction(pts[i][0], pts[i][1]);
00449 
00450                 // Element plus material density ... MAY WANT TO REMOVE ELEMENT DENSITY
00451                 double tmp = rho + rhoi[i];
00452                 rhodvol *= (tmp*thickness*wts[i]);
00453 
00454                 for (int alpha = 0, ia = 0; alpha < 4; alpha++, ia++) {
00455                         Nrho = shp[2][alpha]*rhodvol;
00456                         K(ia,ia) += Nrho;
00457                         ia++;
00458                         K(ia,ia) += Nrho;
00459                 }
00460         }
00461 
00462         return K;
00463 }
00464 
00465 void
00466 FourNodeQuad::zeroLoad(void)
00467 {
00468   Q.Zero();
00469   return;
00470 }
00471 
00472 int 
00473 FourNodeQuad::addLoad(ElementalLoad *theLoad, double loadFactor)
00474 {
00475   opserr << "FourNodeQuad::addLoad - load type unknown for ele with tag: " << this->getTag() << endln;
00476   return -1;
00477 }
00478 
00479 int 
00480 FourNodeQuad::addInertiaLoadToUnbalance(const Vector &accel)
00481 {
00482   int i;
00483   static double rhoi[4];
00484   double sum = this->rho;
00485   for (i = 0; i < 4; i++) {
00486     rhoi[i] = theMaterial[i]->getRho();
00487     sum += rhoi[i];
00488   }
00489   
00490   if (sum == 0.0)
00491     return 0;
00492   
00493   // Get R * accel from the nodes
00494   const Vector &Raccel1 = theNodes[0]->getRV(accel);
00495   const Vector &Raccel2 = theNodes[1]->getRV(accel);
00496   const Vector &Raccel3 = theNodes[2]->getRV(accel);
00497   const Vector &Raccel4 = theNodes[3]->getRV(accel);
00498   
00499   if (2 != Raccel1.Size() || 2 != Raccel2.Size() || 2 != Raccel3.Size() ||
00500       2 != Raccel4.Size()) {
00501     opserr << "FourNodeQuad::addInertiaLoadToUnbalance matrix and vector sizes are incompatable\n";
00502     return -1;
00503   }
00504   
00505   static double ra[8];
00506   
00507   ra[0] = Raccel1(0);
00508   ra[1] = Raccel1(1);
00509   ra[2] = Raccel2(0);
00510   ra[3] = Raccel2(1);
00511   ra[4] = Raccel3(0);
00512   ra[5] = Raccel3(1);
00513   ra[6] = Raccel4(0);
00514   ra[7] = Raccel4(1);
00515   
00516   // Compute mass matrix
00517   this->getMass();
00518   
00519   // Want to add ( - fact * M R * accel ) to unbalance
00520   // Take advantage of lumped mass matrix
00521   for (i = 0; i < 8; i++)
00522     Q(i) += -K(i,i)*ra[i];
00523   
00524   return 0;
00525 }
00526 
00527 const Vector&
00528 FourNodeQuad::getResistingForce()
00529 {
00530         P.Zero();
00531 
00532         double dvol;
00533 
00534         // Loop over the integration points
00535         for (int i = 0; i < 4; i++) {
00536 
00537                 // Determine Jacobian for this integration point
00538                 dvol = this->shapeFunction(pts[i][0], pts[i][1]);
00539                 dvol *= (thickness*wts[i]);
00540 
00541                 // Get material stress response
00542                 const Vector &sigma = theMaterial[i]->getStress();
00543 
00544                 // Perform numerical integration on internal force
00545                 //P = P + (B^ sigma) * intWt(i)*intWt(j) * detJ;
00546                 //P.addMatrixTransposeVector(1.0, B, sigma, intWt(i)*intWt(j)*detJ);
00547                 for (int alpha = 0, ia = 0; alpha < 4; alpha++, ia += 2) {
00548                         
00549                         P(ia) += dvol*(shp[0][alpha]*sigma(0) + shp[1][alpha]*sigma(2));
00550                         
00551                         P(ia+1) += dvol*(shp[1][alpha]*sigma(1) + shp[0][alpha]*sigma(2));
00552 
00553                         // Subtract equiv. body forces from the nodes
00554                         //P = P - (N^ b) * intWt(i)*intWt(j) * detJ;
00555                         //P.addMatrixTransposeVector(1.0, N, b, -intWt(i)*intWt(j)*detJ);
00556                         P(ia) -= dvol*(shp[2][alpha]*b[0]);
00557                         P(ia+1) -= dvol*(shp[2][alpha]*b[1]);
00558                 }
00559         }
00560 
00561         // Subtract pressure loading from resisting force
00562         if (pressure != 0.0) {
00563                 //P = P - pressureLoad;
00564                 P.addVector(1.0, pressureLoad, -1.0);
00565         }
00566         
00567         // Subtract other external nodal loads ... P_res = P_int - P_ext
00568         //P = P - Q;
00569         P.addVector(1.0, Q, -1.0);
00570 
00571         return P;
00572 }
00573 
00574 const Vector&
00575 FourNodeQuad::getResistingForceIncInertia()
00576 {
00577         int i;
00578         static double rhoi[4];
00579         double sum = this->rho;
00580         for (i = 0; i < 4; i++) {
00581           rhoi[i] = theMaterial[i]->getRho();
00582           sum += rhoi[i];
00583         }
00584 
00585         // if no mass terms .. just add damping terms
00586         if (sum == 0.0) {
00587           this->getResistingForce();
00588 
00589           // add the damping forces if rayleigh damping
00590           if (betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00591             P += this->getRayleighDampingForces();
00592 
00593           return P;
00594         }
00595 
00596         const Vector &accel1 = theNodes[0]->getTrialAccel();
00597         const Vector &accel2 = theNodes[1]->getTrialAccel();
00598         const Vector &accel3 = theNodes[2]->getTrialAccel();
00599         const Vector &accel4 = theNodes[3]->getTrialAccel();
00600         
00601         static double a[8];
00602 
00603         a[0] = accel1(0);
00604         a[1] = accel1(1);
00605         a[2] = accel2(0);
00606         a[3] = accel2(1);
00607         a[4] = accel3(0);
00608         a[5] = accel3(1);
00609         a[6] = accel4(0);
00610         a[7] = accel4(1);
00611 
00612         // Compute the current resisting force
00613         this->getResistingForce();
00614 
00615         // Compute the mass matrix
00616         this->getMass();
00617 
00618         // Take advantage of lumped mass matrix
00619         for (i = 0; i < 8; i++)
00620                 P(i) += K(i,i)*a[i];
00621 
00622         // add the damping forces if rayleigh damping
00623         if (alphaM != 0.0 || betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00624           P += this->getRayleighDampingForces();
00625 
00626         return P;
00627 }
00628 
00629 int
00630 FourNodeQuad::sendSelf(int commitTag, Channel &theChannel)
00631 {
00632   int res = 0;
00633   
00634   // note: we don't check for dataTag == 0 for Element
00635   // objects as that is taken care of in a commit by the Domain
00636   // object - don't want to have to do the check if sending data
00637   int dataTag = this->getDbTag();
00638   
00639   // Quad packs its data into a Vector and sends this to theChannel
00640   // along with its dbTag and the commitTag passed in the arguments
00641   static Vector data(6);
00642   data(0) = this->getTag();
00643   data(1) = thickness;
00644   data(2) = rho;
00645   data(3) = b[0];
00646   data(4) = b[1];
00647   data(5) = pressure;
00648   
00649   res += theChannel.sendVector(dataTag, commitTag, data);
00650   if (res < 0) {
00651     opserr << "WARNING FourNodeQuad::sendSelf() - " << this->getTag() << " failed to send Vector\n";
00652     return res;
00653   }           
00654   
00655 
00656   // Now quad sends the ids of its materials
00657   int matDbTag;
00658   
00659   static ID idData(12);
00660   
00661   int i;
00662   for (i = 0; i < 4; i++) {
00663     idData(i) = theMaterial[i]->getClassTag();
00664     matDbTag = theMaterial[i]->getDbTag();
00665     // NOTE: we do have to ensure that the material has a database
00666     // tag if we are sending to a database channel.
00667     if (matDbTag == 0) {
00668       matDbTag = theChannel.getDbTag();
00669                         if (matDbTag != 0)
00670                           theMaterial[i]->setDbTag(matDbTag);
00671     }
00672     idData(i+4) = matDbTag;
00673   }
00674   
00675   idData(8) = connectedExternalNodes(0);
00676   idData(9) = connectedExternalNodes(1);
00677   idData(10) = connectedExternalNodes(2);
00678   idData(11) = connectedExternalNodes(3);
00679 
00680   res += theChannel.sendID(dataTag, commitTag, idData);
00681   if (res < 0) {
00682     opserr << "WARNING FourNodeQuad::sendSelf() - " << this->getTag() << " failed to send ID\n";
00683     return res;
00684   }
00685 
00686   // Finally, quad asks its material objects to send themselves
00687   for (i = 0; i < 4; i++) {
00688     res += theMaterial[i]->sendSelf(commitTag, theChannel);
00689     if (res < 0) {
00690       opserr << "WARNING FourNodeQuad::sendSelf() - " << this->getTag() << " failed to send its Material\n";
00691       return res;
00692     }
00693   }
00694   
00695   return res;
00696 }
00697 
00698 int
00699 FourNodeQuad::recvSelf(int commitTag, Channel &theChannel,
00700                                                 FEM_ObjectBroker &theBroker)
00701 {
00702   int res = 0;
00703   
00704   int dataTag = this->getDbTag();
00705 
00706   // Quad creates a Vector, receives the Vector and then sets the 
00707   // internal data with the data in the Vector
00708   static Vector data(6);
00709   res += theChannel.recvVector(dataTag, commitTag, data);
00710   if (res < 0) {
00711     opserr << "WARNING FourNodeQuad::recvSelf() - failed to receive Vector\n";
00712     return res;
00713   }
00714   
00715   this->setTag((int)data(0));
00716   thickness = data(1);
00717   rho = data(2);
00718   b[0] = data(3);
00719   b[1] = data(4);
00720   pressure = data(5);
00721 
00722   static ID idData(12);
00723   // Quad now receives the tags of its four external nodes
00724   res += theChannel.recvID(dataTag, commitTag, idData);
00725   if (res < 0) {
00726     opserr << "WARNING FourNodeQuad::recvSelf() - " << this->getTag() << " failed to receive ID\n";
00727     return res;
00728   }
00729 
00730   connectedExternalNodes(0) = idData(8);
00731   connectedExternalNodes(1) = idData(9);
00732   connectedExternalNodes(2) = idData(10);
00733   connectedExternalNodes(3) = idData(11);
00734   
00735 
00736   if (theMaterial == 0) {
00737     // Allocate new materials
00738     theMaterial = new NDMaterial *[4];
00739     if (theMaterial == 0) {
00740       opserr << "FourNodeQuad::recvSelf() - Could not allocate NDMaterial* array\n";
00741       return -1;
00742     }
00743     for (int i = 0; i < 4; i++) {
00744       int matClassTag = idData(i);
00745       int matDbTag = idData(i+4);
00746       // Allocate new material with the sent class tag
00747       theMaterial[i] = theBroker.getNewNDMaterial(matClassTag);
00748       if (theMaterial[i] == 0) {
00749         opserr << "FourNodeQuad::recvSelf() - Broker could not create NDMaterial of class type " << matClassTag << endln;
00750         return -1;
00751       }
00752       // Now receive materials into the newly allocated space
00753       theMaterial[i]->setDbTag(matDbTag);
00754       res += theMaterial[i]->recvSelf(commitTag, theChannel, theBroker);
00755       if (res < 0) {
00756 opserr << "NLBeamColumn3d::recvSelf() - material " << i << "failed to recv itself\n";
00757         return res;
00758       }
00759     }
00760   }
00761 
00762   // materials exist , ensure materials of correct type and recvSelf on them
00763   else {
00764     for (int i = 0; i < 4; i++) {
00765       int matClassTag = idData(i);
00766       int matDbTag = idData(i+4);
00767       // Check that material is of the right type; if not,
00768       // delete it and create a new one of the right type
00769       if (theMaterial[i]->getClassTag() != matClassTag) {
00770         delete theMaterial[i];
00771         theMaterial[i] = theBroker.getNewNDMaterial(matClassTag);
00772         if (theMaterial[i] == 0) {
00773 opserr << "NLBeamColumn3d::recvSelf() - material " << i << "failed to create\n";
00774                                 
00775           return -1;
00776         }
00777       }
00778       // Receive the material
00779       theMaterial[i]->setDbTag(matDbTag);
00780       res += theMaterial[i]->recvSelf(commitTag, theChannel, theBroker);
00781       if (res < 0) {
00782 opserr << "NLBeamColumn3d::recvSelf() - material " << i << "failed to recv itself\n";
00783         return res;
00784       }
00785     }
00786   }
00787   
00788   return res;
00789 }
00790 
00791 void
00792 FourNodeQuad::Print(OPS_Stream &s, int flag)
00793 {
00794   if (flag == 2) {
00795 
00796     s << "#FourNodeQuad\n";
00797     
00798     int i;
00799     const int numNodes = 4;
00800     const int nstress = 3 ;
00801     
00802     for (i=0; i<numNodes; i++) {
00803       const Vector &nodeCrd = theNodes[i]->getCrds();
00804       const Vector &nodeDisp = theNodes[i]->getDisp();
00805       s << "#NODE " << nodeCrd(0) << " " << nodeCrd(1) << " " << endln;
00806      }
00807     
00808     // spit out the section location & invoke print on the scetion
00809     const int numMaterials = 4;
00810 
00811     static Vector avgStress(nstress);
00812     static Vector avgStrain(nstress);
00813     avgStress.Zero();
00814     avgStrain.Zero();
00815     for (i=0; i<numMaterials; i++) {
00816       avgStress += theMaterial[i]->getCommittedStress();
00817       avgStrain += theMaterial[i]->getCommittedStrain();
00818     }
00819     avgStress /= numMaterials;
00820     avgStrain /= numMaterials;
00821 
00822     s << "#AVERAGE_STRESS ";
00823     for (i=0; i<nstress; i++)
00824       s << avgStress(i) << " " ;
00825     s << endln;
00826 
00827     s << "#AVERAGE_STRAIN ";
00828     for (i=0; i<nstress; i++)
00829       s << avgStrain(i) << " " ;
00830     s << endln;
00831 
00832   } else {
00833         s << "\nFourNodeQuad, element id:  " << this->getTag() << endln;
00834         s << "\tConnected external nodes:  " << connectedExternalNodes;
00835         s << "\tthickness:  " << thickness << endln;
00836         s << "\tmass density:  " << rho << endln;
00837         s << "\tsurface pressure:  " << pressure << endln;
00838         s << "\tbody forces:  " << b[0] << " " << b[1] << endln;
00839         theMaterial[0]->Print(s,flag);
00840         s << "\tStress (xx yy xy)" << endln;
00841         for (int i = 0; i < 4; i++)
00842                 s << "\t\tGauss point " << i+1 << ": " << theMaterial[i]->getStress();
00843   }
00844 }
00845 
00846 int
00847 FourNodeQuad::displaySelf(Renderer &theViewer, int displayMode, float fact)
00848 {
00849 
00850     // first set the quantity to be displayed at the nodes;
00851     // if displayMode is 1 through 3 we will plot material stresses otherwise 0.0
00852 
00853     static Vector values(4);
00854 
00855     for (int j=0; j<4; j++)
00856            values(j) = 0.0;
00857 
00858     if (displayMode < 4 && displayMode > 0) {
00859         for (int i=0; i<4; i++) {
00860           const Vector &stress = theMaterial[i]->getStress();
00861           values(i) = stress(displayMode-1);
00862         }
00863     }
00864 
00865     // now  determine the end points of the quad based on
00866     // the display factor (a measure of the distorted image)
00867     // store this information in 4 3d vectors v1 through v4
00868     const Vector &end1Crd = theNodes[0]->getCrds();
00869     const Vector &end2Crd = theNodes[1]->getCrds();     
00870     const Vector &end3Crd = theNodes[2]->getCrds();     
00871     const Vector &end4Crd = theNodes[3]->getCrds();     
00872 
00873     static Matrix coords(4,3);
00874 
00875     if (displayMode >= 0) {    
00876       
00877       const Vector &end1Disp = theNodes[0]->getDisp();
00878       const Vector &end2Disp = theNodes[1]->getDisp();
00879       const Vector &end3Disp = theNodes[2]->getDisp();
00880       const Vector &end4Disp = theNodes[3]->getDisp();
00881 
00882       for (int i = 0; i < 2; i++) {
00883         coords(0,i) = end1Crd(i) + end1Disp(i)*fact;
00884         coords(1,i) = end2Crd(i) + end2Disp(i)*fact;    
00885         coords(2,i) = end3Crd(i) + end3Disp(i)*fact;    
00886         coords(3,i) = end4Crd(i) + end4Disp(i)*fact;    
00887       }
00888     } else {
00889       int mode = displayMode * -1;
00890       const Matrix &eigen1 = theNodes[0]->getEigenvectors();
00891       const Matrix &eigen2 = theNodes[1]->getEigenvectors();
00892       const Matrix &eigen3 = theNodes[2]->getEigenvectors();
00893       const Matrix &eigen4 = theNodes[3]->getEigenvectors();
00894       if (eigen1.noCols() >= mode) {
00895         for (int i = 0; i < 2; i++) {
00896           coords(0,i) = end1Crd(i) + eigen1(i,mode-1)*fact;
00897           coords(1,i) = end2Crd(i) + eigen2(i,mode-1)*fact;
00898           coords(2,i) = end3Crd(i) + eigen3(i,mode-1)*fact;
00899           coords(3,i) = end4Crd(i) + eigen4(i,mode-1)*fact;
00900         }    
00901       } else {
00902         for (int i = 0; i < 2; i++) {
00903           coords(0,i) = end1Crd(i);
00904           coords(1,i) = end2Crd(i);
00905           coords(2,i) = end3Crd(i);
00906           coords(3,i) = end4Crd(i);
00907         }    
00908       }
00909     }
00910     
00911     int error = 0;
00912 
00913     // finally we draw the element using drawPolygon
00914     error += theViewer.drawPolygon (coords, values);
00915 
00916     return error;
00917 }
00918 
00919 Response*
00920 FourNodeQuad::setResponse(const char **argv, int argc, 
00921                           Information &eleInfo, OPS_Stream &output)
00922 {
00923   Response *theResponse =0;
00924 
00925   output.tag("ElementOutput");
00926   output.attr("eleType","FourNodeQuad");
00927   output.attr("eleTag",this->getTag());
00928   output.attr("node1",connectedExternalNodes[0]);
00929   output.attr("node2",connectedExternalNodes[1]);
00930   output.attr("node3",connectedExternalNodes[2]);
00931   output.attr("node4",connectedExternalNodes[3]);
00932 
00933   char dataOut[10];
00934   if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0) {
00935     
00936     for (int i=1; i<=4; i++) {
00937       sprintf(dataOut,"P1_%d",i);
00938       output.tag("ResponseType",dataOut);
00939       sprintf(dataOut,"P2_%d",i);
00940       output.tag("ResponseType",dataOut);
00941     }
00942     
00943     theResponse =  new ElementResponse(this, 1, P);
00944   }   else if (strcmp(argv[0],"material") == 0 || strcmp(argv[0],"integrPoint") == 0) {
00945     int pointNum = atoi(argv[1]);
00946     if (pointNum > 0 && pointNum <= 4) {
00947 
00948       output.tag("GaussPoint");
00949       output.attr("number",pointNum);
00950       output.attr("eta",pts[pointNum-1][0]);
00951       output.attr("neta",pts[pointNum-1][1]);
00952 
00953       theResponse =  theMaterial[pointNum-1]->setResponse(&argv[2], argc-2, eleInfo, output);
00954       
00955       output.endTag();
00956 
00957   } else if (strcmp(argv[0],"stresses") ==0) {
00958 
00959       for (int i=0; i<4; i++) {
00960         output.tag("GaussPoint");
00961         output.attr("number",i+1);
00962         output.attr("eta",pts[i][0]);
00963         output.attr("neta",pts[i][1]);
00964 
00965         output.tag("NdMaterialOutput");
00966         output.attr("classType", theMaterial[i]->getClassTag());
00967         output.attr("tag", theMaterial[i]->getTag());
00968 
00969         output.tag("ResponseType","sigma11");
00970         output.tag("ResponseType","sigma22");
00971         output.tag("ResponseType","sigma12");
00972 
00973         output.endTag(); // GaussPoint
00974         output.endTag(); // NdMaterialOutput
00975       }
00976 
00977       theResponse =  new ElementResponse(this, 3, Vector(12));
00978     }
00979   }
00980         
00981   output.endTag(); // ElementOutput
00982 
00983   return theResponse;
00984 }
00985 
00986 int 
00987 FourNodeQuad::getResponse(int responseID, Information &eleInfo)
00988 {
00989   if (responseID == 1) {
00990 
00991     return eleInfo.setVector(this->getResistingForce());
00992 
00993   } else if (responseID == 3) {
00994 
00995     // Loop over the integration points
00996     static Vector stresses(12);
00997     int cnt = 0;
00998     for (int i = 0; i < 4; i++) {
00999 
01000       // Get material stress response
01001       const Vector &sigma = theMaterial[i]->getStress();
01002       stresses(cnt) = sigma(0);
01003       stresses(cnt+1) = sigma(1);
01004       stresses(cnt+2) = sigma(2);
01005       cnt += 3;
01006     }
01007     return eleInfo.setVector(stresses);
01008         
01009   } else
01010 
01011     return -1;
01012 }
01013 
01014 int
01015 FourNodeQuad::setParameter(const char **argv, int argc, Parameter &param)
01016 {
01017   if (argc < 1)
01018     return -1;
01019 
01020   // quad mass density per unit volume
01021   if (strcmp(argv[0],"rho") == 0)
01022     return param.addObject(1, this);
01023 
01024   // quad pressure loading
01025   if (strcmp(argv[0],"pressure") == 0)
01026     return param.addObject(2, this);
01027 
01028   // a material parameter
01029   else if (strstr(argv[0],"material") != 0) {
01030 
01031     if (argc < 3)
01032       return -1;
01033 
01034     int pointNum = atoi(argv[1]);
01035     if (pointNum > 0 && pointNum <= 4)
01036       return theMaterial[pointNum-1]->setParameter(&argv[2], argc-2, param);
01037     else 
01038       return -1;
01039   }
01040   
01041   // otherwise parameter is unknown for the FourNodeQuad class
01042   else
01043     return -1;
01044 }
01045     
01046 int
01047 FourNodeQuad::updateParameter(int parameterID, Information &info)
01048 {
01049   switch (parameterID) {
01050     case -1:
01051       return -1;
01052       
01053         case 1:
01054                 rho = info.theDouble;
01055                 this->getMass();        // update mass matrix
01056                 return 0;
01057         case 2:
01058                 pressure = info.theDouble;
01059                 this->setPressureLoadAtNodes(); // update consistent nodal loads
01060                 return 0;
01061         default: 
01062           /*      
01063           if (parameterID >= 100) { // material parameter
01064             int pointNum = parameterID/100;
01065             if (pointNum > 0 && pointNum <= 4)
01066               return theMaterial[pointNum-1]->updateParameter(parameterID-100*pointNum, info);
01067             else
01068               return -1;
01069           } else // unknown
01070           */
01071             return -1;
01072   }
01073 }
01074 
01075 double FourNodeQuad::shapeFunction(double xi, double eta)
01076 {
01077         const Vector &nd1Crds = theNodes[0]->getCrds();
01078         const Vector &nd2Crds = theNodes[1]->getCrds();
01079         const Vector &nd3Crds = theNodes[2]->getCrds();
01080         const Vector &nd4Crds = theNodes[3]->getCrds();
01081 
01082         double oneMinuseta = 1.0-eta;
01083         double onePluseta = 1.0+eta;
01084         double oneMinusxi = 1.0-xi;
01085         double onePlusxi = 1.0+xi;
01086 
01087         shp[2][0] = 0.25*oneMinusxi*oneMinuseta;        // N_1
01088         shp[2][1] = 0.25*onePlusxi*oneMinuseta;         // N_2
01089         shp[2][2] = 0.25*onePlusxi*onePluseta;          // N_3
01090         shp[2][3] = 0.25*oneMinusxi*onePluseta;         // N_4
01091 
01092         double J[2][2];
01093 
01094         J[0][0] = 0.25 * (-nd1Crds(0)*oneMinuseta + nd2Crds(0)*oneMinuseta +
01095                                 nd3Crds(0)*(onePluseta) - nd4Crds(0)*(onePluseta));
01096 
01097         J[0][1] = 0.25 * (-nd1Crds(0)*oneMinusxi - nd2Crds(0)*onePlusxi +
01098                                 nd3Crds(0)*onePlusxi + nd4Crds(0)*oneMinusxi);
01099 
01100         J[1][0] = 0.25 * (-nd1Crds(1)*oneMinuseta + nd2Crds(1)*oneMinuseta +
01101                                 nd3Crds(1)*onePluseta - nd4Crds(1)*onePluseta);
01102 
01103         J[1][1] = 0.25 * (-nd1Crds(1)*oneMinusxi - nd2Crds(1)*onePlusxi +
01104                                 nd3Crds(1)*onePlusxi + nd4Crds(1)*oneMinusxi);
01105 
01106         double detJ = J[0][0]*J[1][1] - J[0][1]*J[1][0];
01107         double oneOverdetJ = 1.0/detJ;
01108         double L[2][2];
01109 
01110         // L = inv(J)
01111         L[0][0] =  J[1][1]*oneOverdetJ;
01112         L[1][0] = -J[0][1]*oneOverdetJ;
01113         L[0][1] = -J[1][0]*oneOverdetJ;
01114         L[1][1] =  J[0][0]*oneOverdetJ;
01115 
01116     double L00 = 0.25*L[0][0];
01117     double L10 = 0.25*L[1][0];
01118     double L01 = 0.25*L[0][1];
01119     double L11 = 0.25*L[1][1];
01120         
01121         double L00oneMinuseta = L00*oneMinuseta;
01122         double L00onePluseta  = L00*onePluseta;
01123         double L01oneMinusxi  = L01*oneMinusxi;
01124         double L01onePlusxi   = L01*onePlusxi;
01125 
01126         double L10oneMinuseta = L10*oneMinuseta;
01127         double L10onePluseta  = L10*onePluseta;
01128         double L11oneMinusxi  = L11*oneMinusxi;
01129         double L11onePlusxi   = L11*onePlusxi;
01130 
01131         // See Cook, Malkus, Plesha p. 169 for the derivation of these terms
01132     shp[0][0] = -L00oneMinuseta - L01oneMinusxi;        // N_1,1
01133     shp[0][1] =  L00oneMinuseta - L01onePlusxi;         // N_2,1
01134     shp[0][2] =  L00onePluseta  + L01onePlusxi;         // N_3,1
01135     shp[0][3] = -L00onePluseta  + L01oneMinusxi;        // N_4,1
01136         
01137     shp[1][0] = -L10oneMinuseta - L11oneMinusxi;        // N_1,2
01138     shp[1][1] =  L10oneMinuseta - L11onePlusxi;         // N_2,2
01139     shp[1][2] =  L10onePluseta  + L11onePlusxi;         // N_3,2
01140     shp[1][3] = -L10onePluseta  + L11oneMinusxi;        // N_4,2
01141 
01142     return detJ;
01143 }
01144 
01145 void 
01146 FourNodeQuad::setPressureLoadAtNodes(void)
01147 {
01148         pressureLoad.Zero();
01149 
01150         if (pressure == 0.0)
01151                 return;
01152 
01153         const Vector &node1 = theNodes[0]->getCrds();
01154         const Vector &node2 = theNodes[1]->getCrds();
01155         const Vector &node3 = theNodes[2]->getCrds();
01156         const Vector &node4 = theNodes[3]->getCrds();
01157 
01158         double x1 = node1(0);
01159         double y1 = node1(1);
01160         double x2 = node2(0);
01161         double y2 = node2(1);
01162         double x3 = node3(0);
01163         double y3 = node3(1);
01164         double x4 = node4(0);
01165         double y4 = node4(1);
01166 
01167         double dx12 = x2-x1;
01168         double dy12 = y2-y1;
01169         double dx23 = x3-x2;
01170         double dy23 = y3-y2;
01171         double dx34 = x4-x3;
01172         double dy34 = y4-y3;
01173         double dx41 = x1-x4;
01174         double dy41 = y1-y4;
01175 
01176         double pressureOver2 = pressure/2.0;
01177 
01178         // Contribution from side 12
01179         pressureLoad(0) += pressureOver2*dy12;
01180         pressureLoad(2) += pressureOver2*dy12;
01181         pressureLoad(1) += pressureOver2*-dx12;
01182         pressureLoad(3) += pressureOver2*-dx12;
01183 
01184         // Contribution from side 23
01185         pressureLoad(2) += pressureOver2*dy23;
01186         pressureLoad(4) += pressureOver2*dy23;
01187         pressureLoad(3) += pressureOver2*-dx23;
01188         pressureLoad(5) += pressureOver2*-dx23;
01189 
01190         // Contribution from side 34
01191         pressureLoad(4) += pressureOver2*dy34;
01192         pressureLoad(6) += pressureOver2*dy34;
01193         pressureLoad(5) += pressureOver2*-dx34;
01194         pressureLoad(7) += pressureOver2*-dx34;
01195 
01196         // Contribution from side 41
01197         pressureLoad(6) += pressureOver2*dy41;
01198         pressureLoad(0) += pressureOver2*dy41;
01199         pressureLoad(7) += pressureOver2*-dx41;
01200         pressureLoad(1) += pressureOver2*-dx41;
01201 
01202         //pressureLoad = pressureLoad*thickness;
01203 }
01204 
01205 
01206 
01207 
01208 
01209 
01210 
01211 

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