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

CorotTruss.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.2 $
00022 // $Date: 2001/07/20 19:27:00 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/element/truss/CorotTruss.cpp,v $
00024                                                                         
00025 // Written: MHS 
00026 // Created: May 2001
00027 //
00028 // Description: This file contains the class implementation for CorotTruss.
00029 
00030 #include <CorotTruss.h>
00031 #include <Information.h>
00032 
00033 #include <Domain.h>
00034 #include <Node.h>
00035 #include <Channel.h>
00036 #include <FEM_ObjectBroker.h>
00037 #include <UniaxialMaterial.h>
00038 #include <Renderer.h>
00039 
00040 #include <G3Globals.h>
00041 
00042 #include <math.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045 
00046 #include <ElementResponse.h>
00047 
00048 Matrix CorotTruss::M2(2,2);
00049 Matrix CorotTruss::M4(4,4);
00050 Matrix CorotTruss::M6(6,6);
00051 Matrix CorotTruss::M12(12,12);
00052 
00053 Vector CorotTruss::V2(2);
00054 Vector CorotTruss::V4(4);
00055 Vector CorotTruss::V6(6);
00056 Vector CorotTruss::V12(12);
00057 
00058 // constructor:
00059 //  responsible for allocating the necessary space needed by each object
00060 //  and storing the tags of the CorotTruss end nodes.
00061 CorotTruss::CorotTruss(int tag, int dim,
00062       int Nd1, int Nd2, 
00063       UniaxialMaterial &theMat,
00064       double a, double rho)
00065   :Element(tag,ELE_TAG_CorotTruss),     
00066   theMaterial(0), connectedExternalNodes(2),
00067   numDOF(0), numDIM(dim),
00068   Lo(0.0), Ln(0.0), R(3,3),
00069   A(a), M(rho), end1Ptr(0), end2Ptr(0),
00070   theMatrix(0), theVector(0)
00071 {
00072   // get a copy of the material and check we obtained a valid copy
00073   theMaterial = theMat.getCopy();
00074   if (theMaterial == 0) 
00075     g3ErrorHandler->fatal("FATAL CorotTruss::CorotTruss - %d %s %d\n", tag,
00076      "failed to get a copy of material with tag ",
00077      theMat.getTag());
00078   
00079   // ensure the connectedExternalNode ID is of correct size & set values
00080   if (connectedExternalNodes.Size() != 2)
00081     g3ErrorHandler->fatal("FATAL CorotTruss::CorotTruss - %d %s\n", tag,
00082      "failed to create an ID of size 2");
00083   
00084   connectedExternalNodes(0) = Nd1;
00085   connectedExternalNodes(1) = Nd2;        
00086 }
00087 
00088 // constructor:
00089 //   invoked by a FEM_ObjectBroker - blank object that recvSelf needs
00090 //   to be invoked upon
00091 CorotTruss::CorotTruss()
00092   :Element(0,ELE_TAG_CorotTruss),     
00093   theMaterial(0),connectedExternalNodes(2),
00094   numDOF(0), numDIM(0),
00095   Lo(0.0), Ln(0.0), R(3,3),
00096   A(0.0), M(0.0), end1Ptr(0), end2Ptr(0),
00097   theMatrix(0), theVector(0)
00098 {
00099   // ensure the connectedExternalNode ID is of correct size 
00100   if (connectedExternalNodes.Size() != 2)
00101     g3ErrorHandler->fatal("FATAL CorotTruss::CorotTruss - %s\n",
00102      "failed to create an ID of size 2");
00103 }
00104 
00105 //  destructor
00106 //     delete must be invoked on any objects created by the object
00107 //     and on the matertial object.
00108 CorotTruss::~CorotTruss()
00109 {
00110   // invoke the destructor on any objects created by the object
00111   // that the object still holds a pointer to
00112   if (theMaterial != 0)
00113     delete theMaterial;
00114 }
00115 
00116 int
00117 CorotTruss::getNumExternalNodes(void) const
00118 {
00119     return 2;
00120 }
00121 
00122 const ID &
00123 CorotTruss::getExternalNodes(void) 
00124 {
00125  return connectedExternalNodes;
00126 }
00127 
00128 int
00129 CorotTruss::getNumDOF(void) 
00130 {
00131  return numDOF;
00132 }
00133 
00134 // method: setDomain()
00135 //    to set a link to the enclosing Domain and to set the node pointers.
00136 //    also determines the number of dof associated
00137 //    with the CorotTruss element, we set matrix and vector pointers,
00138 //    allocate space for t matrix, determine the length
00139 //    and set the transformation matrix.
00140 void
00141 CorotTruss::setDomain(Domain *theDomain)
00142 {
00143   // check Domain is not null - invoked when object removed from a domain
00144   if (theDomain == 0) {
00145     end1Ptr = 0;
00146     end2Ptr = 0;
00147     Lo = 0.0;
00148     Ln = 0.0;
00149     return;
00150   }
00151   
00152   // first set the node pointers
00153   int Nd1 = connectedExternalNodes(0);
00154   int Nd2 = connectedExternalNodes(1);
00155   end1Ptr = theDomain->getNode(Nd1);
00156   end2Ptr = theDomain->getNode(Nd2); 
00157   
00158   // if can't find both - send a warning message
00159   if ((end1Ptr == 0) || (end2Ptr == 0)) {
00160     g3ErrorHandler->warning("CorotTruss::setDomain() - CorotTruss %d node %d %s\n",
00161        this->getTag(), Nd1,
00162        "does not exist in the model");
00163     
00164     // fill this in so don't segment fault later
00165     numDOF = 6;    
00166     
00167     return;
00168   }
00169   
00170   // now determine the number of dof and the dimesnion    
00171   int dofNd1 = end1Ptr->getNumberDOF();
00172   int dofNd2 = end2Ptr->getNumberDOF(); 
00173   
00174   // if differing dof at the ends - print a warning message
00175   if (dofNd1 != dofNd2) {
00176     g3ErrorHandler->warning("WARNING CorotTruss::setDomain(): nodes %d and %d %s %d\n",Nd1, Nd2,
00177        "have differing dof at ends for CorotTruss",this->getTag());
00178     
00179     // fill this in so don't segment fault later
00180     numDOF = 6;    
00181     
00182     return;
00183   } 
00184   
00185   if (numDIM == 1 && dofNd1 == 1) {
00186     numDOF = 2;
00187     theMatrix = &M2;
00188     theVector = &V2;
00189   }
00190   else if (numDIM == 2 && dofNd1 == 2) {
00191     numDOF = 4;
00192     theMatrix = &M4;
00193     theVector = &V4;
00194   }
00195   else if (numDIM == 2 && dofNd1 == 3) {
00196     numDOF = 6;
00197     theMatrix = &M6;
00198     theVector = &V6;
00199   }
00200   else if (numDIM == 3 && dofNd1 == 3) {
00201     numDOF = 6;
00202     theMatrix = &M6;
00203     theVector = &V6;
00204   }
00205   else if (numDIM == 3 && dofNd1 == 6) {
00206     numDOF = 12;
00207     theMatrix = &M12;
00208     theVector = &V12;
00209   }
00210   else {
00211     g3ErrorHandler->warning("%s -- nodal DOF %d not compatible with element",
00212        "CorotTruss::setDomain", dofNd1);
00213     
00214     // fill this in so don't segment fault later
00215     numDOF = 6;    
00216     
00217     return;
00218   }
00219 
00220  // call the base class method
00221  this->DomainComponent::setDomain(theDomain);
00222 
00223  // now determine the length, cosines and fill in the transformation
00224  // NOTE t = -t(every one else uses for residual calc)
00225  const Vector &end1Crd = end1Ptr->getCrds();
00226  const Vector &end2Crd = end2Ptr->getCrds();
00227 
00228  // Determine global offsets
00229     double cosX[3];
00230     cosX[0] = 0.0;  cosX[1] = 0.0;  cosX[2] = 0.0;
00231     int i;
00232     for (i = 0; i < numDIM; i++) {
00233         cosX[i] += end2Crd(i)-end1Crd(i);
00234     }
00235 
00236  // Set undeformed and initial length
00237  Lo = cosX[0]*cosX[0] + cosX[1]*cosX[1] + cosX[2]*cosX[2];
00238  Lo = sqrt(Lo);
00239  Ln = Lo;
00240 
00241     // Initial offsets
00242     d21[0] = Lo;
00243  d21[1] = 0.0;
00244  d21[2] = 0.0;
00245 
00246  // Set global orientation
00247  cosX[0] /= Lo;
00248  cosX[1] /= Lo;
00249  cosX[2] /= Lo;
00250 
00251  R(0,0) = cosX[0];
00252  R(0,1) = cosX[1];
00253  R(0,2) = cosX[2];
00254 
00255  // Element lies outside the YZ plane
00256  if (fabs(cosX[0]) > 0.0) {
00257   R(1,0) = -cosX[1];
00258   R(1,1) =  cosX[0];
00259   R(1,2) =  0.0;
00260 
00261   R(2,0) = -cosX[0]*cosX[2];
00262   R(2,1) = -cosX[1]*cosX[2];
00263   R(2,2) =  cosX[0]*cosX[0] + cosX[1]*cosX[1];
00264  }
00265  // Element is in the YZ plane
00266  else {
00267   R(1,0) =  0.0;
00268   R(1,1) = -cosX[2];
00269   R(1,2) =  cosX[1];
00270 
00271   R(2,0) =  1.0;
00272   R(2,1) =  0.0;
00273   R(2,2) =  0.0;
00274  }
00275 
00276  // Orthonormalize last two rows of R
00277  double norm;
00278  for (i = 1; i < 3; i++) {
00279   norm = sqrt(R(i,0)*R(i,0) + R(i,1)*R(i,1) + R(i,2)*R(i,2));
00280   R(i,0) /= norm;
00281   R(i,1) /= norm;
00282   R(i,2) /= norm;
00283  }
00284 
00285  // Set lumped mass
00286  M = M*Lo/2;
00287 }
00288 
00289 int
00290 CorotTruss::commitState()
00291 {
00292  // Commit the material
00293  return theMaterial->commitState();
00294 }
00295 
00296 int
00297 CorotTruss::revertToLastCommit()
00298 {
00299  // Revert the material
00300  return theMaterial->revertToLastCommit();
00301 }
00302 
00303 int
00304 CorotTruss::revertToStart()
00305 {
00306  // Revert the material to start
00307  return theMaterial->revertToStart();
00308 }
00309 
00310 int
00311 CorotTruss::update(void)
00312 {
00313  // Nodal displacements
00314  const Vector &end1Disp = end1Ptr->getTrialDisp();
00315  const Vector &end2Disp = end2Ptr->getTrialDisp();    
00316 
00317     // Initial offsets
00318  d21[0] = Lo;
00319  d21[1] = 0.0;
00320  d21[2] = 0.0;
00321 
00322     // Update offsets in basic system due to nodal displacements
00323     for (int i = 0; i < numDIM; i++) {
00324         d21[0] += R(0,i)*(end2Disp(i)-end1Disp(i));
00325         d21[1] += R(1,i)*(end2Disp(i)-end1Disp(i));
00326         d21[2] += R(2,i)*(end2Disp(i)-end1Disp(i));
00327     }
00328 
00329  // Compute new length
00330  Ln = d21[0]*d21[0] + d21[1]*d21[1] + d21[2]*d21[2];
00331  Ln = sqrt(Ln);
00332 
00333  // Compute engineering strain
00334  double strain = (Ln-Lo)/Lo;
00335 
00336  // Set material trial strain
00337  return theMaterial->setTrialStrain(strain);
00338 }
00339 
00340 const Matrix &
00341 CorotTruss::getTangentStiff(void)
00342 {
00343     static Matrix kl(3,3);
00344 
00345     // Material stiffness
00346     //
00347     // Get material tangent
00348  double EA = A*theMaterial->getTangent();
00349  EA /= (Ln*Ln*Lo);
00350 
00351     int i,j;
00352     for (i = 0; i < 3; i++)
00353         for (j = 0; j < 3; j++)
00354             kl(i,j) = EA*d21[i]*d21[j];
00355 
00356  // Geometric stiffness
00357  //
00358  // Get material stress
00359  double q = A*theMaterial->getStress();
00360  double SA = q/(Ln*Ln*Ln);
00361  double SL = q/Ln;
00362 
00363     for (i = 0; i < 3; i++) {
00364         kl(i,i) += SL;
00365         for (j = 0; j < 3; j++)
00366             kl(i,j) -= SA*d21[i]*d21[j];
00367     }
00368     
00369     // Compute R'*kl*R
00370     static Matrix kg(3,3);
00371     kg.addMatrixTripleProduct(0.0, R, kl, 1.0);
00372 
00373     Matrix &K = *theMatrix;
00374     K.Zero();
00375 
00376     // Copy stiffness into appropriate blocks in element stiffness
00377     int numDOF2 = numDOF/2;
00378     for (i = 0; i < numDIM; i++) {
00379         for (j = 0; j < numDIM; j++) {
00380             K(i,j)                 =  kg(i,j);
00381             K(i,j+numDOF2)         = -kg(i,j);
00382             K(i+numDOF2,j)         = -kg(i,j);
00383             K(i+numDOF2,j+numDOF2) =  kg(i,j);
00384         }
00385     }
00386 
00387     return *theMatrix;
00388 }
00389 
00390 const Matrix &
00391 CorotTruss::getSecantStiff(void)
00392 {
00393  return this->getTangentStiff();
00394 }
00395 
00396 const Matrix &
00397 CorotTruss::getDamp(void)
00398 {
00399     theMatrix->Zero();
00400     
00401     return *theMatrix;
00402 }
00403 
00404 const Matrix &
00405 CorotTruss::getMass(void)
00406 {
00407     Matrix &Mass = *theMatrix;
00408     Mass.Zero();
00409 
00410     int numDOF2 = numDOF/2;
00411     for (int i = 0; i < numDIM; i++) {
00412         Mass(i,i)                 = M;
00413         Mass(i+numDOF2,i+numDOF2) = M;
00414     }
00415 
00416     return *theMatrix;
00417 }
00418 
00419 void 
00420 CorotTruss::zeroLoad(void)
00421 {
00422  return;
00423 }
00424 
00425 int 
00426 CorotTruss::addLoad(const Vector &addP)
00427 {
00428  return 0;
00429 }
00430 
00431 int 
00432 CorotTruss::addInertiaLoadToUnbalance(const Vector &accel)
00433 {
00434  return 0;
00435 }
00436 
00437 const Vector &
00438 CorotTruss::getResistingForce()
00439 {
00440  // Get material stress
00441  double SA = A*theMaterial->getStress();
00442  SA /= Ln;
00443 
00444     static Vector ql(3);
00445 
00446  ql(0) = d21[0]*SA;
00447  ql(1) = d21[1]*SA;
00448  ql(2) = d21[2]*SA;
00449 
00450     static Vector qg(3);
00451     qg.addMatrixTransposeVector(0.0, R, ql, 1.0);
00452 
00453     Vector &P = *theVector;
00454     P.Zero();
00455 
00456     // Copy forces into appropriate places
00457     int numDOF2 = numDOF/2;
00458     for (int i = 0; i < numDIM; i++) {
00459         P(i)         = -qg(i);
00460         P(i+numDOF2) =  qg(i);
00461     }
00462 
00463     return *theVector;
00464 }
00465 
00466 const Vector &
00467 CorotTruss::getResistingForceIncInertia()
00468 { 
00469     Vector &P = *theVector;
00470     P = this->getResistingForce();
00471     
00472     if (M != 0.0) {
00473  
00474      const Vector &accel1 = end1Ptr->getTrialAccel();
00475      const Vector &accel2 = end2Ptr->getTrialAccel(); 
00476  
00477         int numDOF2 = numDOF/2;
00478      for (int i = 0; i < numDIM; i++) {
00479          P(i)        += M*accel1(i);
00480          P(i+numDOF2) += M*accel2(i);
00481      }
00482     }
00483 
00484     return *theVector;
00485 }
00486 
00487 int
00488 CorotTruss::sendSelf(int commitTag, Channel &theChannel)
00489 {
00490  return -1;
00491 }
00492 
00493 int
00494 CorotTruss::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00495 {
00496  return -1;
00497 }
00498 
00499 int
00500 CorotTruss::displaySelf(Renderer &theViewer, int displayMode, float fact)
00501 {
00502  // ensure setDomain() worked
00503  if (Ln == 0.0)
00504   return 0;
00505 
00506  // first determine the two end points of the CorotTruss based on
00507  // the display factor (a measure of the distorted image)
00508  // store this information in 2 3d vectors v1 and v2
00509  const Vector &end1Crd = end1Ptr->getCrds();
00510  const Vector &end2Crd = end2Ptr->getCrds(); 
00511  const Vector &end1Disp = end1Ptr->getDisp();
00512  const Vector &end2Disp = end2Ptr->getDisp();    
00513 
00514  static Vector v1(3);
00515  static Vector v2(3);
00516  for (int i = 0; i < numDIM; i++) {
00517   v1(i) = end1Crd(i)+end1Disp(i)*fact;
00518   v2(i) = end2Crd(i)+end2Disp(i)*fact;    
00519  }
00520 
00521  return theViewer.drawLine(v1, v2, 1.0, 1.0);
00522 }
00523 
00524 void
00525 CorotTruss::Print(ostream &s, int flag)
00526 {
00527  s << "\nCorotTruss, tag: " << this->getTag() << endl;
00528  s << "\tConnected Nodes: " << connectedExternalNodes;
00529  s << "\tSection Area: " << A << endl;
00530  s << "\tUndeformed Length: " << Lo << endl;
00531  s << "\tCurrent Length: " << Ln << endl;
00532  s << "\tRotation matrix: " << endl;
00533 
00534  if (theMaterial) {
00535   s << "\tAxial Force: " << A*theMaterial->getStress() << endl;
00536   s << "\tUniaxialMaterial, tag: " << theMaterial->getTag() << endl;
00537   theMaterial->Print(s,flag);
00538  }
00539 }
00540 
00541 Response*
00542 CorotTruss::setResponse(char **argv, int argc, Information &eleInfo)
00543 {
00544     // force (axialForce)
00545     if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0 || strcmp(argv[0],"axialForce") == 0)
00546   return new ElementResponse(this, 1, 0.0);
00547 
00548     else if (strcmp(argv[0],"defo") == 0 || strcmp(argv[0],"deformations") == 0 ||
00549   strcmp(argv[0],"deformation") == 0)
00550   return new ElementResponse(this, 2, 0.0);
00551 
00552     // a material quantity    
00553     else if (strcmp(argv[0],"material") == 0)
00554   return theMaterial->setResponse(&argv[1], argc-1, eleInfo);
00555     
00556  else
00557   return 0;
00558 }
00559 
00560 int 
00561 CorotTruss::getResponse(int responseID, Information &eleInfo)
00562 {
00563   switch (responseID) {
00564     case 1:
00565    return eleInfo.setDouble(A * theMaterial->getStress());
00566       
00567     case 2:
00568    return eleInfo.setDouble(Lo * theMaterial->getStrain());
00569       
00570     default:
00571    return 0;
00572   }
00573 }
Copyright Contact Us