Element.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.19 $
00022 // $Date: 2006/09/05 21:00:46 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/element/Element.cpp,v $
00024                                                                         
00025                                                                         
00026 // Written: fmk 11/95
00027 //
00028 // Purpose: This file contains the class definition for Element.
00029 // Element is an abstract base class and thus no objects of it's type
00030 // can be instantiated. It has pure virtual functions which must be
00031 // implemented in it's derived classes. 
00032 //
00033 // The interface:
00034 //
00035 
00036 #include <stdlib.h>
00037 
00038 #include "Element.h"
00039 #include "ElementResponse.h"
00040 #include <Renderer.h>
00041 #include <Vector.h>
00042 #include <Matrix.h>
00043 #include <Node.h>
00044 #include <Domain.h>
00045 
00046 Matrix **Element::theMatrices; 
00047 Vector **Element::theVectors1; 
00048 Vector **Element::theVectors2; 
00049 int  Element::numMatrices(0);
00050 
00051 // Element(int tag, int noExtNodes);
00052 //      constructor that takes the element's unique tag and the number
00053 //      of external nodes for the element.
00054 
00055 Element::Element(int tag, int cTag) 
00056   :DomainComponent(tag, cTag), alphaM(0.0), 
00057   betaK(0.0), betaK0(0.0), betaKc(0.0), 
00058   Kc(0), index(-1), nodeIndex(-1)
00059 {
00060     // does nothing
00061 }
00062 
00063 
00064 Element::~Element() 
00065 {
00066   if (Kc != 0)
00067     delete Kc;
00068 }
00069 
00070 int
00071 Element::commitState(void)
00072 {
00073   if (Kc != 0)
00074     *Kc = this->getTangentStiff();
00075   
00076   return 0;
00077 }
00078 
00079 int
00080 Element::update(void)
00081 {
00082     return 0;
00083 }
00084 
00085 int
00086 Element::revertToStart(void)
00087 {
00088   return 0;
00089 }
00090 
00091 
00092 int
00093 Element::setRayleighDampingFactors(double alpham, double betak, double betak0, double betakc)
00094 {
00095   alphaM = alpham;
00096   betaK  = betak;
00097   betaK0 = betak0;
00098   betaKc = betakc;
00099 
00100   // check that memory has been allocated to store compute/return
00101   // damping matrix & residual force calculations
00102   if (index == -1) {
00103     int numDOF = this->getNumDOF();
00104 
00105     for (int i=0; i<numMatrices; i++) {
00106       Matrix *aMatrix = theMatrices[i];
00107       if (aMatrix->noRows() == numDOF) {
00108         index = i;
00109         i = numMatrices;
00110       }
00111     }
00112     if (index == -1) {
00113       Matrix **nextMatrices = new Matrix *[numMatrices+1];
00114       if (nextMatrices == 0) {
00115         opserr << "Element::getTheMatrix - out of memory\n";
00116       }
00117           int j;
00118       for (j=0; j<numMatrices; j++)
00119         nextMatrices[j] = theMatrices[j];
00120       Matrix *theMatrix = new Matrix(numDOF, numDOF);
00121       if (theMatrix == 0) {
00122         opserr << "Element::getTheMatrix - out of memory\n";
00123         exit(-1);
00124       }
00125       nextMatrices[numMatrices] = theMatrix;
00126 
00127       Vector **nextVectors1 = new Vector *[numMatrices+1];
00128       Vector **nextVectors2 = new Vector *[numMatrices+1];
00129       if (nextVectors1 == 0 || nextVectors2 == 0) {
00130         opserr << "Element::getTheVector - out of memory\n";
00131         exit(-1);
00132       }
00133 
00134       for (j=0; j<numMatrices; j++) {
00135         nextVectors1[j] = theVectors1[j];
00136         nextVectors2[j] = theVectors2[j];
00137       }
00138         
00139       Vector *theVector1 = new Vector(numDOF);
00140       Vector *theVector2 = new Vector(numDOF);
00141       if (theVector1 == 0 || theVector2 == 0) {
00142         opserr << "Element::getTheVector - out of memory\n";
00143         exit(-1);
00144       }
00145 
00146       nextVectors1[numMatrices] = theVector1;
00147       nextVectors2[numMatrices] = theVector2;
00148 
00149       if (numMatrices != 0) {
00150         delete [] theMatrices;
00151         delete [] theVectors1;
00152         delete [] theVectors2;
00153       }
00154       index = numMatrices;
00155       numMatrices++;
00156       theMatrices = nextMatrices;
00157       theVectors1 = nextVectors1;
00158       theVectors2 = nextVectors2;
00159     }
00160   }
00161 
00162   // if need storage for Kc go get it
00163   if (betaKc != 0.0) {  
00164     if (Kc == 0) 
00165       Kc = new Matrix(this->getTangentStiff());
00166     if (Kc == 0) {
00167       opserr << "WARNING - ELEMENT::setRayleighDampingFactors - out of memory\n";
00168       betaKc = 0.0;
00169     }
00170 
00171     // if don't need storage for Kc & have allocated some for it, free the memory
00172   } else if (Kc != 0) { 
00173       delete Kc;
00174       Kc = 0;
00175   }
00176 
00177   return 0;
00178 }
00179 
00180 const Matrix &
00181 Element::getDamp(void) 
00182 {
00183   if (index  == -1) {
00184     this->setRayleighDampingFactors(0.0, 0.0, 0.0, 0.0);
00185   }
00186 
00187   // now compute the damping matrix
00188   Matrix *theMatrix = theMatrices[index]; 
00189   theMatrix->Zero();
00190   if (alphaM != 0.0)
00191     theMatrix->addMatrix(0.0, this->getMass(), alphaM);
00192   if (betaK != 0.0)
00193     theMatrix->addMatrix(1.0, this->getTangentStiff(), betaK);      
00194   if (betaK0 != 0.0)
00195     theMatrix->addMatrix(1.0, this->getInitialStiff(), betaK0);      
00196   if (betaKc != 0.0)
00197     theMatrix->addMatrix(1.0, *Kc, betaKc);      
00198 
00199   // return the computed matrix
00200   return *theMatrix;
00201 }
00202 
00203 
00204 
00205 const Matrix &
00206 Element::getMass(void)
00207 {
00208   if (index  == -1) {
00209     this->setRayleighDampingFactors(0.0, 0.0, 0.0, 0.0);
00210   }
00211 
00212   // zero the matrix & return it
00213   Matrix *theMatrix = theMatrices[index]; 
00214   theMatrix->Zero();
00215   return *theMatrix;
00216 }
00217 
00218 const Vector &
00219 Element::getResistingForceIncInertia(void) 
00220 {
00221   if (index == -1) {
00222     this->setRayleighDampingFactors(0.0, 0.0, 0.0, 0.0);
00223   }
00224 
00225   Matrix *theMatrix = theMatrices[index]; 
00226   Vector *theVector = theVectors2[index];
00227   Vector *theVector2 = theVectors1[index];
00228 
00229   //
00230   // perform: R = P(U) - Pext(t);
00231   //
00232 
00233   (*theVector) = this->getResistingForce();
00234 
00235   //
00236   // perform: R = R - M * a
00237   //
00238 
00239   int loc = 0;
00240   Node **theNodes = this->getNodePtrs();
00241   int numNodes = this->getNumExternalNodes();
00242 
00243   int i;
00244   for (i=0; i<numNodes; i++) {
00245     const Vector &acc = theNodes[i]->getAccel();
00246     for (int i=0; i<acc.Size(); i++) {
00247       (*theVector2)(loc++) = acc(i);
00248     }
00249   }
00250   theVector->addMatrixVector(1.0, this->getMass(), *theVector2, +1.0);
00251 
00252   //
00253   // perform: R = R + (alphaM * M + betaK0 * K0 + betaK * K) * v
00254   //            = R + D * v
00255   //
00256 
00257   // determine the vel vector from ele nodes
00258   loc = 0;
00259   for (i=0; i<numNodes; i++) {
00260     const Vector &vel = theNodes[i]->getTrialVel();
00261     for (int i=0; i<vel.Size(); i++) {
00262       (*theVector2)(loc++) = vel[i];
00263     }
00264   }
00265 
00266   // now compute the damping matrix
00267   theMatrix->Zero();
00268   if (alphaM != 0.0)
00269     theMatrix->addMatrix(0.0, this->getMass(), alphaM);
00270   if (betaK != 0.0)
00271     theMatrix->addMatrix(1.0, this->getTangentStiff(), betaK);      
00272   if (betaK0 != 0.0)
00273     theMatrix->addMatrix(1.0, this->getInitialStiff(), betaK0);      
00274   if (betaKc != 0.0)
00275     theMatrix->addMatrix(1.0, *Kc, betaKc);      
00276 
00277   // finally the D * v
00278   theVector->addMatrixVector(1.0, *theMatrix, *theVector2, 1.0);
00279 
00280   return *theVector;
00281 }
00282 
00283 
00284 const Vector &
00285 Element::getRayleighDampingForces(void) 
00286 {
00287 
00288   if (index == -1) {
00289     this->setRayleighDampingFactors(0.0, 0.0, 0.0, 0.0);
00290   }
00291 
00292   Matrix *theMatrix = theMatrices[index]; 
00293   Vector *theVector = theVectors2[index];
00294   Vector *theVector2 = theVectors1[index];
00295 
00296   //
00297   // perform: R = (alphaM * M + betaK0 * K0 + betaK * K) * v
00298   //            = D * v
00299   //
00300 
00301   // determine the vel vector from ele nodes
00302   Node **theNodes = this->getNodePtrs();
00303   int numNodes = this->getNumExternalNodes();
00304   int loc = 0;
00305   for (int i=0; i<numNodes; i++) {
00306     const Vector &vel = theNodes[i]->getTrialVel();
00307     for (int i=0; i<vel.Size(); i++) {
00308       (*theVector2)(loc++) = vel[i];
00309     }
00310   }
00311 
00312   // now compute the damping matrix
00313   theMatrix->Zero();
00314   if (alphaM != 0.0)
00315     theMatrix->addMatrix(0.0, this->getMass(), alphaM);
00316   if (betaK != 0.0)
00317     theMatrix->addMatrix(1.0, this->getTangentStiff(), betaK);      
00318   if (betaK0 != 0.0)
00319     theMatrix->addMatrix(1.0, this->getInitialStiff(), betaK0);      
00320   if (betaKc != 0.0)
00321     theMatrix->addMatrix(1.0, *Kc, betaKc);      
00322 
00323   // finally the D * v
00324   theVector->addMatrixVector(0.0, *theMatrix, *theVector2, 1.0);
00325 
00326   return *theVector;
00327 }
00328 
00329 int 
00330 Element::addLoad(ElementalLoad *theLoad, double loadFactor) {
00331   return 0;
00332 }
00333 
00334 /*
00335 int 
00336 Element::addInertiaLoadToUnbalance(const Vector &accel)
00337 {
00338   // some vectors to hold the load increment and RV
00339   int ndof = this->getNumDOF();
00340   Vector load(ndof);
00341   Vector RV(ndof);
00342 
00343   // 
00344   // for each node we will add it's R*accel contribution to RV
00345   //
00346 
00347   const ID &theNodes = this->getExternalNodes();
00348   int numNodes = theNodes.Size();
00349   int loc = 0;
00350   Domain *theDomain = this->getDomain();
00351   for (int i=0; i<numNodes; i++) {
00352     Node *theNode = theDomain->getNode(theNodes(i));
00353     if (theNode == 0)
00354       return -1;
00355     else {
00356       int numNodeDOF = theNode->getNumberDOF();
00357       const Vector &nodeRV = theNode->getRV(accel);
00358       for (int j=0; j<numNodeDOF; j++)
00359 #ifdef _G3DEBUG
00360         if (loc<ndof)
00361 #endif
00362           RV(loc++) = nodeRV(j);
00363     }
00364   }
00365 
00366   //
00367   // now we determine - M * R * accel
00368   //
00369   const Matrix &mass = this->getMass();
00370   load = mass * RV;
00371   load *= -1.0;
00372 
00373   return this->addLoad(load);
00374 }
00375 */
00376 
00377 bool
00378 Element::isSubdomain(void)
00379 {
00380     return false;
00381 }
00382 
00383 Response*
00384 Element::setResponse(const char **argv, int argc, Information &eleInfo, OPS_Stream &output)
00385 {
00386   Response *theResponse = 0;
00387 
00388   output.tag("ElementOutput");
00389   output.attr("eleType",this->getClassType());
00390   output.attr("eleTag",this->getTag());
00391   int numNodes = this->getNumExternalNodes();
00392   const ID &nodes = this->getExternalNodes();
00393   static char nodeData[32];
00394 
00395   for (int i=0; i<numNodes; i++) {
00396     sprintf(nodeData,"node%d",i+1);
00397     output.attr(nodeData,nodes(i));
00398   }
00399 
00400   if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0 ||
00401       strcmp(argv[0],"globalForce") == 0 || strcmp(argv[0],"globalForces") == 0) {
00402     const Vector &force = this->getResistingForce();
00403     int size = force.Size();
00404     for (int i=0; i<size; i++) {
00405       sprintf(nodeData,"P%d",i+1);
00406       output.tag("ResponseType",nodeData);
00407     }
00408     theResponse = new ElementResponse(this, 1, this->getResistingForce());
00409   }
00410   output.endTag();
00411   return theResponse;
00412 }
00413 
00414 int
00415 Element::getResponse(int responseID, Information &eleInfo)
00416 {
00417   switch (responseID) {
00418   case 1: // global forces
00419     return eleInfo.setVector(this->getResistingForce());
00420   default:
00421     return -1;
00422   }
00423 }
00424 
00425 int
00426 Element::getResponseSensitivity(int responseID, int gradNumber,
00427                                 Information &eleInfo)
00428 {
00429   return -1;
00430 }
00431 
00432 // AddingSensitivity:BEGIN //////////////////////////////////////////
00433 const Vector &
00434 Element::getResistingForceSensitivity(int gradNumber)
00435 {
00436         static Vector dummy(1);
00437         return dummy;
00438 }
00439 
00440 const Matrix &
00441 Element::getInitialStiffSensitivity(int gradNumber)
00442 {
00443         static Matrix dummy(1,1);
00444         return dummy;
00445 }
00446 
00447 const Matrix &
00448 Element::getMassSensitivity(int gradNumber)
00449 {
00450         static Matrix dummy(1,1);
00451         return dummy;
00452 }
00453 
00454 int
00455 Element::commitSensitivity(int gradNumber, int numGrads)
00456 {
00457         return -1;
00458 }
00459 
00460 int
00461 Element::addInertiaLoadSensitivityToUnbalance(const Vector &accel, bool tag)
00462 {
00463         return -1;
00464 }
00465 
00466 
00467 
00468 // AddingSensitivity:END ///////////////////////////////////////////
00469 
00470 
00471 const Matrix &
00472 Element::getDampSensitivity(int gradNumber) 
00473 {
00474   if (index  == -1) {
00475     this->setRayleighDampingFactors(0.0, 0.0, 0.0, 0.0);
00476   }
00477 
00478   // now compute the damping matrix
00479   Matrix *theMatrix = theMatrices[index]; 
00480   theMatrix->Zero();
00481   if (alphaM != 0.0) {
00482     theMatrix->addMatrix(0.0, this->getMassSensitivity(gradNumber), alphaM);
00483   }
00484   if (betaK != 0.0) {
00485         theMatrix->addMatrix(1.0, this->getTangentStiff(), 0.0); // Don't use this and DDM      
00486         opserr << "Rayleigh damping with non-zero betaCurrentTangent is not compatible with DDM sensitivity analysis" << endln;
00487   }
00488   if (betaK0 != 0.0) {
00489     theMatrix->addMatrix(1.0, this->getInitialStiffSensitivity(gradNumber), betaK0);      
00490   }
00491   if (betaKc != 0.0) {
00492     theMatrix->addMatrix(1.0, *Kc, 0.0);      // Don't use this and DDM   
00493         opserr << "Rayleigh damping with non-zero betaCommittedTangent is not compatible with DDM sensitivity analysis" << endln;
00494   }
00495 
00496   // return the computed matrix
00497   return *theMatrix;
00498 }
00499 
00500 
00501 
00502 int 
00503 Element::addResistingForceToNodalReaction(bool inclInertia) 
00504 {
00505   int result = 0;
00506   int numNodes = this->getNumExternalNodes();
00507   Node **theNodes = this->getNodePtrs();
00508 
00509   //
00510   // first we create the nodes in static arrays as presume
00511   // we are going to do this many times & save new/delete
00512   //
00513 
00514   if (nodeIndex == -1) {
00515     int numLastDOF = -1;
00516     for (int i=0; i<numNodes; i++) {
00517       int numNodalDOF = theNodes[i]->getNumberDOF();
00518 
00519       if (numNodalDOF != 0 && numNodalDOF != numLastDOF) {
00520         // see if an existing vector will do
00521         int j;
00522         for (j=0; j<numMatrices; j++) {
00523           if (theVectors1[j]->Size() == numNodalDOF)
00524             nodeIndex = j;
00525             j = numMatrices+2;
00526         }
00527 
00528         // if not we need to enlarge the bool of temp vectors, matrices
00529         if (j != (numMatrices+2)) {
00530             Matrix **nextMatrices = new Matrix *[numMatrices+1];
00531             if (nextMatrices == 0) {
00532               opserr << "Element::addResistingForceToNodalReaction - out of memory\n";
00533             }
00534             int j;
00535             for (j=0; j<numMatrices; j++)
00536               nextMatrices[j] = theMatrices[j];
00537             Matrix *theMatrix = new Matrix(numNodalDOF, numNodalDOF);
00538             if (theMatrix == 0) {
00539               opserr << "Element::addResistingForceToNodalReaction - out of memory\n";
00540               exit(-1);
00541             }
00542             nextMatrices[numMatrices] = theMatrix;
00543             
00544             Vector **nextVectors1 = new Vector *[numMatrices+1];
00545             Vector **nextVectors2 = new Vector *[numMatrices+1];
00546             if (nextVectors1 == 0 || nextVectors2 == 0) {
00547               opserr << "Element::addResistingForceToNodalReaction - out of memory\n";
00548               exit(-1);
00549             }
00550             
00551             for (j=0; j<numMatrices; j++) {
00552               nextVectors1[j] = theVectors1[j];
00553               nextVectors2[j] = theVectors2[j];
00554             }
00555             
00556             Vector *theVector1 = new Vector(numNodalDOF);
00557             Vector *theVector2 = new Vector(numNodalDOF);
00558             if (theVector1 == 0 || theVector2 == 0) {
00559               opserr << "Element::addResistingForceToNodalReaction - out of memory\n";
00560               exit(-1);
00561             }
00562             
00563             nextVectors1[numMatrices] = theVector1;
00564             nextVectors2[numMatrices] = theVector2;
00565             
00566             if (numMatrices != 0) {
00567               delete [] theMatrices;
00568               delete [] theVectors1;
00569               delete [] theVectors2;
00570             }
00571             nodeIndex = numMatrices;
00572             numMatrices++;
00573             theMatrices = nextMatrices;
00574             theVectors1 = nextVectors1;
00575             theVectors2 = nextVectors2;
00576         }
00577       }
00578       numLastDOF = numNodalDOF;
00579     }
00580   }
00581 
00582   //
00583   // now determine the resisting force
00584   //
00585 
00586   const Vector *theResistingForce;
00587   if (inclInertia == 0)
00588     theResistingForce = &(this->getResistingForce());
00589   else
00590     theResistingForce = &(this->getResistingForceIncInertia());
00591 
00592   if (nodeIndex == -1) {
00593     opserr << "LOGIC ERROR Element::addResistingForceToNodalReaction() -HUH!\n";
00594     return -1;
00595   }
00596   
00597   //
00598   // iterate over the elements nodes; determine nodes contribution & add it
00599   //
00600 
00601   int nodalDOFCount = 0;
00602 
00603   for (int i=0; i<numNodes; i++) {
00604     Node *theNode = theNodes[i];
00605 
00606     int numNodalDOF = theNode->getNumberDOF();
00607     Vector *theVector = theVectors1[nodeIndex];
00608     if (theVector->Size() != numNodalDOF) {
00609       for (int j=0; j<numMatrices; j++)
00610         if (theVectors1[j]->Size() == numNodalDOF) {
00611           j = numMatrices;
00612           theVector = theVectors1[j];
00613         }
00614     }
00615     for (int j=0; j<numNodalDOF; j++) {
00616       (*theVector)(j) = (*theResistingForce)(nodalDOFCount);
00617       nodalDOFCount++;
00618     }
00619     result +=theNode->addReactionForce(*theVector, 1.0);
00620   }
00621 
00622   return result;
00623 }

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