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

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