ZeroLength.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/08/07 22:15:49 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/element/zeroLength/ZeroLength.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/element/ZeroLength/ZeroLength.C
00027 // 
00028 // Written: GLF
00029 // Created: 12/99
00030 // Revision: A
00031 //
00032 // Description: This file contains the implementation for the ZeroLength class.
00033 //
00034 // What: "@(#) ZeroLength.C, revA"
00035 
00036 #include "ZeroLength.h"
00037 #include <Information.h>
00038 
00039 #include <Domain.h>
00040 #include <Node.h>
00041 #include <Channel.h>
00042 #include <FEM_ObjectBroker.h>
00043 #include <UniaxialMaterial.h>
00044 #include <Renderer.h>
00045 
00046 #include <math.h>
00047 #include <stdlib.h>
00048 #include <string.h>
00049 
00050 #include <ElementResponse.h>
00051 
00052 // initialise the class wide variables
00053 Matrix ZeroLength::ZeroLengthM2(2,2);
00054 Matrix ZeroLength::ZeroLengthM4(4,4);
00055 Matrix ZeroLength::ZeroLengthM6(6,6);
00056 Matrix ZeroLength::ZeroLengthM12(12,12);
00057 Vector ZeroLength::ZeroLengthV2(2);
00058 Vector ZeroLength::ZeroLengthV4(4);
00059 Vector ZeroLength::ZeroLengthV6(6);
00060 Vector ZeroLength::ZeroLengthV12(12);
00061 
00062 //  Constructor:
00063 //  responsible for allocating the necessary space needed by each object
00064 //  and storing the tags of the ZeroLength end nodes.
00065 
00066 //  Construct element with one unidirectional material (numMaterials1d=1)
00067 ZeroLength::ZeroLength(int tag,
00068                        int dim,
00069                        int Nd1, int Nd2, 
00070                        const Vector &x, const Vector &yp,
00071                        UniaxialMaterial &theMat,
00072                        int direction )
00073  :Element(tag,ELE_TAG_ZeroLength),     
00074   connectedExternalNodes(2),
00075   dimension(dim), numDOF(0), transformation(3,3),
00076   theMatrix(0), theVector(0),
00077   numMaterials1d(1), theMaterial1d(0), dir1d(0), t1d(0)
00078 {
00079   // allocate memory for numMaterials1d uniaxial material models
00080   theMaterial1d = new UniaxialMaterial*  [numMaterials1d];
00081   dir1d   = new ID(numMaterials1d);
00082   
00083   if ( theMaterial1d == 0 || dir1d == 0 ) {
00084     opserr << "FATAL ZeroLength::ZeroLength - failed to create a 1d  material or direction array\n";
00085     exit(-1);
00086   }
00087 
00088   // initialize uniaxial materials and directions and check for valid values
00089   (*dir1d)(0) = direction;
00090   this->checkDirection( *dir1d );
00091   
00092   // get a copy of the material and check we obtained a valid copy
00093   theMaterial1d[0] = theMat.getCopy();
00094   if (theMaterial1d[0] == 0) {
00095     opserr << "FATAL ZeroLength::ZeroLength - failed to get a copy of material " << theMat.getTag() << endln;
00096     exit(-1);
00097   }
00098 
00099   // establish the connected nodes and set up the transformation matrix for orientation
00100   this->setUp( Nd1, Nd2, x, yp);
00101 }
00102 
00103 
00104 //  Construct element with multiple unidirectional materials
00105 ZeroLength::ZeroLength(int tag,
00106                        int dim,
00107                        int Nd1, int Nd2, 
00108                        const Vector& x, const Vector& yp,
00109                        int n1dMat,
00110                        UniaxialMaterial** theMat,
00111                        const ID& direction )
00112  :Element(tag,ELE_TAG_ZeroLength),     
00113   connectedExternalNodes(2),
00114   dimension(dim), numDOF(0), transformation(3,3),
00115   theMatrix(0), theVector(0),
00116   numMaterials1d(n1dMat), theMaterial1d(0), dir1d(0), t1d(0)
00117 {
00118 
00119     // allocate memory for numMaterials1d uniaxial material models
00120     theMaterial1d = new UniaxialMaterial*  [numMaterials1d];
00121     dir1d         = new ID(numMaterials1d);
00122     
00123     if ( theMaterial1d == 0 || dir1d == 0 ) {
00124       opserr << "FATAL ZeroLength::ZeroLength - failed to create a 1d  material or direction array\n";
00125       exit(-1);
00126     }
00127     
00128     // initialize uniaxial materials and directions and check for valid values
00129     *dir1d = direction;
00130     this->checkDirection( *dir1d );
00131     
00132     // get a copy of the material objects and check we obtained a valid copy
00133     for (int i=0; i<numMaterials1d; i++) {
00134       theMaterial1d[i] = theMat[i]->getCopy();
00135       if (theMaterial1d[i] == 0) {
00136         opserr << "FATAL ZeroLength::ZeroLength - failed to get a copy of material " <<theMat[i]->getTag() << endln;
00137         exit(-1);
00138       }
00139      }
00140         
00141     // establish the connected nodes and set up the transformation matrix for orientation
00142     this->setUp( Nd1, Nd2, x, yp);
00143 }
00144 
00145 
00146 //   Constructor:
00147 //   invoked by a FEM_ObjectBroker - blank object that recvSelf needs
00148 //   to be invoked upon
00149 ZeroLength::ZeroLength(void)
00150   :Element(0,ELE_TAG_ZeroLength),     
00151   connectedExternalNodes(2),
00152   dimension(0), numDOF(0), transformation(3,3),
00153   theMatrix(0), theVector(0),
00154   numMaterials1d(0), theMaterial1d(0),
00155   dir1d(0), t1d(0)
00156 {
00157     // ensure the connectedExternalNode ID is of correct size 
00158     if (connectedExternalNodes.Size() != 2)
00159       opserr << "FATAL ZeroLength::ZeroLength - failed to create an ID of correct size\n";
00160 }
00161 
00162 
00163 //  Destructor:
00164 //  delete must be invoked on any objects created by the object
00165 //  and on the matertial object.
00166 ZeroLength::~ZeroLength()
00167 {
00168     // invoke the destructor on any objects created by the object
00169     // that the object still holds a pointer to
00170 
00171     // invoke destructors on material objects
00172     for (int mat=0; mat<numMaterials1d; mat++) 
00173         delete theMaterial1d[mat];
00174 
00175     // delete memory of 1d materials    
00176     if (theMaterial1d != 0)
00177         delete [] theMaterial1d;
00178 
00179     if (t1d != 0)
00180         delete t1d;
00181     if (dir1d != 0 )
00182         delete dir1d;
00183 }
00184 
00185 
00186 int
00187 ZeroLength::getNumExternalNodes(void) const
00188 {
00189     return 2;
00190 }
00191 
00192 
00193 const ID &
00194 ZeroLength::getExternalNodes(void) 
00195 {
00196     return connectedExternalNodes;
00197 }
00198 
00199 
00200 
00201 Node **
00202 ZeroLength::getNodePtrs(void) 
00203 {
00204   return theNodes;
00205 }
00206 
00207 int
00208 ZeroLength::getNumDOF(void) 
00209 {
00210     return numDOF;
00211 }
00212 
00213 
00214 // method: setDomain()
00215 //    to set a link to the enclosing Domain and to set the node pointers.
00216 //    also determines the number of dof associated
00217 //    with the ZeroLength element, we set matrix and vector pointers,
00218 //    allocate space for t matrix and define it as the basic deformation-
00219 //    displacement transformation matrix.
00220 void
00221 ZeroLength::setDomain(Domain *theDomain)
00222 {
00223     // check Domain is not null - invoked when object removed from a domain
00224     if (theDomain == 0) {
00225         theNodes[0] = 0;
00226         theNodes[1] = 0;
00227         return;
00228     }
00229 
00230     // set default values for error conditions
00231     numDOF = 2;
00232     theMatrix = &ZeroLengthM2;
00233     theVector = &ZeroLengthV2;
00234     
00235     // first set the node pointers
00236     int Nd1 = connectedExternalNodes(0);
00237     int Nd2 = connectedExternalNodes(1);
00238     theNodes[0] = theDomain->getNode(Nd1);
00239     theNodes[1] = theDomain->getNode(Nd2);      
00240 
00241     // if can't find both - send a warning message
00242     if ( theNodes[0] == 0 || theNodes[1] == 0 ) {
00243       if (theNodes[0] == 0) 
00244         opserr << "WARNING ZeroLength::setDomain() - Nd1: " << Nd1 << " does not exist in ";
00245       else
00246         opserr << "WARNING ZeroLength::setDomain() - Nd2: " << Nd2 << " does not exist in ";
00247 
00248       opserr << "model for ZeroLength ele: " << this->getTag() << endln;
00249 
00250       return;
00251     }
00252 
00253     // now determine the number of dof and the dimension    
00254     int dofNd1 = theNodes[0]->getNumberDOF();
00255     int dofNd2 = theNodes[1]->getNumberDOF();   
00256 
00257     // if differing dof at the ends - print a warning message
00258     if ( dofNd1 != dofNd2 ) {
00259       opserr << "WARNING ZeroLength::setDomain(): nodes " << Nd1 << " and " << Nd2 <<
00260         "have differing dof at ends for ZeroLength " << this->getTag() << endln;
00261       return;
00262     }   
00263 
00264     // Check that length is zero within tolerance
00265     const Vector &end1Crd = theNodes[0]->getCrds();
00266     const Vector &end2Crd = theNodes[1]->getCrds();     
00267     Vector diff = end1Crd - end2Crd;
00268     double L  = diff.Norm();
00269     double v1 = end1Crd.Norm();
00270     double v2 = end2Crd.Norm();
00271     double vm;
00272     
00273     vm = (v1<v2) ? v2 : v1;
00274 
00275 
00276     if (L > LENTOL*vm)
00277       opserr << "WARNING ZeroLength::setDomain(): Element " << this->getTag() << " has L= " << L << 
00278         ", which is greater than the tolerance\n";
00279         
00280     // call the base class method
00281     this->DomainComponent::setDomain(theDomain);
00282     
00283     // set the number of dof for element and set matrix and vector pointer
00284     if (dimension == 1 && dofNd1 == 1) {
00285         numDOF = 2;    
00286         theMatrix = &ZeroLengthM2;
00287         theVector = &ZeroLengthV2;
00288         elemType  = D1N2;
00289     }
00290     else if (dimension == 2 && dofNd1 == 2) {
00291         numDOF = 4;
00292         theMatrix = &ZeroLengthM4;
00293         theVector = &ZeroLengthV4;
00294         elemType  = D2N4;
00295     }
00296     else if (dimension == 2 && dofNd1 == 3) {
00297         numDOF = 6;     
00298         theMatrix = &ZeroLengthM6;
00299         theVector = &ZeroLengthV6;
00300         elemType  = D2N6;
00301     }
00302     else if (dimension == 3 && dofNd1 == 3) {
00303         numDOF = 6;     
00304         theMatrix = &ZeroLengthM6;
00305         theVector = &ZeroLengthV6;
00306         elemType  = D3N6;
00307     }
00308     else if (dimension == 3 && dofNd1 == 6) {
00309         numDOF = 12;        
00310         theMatrix = &ZeroLengthM12;
00311         theVector = &ZeroLengthV12;
00312         elemType  = D3N12;
00313     }
00314     else {
00315       opserr << "WARNING ZeroLength::setDomain cannot handle " << dimension << 
00316         "dofs at nodes in " << dofNd1 << " d problem\n"; 
00317       return;
00318     }
00319 
00320     // create the basic deformation-displacement transformation matrix for the element
00321     // for 1d materials (uniaxial materials)
00322     if ( numMaterials1d > 0 )
00323         this->setTran1d( elemType, numMaterials1d );
00324 }        
00325 
00326 
00327 int
00328 ZeroLength::commitState()
00329 {
00330     int code=0;
00331 
00332     // call element commitState to do any base class stuff
00333     if ((code = this->Element::commitState()) != 0) {
00334       opserr << "ZeroLength::commitState () - failed in base class";
00335     }    
00336 
00337     // commit 1d materials
00338     for (int i=0; i<numMaterials1d; i++) 
00339         code += theMaterial1d[i]->commitState();
00340 
00341     return code;
00342 }
00343 
00344 int
00345 ZeroLength::revertToLastCommit()
00346 {
00347     int code=0;
00348     
00349     // revert state for 1d materials
00350     for (int i=0; i<numMaterials1d; i++)
00351         code += theMaterial1d[i]->revertToLastCommit();
00352     
00353     return code;
00354 }
00355 
00356 
00357 int
00358 ZeroLength::revertToStart()
00359 {   
00360     int code=0;
00361     
00362     // revert to start for 1d materials
00363     for (int i=0; i<numMaterials1d; i++)
00364         code += theMaterial1d[i]->revertToStart();
00365     
00366     return code;
00367 }
00368 
00369 
00370 int
00371 ZeroLength::update(void)
00372 {
00373     double strain;
00374     double strainRate;
00375 
00376     // get trial displacements and take difference
00377     const Vector& disp1 = theNodes[0]->getTrialDisp();
00378     const Vector& disp2 = theNodes[1]->getTrialDisp();
00379     Vector  diff  = disp2-disp1;
00380     const Vector& vel1  = theNodes[0]->getTrialVel();
00381     const Vector& vel2  = theNodes[1]->getTrialVel();
00382     Vector  diffv = vel2-vel1;
00383     
00384     // loop over 1d materials
00385     
00386     //    Matrix& tran = *t1d;
00387     int ret = 0;
00388     for (int mat=0; mat<numMaterials1d; mat++) {
00389         // compute strain and rate; set as current trial for material
00390         strain     = this->computeCurrentStrain1d(mat,diff );
00391         strainRate = this->computeCurrentStrain1d(mat,diffv);
00392         ret += theMaterial1d[mat]->setTrialStrain(strain,strainRate);
00393     }
00394 
00395     return ret;
00396 }
00397 
00398 const Matrix &
00399 ZeroLength::getTangentStiff(void)
00400 {
00401     double E;
00402 
00403     // stiff is a reference to the matrix holding the stiffness matrix
00404     Matrix& stiff = *theMatrix;
00405     
00406     // zero stiffness matrix
00407     stiff.Zero();
00408     
00409     // loop over 1d materials
00410     
00411     Matrix& tran = *t1d;;
00412     for (int mat=0; mat<numMaterials1d; mat++) {
00413       
00414       // get tangent for material
00415       E = theMaterial1d[mat]->getTangent();
00416       
00417       // compute contribution of material to tangent matrix
00418       for (int i=0; i<numDOF; i++)
00419         for(int j=0; j<i+1; j++)
00420           stiff(i,j) +=  tran(mat,i) * E * tran(mat,j);
00421       
00422     }
00423 
00424     // end loop over 1d materials 
00425     
00426     // complete symmetric stiffness matrix
00427     for (int i=0; i<numDOF; i++)
00428       for(int j=0; j<i; j++)
00429         stiff(j,i) = stiff(i,j);
00430 
00431     return stiff;
00432 }
00433 
00434 
00435 const Matrix &
00436 ZeroLength::getInitialStiff(void)
00437 {
00438     double E;
00439 
00440     // stiff is a reference to the matrix holding the stiffness matrix
00441     Matrix& stiff = *theMatrix;
00442     
00443     // zero stiffness matrix
00444     stiff.Zero();
00445     
00446     // loop over 1d materials
00447     
00448     Matrix& tran = *t1d;;
00449     for (int mat=0; mat<numMaterials1d; mat++) {
00450       
00451       // get tangent for material
00452       E = theMaterial1d[mat]->getInitialTangent();
00453       
00454       // compute contribution of material to tangent matrix
00455       for (int i=0; i<numDOF; i++)
00456         for(int j=0; j<i+1; j++)
00457           stiff(i,j) +=  tran(mat,i) * E * tran(mat,j);
00458       
00459     }
00460 
00461     // end loop over 1d materials 
00462     
00463     // complete symmetric stiffness matrix
00464     for (int i=0; i<numDOF; i++)
00465       for(int j=0; j<i; j++)
00466         stiff(j,i) = stiff(i,j);
00467 
00468     return stiff;
00469 }
00470     
00471 
00472 const Matrix &
00473 ZeroLength::getDamp(void)
00474 {
00475     double eta;
00476 
00477     // damp is a reference to the matrix holding the damping matrix
00478     Matrix& damp = *theMatrix;
00479  
00480     // zero stiffness matrix
00481     damp.Zero();
00482     
00483     // loop over 1d materials
00484     Matrix& tran = *t1d;;
00485     for (int mat=0; mat<numMaterials1d; mat++) {
00486         
00487         // get tangent for material
00488         eta = theMaterial1d[mat]->getDampTangent();
00489         
00490         // compute contribution of material to tangent matrix
00491         for (int i=0; i<numDOF; i++)
00492             for(int j=0; j<i+1; j++)
00493                 damp(i,j) +=  tran(mat,i) * eta * tran(mat,j);
00494 
00495     } // end loop over 1d materials 
00496 
00497     // complete symmetric stiffness matrix
00498     for (int i=0; i<numDOF; i++)
00499         for(int j=0; j<i; j++)
00500             damp(j,i) = damp(i,j);
00501 
00502     return damp;
00503 }
00504 
00505 
00506 const Matrix &
00507 ZeroLength::getMass(void)
00508 {
00509     // no mass 
00510     theMatrix->Zero();    
00511     return *theMatrix; 
00512 }
00513 
00514 
00515 void 
00516 ZeroLength::zeroLoad(void)
00517 {
00518   // does nothing now
00519 }
00520 
00521 int 
00522 ZeroLength::addLoad(ElementalLoad *theLoad, double loadFactor)
00523 {
00524   opserr << "ZeroLength::addLoad - load type unknown for truss with tag: " << this->getTag() << endln;
00525   
00526   return -1;
00527 }
00528 
00529 int 
00530 ZeroLength::addInertiaLoadToUnbalance(const Vector &accel)
00531 {
00532   // does nothing as element has no mass yet!
00533   return 0;
00534 }
00535 
00536 
00537 const Vector &
00538 ZeroLength::getResistingForce()
00539 {
00540     double force;
00541     
00542     // zero the residual
00543     theVector->Zero();
00544     
00545     // loop over 1d materials
00546     for (int mat=0; mat<numMaterials1d; mat++) {
00547         
00548         // get resisting force for material
00549         force = theMaterial1d[mat]->getStress();
00550         
00551         // compute residual due to resisting force
00552         for (int i=0; i<numDOF; i++)
00553             (*theVector)(i)  += (*t1d)(mat,i) * force;
00554         
00555     } // end loop over 1d materials 
00556 
00557     return *theVector;
00558 }
00559 
00560 
00561 const Vector &
00562 ZeroLength::getResistingForceIncInertia()
00563 {       
00564     // there is no mass, so return
00565     
00566     return this->getResistingForce();
00567 }
00568 
00569 
00570 int
00571 ZeroLength::sendSelf(int commitTag, Channel &theChannel)
00572 {
00573         int res = 0;
00574 
00575         // note: we don't check for dataTag == 0 for Element
00576         // objects as that is taken care of in a commit by the Domain
00577         // object - don't want to have to do the check if sending data
00578         int dataTag = this->getDbTag();
00579 
00580         // ZeroLength packs its data into an ID and sends this to theChannel
00581         // along with its dbTag and the commitTag passed in the arguments
00582 
00583         // Make one size bigger so not a multiple of 3, otherwise will conflict
00584         // with classTags ID
00585         static ID idData(6+1);
00586 
00587         idData(0) = this->getTag();
00588         idData(1) = dimension;
00589         idData(2) = numDOF;
00590         idData(3) = numMaterials1d;
00591         idData(4) = connectedExternalNodes(0);
00592         idData(5) = connectedExternalNodes(1);
00593 
00594         res += theChannel.sendID(dataTag, commitTag, idData);
00595         if (res < 0) {
00596           opserr << "ZeroLength::sendSelf -- failed to send ID data\n";
00597           return res;
00598         }
00599 
00600         // Send the 3x3 direction cosine matrix, have to send it since it is only set
00601         // in the constructor and not setDomain()
00602         res += theChannel.sendMatrix(dataTag, commitTag, transformation);
00603         if (res < 0) {
00604           opserr <<  "ZeroLength::sendSelf -- failed to send transformation Matrix\n";
00605           return res;
00606         }
00607 
00608         if (numMaterials1d < 1)
00609           return res;
00610         else {
00611           ID classTags(numMaterials1d*3);
00612           
00613           int i;
00614           // Loop over the materials and send them
00615           for (i = 0; i < numMaterials1d; i++) {
00616             int matDbTag = theMaterial1d[i]->getDbTag();
00617             if (matDbTag == 0) {
00618               matDbTag = theChannel.getDbTag();
00619               if (matDbTag != 0)
00620                 theMaterial1d[i]->setDbTag(matDbTag);
00621             }
00622             classTags(i) = matDbTag;
00623             classTags(numMaterials1d+i) = theMaterial1d[i]->getClassTag();
00624             classTags(2*numMaterials1d+i) = (*dir1d)(i);
00625           }
00626           
00627           res += theChannel.sendID(dataTag, commitTag, classTags);
00628           if (res < 0) {
00629             opserr << " ZeroLength::sendSelf -- failed to send classTags ID\n";
00630             return res;
00631           }
00632         
00633           for (i = 0; i < numMaterials1d; i++) {
00634             res += theMaterial1d[i]->sendSelf(commitTag, theChannel);
00635             if (res < 0) {
00636               opserr << "ZeroLength::sendSelf -- failed to send Material1d " << i << endln;
00637                 
00638               return res;
00639           }
00640                 }
00641         }
00642 
00643         return res;
00644 }
00645 
00646 int
00647 ZeroLength::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00648 {
00649   int res = 0;
00650   
00651   int dataTag = this->getDbTag();
00652 
00653   // ZeroLength creates an ID, receives the ID and then sets the 
00654   // internal data with the data in the ID
00655 
00656   static ID idData(6+1);
00657 
00658   res += theChannel.recvID(dataTag, commitTag, idData);
00659   if (res < 0) {
00660     opserr << "ZeroLength::recvSelf -- failed to receive ID data\n";
00661                             
00662     return res;
00663   }
00664 
00665   res += theChannel.recvMatrix(dataTag, commitTag, transformation);
00666   if (res < 0) {
00667     opserr << "ZeroLength::recvSelf -- failed to receive transformation Matrix\n";
00668                             
00669     return res;
00670   }
00671 
00672   this->setTag(idData(0));
00673   dimension = idData(1);
00674   numDOF = idData(2);
00675   connectedExternalNodes(0) = idData(4);
00676   connectedExternalNodes(1) = idData(5);
00677   
00678   if (idData(3) < 1) {
00679     numMaterials1d = 0;
00680     if (dir1d != 0) {
00681       delete dir1d;
00682       dir1d = 0;
00683     }
00684     return res;
00685   }
00686   else {
00687     // Check that there is correct number of materials, reallocate if needed
00688     if (numMaterials1d != idData(3)) {
00689       int i;
00690       if (theMaterial1d != 0) {
00691         for (i = 0; i < numMaterials1d; i++)
00692           delete theMaterial1d[i];
00693         delete [] theMaterial1d;
00694         theMaterial1d = 0;
00695       }
00696       
00697       numMaterials1d = idData(3);
00698       
00699       theMaterial1d = new UniaxialMaterial *[numMaterials1d];
00700       if (theMaterial1d == 0) {
00701         opserr << "ZeroLength::recvSelf -- failed to new Material1d array\n";
00702         return -1;
00703       }
00704       
00705       for (i = 0; i < numMaterials1d; i++)
00706         theMaterial1d[i] = 0;
00707       
00708       // Allocate ID array for directions
00709       if (dir1d != 0)
00710         delete dir1d;
00711       dir1d = new ID(numMaterials1d);
00712       if (dir1d == 0) {
00713         opserr << "ZeroLength::recvSelf -- failed to new dir ID\n";
00714                                 
00715         return -1;
00716       }
00717     }
00718     
00719     ID classTags(3*numMaterials1d);
00720     res += theChannel.recvID(dataTag, commitTag, classTags);
00721     if (res < 0) {
00722       opserr << "ZeroLength::recvSelf -- failed to receive classTags ID\n";
00723       return res;
00724     }
00725     
00726     for (int i = 0; i < numMaterials1d; i++) {
00727       int matClassTag = classTags(numMaterials1d+i);
00728       
00729       // If null, get a new one from the broker
00730       if (theMaterial1d[i] == 0)
00731         theMaterial1d[i] = theBroker.getNewUniaxialMaterial(matClassTag);
00732       
00733       // If wrong type, get a new one from the broker
00734       if (theMaterial1d[i]->getClassTag() != matClassTag) {
00735         delete theMaterial1d[i];
00736         theMaterial1d[i] = theBroker.getNewUniaxialMaterial(matClassTag);
00737       }
00738       
00739       // Check if either allocation failed from broker
00740       if (theMaterial1d[i] == 0) {
00741         opserr << "ZeroLength::recvSelf  -- failed to allocate new Material1d " << i << endln;
00742         return -1;
00743       }
00744       
00745       // Receive the materials
00746       theMaterial1d[i]->setDbTag(classTags(i));
00747       res += theMaterial1d[i]->recvSelf(commitTag, theChannel, theBroker);
00748       if (res < 0) {
00749         opserr << "ZeroLength::recvSelf  -- failed to receive new Material1d " << i << endln;
00750         return res;
00751       }
00752       
00753       // Set material directions
00754       (*dir1d)(i) = classTags(2*numMaterials1d+i);
00755     }
00756   }
00757 
00758   return res;
00759 }
00760 
00761 
00762 int
00763 ZeroLength::displaySelf(Renderer &theViewer, int displayMode, float fact)
00764 {
00765     // ensure setDomain() worked
00766     if (theNodes[0] == 0 || theNodes[1] == 0 )
00767        return 0;
00768 
00769     // first determine the two end points of the ZeroLength based on
00770     // the display factor (a measure of the distorted image)
00771     // store this information in 2 3d vectors v1 and v2
00772     const Vector &end1Crd = theNodes[0]->getCrds();
00773     const Vector &end2Crd = theNodes[1]->getCrds();     
00774     const Vector &end1Disp = theNodes[0]->getDisp();
00775     const Vector &end2Disp = theNodes[1]->getDisp();    
00776 
00777     if (displayMode == 1 || displayMode == 2) {
00778         Vector v1(3);
00779         Vector v2(3);
00780         for (int i=0; i<dimension; i++) {
00781             v1(i) = end1Crd(i)+end1Disp(i)*fact;
00782             v2(i) = end2Crd(i)+end2Disp(i)*fact;    
00783         }
00784         
00785         // don't display strain or force
00786         double strain = 0.0;
00787         double force  = 0.0;
00788     
00789         if (displayMode == 2) // use the strain as the drawing measure
00790             return theViewer.drawLine(v1, v2, strain, strain);  
00791         else { // otherwise use the axial force as measure
00792             return theViewer.drawLine(v1,v2, force, force);
00793         }
00794     }
00795     return 0;
00796 }
00797 
00798 
00799 void
00800 ZeroLength::Print(OPS_Stream &s, int flag)
00801 {
00802     // compute the strain and axial force in the member
00803     double strain=0.0;
00804     double force =0.0;
00805     
00806     for (int i=0; i<numDOF; i++)
00807         (*theVector)(i) = (*t1d)(0,i)*force;
00808 
00809     if (flag == 0) { // print everything
00810         s << "Element: " << this->getTag(); 
00811         s << " type: ZeroLength  iNode: " << connectedExternalNodes(0);
00812         s << " jNode: " << connectedExternalNodes(1) << endln;
00813         for (int j = 0; j < numMaterials1d; j++) {
00814                 s << "\tMaterial1d, tag: " << theMaterial1d[j]->getTag() 
00815                         << ", dir: " << (*dir1d)(j) << endln;
00816                 s << *(theMaterial1d[j]);
00817         }
00818     } else if (flag == 1) {
00819         s << this->getTag() << "  " << strain << "  ";
00820     }
00821 }
00822 
00823 Response*
00824 ZeroLength::setResponse(const char **argv, int argc, Information &eleInformation, OPS_Stream &output)
00825 {
00826   Response *theResponse = 0;
00827 
00828   output.tag("ElementOutput");
00829   output.attr("eleType","ZeroLength");
00830   output.attr("eleTag",this->getTag());
00831   output.attr("node1",connectedExternalNodes[0]);
00832   output.attr("node2",connectedExternalNodes[1]);
00833 
00834   char outputData[10];
00835 
00836   if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0) {
00837 
00838     for (int i=0; i<numMaterials1d; i++) {
00839       sprintf(outputData,"P%d",i+1);
00840       output.tag("ResponseType",outputData);
00841     }
00842 
00843     theResponse =  new ElementResponse(this, 1, Vector(numMaterials1d));
00844   
00845   }  else if (strcmp(argv[0],"defo") == 0 || strcmp(argv[0],"deformations") == 0 ||
00846               strcmp(argv[0],"deformation") == 0) {
00847 
00848     for (int i=0; i<numMaterials1d; i++) {
00849       sprintf(outputData,"e%d",i+1);
00850       output.tag("ResponseType",outputData);
00851     }
00852 
00853     theResponse =  new ElementResponse(this, 2, Vector(numMaterials1d));
00854   
00855   }  else if ((strcmp(argv[0],"defoANDforce") == 0) ||
00856            (strcmp(argv[0],"deformationANDforces") == 0) ||
00857               (strcmp(argv[0],"deformationsANDforces") == 0)) {
00858         int i;
00859     for (i=0; i<numMaterials1d; i++) {
00860       sprintf(outputData,"e%d",i+1);
00861       output.tag("ResponseType",outputData);
00862     }
00863     for (i=0; i<numMaterials1d; i++) {
00864       sprintf(outputData,"P%d",i+1);
00865       output.tag("ResponseType",outputData);
00866     }
00867 
00868     theResponse =  new ElementResponse(this, 4, Vector(2*numMaterials1d));
00869 
00870   }  else if (strcmp(argv[0],"material") == 0) {
00871     if (argc > 2) {
00872       int matNum = atoi(argv[1]);
00873       if (matNum >= 1 && matNum <= numMaterials1d)
00874         theResponse =  theMaterial1d[matNum-1]->setResponse(&argv[2], argc-2, eleInformation, output);
00875     }
00876   }
00877 
00878   output.endTag();
00879 
00880   return theResponse;
00881 }
00882 
00883 int 
00884 ZeroLength::getResponse(int responseID, Information &eleInformation)
00885 {
00886   const Vector& disp1 = theNodes[0]->getTrialDisp();
00887   const Vector& disp2 = theNodes[1]->getTrialDisp();
00888   const Vector  diff  = disp2-disp1;
00889   
00890   switch (responseID) {
00891   case -1:
00892     return -1;
00893     
00894   case 1:
00895     if (eleInformation.theVector != 0) {
00896       for (int i = 0; i < numMaterials1d; i++)
00897         (*(eleInformation.theVector))(i) = theMaterial1d[i]->getStress();
00898     }
00899     return 0;
00900     
00901   case 2:
00902     if (eleInformation.theVector != 0) {
00903       for (int i = 0; i < numMaterials1d; i++)
00904         (*(eleInformation.theVector))(i) = theMaterial1d[i]->getStrain();
00905     }
00906     return 0;      
00907     
00908   case 4:
00909     if (eleInformation.theVector != 0) {
00910       for (int i = 0; i < numMaterials1d; i++) {
00911         (*(eleInformation.theVector))(i) = theMaterial1d[i]->getStrain();
00912         (*(eleInformation.theVector))(i+numMaterials1d) = theMaterial1d[i]->getStress();
00913       }
00914     }
00915     return 0;      
00916     
00917   case 3:
00918     if (eleInformation.theMatrix != 0) {
00919       for (int i = 0; i < numMaterials1d; i++)
00920         (*(eleInformation.theMatrix))(i,i) = theMaterial1d[i]->getTangent();
00921     }
00922     return 0;      
00923     
00924   default:
00925     return -1;
00926   }
00927 }
00928 
00929 
00930 // Private methods
00931 
00932 
00933 // Establish the external nodes and set up the transformation matrix
00934 // for orientation
00935 void
00936 ZeroLength::setUp( int Nd1, int Nd2,
00937                    const Vector &x,
00938                    const Vector &yp )
00939 { 
00940     // ensure the connectedExternalNode ID is of correct size & set values
00941     if (connectedExternalNodes.Size() != 2)
00942       opserr << "FATAL ZeroLength::setUp - failed to create an ID of correct size\n";
00943     
00944     connectedExternalNodes(0) = Nd1;
00945     connectedExternalNodes(1) = Nd2;
00946 
00947         int i;
00948     for (i=0; i<2; i++)
00949       theNodes[i] = 0;
00950 
00951     // check that vectors for orientation are correct size
00952     if ( x.Size() != 3 || yp.Size() != 3 )
00953         opserr << "FATAL ZeroLength::setUp - incorrect dimension of orientation vectors\n";
00954 
00955     // establish orientation of element for the tranformation matrix
00956     // z = x cross yp
00957     Vector z(3);
00958     z(0) = x(1)*yp(2) - x(2)*yp(1);
00959     z(1) = x(2)*yp(0) - x(0)*yp(2);
00960     z(2) = x(0)*yp(1) - x(1)*yp(0);
00961 
00962     // y = z cross x
00963     Vector y(3);
00964     y(0) = z(1)*x(2) - z(2)*x(1);
00965     y(1) = z(2)*x(0) - z(0)*x(2);
00966     y(2) = z(0)*x(1) - z(1)*x(0);
00967 
00968     // compute length(norm) of vectors
00969     double xn = x.Norm();
00970     double yn = y.Norm();
00971     double zn = z.Norm();
00972 
00973     // check valid x and y vectors, i.e. not parallel and of zero length
00974     if (xn == 0 || yn == 0 || zn == 0) {
00975       opserr << "FATAL ZeroLength::setUp - invalid vectors to constructor\n";
00976     }
00977     
00978     // create transformation matrix of direction cosines
00979     for ( i=0; i<3; i++ ) {
00980         transformation(0,i) = x(i)/xn;
00981         transformation(1,i) = y(i)/yn;
00982         transformation(2,i) = z(i)/zn;
00983      }
00984 
00985 }
00986 
00987 
00988 // Check that direction is in the range of 0 to 5
00989 void
00990 ZeroLength::checkDirection( ID &dir ) const
00991 {
00992     for ( int i=0; i<dir.Size(); i++)
00993         if ( dir(i) < 0 || dir(i) > 5 ) {
00994           opserr << "WARNING ZeroLength::checkDirection - incorrect direction " << dir(i) << " is set to 0\n";
00995           dir(i) = 0;
00996         }
00997 }
00998 
00999 
01000 // Set basic deformation-displacement transformation matrix for 1d
01001 // uniaxial materials
01002 void
01003 ZeroLength::setTran1d( Etype elemType,
01004                        int   numMat )
01005 {
01006     enum Dtype { TRANS, ROTATE };
01007     
01008     int   indx, dir;
01009     Dtype dirType;
01010     
01011     // Create 1d transformation matrix
01012     t1d = new Matrix(numMat,numDOF);
01013     
01014     if (t1d == 0)
01015         opserr << "FATAL ZeroLength::setTran1d - can't allocate 1d transformation matrix\n";
01016     
01017     // Use reference for convenience and zero matrix.
01018     Matrix& tran = *t1d;
01019     tran.Zero();
01020     
01021     // loop over materials, setting row in tran for each material depending on dimensionality of element
01022     
01023     for ( int i=0; i<numMat; i++ ) {
01024         
01025         dir  = (*dir1d)(i);     // direction 0 to 5;
01026         indx = dir % 3;         // direction 0, 1, 2 for axis of translation or rotation
01027         
01028         // set direction type to translation or rotation
01029         dirType = (dir<3) ? TRANS : ROTATE;
01030         
01031         // now switch on dimensionality of element
01032         
01033         switch (elemType) {
01034                     
01035           case D1N2:
01036             if (dirType == TRANS)
01037                 tran(i,1) = transformation(indx,0);
01038             break;
01039                  
01040           case D2N4:
01041             if (dirType == TRANS) {
01042                 tran(i,2) = transformation(indx,0);  
01043                 tran(i,3) = transformation(indx,1);
01044             }
01045             break;
01046                  
01047           case D2N6: 
01048             if (dirType == TRANS) {
01049                 tran(i,3) = transformation(indx,0);  
01050                 tran(i,4) = transformation(indx,1);
01051                 tran(i,5) = 0.0;
01052             } else if (dirType == ROTATE) {
01053                 tran(i,3) = 0.0;
01054                 tran(i,4) = 0.0;
01055                 tran(i,5) = transformation(indx,2);
01056             }
01057             break;
01058                     
01059           case D3N6:
01060             if (dirType == TRANS) {
01061                 tran(i,3) = transformation(indx,0);  
01062                 tran(i,4) = transformation(indx,1);
01063                 tran(i,5) = transformation(indx,2);
01064             }
01065             break;
01066                  
01067           case D3N12:
01068             if (dirType == TRANS) {
01069                 tran(i,6)  = transformation(indx,0);  
01070                 tran(i,7)  = transformation(indx,1);
01071                 tran(i,8)  = transformation(indx,2);
01072                 tran(i,9)  = 0.0;
01073                 tran(i,10) = 0.0;
01074                 tran(i,11) = 0.0;
01075             } else if (dirType == ROTATE) {
01076                 tran(i,6)  = 0.0;
01077                 tran(i,7)  = 0.0;
01078                 tran(i,8)  = 0.0;
01079                 tran(i,9)  = transformation(indx,0);
01080                 tran(i,10) = transformation(indx,1);
01081                 tran(i,11) = transformation(indx,2);
01082             }
01083             break;
01084                  
01085         } // end switch
01086         
01087         // fill in first half of transformation matrix with
01088         // negative sign
01089         
01090         for (int j=0; j < numDOF/2; j++ )
01091             tran(i,j) = -tran(i,j+numDOF/2);
01092         
01093     } // end loop over 1d materials
01094 }
01095                      
01096 
01097 // Compute current strain for 1d material mat
01098 // dispDiff are the displacements of node 2 minus those
01099 // of node 1
01100 double
01101 ZeroLength::computeCurrentStrain1d( int mat,
01102                                     const Vector& dispDiff ) const
01103 {
01104     double strain = 0.0;
01105 
01106     for (int i=0; i<numDOF/2; i++){
01107         strain += -dispDiff(i) * (*t1d)(mat,i);
01108     }
01109 
01110     return strain;
01111 }
01112               
01113 void
01114 ZeroLength::updateDir(const Vector& x, const Vector& y)
01115 {
01116         this->setUp(connectedExternalNodes(0), connectedExternalNodes(1), x, y);
01117         this->setTran1d(elemType, numMaterials1d);
01118 }

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