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.26 $
00022 // $Date: 2006/09/05 21:15:19 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/element/truss/Truss.cpp,v $
00024                                                                         
00025                                                                         
00026 // Written: fmk 
00027 // Created: 07/98
00028 // Revision: A
00029 //
00030 // Description: This file contains the implementation for the Truss class.
00031 //
00032 // What: "@(#) Truss.C, revA"
00033 
00034 #include <Truss.h>
00035 #include <Information.h>
00036 #include <Parameter.h>
00037 
00038 #include <Domain.h>
00039 #include <Node.h>
00040 #include <Channel.h>
00041 #include <FEM_ObjectBroker.h>
00042 #include <UniaxialMaterial.h>
00043 #include <Renderer.h>
00044 
00045 #include <math.h>
00046 #include <stdlib.h>
00047 #include <string.h>
00048 
00049 #include <ElementResponse.h>
00050 
00051 //#include <fstream>
00052 
00053 // initialise the class wide variables
00054 Matrix Truss::trussM2(2,2);
00055 Matrix Truss::trussM4(4,4);
00056 Matrix Truss::trussM6(6,6);
00057 Matrix Truss::trussM12(12,12);
00058 Vector Truss::trussV2(2);
00059 Vector Truss::trussV4(4);
00060 Vector Truss::trussV6(6);
00061 Vector Truss::trussV12(12);
00062 
00063 // constructor:
00064 //  responsible for allocating the necessary space needed by each object
00065 //  and storing the tags of the truss end nodes.
00066 Truss::Truss(int tag, 
00067              int dim,
00068              int Nd1, int Nd2, 
00069              UniaxialMaterial &theMat,
00070              double a, double r)
00071  :Element(tag,ELE_TAG_Truss),     
00072   theMaterial(0), connectedExternalNodes(2),
00073   dimension(dim), numDOF(0), theLoad(0),
00074   theMatrix(0), theVector(0),
00075   L(0.0), A(a), rho(r)
00076 {
00077     // get a copy of the material and check we obtained a valid copy
00078     theMaterial = theMat.getCopy();
00079     if (theMaterial == 0) {
00080       opserr << "FATAL Truss::Truss - " << tag <<
00081         "failed to get a copy of material with tag " << theMat.getTag() << endln;
00082       exit(-1);
00083     }
00084     
00085     // ensure the connectedExternalNode ID is of correct size & set values
00086     if (connectedExternalNodes.Size() != 2) {
00087       opserr << "FATAL Truss::Truss - " <<  tag << "failed to create an ID of size 2\n";
00088       exit(-1);
00089     }
00090 
00091     connectedExternalNodes(0) = Nd1;
00092     connectedExternalNodes(1) = Nd2;        
00093 
00094     // set node pointers to NULL
00095     for (int i=0; i<2; i++)
00096       theNodes[i] = 0;
00097 
00098     cosX[0] = 0.0;
00099     cosX[1] = 0.0;
00100     cosX[2] = 0.0;
00101 
00102 // AddingSensitivity:BEGIN /////////////////////////////////////
00103         parameterID = 0;
00104         theLoadSens = 0;
00105 // AddingSensitivity:END //////////////////////////////////////
00106 }
00107 
00108 // constructor:
00109 //   invoked by a FEM_ObjectBroker - blank object that recvSelf needs
00110 //   to be invoked upon
00111 Truss::Truss()
00112 :Element(0,ELE_TAG_Truss),     
00113  theMaterial(0),connectedExternalNodes(2),
00114  dimension(0), numDOF(0), theLoad(0),
00115  theMatrix(0), theVector(0),
00116   L(0.0), A(0.0), rho(0.0)
00117 {
00118     // ensure the connectedExternalNode ID is of correct size 
00119   if (connectedExternalNodes.Size() != 2) {
00120       opserr << "FATAL Truss::Truss - failed to create an ID of size 2\n";
00121       exit(-1);
00122   }
00123 
00124   for (int i=0; i<2; i++)
00125     theNodes[i] = 0;
00126 
00127   cosX[0] = 0.0;
00128   cosX[1] = 0.0;
00129   cosX[2] = 0.0;
00130 
00131 // AddingSensitivity:BEGIN /////////////////////////////////////
00132         parameterID = 0;
00133         theLoadSens = 0;
00134 // AddingSensitivity:END //////////////////////////////////////
00135 }
00136 
00137 //  destructor
00138 //     delete must be invoked on any objects created by the object
00139 //     and on the matertial object.
00140 Truss::~Truss()
00141 {
00142     // invoke the destructor on any objects created by the object
00143     // that the object still holds a pointer to
00144     if (theMaterial != 0)
00145         delete theMaterial;
00146     if (theLoad != 0)
00147         delete theLoad;
00148     if (theLoadSens != 0)
00149         delete theLoadSens;
00150 }
00151 
00152 
00153 int
00154 Truss::getNumExternalNodes(void) const
00155 {
00156     return 2;
00157 }
00158 
00159 const ID &
00160 Truss::getExternalNodes(void) 
00161 {
00162     return connectedExternalNodes;
00163 }
00164 
00165 Node **
00166 Truss::getNodePtrs(void) 
00167 {
00168   return theNodes;
00169 }
00170 
00171 int
00172 Truss::getNumDOF(void) 
00173 {
00174     return numDOF;
00175 }
00176 
00177 
00178 // method: setDomain()
00179 //    to set a link to the enclosing Domain and to set the node pointers.
00180 //    also determines the number of dof associated
00181 //    with the truss element, we set matrix and vector pointers,
00182 //    allocate space for t matrix, determine the length
00183 //    and set the transformation matrix.
00184 void
00185 Truss::setDomain(Domain *theDomain)
00186 {
00187     // check Domain is not null - invoked when object removed from a domain
00188     if (theDomain == 0) {
00189         theNodes[0] = 0;
00190         theNodes[1] = 0;
00191         L = 0;
00192         return;
00193     }
00194 
00195     // first set the node pointers
00196     int Nd1 = connectedExternalNodes(0);
00197     int Nd2 = connectedExternalNodes(1);
00198     theNodes[0] = theDomain->getNode(Nd1);
00199     theNodes[1] = theDomain->getNode(Nd2);      
00200     
00201     // if can't find both - send a warning message
00202     if ((theNodes[0] == 0) || (theNodes[1] == 0)) {
00203       if (theNodes[0] == 0)
00204         opserr <<"Truss::setDomain() - truss" << this->getTag() << " node " << Nd1 <<
00205           "does not exist in the model\n";
00206       else
00207         opserr <<"Truss::setDomain() - truss" << this->getTag() << " node " << Nd2 <<
00208           "does not exist in the model\n";
00209 
00210       // fill this in so don't segment fault later
00211       numDOF = 2;    
00212       theMatrix = &trussM2;
00213       theVector = &trussV2;     
00214 
00215       return;
00216     }
00217 
00218     // now determine the number of dof and the dimesnion    
00219     int dofNd1 = theNodes[0]->getNumberDOF();
00220     int dofNd2 = theNodes[1]->getNumberDOF();   
00221 
00222     // if differing dof at the ends - print a warning message
00223     if (dofNd1 != dofNd2) {
00224       opserr <<"WARNING Truss::setDomain(): nodes " << Nd1 << " and " << Nd2 <<
00225         "have differing dof at ends for truss " << this->getTag() << endln;
00226 
00227       // fill this in so don't segment fault later
00228       numDOF = 2;    
00229       theMatrix = &trussM2;
00230       theVector = &trussV2;     
00231         
00232       return;
00233     }   
00234 
00235     // call the base class method
00236     this->DomainComponent::setDomain(theDomain);
00237 
00238     // now set the number of dof for element and set matrix and vector pointer
00239     if (dimension == 1 && dofNd1 == 1) {
00240         numDOF = 2;    
00241         theMatrix = &trussM2;
00242         theVector = &trussV2;
00243     }
00244     else if (dimension == 2 && dofNd1 == 2) {
00245         numDOF = 4;
00246         theMatrix = &trussM4;
00247         theVector = &trussV4;   
00248     }
00249     else if (dimension == 2 && dofNd1 == 3) {
00250         numDOF = 6;     
00251         theMatrix = &trussM6;
00252         theVector = &trussV6;           
00253     }
00254     else if (dimension == 3 && dofNd1 == 3) {
00255         numDOF = 6;     
00256         theMatrix = &trussM6;
00257         theVector = &trussV6;                   
00258     }
00259     else if (dimension == 3 && dofNd1 == 6) {
00260         numDOF = 12;        
00261         theMatrix = &trussM12;
00262         theVector = &trussV12;                  
00263     }
00264     else {
00265       opserr <<"WARNING Truss::setDomain cannot handle " << dimension << " dofs at nodes in " << 
00266         dofNd1  << " problem\n";
00267 
00268       numDOF = 2;    
00269       theMatrix = &trussM2;
00270       theVector = &trussV2;     
00271       return;
00272     }
00273 
00274     if (theLoad == 0)
00275       theLoad = new Vector(numDOF);
00276     else if (theLoad->Size() != numDOF) {
00277       delete theLoad;
00278       theLoad = new Vector(numDOF);
00279     }
00280 
00281     if (theLoad == 0) {
00282       opserr << "Truss::setDomain - truss " << this->getTag() << 
00283         "out of memory creating vector of size" << numDOF << endln;
00284       exit(-1);
00285       return;
00286     }          
00287     
00288     // now determine the length, cosines and fill in the transformation
00289     // NOTE t = -t(every one else uses for residual calc)
00290     const Vector &end1Crd = theNodes[0]->getCrds();
00291     const Vector &end2Crd = theNodes[1]->getCrds();     
00292 
00293     if (dimension == 1) {
00294       double dx = end2Crd(0)-end1Crd(0);        
00295 
00296       L = sqrt(dx*dx);
00297       
00298       if (L == 0.0) {
00299         opserr <<"WARNING Truss::setDomain() - truss " << this->getTag() << " has zero length\n";
00300         return;
00301       }
00302 
00303       cosX[0] = 1.0;
00304     }
00305     else if (dimension == 2) {
00306         double dx = end2Crd(0)-end1Crd(0);
00307         double dy = end2Crd(1)-end1Crd(1);      
00308     
00309         L = sqrt(dx*dx + dy*dy);
00310     
00311         if (L == 0.0) {
00312           opserr <<"WARNING Truss::setDomain() - truss " << this->getTag() << " has zero length\n";
00313           return;
00314         }
00315         
00316         cosX[0] = dx/L;
00317         cosX[1] = dy/L;
00318     }
00319     else {
00320         double dx = end2Crd(0)-end1Crd(0);
00321         double dy = end2Crd(1)-end1Crd(1);      
00322         double dz = end2Crd(2)-end1Crd(2);              
00323     
00324         L = sqrt(dx*dx + dy*dy + dz*dz);
00325     
00326         if (L == 0.0) {
00327           opserr <<"WARNING Truss::setDomain() - truss " << this->getTag() << " has zero length\n";
00328           return;
00329         }
00330         
00331         cosX[0] = dx/L;
00332         cosX[1] = dy/L;
00333         cosX[2] = dz/L;
00334     }
00335 }        
00336 
00337 
00338 int
00339 Truss::commitState()
00340 {
00341   int retVal = 0;
00342   // call element commitState to do any base class stuff
00343   if ((retVal = this->Element::commitState()) != 0) {
00344     opserr << "Truss::commitState () - failed in base class";
00345   }    
00346   retVal = theMaterial->commitState();
00347   return retVal;
00348 }
00349 
00350 int
00351 Truss::revertToLastCommit()
00352 {
00353     return theMaterial->revertToLastCommit();
00354 }
00355 
00356 int
00357 Truss::revertToStart()
00358 {
00359     return theMaterial->revertToStart();
00360 }
00361 
00362 int
00363 Truss::update(void)
00364 {
00365     // determine the current strain given trial displacements at nodes
00366     double strain = this->computeCurrentStrain();
00367     double rate = this->computeCurrentStrainRate();
00368     return theMaterial->setTrialStrain(strain, rate);
00369 }
00370 
00371 
00372 const Matrix &
00373 Truss::getTangentStiff(void)
00374 {
00375     if (L == 0.0) { // - problem in setDomain() no further warnings
00376         theMatrix->Zero();
00377         return *theMatrix;
00378     }
00379     
00380     double E = theMaterial->getTangent();
00381 
00382     // come back later and redo this if too slow
00383     Matrix &stiff = *theMatrix;
00384 
00385     int numDOF2 = numDOF/2;
00386     double temp;
00387     double EAoverL = E*A/L;
00388     for (int i = 0; i < dimension; i++) {
00389       for (int j = 0; j < dimension; j++) {
00390         temp = cosX[i]*cosX[j]*EAoverL;
00391         stiff(i,j) = temp;
00392         stiff(i+numDOF2,j) = -temp;
00393         stiff(i,j+numDOF2) = -temp;
00394         stiff(i+numDOF2,j+numDOF2) = temp;
00395       }
00396     }
00397 
00398     return stiff;
00399 }
00400 
00401 
00402 const Matrix &
00403 Truss::getInitialStiff(void)
00404 {
00405     if (L == 0.0) { // - problem in setDomain() no further warnings
00406         theMatrix->Zero();
00407         return *theMatrix;
00408     }
00409     
00410     double E = theMaterial->getInitialTangent();
00411 
00412     // come back later and redo this if too slow
00413     Matrix &stiff = *theMatrix;
00414 
00415     int numDOF2 = numDOF/2;
00416     double temp;
00417     double EAoverL = E*A/L;
00418     for (int i = 0; i < dimension; i++) {
00419       for (int j = 0; j < dimension; j++) {
00420         temp = cosX[i]*cosX[j]*EAoverL;
00421         stiff(i,j) = temp;
00422         stiff(i+numDOF2,j) = -temp;
00423         stiff(i,j+numDOF2) = -temp;
00424         stiff(i+numDOF2,j+numDOF2) = temp;
00425       }
00426     }
00427 
00428     return *theMatrix;
00429 }
00430 
00431 const Matrix &
00432 Truss::getDamp(void)
00433 {
00434     if (L == 0.0) { // - problem in setDomain() no further warnings
00435         theMatrix->Zero();
00436         return *theMatrix;
00437     }
00438     
00439     double eta = theMaterial->getDampTangent();
00440 
00441     // come back later and redo this if too slow
00442     Matrix &damp = *theMatrix;
00443 
00444     int numDOF2 = numDOF/2;
00445     double temp;
00446     double etaAoverL = eta*A/L;
00447     for (int i = 0; i < dimension; i++) {
00448       for (int j = 0; j < dimension; j++) {
00449         temp = cosX[i]*cosX[j]*etaAoverL;
00450         damp(i,j) = temp;
00451         damp(i+numDOF2,j) = -temp;
00452         damp(i,j+numDOF2) = -temp;
00453         damp(i+numDOF2,j+numDOF2) = temp;
00454       }
00455     }
00456 
00457     return damp;
00458 }
00459 
00460 
00461 const Matrix &
00462 Truss::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   int numDOF2 = numDOF/2;
00475   for (int i = 0; i < dimension; i++) {
00476     mass(i,i) = M;
00477     mass(i+numDOF2,i+numDOF2) = M;
00478   }
00479 
00480   return mass;
00481 }
00482 
00483 void 
00484 Truss::zeroLoad(void)
00485 {
00486   theLoad->Zero();
00487 }
00488 
00489 int 
00490 Truss::addLoad(ElementalLoad *theLoad, double loadFactor)
00491 
00492 {  
00493   opserr <<"Truss::addLoad - load type unknown for truss with tag: " << this->getTag() << endln;
00494   
00495   return -1;
00496 }
00497 
00498 int 
00499 Truss::addInertiaLoadToUnbalance(const Vector &accel)
00500 {
00501     // check for a quick return
00502     if (L == 0.0 || rho == 0.0) 
00503         return 0;
00504 
00505   // get R * accel from the nodes
00506   const Vector &Raccel1 = theNodes[0]->getRV(accel);
00507   const Vector &Raccel2 = theNodes[1]->getRV(accel);    
00508 
00509   int nodalDOF = numDOF/2;
00510     
00511 #ifdef _G3DEBUG    
00512   if (nodalDOF != Raccel1.Size() || nodalDOF != Raccel2.Size()) {
00513     opserr <<"Truss::addInertiaLoadToUnbalance " <<
00514       "matrix and vector sizes are incompatable\n";
00515     return -1;
00516   }
00517 #endif
00518     
00519   double M = 0.5*rho*L;
00520     // want to add ( - fact * M R * accel ) to unbalance
00521     for (int i=0; i<dimension; i++) {
00522         double val1 = Raccel1(i);
00523         double val2 = Raccel2(i);       
00524         
00525         // perform - fact * M*(R * accel) // remember M a diagonal matrix
00526         val1 *= -M;
00527         val2 *= -M;
00528         
00529         (*theLoad)(i) += val1;
00530         (*theLoad)(i+nodalDOF) += val2;
00531     }   
00532 
00533     return 0;
00534 }
00535 
00536 
00537 int 
00538 Truss::addInertiaLoadSensitivityToUnbalance(const Vector &accel, bool somethingRandomInMotions)
00539 {
00540 
00541   if (theLoadSens == 0) {
00542     theLoadSens = new Vector(numDOF);
00543   }
00544   else {
00545     theLoadSens->Zero();
00546   }
00547   
00548   
00549   if (somethingRandomInMotions) {
00550     
00551     
00552     // check for a quick return
00553     if (L == 0.0 || rho == 0.0) 
00554       return 0;
00555     
00556     // get R * accel from the nodes
00557     const Vector &Raccel1 = theNodes[0]->getRV(accel);
00558     const Vector &Raccel2 = theNodes[1]->getRV(accel);    
00559     
00560     int nodalDOF = numDOF/2;
00561     
00562 #ifdef _G3DEBUG    
00563     if (nodalDOF != Raccel1.Size() || nodalDOF != Raccel2.Size()) {
00564       opserr << "Truss::addInertiaLoadToUnbalance " <<
00565         "matrix and vector sizes are incompatable\n";
00566       return -1;
00567     }
00568 #endif
00569     
00570         double M  = 0.5*rho*L;
00571     // want to add ( - fact * M R * accel ) to unbalance
00572     for (int i=0; i<dimension; i++) {
00573       double val1 = Raccel1(i);
00574       double val2 = Raccel2(i); 
00575       
00576       // perform - fact * M*(R * accel) // remember M a diagonal matrix
00577       val1 *= M;
00578       val2 *= M;
00579       
00580       (*theLoadSens)(i) = val1;
00581       (*theLoadSens)(i+nodalDOF) = val2;
00582     }   
00583   }
00584   else {
00585     
00586     // check for a quick return
00587     if (L == 0.0 || rho == 0.0) 
00588       return 0;
00589     
00590     // get R * accel from the nodes
00591     const Vector &Raccel1 = theNodes[0]->getRV(accel);
00592     const Vector &Raccel2 = theNodes[1]->getRV(accel);    
00593     
00594     int nodalDOF = numDOF/2;
00595     
00596 #ifdef _G3DEBUG    
00597     if (nodalDOF != Raccel1.Size() || nodalDOF != Raccel2.Size()) {
00598       opserr << "Truss::addInertiaLoadToUnbalance " <<
00599         "matrix and vector sizes are incompatable\n";
00600       return -1;
00601     }
00602 #endif
00603     
00604     double massDerivative = 0.0;
00605     if (parameterID == 2) {
00606       massDerivative = 0.5*L;
00607     }
00608       
00609     // want to add ( - fact * M R * accel ) to unbalance
00610     for (int i=0; i<dimension; i++) {
00611       double val1 = Raccel1(i);
00612       double val2 = Raccel2(i); 
00613       
00614       // perform - fact * M*(R * accel) // remember M a diagonal matrix
00615       
00616       val1 *= massDerivative;
00617       val2 *= massDerivative;
00618       
00619       (*theLoadSens)(i) = val1;
00620       (*theLoadSens)(i+nodalDOF) = val2;
00621     }   
00622   }
00623   return 0;
00624 }
00625 
00626 const Vector &
00627 Truss::getResistingForce()
00628 {       
00629     if (L == 0.0) { // - problem in setDomain() no further warnings
00630         theVector->Zero();
00631         return *theVector;
00632     }
00633     
00634     // R = Ku - Pext
00635     // Ku = F * transformation
00636     double force = A*theMaterial->getStress();
00637     int numDOF2 = numDOF/2;
00638     double temp;
00639     for (int i = 0; i < dimension; i++) {
00640       temp = cosX[i]*force;
00641       (*theVector)(i) = -temp;
00642       (*theVector)(i+numDOF2) = temp;
00643     }
00644 
00645     // subtract external load:  Ku - P
00646     (*theVector) -= *theLoad;
00647 
00648     return *theVector;
00649 }
00650 
00651 
00652 const Vector &
00653 Truss::getResistingForceIncInertia()
00654 {       
00655     this->getResistingForce();
00656     
00657     // now include the mass portion
00658     if (L != 0.0 && rho != 0.0) {
00659         
00660         const Vector &accel1 = theNodes[0]->getTrialAccel();
00661         const Vector &accel2 = theNodes[1]->getTrialAccel();    
00662         
00663         int numDOF2 = numDOF/2;
00664         double M = 0.5*rho*L;
00665         for (int i = 0; i < dimension; i++) {
00666             (*theVector)(i) += M*accel1(i);
00667             (*theVector)(i+numDOF2) += M*accel2(i);
00668         }
00669 
00670         // add the damping forces if rayleigh damping
00671         if (alphaM != 0.0 || betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00672           (*theVector) += this->getRayleighDampingForces();
00673     }  else {
00674 
00675       // add the damping forces if rayleigh damping
00676       if (betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00677         (*theVector) += this->getRayleighDampingForces();
00678     }
00679     
00680     return *theVector;
00681 }
00682 
00683 int
00684 Truss::sendSelf(int commitTag, Channel &theChannel)
00685 {
00686   int res;
00687 
00688   // note: we don't check for dataTag == 0 for Element
00689   // objects as that is taken care of in a commit by the Domain
00690   // object - don't want to have to do the check if sending data
00691   int dataTag = this->getDbTag();
00692 
00693   // truss packs it's data into a Vector and sends this to theChannel
00694   // along with it's dbTag and the commitTag passed in the arguments
00695 
00696   static Vector data(7);
00697   data(0) = this->getTag();
00698   data(1) = dimension;
00699   data(2) = numDOF;
00700   data(3) = A;
00701   data(6) = rho;
00702   
00703   data(4) = theMaterial->getClassTag();
00704   int matDbTag = theMaterial->getDbTag();
00705 
00706   // NOTE: we do have to ensure that the material has a database
00707   // tag if we are sending to a database channel.
00708   if (matDbTag == 0) {
00709     matDbTag = theChannel.getDbTag();
00710     if (matDbTag != 0)
00711       theMaterial->setDbTag(matDbTag);
00712   }
00713   data(5) = matDbTag;
00714 
00715   res = theChannel.sendVector(dataTag, commitTag, data);
00716   if (res < 0) {
00717     opserr <<"WARNING Truss::sendSelf() - " << this->getTag() << " failed to send Vector\n";
00718     return -1;
00719   }           
00720 
00721   // truss then sends the tags of it's two end nodes
00722 
00723   res = theChannel.sendID(dataTag, commitTag, connectedExternalNodes);
00724   if (res < 0) {
00725     opserr <<"WARNING Truss::sendSelf() - " << this->getTag() << " failed to send Vector\n";
00726     return -2;
00727   }
00728 
00729   // finally truss asks it's material object to send itself
00730   res = theMaterial->sendSelf(commitTag, theChannel);
00731   if (res < 0) {
00732     opserr <<"WARNING Truss::sendSelf() - " << this->getTag() << " failed to send its Material\n";
00733     return -3;
00734   }
00735 
00736   return 0;
00737 }
00738 
00739 int
00740 Truss::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00741 {
00742   int res;
00743   int dataTag = this->getDbTag();
00744 
00745   // truss creates a Vector, receives the Vector and then sets the 
00746   // internal data with the data in the Vector
00747 
00748   static Vector data(7);
00749   res = theChannel.recvVector(dataTag, commitTag, data);
00750   if (res < 0) {
00751     opserr <<"WARNING Truss::recvSelf() - failed to receive Vector\n";
00752     return -1;
00753   }           
00754 
00755   this->setTag((int)data(0));
00756   dimension = (int)data(1);
00757   numDOF = (int)data(2);
00758   A = data(3);
00759   rho = data(6);
00760   
00761   // truss now receives the tags of it's two external nodes
00762   res = theChannel.recvID(dataTag, commitTag, connectedExternalNodes);
00763   if (res < 0) {
00764     opserr <<"WARNING Truss::recvSelf() - " << this->getTag() << " failed to receive ID\n";
00765     return -2;
00766   }
00767 
00768   // finally truss creates a material object of the correct type,
00769   // sets its database tag and asks this new object to recveive itself.
00770 
00771   int matClass = (int)data(4);
00772   int matDb = (int)data(5);
00773 
00774   // check if we have a material object already & if we do if of right type
00775   if ((theMaterial == 0) || (theMaterial->getClassTag() != matClass)) {
00776 
00777     // if old one .. delete it
00778     if (theMaterial != 0)
00779       delete theMaterial;
00780 
00781     // create a new material object
00782     theMaterial = theBroker.getNewUniaxialMaterial(matClass);
00783     if (theMaterial == 0) {
00784       opserr <<"WARNING Truss::recvSelf() - " << this->getTag() 
00785         << " failed to get a blank Material of type " << matClass << endln;
00786       return -3;
00787     }
00788   }
00789 
00790   theMaterial->setDbTag(matDb); // note: we set the dbTag before we receive the material
00791   res = theMaterial->recvSelf(commitTag, theChannel, theBroker);
00792   if (res < 0) {
00793     opserr <<"WARNING Truss::recvSelf() - "<< this->getTag() << "failed to receive its Material\n";
00794     return -3;    
00795   }
00796 
00797   return 0;
00798 }
00799 
00800 
00801 int
00802 Truss::displaySelf(Renderer &theViewer, int displayMode, float fact)
00803 {
00804     // ensure setDomain() worked
00805     if (L == 0.0)
00806        return 0;
00807 
00808     // first determine the two end points of the truss based on
00809     // the display factor (a measure of the distorted image)
00810     // store this information in 2 3d vectors v1 and v2
00811     const Vector &end1Crd = theNodes[0]->getCrds();
00812     const Vector &end2Crd = theNodes[1]->getCrds();     
00813 
00814     static Vector v1(3);
00815     static Vector v2(3);
00816 
00817     if (displayMode == 1 || displayMode == 2) {
00818       const Vector &end1Disp = theNodes[0]->getDisp();
00819       const Vector &end2Disp = theNodes[1]->getDisp();    
00820 
00821         for (int i=0; i<dimension; i++) {
00822             v1(i) = end1Crd(i)+end1Disp(i)*fact;
00823             v2(i) = end2Crd(i)+end2Disp(i)*fact;    
00824         }
00825         
00826         // compute the strain and axial force in the member
00827         double strain, force;
00828         if (L == 0.0) {
00829             strain = 0.0;
00830             force = 0.0;
00831         } else {
00832             strain = this->computeCurrentStrain();
00833             theMaterial->setTrialStrain(strain);
00834             force = A*theMaterial->getStress();    
00835         }
00836     
00837         if (displayMode == 2) // use the strain as the drawing measure
00838           return theViewer.drawLine(v1, v2, strain, strain);    
00839         else { // otherwise use the axial force as measure
00840           return theViewer.drawLine(v1,v2, force, force);
00841         }
00842     } else if (displayMode < 0) {
00843       int mode = displayMode  *  -1;
00844       const Matrix &eigen1 = theNodes[0]->getEigenvectors();
00845       const Matrix &eigen2 = theNodes[1]->getEigenvectors();
00846       if (eigen1.noCols() >= mode) {
00847         for (int i = 0; i < dimension; i++) {
00848           v1(i) = end1Crd(i) + eigen1(i,mode-1)*fact;
00849           v2(i) = end2Crd(i) + eigen2(i,mode-1)*fact;    
00850         }    
00851       } else {
00852         for (int i = 0; i < dimension; i++) {
00853           v1(i) = end1Crd(i);
00854           v2(i) = end2Crd(i);
00855         }    
00856       }
00857     }
00858     return 0;
00859 }
00860 
00861 
00862 void
00863 Truss::Print(OPS_Stream &s, int flag)
00864 {
00865     // compute the strain and axial force in the member
00866     double strain, force;
00867     strain = theMaterial->getStrain();
00868     force = A * theMaterial->getStress();
00869     
00870     if (flag == 0) { // print everything
00871         s << "Element: " << this->getTag(); 
00872         s << " type: Truss  iNode: " << connectedExternalNodes(0);
00873         s << " jNode: " << connectedExternalNodes(1);
00874         s << " Area: " << A << " Mass/Length: " << rho;
00875         
00876         s << " \n\t strain: " << strain;
00877         s << " axial load: " <<  force;
00878         if (L != 0.0) {
00879           int numDOF2 = numDOF/2;
00880           double temp;
00881           for (int i = 0; i < dimension; i++) {
00882             temp = cosX[i]*force;
00883             (*theVector)(i) = -temp;
00884             (*theVector)(i+numDOF2) = temp;
00885           }
00886           s << " \n\t unbalanced load: " << *theVector; 
00887         }
00888 
00889         s << " \t Material: " << *theMaterial;
00890         s << endln;
00891     } else if (flag == 1) {
00892         s << this->getTag() << "  " << strain << "  ";
00893         s << force << endln;
00894     }
00895 }
00896 
00897 double
00898 Truss::computeCurrentStrain(void) const
00899 {
00900     // NOTE method will not be called if L == 0
00901 
00902     // determine the strain
00903     const Vector &disp1 = theNodes[0]->getTrialDisp();
00904     const Vector &disp2 = theNodes[1]->getTrialDisp();  
00905 
00906     double dLength = 0.0;
00907     for (int i = 0; i < dimension; i++)
00908       dLength += (disp2(i)-disp1(i))*cosX[i];
00909   
00910     // this method should never be called with L == 0
00911     return dLength/L;
00912 }
00913 
00914 double
00915 Truss::computeCurrentStrainRate(void) const
00916 {
00917     // NOTE method will not be called if L == 0
00918 
00919     // determine the strain
00920     const Vector &vel1 = theNodes[0]->getTrialVel();
00921     const Vector &vel2 = theNodes[1]->getTrialVel();    
00922 
00923     double dLength = 0.0;
00924     for (int i = 0; i < dimension; i++){
00925         dLength += (vel2(i)-vel1(i))*cosX[i];
00926     }
00927 
00928     // this method should never be called with L == 0
00929     return dLength/L;
00930 }
00931 
00932 Response*
00933 Truss::setResponse(const char **argv, int argc, Information &eleInfo, OPS_Stream &output)
00934 {
00935 
00936   Response *theResponse = 0;
00937 
00938   output.tag("ElementOutput");
00939   output.attr("eleType","Truss");
00940   output.attr("eleTag",this->getTag());
00941   output.attr("node1",connectedExternalNodes[0]);
00942   output.attr("node2",connectedExternalNodes[1]);
00943 
00944   //
00945   // we compare argv[0] for known response types for the Truss
00946   //
00947 
00948   if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0 || strcmp(argv[0],"axialForce") == 0) {
00949     opserr << "HELLO\n";
00950     output.tag("ResponseType", "N");
00951     theResponse =  new ElementResponse(this, 1, 0.0);
00952 
00953   } else if (strcmp(argv[0],"defo") == 0 || strcmp(argv[0],"deformations") == 0 ||
00954              strcmp(argv[0],"deformation") == 0) {
00955 
00956     output.tag("ResponseType", "eps");
00957     theResponse = new ElementResponse(this, 2, 0.0);
00958 
00959   // a material quantity    
00960   } else if (strcmp(argv[0],"material") == 0 || strcmp(argv[0],"-material") == 0) {
00961 
00962     theResponse =  theMaterial->setResponse(&argv[1], argc-1, eleInfo, output);
00963   }
00964 
00965   output.endTag();
00966   return theResponse;
00967 }
00968 
00969 int 
00970 Truss::getResponse(int responseID, Information &eleInfo)
00971 {
00972   switch (responseID) {
00973     case 1:
00974       return eleInfo.setDouble(A * theMaterial->getStress());
00975       
00976     case 2:
00977       return eleInfo.setDouble(L * theMaterial->getStrain());
00978       
00979     case 3:
00980       return eleInfo.setMatrix(this->getTangentStiff());
00981 
00982     default:
00983       return 0;
00984   }
00985 }
00986 
00987 // AddingSensitivity:BEGIN ///////////////////////////////////
00988 int
00989 Truss::setParameter(const char **argv, int argc, Parameter &param)
00990 {
00991   if (argc < 1)
00992     return -1;
00993   
00994   // Cross sectional area of the truss
00995   if (strcmp(argv[0],"A") == 0)
00996     return param.addObject(1, this);
00997   
00998   // Mass densitity of the truss
00999   if (strcmp(argv[0],"rho") == 0)
01000     return param.addObject(2, this);
01001   
01002   // Explicit specification of a material parameter
01003   if (strstr(argv[0],"material") != 0) {
01004     
01005     if (argc < 2)
01006       return -1;
01007     
01008     else
01009       return theMaterial->setParameter(&argv[1], argc-1, param);
01010   } 
01011   
01012   // Otherwise, send it to the material
01013   else
01014     return theMaterial->setParameter(argv, argc, param);
01015 }
01016 
01017 int
01018 Truss::updateParameter (int parameterID, Information &info)
01019 {
01020   switch (parameterID) {
01021   case 1:
01022     A = info.theDouble;
01023     return 0;
01024   case 2:
01025     rho = info.theDouble;
01026     return 0;
01027   default:
01028     return -1;
01029   }
01030 }
01031 
01032 int
01033 Truss::activateParameter(int passedParameterID)
01034 {
01035   parameterID = passedParameterID;
01036   
01037   return 0;
01038 }
01039 
01040 
01041 const Matrix &
01042 Truss::getKiSensitivity(int gradNumber)
01043 {
01044   Matrix &stiff = *theMatrix;
01045   stiff.Zero();
01046     
01047   if (parameterID == 0) {
01048   }
01049   else if (parameterID == 1) {
01050     // If cross sectional area is random
01051     double E = theMaterial->getInitialTangent();
01052     
01053     int numDOF2 = numDOF/2;
01054     double temp;
01055     double EoverL = E/L;
01056     for (int i = 0; i < dimension; i++) {
01057       for (int j = 0; j < dimension; j++) {
01058         temp = cosX[i]*cosX[j]*EoverL;
01059         stiff(i,j) = temp;
01060         stiff(i+numDOF2,j) = -temp;
01061         stiff(i,j+numDOF2) = -temp;
01062         stiff(i+numDOF2,j+numDOF2) = temp;
01063       }
01064     }
01065   }
01066   else if (parameterID == 2) {
01067     // Nothing here when 'rho' is random
01068   }
01069   else {
01070     double Esens = theMaterial->getInitialTangentSensitivity(gradNumber);
01071 
01072     int numDOF2 = numDOF/2;
01073     double temp;
01074     double EAoverL = Esens*A/L;
01075     for (int i = 0; i < dimension; i++) {
01076       for (int j = 0; j < dimension; j++) {
01077         temp = cosX[i]*cosX[j]*EAoverL;
01078         stiff(i,j) = temp;
01079         stiff(i+numDOF2,j) = -temp;
01080         stiff(i,j+numDOF2) = -temp;
01081         stiff(i+numDOF2,j+numDOF2) = temp;
01082       }
01083     }
01084   }
01085   
01086   return stiff;
01087 }
01088 
01089 const Matrix &
01090 Truss::getMassSensitivity(int gradNumber)
01091 {
01092   Matrix &mass = *theMatrix;
01093   mass.Zero();
01094 
01095   if (parameterID == 2) {
01096     double massDerivative = 0.5*L;
01097 
01098     int numDOF2 = numDOF/2;
01099     for (int i = 0; i < dimension; i++) {
01100       mass(i,i) = massDerivative;
01101       mass(i+numDOF2,i+numDOF2) = massDerivative;
01102     }
01103   }
01104 
01105   return mass;
01106 }
01107 
01108 const Vector &
01109 Truss::getResistingForceSensitivity(int gradNumber)
01110 {
01111         theVector->Zero();
01112 
01113         // Initial declarations
01114         int i;
01115         double stressSensitivity, temp1, temp2;
01116 
01117         // Make sure the material is up to date
01118         double strain = this->computeCurrentStrain();
01119         double rate = this->computeCurrentStrainRate();
01120         theMaterial->setTrialStrain(strain,rate);
01121 
01122         // Contribution from material
01123         stressSensitivity = theMaterial->getStressSensitivity(gradNumber,true);
01124 
01125         // Check if a nodal coordinate is random
01126         double dcosXdh[3];
01127         dcosXdh[0] = 0.0;
01128         dcosXdh[1] = 0.0;
01129         dcosXdh[2] = 0.0;
01130         
01131         int nodeParameterID0 = theNodes[0]->getCrdsSensitivity();
01132         int nodeParameterID1 = theNodes[1]->getCrdsSensitivity();
01133         if (nodeParameterID0 != 0 || nodeParameterID1 != 0) {
01134         
01135           double dx = L*cosX[0];
01136           double dy = L*cosX[1];
01137           //double dz = L*cosX[2];
01138 
01139                 // Compute derivative of transformation matrix (assume 4 dofs)
01140                 if (nodeParameterID0 == 1) { // here x1 is random
01141                         temp1 = (-L+dx*dx/L)/(L*L);
01142                         temp2 = dx*dy/(L*L*L);
01143                         //dtdh(0) = -temp1;
01144                         //dtdh(1) = -temp2;
01145                         //dtdh(2) = temp1;
01146                         //dtdh(3) = temp2;
01147                         dcosXdh[0] = temp1;
01148                         dcosXdh[1] = temp2;
01149                         dcosXdh[2] = 0.0;
01150                 }
01151                 if (nodeParameterID0 == 2) { // here y1 is random
01152                         temp1 = (-L+dy*dy/L)/(L*L);
01153                         temp2 = dx*dy/(L*L*L);
01154                         //dtdh(0) = -temp2;
01155                         //dtdh(1) = -temp1;
01156                         //dtdh(2) = temp2;
01157                         //dtdh(3) = temp1;
01158                         dcosXdh[0] = temp2;
01159                         dcosXdh[1] = temp1;
01160                         dcosXdh[2] = 0.0;
01161                 }
01162                 if (nodeParameterID1 == 1) { // here x2 is random
01163                         temp1 = (L-dx*dx/L)/(L*L);
01164                         temp2 = -dx*dy/(L*L*L);
01165                         //dtdh(0) = -temp1;
01166                         //dtdh(1) = -temp2;
01167                         //dtdh(2) = temp1;
01168                         //dtdh(3) = temp2;
01169                         dcosXdh[0] = temp1;
01170                         dcosXdh[1] = temp2;
01171                         dcosXdh[2] = 0.0;
01172                 }
01173                 if (nodeParameterID1 == 2) { // here y2 is random
01174                         temp1 = (L-dy*dy/L)/(L*L);
01175                         temp2 = -dx*dy/(L*L*L);
01176                         //dtdh(0) = -temp2;
01177                         //dtdh(1) = -temp1;
01178                         //dtdh(2) = temp2;
01179                         //dtdh(3) = temp1;
01180                         dcosXdh[0] = temp2;
01181                         dcosXdh[1] = temp1;
01182                         dcosXdh[2] = 0.0;
01183                 }
01184 
01185                 const Vector &disp1 = theNodes[0]->getTrialDisp();
01186                 const Vector &disp2 = theNodes[1]->getTrialDisp();
01187                 double dLengthDerivative = 0.0;
01188                 for (i = 0; i < dimension; i++) {
01189                         dLengthDerivative += (disp2(i)-disp1(i))*dcosXdh[i];
01190                 }
01191 
01192                 double materialTangent = theMaterial->getTangent();
01193                 double strainSensitivity;
01194 
01195                 if (nodeParameterID0 == 1) {            // here x1 is random
01196                         strainSensitivity = (dLengthDerivative*L+strain*dx)/(L*L);
01197                 }
01198                 if (nodeParameterID0 == 2) {    // here y1 is random
01199                         strainSensitivity = (dLengthDerivative*L+strain*dy)/(L*L);
01200                 }
01201                 if (nodeParameterID1 == 1) {            // here x2 is random
01202                         strainSensitivity = (dLengthDerivative*L-strain*dx)/(L*L);
01203                 }
01204                 if (nodeParameterID1 == 2) {    // here y2 is random
01205                         strainSensitivity = (dLengthDerivative*L-strain*dy)/(L*L);
01206                 }
01207                 stressSensitivity += materialTangent * strainSensitivity;
01208         }
01209 
01210 
01211         // Compute sensitivity depending on 'parameter'
01212         double stress = theMaterial->getStress();
01213         int numDOF2 = numDOF/2;
01214         double temp;
01215         if (parameterID == 1) {                 // Cross-sectional area
01216           for (i = 0; i < dimension; i++) {
01217             temp = (stress + A*stressSensitivity)*cosX[i];
01218             (*theVector)(i) = -temp;
01219             (*theVector)(i+numDOF2) = temp;
01220           }
01221         }
01222         else {          // Density, material parameter or nodal coordinate
01223           for (i = 0; i < dimension; i++) {
01224             temp = A*(stressSensitivity*cosX[i] + stress*dcosXdh[i]);
01225             (*theVector)(i) = -temp;
01226             (*theVector)(i+numDOF2) = temp;
01227           }
01228         }
01229 
01230         // subtract external load sensitivity
01231         if (theLoadSens == 0) {
01232                 theLoadSens = new Vector(numDOF);
01233         }
01234         (*theVector) -= *theLoadSens;
01235 
01236         return *theVector;
01237 }
01238 
01239 int
01240 Truss::commitSensitivity(int gradNumber, int numGrads)
01241 {
01242         // Initial declarations
01243         int i; 
01244         double strainSensitivity, temp1, temp2;
01245 
01246         // Displacement difference between the two ends
01247         double strain = this->computeCurrentStrain();
01248         double dLength = strain*L;
01249 
01250         // Displacement sensitivity difference between the two ends
01251         double sens1;
01252         double sens2;
01253         double dSensitivity = 0.0;
01254         for (i=0; i<dimension; i++){
01255           sens1 = theNodes[0]->getDispSensitivity(i+1, gradNumber);
01256           sens2 = theNodes[1]->getDispSensitivity(i+1, gradNumber);
01257           dSensitivity += (sens2-sens1)*cosX[i];
01258         }
01259 
01260         strainSensitivity = dSensitivity/L;
01261 
01262         // Check if a nodal coordinate is random
01263         int nodeParameterID0 = theNodes[0]->getCrdsSensitivity();
01264         int nodeParameterID1 = theNodes[1]->getCrdsSensitivity();
01265         if (nodeParameterID0 != 0 || nodeParameterID1 != 0) {
01266 
01267           double dx = L*cosX[0];
01268           double dy = L*cosX[1];
01269           //double dz = L*cosX[2];
01270 
01271                 // Compute derivative of transformation matrix (assume 4 dofs)
01272                 double dcosXdh[3];
01273 
01274                 if (nodeParameterID0 == 1) { // here x1 is random
01275                         temp1 = (-L+dx*dx/L)/(L*L);
01276                         temp2 = dx*dy/(L*L*L);
01277                         //dtdh(0) = -temp1;
01278                         //dtdh(1) = -temp2;
01279                         //dtdh(2) = temp1;
01280                         //dtdh(3) = temp2;
01281                         dcosXdh[0] = temp1;
01282                         dcosXdh[1] = temp2;
01283                         dcosXdh[2] = 0.0;
01284                 }
01285                 if (nodeParameterID0 == 2) { // here y1 is random
01286                         temp1 = (-L+dy*dy/L)/(L*L);
01287                         temp2 = dx*dy/(L*L*L);
01288                         //dtdh(0) = -temp2;
01289                         //dtdh(1) = -temp1;
01290                         //dtdh(2) = temp2;
01291                         //dtdh(3) = temp1;
01292                         dcosXdh[0] = temp2;
01293                         dcosXdh[1] = temp1;
01294                         dcosXdh[2] = 0.0;
01295                 }
01296 
01297                 if (nodeParameterID1 == 1) { // here x2 is random
01298                         temp1 = (L-dx*dx/L)/(L*L);
01299                         temp2 = -dx*dy/(L*L*L);
01300                         //dtdh(0) = -temp1;
01301                         //dtdh(1) = -temp2;
01302                         //dtdh(2) = temp1;
01303                         //dtdh(3) = temp2;
01304                         dcosXdh[0] = temp1;
01305                         dcosXdh[1] = temp2;
01306                         dcosXdh[2] = 0.0;
01307                 }
01308                 if (nodeParameterID1 == 2) { // here y2 is random
01309                         temp1 = (L-dy*dy/L)/(L*L);
01310                         temp2 = -dx*dy/(L*L*L);
01311                         //dtdh(0) = -temp2;
01312                         //dtdh(1) = -temp1;
01313                         //dtdh(2) = temp2;
01314                         //dtdh(3) = temp1;
01315                         dcosXdh[0] = temp2;
01316                         dcosXdh[1] = temp1;
01317                         dcosXdh[2] = 0.0;
01318                 }
01319 
01320                 const Vector &disp1 = theNodes[0]->getTrialDisp();
01321                 const Vector &disp2 = theNodes[1]->getTrialDisp();
01322                 double dLengthDerivative = 0.0;
01323                 for (i = 0; i < dimension; i++){
01324                         dLengthDerivative += (disp2(i)-disp1(i))*dcosXdh[i];
01325                 }
01326 
01327                 strainSensitivity += dLengthDerivative/L;
01328 
01329                 if (nodeParameterID0 == 1) {            // here x1 is random
01330                         strainSensitivity += dLength/(L*L*L)*dx;
01331                 }
01332                 if (nodeParameterID0 == 2) {    // here y1 is random
01333                         strainSensitivity += dLength/(L*L*L)*dy;
01334                 }
01335                 if (nodeParameterID1 == 1) {            // here x2 is random
01336                         strainSensitivity -= dLength/(L*L*L)*dx;
01337                 }
01338                 if (nodeParameterID1 == 2) {    // here y2 is random
01339                         strainSensitivity -= dLength/(L*L*L)*dy;
01340                 }
01341         }
01342         
01343         // Pass it down to the material
01344         theMaterial->commitSensitivity(strainSensitivity, gradNumber, numGrads);
01345 
01346         return 0;
01347 }
01348 
01349 // AddingSensitivity:END /////////////////////////////////////////////

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