Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

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