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

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