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

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