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

Truss.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.6 $
00022 // $Date: 2001/07/13 22:42:34 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/element/truss/Truss.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/element/truss/Truss.C
00027 // 
00028 // Written: fmk 
00029 // Created: 07/98
00030 // Revision: A
00031 //
00032 // Description: This file contains the implementation for the Truss class.
00033 //
00034 // What: "@(#) Truss.C, revA"
00035 
00036 #include "Truss.h"
00037 #include <Information.h>
00038 
00039 #include <Domain.h>
00040 #include <Node.h>
00041 #include <Channel.h>
00042 #include <FEM_ObjectBroker.h>
00043 #include <UniaxialMaterial.h>
00044 #include <Renderer.h>
00045 
00046 #include <G3Globals.h>
00047 
00048 #include <math.h>
00049 #include <stdlib.h>
00050 #include <string.h>
00051 
00052 #include <ElementResponse.h>
00053 
00054 // initialise the class wide variables
00055 Matrix Truss::trussM2(2,2);
00056 Matrix Truss::trussM4(4,4);
00057 Matrix Truss::trussM6(6,6);
00058 Matrix Truss::trussM12(12,12);
00059 Vector Truss::trussV2(2);
00060 Vector Truss::trussV4(4);
00061 Vector Truss::trussV6(6);
00062 Vector Truss::trussV12(12);
00063 
00064 // constructor:
00065 //  responsible for allocating the necessary space needed by each object
00066 //  and storing the tags of the truss end nodes.
00067 Truss::Truss(int tag, 
00068       int dim,
00069       int Nd1, int Nd2, 
00070       UniaxialMaterial &theMat,
00071       double a, double rho)
00072  :Element(tag,ELE_TAG_Truss),     
00073   theMaterial(0), connectedExternalNodes(2),
00074   dimension(dim), numDOF(0), theLoad(0),
00075   theMatrix(0), theVector(0), t(0),
00076   L(0.0), A(a), M(rho), end1Ptr(0), end2Ptr(0)
00077 {
00078     // get a copy of the material and check we obtained a valid copy
00079     theMaterial = theMat.getCopy();
00080     if (theMaterial == 0) 
00081       g3ErrorHandler->fatal("FATAL Truss::Truss - %d %s %d\n", tag,
00082        "failed to get a copy of material with tag ",
00083        theMat.getTag());
00084 
00085     // ensure the connectedExternalNode ID is of correct size & set values
00086     if (connectedExternalNodes.Size() != 2)
00087       g3ErrorHandler->fatal("FATAL Truss::Truss - %d %s\n", tag,
00088        "failed to create an ID of size 2");
00089     connectedExternalNodes(0) = Nd1;
00090     connectedExternalNodes(1) = Nd2;        
00091 }
00092 
00093 // constructor:
00094 //   invoked by a FEM_ObjectBroker - blank object that recvSelf needs
00095 //   to be invoked upon
00096 Truss::Truss()
00097 :Element(0,ELE_TAG_Truss),     
00098  theMaterial(0),connectedExternalNodes(2),
00099  dimension(0), numDOF(0),
00100  theMatrix(0), theVector(0), t(0), 
00101  L(0.0), A(0.0), M(0.0), end1Ptr(0), end2Ptr(0)
00102 {
00103     // ensure the connectedExternalNode ID is of correct size 
00104     if (connectedExternalNodes.Size() != 2)
00105       g3ErrorHandler->fatal("FATAL Truss::Truss - %s\n",
00106        "failed to create an ID of size 2");
00107 }
00108 
00109 //  destructor
00110 //     delete must be invoked on any objects created by the object
00111 //     and on the matertial object.
00112 Truss::~Truss()
00113 {
00114     // invoke the destructor on any objects created by the object
00115     // that the object still holds a pointer to
00116     if (theMaterial != 0)
00117  delete theMaterial;
00118     if (t != 0)
00119  delete t;
00120     if (theLoad != 0)
00121  delete theLoad;
00122 }
00123 
00124 
00125 int
00126 Truss::getNumExternalNodes(void) const
00127 {
00128     return 2;
00129 }
00130 
00131 const ID &
00132 Truss::getExternalNodes(void) 
00133 {
00134     return connectedExternalNodes;
00135 }
00136 
00137 int
00138 Truss::getNumDOF(void) 
00139 {
00140     return numDOF;
00141 }
00142 
00143 
00144 // method: setDomain()
00145 //    to set a link to the enclosing Domain and to set the node pointers.
00146 //    also determines the number of dof associated
00147 //    with the truss element, we set matrix and vector pointers,
00148 //    allocate space for t matrix, determine the length
00149 //    and set the transformation matrix.
00150 void
00151 Truss::setDomain(Domain *theDomain)
00152 {
00153     // check Domain is not null - invoked when object removed from a domain
00154     if (theDomain == 0) {
00155  end1Ptr = 0;
00156  end2Ptr = 0;
00157  L = 0;
00158  return;
00159     }
00160 
00161     // first set the node pointers
00162     int Nd1 = connectedExternalNodes(0);
00163     int Nd2 = connectedExternalNodes(1);
00164     end1Ptr = theDomain->getNode(Nd1);
00165     end2Ptr = theDomain->getNode(Nd2); 
00166 
00167     // if can't find both - send a warning message
00168     if ((end1Ptr == 0) || (end2Ptr == 0)) {
00169  g3ErrorHandler->warning("Truss::setDomain() - truss %d node %d %s\n",
00170     this->getTag(), Nd1,
00171     "does not exist in the model");
00172 
00173       // fill this in so don't segment fault later
00174       numDOF = 2;    
00175       theMatrix = &trussM2;
00176       theVector = &trussV2; 
00177 
00178       return;
00179     }
00180 
00181     // now determine the number of dof and the dimesnion    
00182     int dofNd1 = end1Ptr->getNumberDOF();
00183     int dofNd2 = end2Ptr->getNumberDOF(); 
00184 
00185     // if differing dof at the ends - print a warning message
00186     if (dofNd1 != dofNd2) {
00187       g3ErrorHandler->warning("WARNING Truss::setDomain(): nodes %d and %d %s %d\n",Nd1, Nd2,
00188          "have differing dof at ends for truss",this->getTag());
00189 
00190       // fill this in so don't segment fault later
00191       numDOF = 2;    
00192       theMatrix = &trussM2;
00193       theVector = &trussV2; 
00194  
00195       return;
00196     } 
00197 
00198     // call the base class method
00199     this->DomainComponent::setDomain(theDomain);
00200 
00201     // now set the number of dof for element and set matrix and vector pointer
00202     if (dimension == 1 && dofNd1 == 1) {
00203  numDOF = 2;    
00204  theMatrix = &trussM2;
00205  theVector = &trussV2;
00206     }
00207     else if (dimension == 2 && dofNd1 == 2) {
00208  numDOF = 4;
00209  theMatrix = &trussM4;
00210  theVector = &trussV4; 
00211     }
00212     else if (dimension == 2 && dofNd1 == 3) {
00213  numDOF = 6; 
00214  theMatrix = &trussM6;
00215  theVector = &trussV6;  
00216     }
00217     else if (dimension == 3 && dofNd1 == 3) {
00218  numDOF = 6; 
00219  theMatrix = &trussM6;
00220  theVector = &trussV6;   
00221     }
00222     else if (dimension == 3 && dofNd1 == 6) {
00223  numDOF = 12;     
00224  theMatrix = &trussM12;
00225  theVector = &trussV12;   
00226     }
00227     else {
00228       g3ErrorHandler->warning("WARNING Truss::setDomain cannot handle %d dofs at nodes in %d d problem\n",
00229          dimension,dofNd1);
00230 
00231       numDOF = 2;    
00232       theMatrix = &trussM2;
00233       theVector = &trussV2; 
00234       return;
00235     }
00236 
00237 
00238     // create a transformation matrix for the element
00239     t = new Matrix(1,numDOF);
00240     theLoad = new Vector(numDOF);
00241     
00242     if (t == 0 || (t->noCols() != numDOF)) {
00243       g3ErrorHandler->fatal("Truss::setDomain - truss %d %s %d\n",
00244        this->getTag(), 
00245        "out of memory creating T matrix of size 1 x",
00246        numDOF); 
00247       
00248       return;
00249     }      
00250     
00251     if (theLoad == 0) {
00252  g3ErrorHandler->fatal("Truss::setDomain - truss %d %s %d\n",
00253          this->getTag(), 
00254          "out of memory creating vector of size",
00255          numDOF); 
00256       return;
00257     }          
00258     
00259     // now determine the length, cosines and fill in the transformation
00260     // NOTE t = -t(every one else uses for residual calc)
00261     const Vector &end1Crd = end1Ptr->getCrds();
00262     const Vector &end2Crd = end2Ptr->getCrds(); 
00263 
00264     if (dimension == 1) {
00265  Matrix &trans = *t;      
00266  trans(0,0) = -1;
00267  trans(0,1) = 1;
00268 
00269  double dx = end2Crd(0)-end1Crd(0); 
00270  L = sqrt(dx*dx);
00271  
00272  if (L == 0.0) {
00273    g3ErrorHandler->warning("WARNING Truss::setDomain() - truss %d has zero length\n",
00274       this->getTag());
00275    return;
00276  } 
00277 
00278     } else if (dimension == 2) {
00279  double dx = end2Crd(0)-end1Crd(0);
00280  double dy = end2Crd(1)-end1Crd(1); 
00281     
00282  L = sqrt(dx*dx + dy*dy);
00283     
00284  if (L == 0.0) {
00285    g3ErrorHandler->warning("WARNING Truss::setDomain() - truss %d has zero length\n",
00286       this->getTag());
00287    return;
00288  }
00289  
00290  double cs = dx/L;
00291  double sn = dy/L;
00292 
00293  Matrix &trans = *t;
00294  if (numDOF == 4) {
00295      trans(0,0) = -cs;
00296      trans(0,1) = -sn;
00297      trans(0,2) = cs;
00298      trans(0,3) = sn;
00299  } else { // it must be 6
00300      trans(0,0) = -cs;
00301      trans(0,1) = -sn;
00302      trans(0,2) = 0.0;
00303      trans(0,3) = cs;
00304      trans(0,4) = sn; 
00305      trans(0,5) = 0.0;
00306  }     
00307 
00308     } else {
00309  double dx = end2Crd(0)-end1Crd(0);
00310  double dy = end2Crd(1)-end1Crd(1); 
00311  double dz = end2Crd(2)-end1Crd(2);  
00312     
00313  L = sqrt(dx*dx + dy*dy + dz*dz);
00314     
00315  if (L == 0.0) {
00316    g3ErrorHandler->warning("WARNING Truss::setDomain() - truss %d has zero length\n",
00317       this->getTag());
00318    return;
00319  }
00320  
00321  double cx = dx/L;
00322  double cy = dy/L;
00323  double cz = dz/L; 
00324 
00325  Matrix &trans = *t; 
00326  if (numDOF == 6) {
00327      trans(0,0) = -cx;
00328      trans(0,1) = -cy;
00329      trans(0,2) = -cz;
00330      trans(0,3) = cx;
00331      trans(0,4) = cy;
00332      trans(0,5) = cz;     
00333  } else { // it must be 12
00334      trans(0,0) = -cx;
00335      trans(0,1) = -cy;
00336      trans(0,2) = -cz;
00337      trans(0,3) = 0;
00338      trans(0,4) = 0;
00339      trans(0,5) = 0;     
00340      trans(0,6) = cx;
00341      trans(0,7) = cy;
00342      trans(0,8) = cz;
00343      trans(0,9) = 0;
00344      trans(0,10) = 0;
00345      trans(0,11) = 0;          
00346  }     
00347     }
00348     
00349     // determine the nodal mass for lumped mass approach
00350     M = M * A * L/2;
00351     
00352     this->update();
00353 }     
00354 
00355 
00356 int
00357 Truss::commitState()
00358 {
00359     return theMaterial->commitState();
00360 }
00361 
00362 int
00363 Truss::revertToLastCommit()
00364 {
00365     return theMaterial->revertToLastCommit();
00366 }
00367 
00368 int
00369 Truss::revertToStart()
00370 {
00371     return theMaterial->revertToStart();
00372 }
00373 
00374 int
00375 Truss::update(void)
00376 {
00377     // determine the current strain given trial displacements at nodes
00378     double strain = this->computeCurrentStrain();
00379     double rate = this->computeCurrentStrainRate();
00380     return theMaterial->setTrialStrain(strain, rate);
00381 }
00382 
00383 
00384 const Matrix &
00385 Truss::getTangentStiff(void)
00386 {
00387     if (L == 0.0) { // - problem in setDomain() no further warnings
00388  theMatrix->Zero();
00389  return *theMatrix;
00390     }
00391     
00392     double E = theMaterial->getTangent();
00393 
00394     // come back later and redo this if too slow
00395     Matrix &stiff = *theMatrix;
00396     Matrix &trans = *t;
00397 
00398     stiff = trans^trans;
00399 
00400     stiff *= A*E/L;  
00401 
00402     return *theMatrix;
00403 }
00404 
00405 const Matrix &
00406 Truss::getSecantStiff(void)
00407 {
00408     if (L == 0.0) { // - problem in setDomain() no further warnings
00409  theMatrix->Zero();
00410  return *theMatrix;
00411     }
00412     
00413     // get the current E from the material for this strain
00414     double strain = this->computeCurrentStrain();
00415 
00416     double stress = theMaterial->getStress();    
00417     double E = stress/strain;
00418 
00419     // come back later and redo this if too slow
00420     Matrix &stiff = *theMatrix;
00421     Matrix &trans = *t;
00422     stiff = trans^trans;
00423     stiff *= A*E/L;  
00424     
00425     return *theMatrix;
00426 }
00427     
00428 const Matrix &
00429 Truss::getDamp(void)
00430 {
00431     if (L == 0.0) { // - problem in setDomain() no further warnings
00432  theMatrix->Zero();
00433  return *theMatrix;
00434     }
00435     
00436     double eta = theMaterial->getDampTangent();
00437 
00438     // come back later and redo this if too slow
00439     Matrix &damp = *theMatrix;
00440     Matrix &trans = *t;
00441 
00442     damp = trans^trans;
00443 
00444     damp *= A*eta/L;
00445 
00446     return *theMatrix;
00447 }
00448 
00449 
00450 const Matrix &
00451 Truss::getMass(void)
00452 {   // zero the matrix
00453     theMatrix->Zero();    
00454   
00455     // check for quick return
00456     if (L == 0.0 || M == 0.0) { // - problem in setDomain() no further warnings
00457  return *theMatrix;
00458     }    
00459 
00460     Matrix &mass = *theMatrix;
00461     if (dimension == 1 && numDOF == 2) {
00462  mass(0,0) = M; 
00463  mass(1,1) = M;
00464     }
00465     else if (dimension == 2 && numDOF == 4) {
00466  mass(0,0) = M; 
00467  mass(1,1) = M;
00468  mass(2,2) = M; 
00469  mass(3,3) = M; 
00470     }
00471     else if (dimension == 2 && numDOF == 6) {
00472  mass(0,0) = M; 
00473  mass(1,1) = M;
00474  mass(3,3) = M;
00475  mass(4,4) = M; 
00476     }
00477     else if (dimension == 3 && numDOF == 6) {
00478  mass(0,0) = M; 
00479  mass(1,1) = M;
00480  mass(2,2) = M; 
00481  mass(3,3) = M;
00482  mass(4,4) = M; 
00483  mass(5,5) = M;  
00484     }
00485     else if (dimension == 3 && numDOF == 12) {
00486  mass(0,0) = M; 
00487  mass(1,1) = M;
00488  mass(2,2) = M; 
00489  mass(6,6) = M; 
00490  mass(7,7) = M;
00491  mass(8,8) = M; 
00492     }
00493     
00494     return *theMatrix; // so it will compile
00495 }
00496 
00497 
00498 
00499 void 
00500 Truss::zeroLoad(void)
00501 {
00502     theLoad->Zero();
00503 }
00504 
00505 int 
00506 Truss::addLoad(const Vector &addP)
00507 {
00508 #ifdef _G3DEBUG    
00509     if (dimension != addP.Size()) {
00510  g3ErrorHandler->warning("Truss::addPtoUnbalance %s\n",
00511     "matrix and vector sizes are incompatable");
00512  return -1;
00513     }
00514 #endif
00515     (*theLoad) += addP;
00516  return 0;
00517 }
00518 
00519 int 
00520 Truss::addInertiaLoadToUnbalance(const Vector &accel)
00521 {
00522     // check for a quick return
00523     if (L == 0.0 || M == 0.0) 
00524  return 0;
00525 
00526     // get R * accel from the nodes
00527     const Vector &Raccel1 = end1Ptr->getRV(accel);
00528     const Vector &Raccel2 = end2Ptr->getRV(accel);    
00529 
00530     int nodalDOF = numDOF/2;
00531     
00532 #ifdef _G3DEBUG    
00533     if (nodalDOF != Raccel1.Size() || nodalDOF != Raccel2.Size()) {
00534  g3ErrorHandler->warning("Truss::addInertiaLoadToUnbalance %s\n",
00535     "matrix and vector sizes are incompatable");
00536  return -1;
00537     }
00538 #endif
00539     
00540     // want to add ( - fact * M R * accel ) to unbalance
00541     for (int i=0; i<dimension; i++) {
00542  double val1 = Raccel1(i);
00543  double val2 = Raccel2(i); 
00544  
00545  // perform - fact * M*(R * accel) // remember M a diagonal matrix
00546  val1 *= -M;
00547  val2 *= -M;
00548  
00549  (*theLoad)(i) += val1;
00550  (*theLoad)(i+nodalDOF) += val2;
00551     } 
00552 
00553     return 0;
00554 }
00555 
00556 const Vector &
00557 Truss::getResistingForce()
00558 { 
00559     if (L == 0.0) { // - problem in setDomain() no further warnings
00560  theVector->Zero();
00561  return *theVector;
00562     }
00563     
00564     // R = Ku - Pext
00565     // Ku = F * transformation
00566     double force = A*theMaterial->getStress();
00567     for (int i=0; i<numDOF; i++)
00568  (*theVector)(i) = (*t)(0,i)*force;
00569 
00570     // subtract external load:  Ku - P
00571     (*theVector) -= *theLoad;
00572     
00573     return *theVector;
00574 }
00575 
00576 
00577 const Vector &
00578 Truss::getResistingForceIncInertia()
00579 { 
00580     this->getResistingForce();
00581     
00582     // now include the mass portion
00583     if (L != 0.0 && M != 0.0) {
00584  
00585  // remember we set M = M*A*L/2 in setDoamin()
00586  const Vector &accel1 = end1Ptr->getTrialAccel();
00587  const Vector &accel2 = end2Ptr->getTrialAccel(); 
00588  
00589  int dof = dimension;
00590  int start = numDOF/2;
00591  for (int i=0; i<dof; i++) {
00592      (*theVector)(i) = (*theVector)(i) + M*accel1(i);
00593      (*theVector)(i+start) = (*theVector)(i+start) + M*accel2(i);
00594  }
00595     }    
00596     
00597     return *theVector;
00598 }
00599 
00600 
00601 int
00602 Truss::sendSelf(int commitTag, Channel &theChannel)
00603 {
00604   int res;
00605 
00606   // note: we don't check for dataTag == 0 for Element
00607   // objects as that is taken care of in a commit by the Domain
00608   // object - don't want to have to do the check if sending data
00609   int dataTag = this->getDbTag();
00610 
00611   // truss packs it's data into a Vector and sends this to theChannel
00612   // along with it's dbTag and the commitTag passed in the arguments
00613 
00614   static Vector data(7);
00615   data(0) = this->getTag();
00616   data(1) = dimension;
00617   data(2) = numDOF;
00618   data(3) = A;
00619   if (L != 0)
00620       data(6) = M * 2 / (L*A);
00621   else
00622       data(6) = M;
00623   
00624   data(4) = theMaterial->getClassTag();
00625   int matDbTag = theMaterial->getDbTag();
00626 
00627   // NOTE: we do have to ensure that the material has a database
00628   // tag if we are sending to a database channel.
00629   if (matDbTag == 0) {
00630     matDbTag = theChannel.getDbTag();
00631     if (matDbTag != 0)
00632       theMaterial->setDbTag(matDbTag);
00633   }
00634   data(5) = matDbTag;
00635 
00636   res = theChannel.sendVector(dataTag, commitTag, data);
00637   if (res < 0) {
00638     g3ErrorHandler->warning("WARNING Truss::sendSelf() - %d failed to send Vector\n",this->getTag());
00639     return -1;
00640   }       
00641 
00642   // truss then sends the tags of it's two end nodes
00643 
00644   res = theChannel.sendID(dataTag, commitTag, connectedExternalNodes);
00645   if (res < 0) {
00646     g3ErrorHandler->warning("WARNING Truss::sendSelf() - %d failed to send Vector\n",this->getTag());
00647     return -2;
00648   }
00649 
00650   // finally truss asks it's material object to send itself
00651   res = theMaterial->sendSelf(commitTag, theChannel);
00652   if (res < 0) {
00653     g3ErrorHandler->warning("WARNING Truss::sendSelf() - %d failed to send its Material\n",this->getTag());
00654     return -3;
00655   }
00656 
00657   return 0;
00658 }
00659 
00660 int
00661 Truss::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00662 {
00663 
00664   int res;
00665   int dataTag = this->getDbTag();
00666 
00667   // truss creates a Vector, receives the Vector and then sets the 
00668   // internal data with the data in the Vector
00669 
00670   static Vector data(7);
00671   res = theChannel.recvVector(dataTag, commitTag, data);
00672   if (res < 0) {
00673     g3ErrorHandler->warning("WARNING Truss::recvSelf() - failed to receive Vector\n");
00674     return -1;
00675   }       
00676 
00677   this->setTag((int)data(0));
00678   dimension = data(1);
00679   numDOF = data(2);
00680   A = data(3);
00681   M = data(6);
00682   
00683   // truss now receives the tags of it's two external nodes
00684   res = theChannel.recvID(dataTag, commitTag, connectedExternalNodes);
00685   if (res < 0) {
00686     g3ErrorHandler->warning("WARNING Truss::recvSelf() - %d failed to receive ID\n", this->getTag());
00687     return -2;
00688   }
00689 
00690   // finally truss creates a material object of the correct type,
00691   // sets its database tag and asks this new object to recveive itself.
00692 
00693   int matClass = data(4);
00694   int matDb = data(5);
00695 
00696   // check if we have a material object already & if we do if of right type
00697   if ((theMaterial == 0) || (theMaterial->getClassTag() != matClass)) {
00698 
00699     // if old one .. delete it
00700     if (theMaterial != 0)
00701       delete theMaterial;
00702 
00703     // create a new material object
00704     theMaterial = theBroker.getNewUniaxialMaterial(matClass);
00705     if (theMaterial == 0) {
00706       g3ErrorHandler->warning("WARNING Truss::recvSelf() - %d failed to get a blank Material of type %d\n", 
00707          this->getTag(), matClass);
00708       return -3;
00709     }
00710   }
00711 
00712   theMaterial->setDbTag(matDb); // note: we set the dbTag before we receive the material
00713   res = theMaterial->recvSelf(commitTag, theChannel, theBroker);
00714   if (res < 0) {
00715     g3ErrorHandler->warning("WARNING Truss::recvSelf() - %d failed to receive its Material\n", this->getTag());
00716     return -3;    
00717   }
00718 
00719   return 0;
00720 }
00721 
00722 
00723 int
00724 Truss::displaySelf(Renderer &theViewer, int displayMode, float fact)
00725 {
00726     // ensure setDomain() worked
00727     if (L == 0.0)
00728        return 0;
00729 
00730     // first determine the two end points of the truss based on
00731     // the display factor (a measure of the distorted image)
00732     // store this information in 2 3d vectors v1 and v2
00733     const Vector &end1Crd = end1Ptr->getCrds();
00734     const Vector &end2Crd = end2Ptr->getCrds(); 
00735     const Vector &end1Disp = end1Ptr->getDisp();
00736     const Vector &end2Disp = end2Ptr->getDisp();    
00737 
00738     if (displayMode == 1 || displayMode == 2) {
00739  Vector v1(3);
00740  Vector v2(3);
00741  for (int i=0; i<dimension; i++) {
00742      v1(i) = end1Crd(i)+end1Disp(i)*fact;
00743      v2(i) = end2Crd(i)+end2Disp(i)*fact;    
00744  }
00745  
00746  // compute the strain and axial force in the member
00747  double strain, force;
00748  if (L == 0.0) {
00749      strain = 0.0;
00750      force = 0.0;
00751  } else {
00752      strain = this->computeCurrentStrain();
00753      theMaterial->setTrialStrain(strain);
00754      force = A*theMaterial->getStress();    
00755  }
00756     
00757  if (displayMode == 2) // use the strain as the drawing measure
00758      return theViewer.drawLine(v1, v2, strain, strain); 
00759  else { // otherwise use the axial force as measure
00760      return theViewer.drawLine(v1,v2, force, force);
00761  }
00762     }
00763     return 0;
00764 }
00765 
00766 
00767 void
00768 Truss::Print(ostream &s, int flag)
00769 {
00770     // compute the strain and axial force in the member
00771     double strain, force;
00772     if (L == 0.0) {
00773  strain = 0;
00774  force = 0.0;
00775     } else {
00776  strain = this->computeCurrentStrain();
00777  theMaterial->setTrialStrain(strain);
00778  force = A*theMaterial->getStress();    
00779     }
00780     
00781     for (int i=0; i<numDOF; i++)
00782  (*theVector)(i) = (*t)(0,i)*force;
00783     
00784     if (flag == 0) { // print everything
00785  s << "Element: " << this->getTag(); 
00786  s << " type: Truss  iNode: " << connectedExternalNodes(0);
00787  s << " jNode: " << connectedExternalNodes(1);
00788  s << " Area: " << A << " Total Mass: " << M*2;
00789  
00790  s << " \n\t strain: " << strain;
00791  s << " axial load: " << A*theMaterial->getStress();
00792  if (theVector != 0) 
00793      s << " \n\t unbalanced load: " << *theVector; 
00794  s << " \t Material: " << *theMaterial;
00795  s << endl;
00796     } else if (flag == 1) {
00797  s << this->getTag() << "  " << strain << "  ";
00798  s << A*theMaterial->getStress() << endl;
00799     }
00800 }
00801 
00802 double
00803 Truss::computeCurrentStrain(void) const
00804 {
00805     // NOTE method will not be called if L == 0
00806 
00807     // determine the strain
00808     const Vector &disp1 = end1Ptr->getTrialDisp();
00809     const Vector &disp2 = end2Ptr->getTrialDisp(); 
00810 
00811     double dLength = 0.0;
00812     for (int i=0; i<dimension; i++){
00813  dLength -= (disp2(i)-disp1(i))* (*t)(0,i);
00814     }
00815 
00816     // this method should never be called with L == 0
00817     return dLength/L;
00818 }
00819 
00820 double
00821 Truss::computeCurrentStrainRate(void) const
00822 {
00823     // NOTE method will not be called if L == 0
00824 
00825     // determine the strain
00826     const Vector &vel1 = end1Ptr->getTrialVel();
00827     const Vector &vel2 = end2Ptr->getTrialVel(); 
00828 
00829     double dLength = 0.0;
00830     for (int i=0; i<dimension; i++){
00831  dLength -= (vel2(i)-vel1(i))* (*t)(0,i);
00832     }
00833 
00834     // this method should never be called with L == 0
00835     return dLength/L;
00836 }
00837 
00838 Response*
00839 Truss::setResponse(char **argv, int argc, Information &eleInfo)
00840 {
00841   //
00842   // we compare argv[0] for known response types for the Truss
00843   //
00844 
00845   if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0 || strcmp(argv[0],"axialForce") == 0)
00846     return new ElementResponse(this, 1, 0.0);
00847 
00848   else if (strcmp(argv[0],"defo") == 0 || strcmp(argv[0],"deformations") == 0 ||
00849     strcmp(argv[0],"deformation") == 0)
00850     return new ElementResponse(this, 2, 0.0);
00851 
00852   // tangent stiffness matrix
00853   else if (strcmp(argv[0],"stiff") == 0)
00854     return new ElementResponse(this, 3, *theMatrix);
00855 
00856   // a material quantity    
00857   else if (strcmp(argv[0],"material") == 0)
00858     return theMaterial->setResponse(&argv[1], argc-1, eleInfo);
00859   
00860   else
00861     return 0;
00862 }
00863 
00864 int 
00865 Truss::getResponse(int responseID, Information &eleInfo)
00866 {
00867  double strain;
00868   switch (responseID) {
00869     case 1:
00870       //strain = this->computeCurrentStrain();
00871       //theMaterial->setTrialStrain(strain);
00872       //eleInformation.theDouble = A*theMaterial->getStress();    
00873       //return 0;
00874       return eleInfo.setDouble(A * theMaterial->getStress());
00875       
00876     case 2:
00877       //strain = this->computeCurrentStrain();
00878       //eleInformation.theDouble = strain*L;    
00879       //return 0;      
00880       return eleInfo.setDouble(L * theMaterial->getStrain());
00881       
00882     case 3:
00883       //if (eleInformation.theMatrix != 0)
00884       //*(eleInformation.theMatrix) = this->getTangentStiff();
00885       //return 0;      
00886       return eleInfo.setMatrix(this->getTangentStiff());
00887 
00888     default:
00889       return 0;
00890   }
00891 }
00892 
00893 
00894 int
00895 Truss::setParameter (char **argv, int argc, Information &info)
00896 {
00897     if (argc < 1)
00898         return -1;
00899 
00900     // Cross sectional area of the truss itself
00901     if (strcmp(argv[0],"A") == 0) {
00902         info.theType = DoubleType;
00903         return 1;
00904     }
00905 
00906     // a material parameter
00907     if (strcmp(argv[0],"material") == 0) {
00908       int ok = theMaterial->setParameter(&argv[1], argc-1, info);
00909       if (ok < 0)
00910  return -1;
00911       else
00912  return ok + 100;
00913     } 
00914     
00915     // otherwise parameter is unknown for the Truss class
00916     else
00917       return -1;
00918 }
00919     
00920 int
00921 Truss::updateParameter (int parameterID, Information &info)
00922 {
00923   switch (parameterID) {
00924     case -1:
00925       return -1;
00926       
00927     case 1:
00928         this->A = info.theDouble;
00929         return 0;
00930 
00931     default:
00932       if (parameterID >= 100)
00933    return theMaterial->updateParameter(parameterID-100, info);
00934       else
00935    return -1;
00936   }
00937 }
Copyright Contact Us