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

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