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

ZeroLengthND.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.2 $
00022 // $Date: 2000/12/18 10:40:50 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/element/zeroLength/ZeroLengthND.cpp,v $
00024                                                                         
00025 // Written: MHS
00026 // Created: Sept 2000
00027 //
00028 // Description: This file contains the implementation for the 
00029 // ZeroLengthND class.
00030 
00031 #include <ZeroLengthND.h>
00032 #include <Information.h>
00033 
00034 #include <Domain.h>
00035 #include <Node.h>
00036 #include <Channel.h>
00037 #include <FEM_ObjectBroker.h>
00038 #include <NDMaterial.h>
00039 #include <UniaxialMaterial.h>
00040 #include <Renderer.h>
00041 #include <ElementResponse.h>
00042 
00043 #include <G3Globals.h>
00044 
00045 #include <math.h>
00046 #include <stdlib.h>
00047 #include <string.h>
00048 
00049 Matrix ZeroLengthND::K6(6,6);
00050 Matrix ZeroLengthND::K12(12,12);
00051 
00052 Vector ZeroLengthND::P6(6);
00053 Vector ZeroLengthND::P12(12);
00054 
00055 Vector ZeroLengthND::v2(2);
00056 Vector ZeroLengthND::v3(3);
00057 
00058 //  Constructor:
00059 //  responsible for allocating the necessary space needed by each object
00060 //  and storing the tags of the ZeroLengthND end nodes.
00061 
00062 ZeroLengthND::ZeroLengthND(int tag, int dim, int Nd1, int Nd2, 
00063         const Vector& x, const Vector& yprime, 
00064      NDMaterial &theNDmat) : 
00065 Element(tag, ELE_TAG_ZeroLengthND),
00066 connectedExternalNodes(2),
00067 dimension(dim), numDOF(0), 
00068 transformation(3,3), A(0), v(0), e(0.0), K(0), P(0),
00069 end1Ptr(0), end2Ptr(0), theNDMaterial(0), the1DMaterial(0), order(0)
00070 {
00071  // Obtain copy of Nd material model
00072  theNDMaterial = theNDmat.getCopy();
00073  
00074  if (theNDMaterial == 0)
00075   g3ErrorHandler->fatal("%s -- failed to get copy of NDMaterial",
00076    "ZeroLengthND::ZeroLengthND");
00077 
00078  // Get the material order
00079  order = theNDMaterial->getOrder();
00080 
00081  // Check material order
00082  if (order < 2 || order > 3)
00083   g3ErrorHandler->fatal("%s -- NDMaterial not of order 2 or 3",
00084    "ZeroLengthND::ZeroLengthND");
00085 
00086  // Set up the transformation matrix of direction cosines
00087  this->setUp(Nd1, Nd2, x, yprime);
00088 }
00089 
00090 ZeroLengthND::ZeroLengthND(int tag, int dim, int Nd1, int Nd2, 
00091         const Vector& x, const Vector& yprime, 
00092      NDMaterial &theNDmat, UniaxialMaterial &the1Dmat) : 
00093 Element(tag, ELE_TAG_ZeroLengthND),
00094 connectedExternalNodes(2),
00095 dimension(dim), numDOF(0), 
00096 transformation(3,3), A(0), v(0), e(0.0), K(0), P(0),
00097 end1Ptr(0), end2Ptr(0), theNDMaterial(0), the1DMaterial(0), order(0)
00098 {
00099  // Obtain copy of Nd material model
00100  theNDMaterial = theNDmat.getCopy();
00101  
00102  if (theNDMaterial == 0)
00103   g3ErrorHandler->fatal("%s -- failed to get copy of NDMaterial",
00104    "ZeroLengthND::ZeroLengthND");
00105 
00106  // Obtain copy of 1d material model
00107  the1DMaterial = the1Dmat.getCopy();
00108  
00109  if (the1DMaterial == 0)
00110   g3ErrorHandler->fatal("%s -- failed to get copy of UniaxialMaterial",
00111    "ZeroLength1D::ZeroLength1D");
00112 
00113  // Get the material order
00114  order = theNDMaterial->getOrder();
00115 
00116  if (order != 2)
00117   g3ErrorHandler->fatal("%s -- NDMaterial not of order 2",
00118    "ZeroLengthND::ZeroLengthND");
00119 
00120  // Set up the transformation matrix of direction cosines
00121  this->setUp(Nd1, Nd2, x, yprime);
00122 }
00123 
00124 ZeroLengthND::ZeroLengthND() : 
00125 Element(0, ELE_TAG_ZeroLengthND),
00126 connectedExternalNodes(2),
00127 dimension(0), numDOF(0), 
00128 transformation(3,3), A(0), v(0), e(0.0), K(0), P(0),
00129 end1Ptr(0), end2Ptr(0), theNDMaterial(0), the1DMaterial(0), order(0)
00130 {
00131 
00132 }
00133 
00134 ZeroLengthND::~ZeroLengthND()
00135 {
00136     // invoke the destructor on any objects created by the object
00137     // that the object still holds a pointer to
00138     
00139  if (theNDMaterial != 0)
00140   delete theNDMaterial;
00141  if (the1DMaterial != 0)
00142   delete the1DMaterial;
00143  if (A != 0)
00144   delete A;
00145 }
00146 
00147 int
00148 ZeroLengthND::getNumExternalNodes(void) const
00149 {
00150     return 2;
00151 }
00152 
00153 const ID &
00154 ZeroLengthND::getExternalNodes(void) 
00155 {
00156     return connectedExternalNodes;
00157 }
00158 
00159 int
00160 ZeroLengthND::getNumDOF(void) 
00161 {
00162     return numDOF;
00163 }
00164 
00165 // method: setDomain()
00166 //    to set a link to the enclosing Domain and to set the node pointers.
00167 //    also determines the number of dof associated
00168 //    with the ZeroLengthND element, we set matrix and vector pointers,
00169 //    allocate space for t matrix and define it as the basic deformation-
00170 //    displacement transformation matrix.
00171 void
00172 ZeroLengthND::setDomain(Domain *theDomain)
00173 {
00174     // check Domain is not null - invoked when object removed from a domain
00175     if (theDomain == 0) {
00176   end1Ptr = 0;
00177   end2Ptr = 0;
00178   return;
00179     }
00180 
00181     // first set the node pointers
00182     int Nd1 = connectedExternalNodes(0);
00183     int Nd2 = connectedExternalNodes(1);
00184     end1Ptr = theDomain->getNode(Nd1);
00185     end2Ptr = theDomain->getNode(Nd2); 
00186 
00187     // if can't find both - send a warning message
00188     if (end1Ptr == 0 || end2Ptr == 0) {
00189   if (end1Ptr == 0) 
00190    g3ErrorHandler->warning("%s -- Nd1: %d does not exist in ",
00191     "ZeroLengthND::setDomain()", Nd1);
00192   else
00193    g3ErrorHandler->warning("%s -- Nd2: %d does not exist in ",
00194     "ZeroLengthND::setDomain()", Nd2);
00195 
00196   g3ErrorHandler->warning("model for ZeroLengthND with id %d",
00197    this->getTag());
00198 
00199   return;
00200     }
00201 
00202     // now determine the number of dof and the dimension    
00203     int dofNd1 = end1Ptr->getNumberDOF();
00204     int dofNd2 = end2Ptr->getNumberDOF(); 
00205 
00206     // if differing dof at the ends - print a warning message
00207     if (dofNd1 != dofNd2) {
00208   g3ErrorHandler->warning("%s -- nodes %d and %d %s %d\n",Nd1, Nd2,
00209    "ZeroLengthND::setDomain()",
00210    "have differing dof at ends for ZeroLengthND ",
00211    this->getTag());
00212   return;
00213     } 
00214 
00215  numDOF = 2*dofNd1;
00216 
00217  if (numDOF != 6 && numDOF != 12)
00218   g3ErrorHandler->warning("%s -- element only works for 3 (2d) or 6 (3d) dof per node"
00219          "ZeroLengthND::setDomain()");
00220 
00221     // Check that length is zero within tolerance
00222     const Vector &end1Crd = end1Ptr->getCrds();
00223     const Vector &end2Crd = end2Ptr->getCrds(); 
00224     const Vector     diff = end1Crd - end2Crd;
00225     double L  = diff.Norm();
00226     double v1 = end1Crd.Norm();
00227     double v2 = end2Crd.Norm();
00228     double vm;
00229     
00230     vm = (v1<v2) ? v2 : v1;
00231     
00232     if (L > LENTOL*vm)
00233   g3ErrorHandler->warning("%s -- Element %d has L=%e, which is greater than the tolerance",
00234    "ZeroLengthND::setDomain()", this->getTag(), L);
00235         
00236     // call the base class method
00237     this->DomainComponent::setDomain(theDomain);
00238     
00239  // Set up the A matrix
00240  this->setTransformation();
00241 }     
00242 
00243 int
00244 ZeroLengthND::commitState()
00245 {
00246  int err = 0;
00247 
00248  // Commit the NDMaterial
00249  err += theNDMaterial->commitState();
00250 
00251  // Commit the UniaxialMaterial
00252  if (the1DMaterial != 0)
00253   err += the1DMaterial->commitState();
00254 
00255  return err;
00256 }
00257 
00258 int
00259 ZeroLengthND::revertToLastCommit()
00260 {
00261  int err = 0;
00262 
00263  // Revert the NDMaterial
00264  err += theNDMaterial->revertToLastCommit();
00265 
00266  // Revert the UniaxialMaterial
00267  if (the1DMaterial != 0)
00268   err += the1DMaterial->revertToLastCommit();
00269 
00270  return err;
00271 }
00272 
00273 int
00274 ZeroLengthND::revertToStart()
00275 {
00276  int err = 0;
00277 
00278  // Revert the NDMaterial to start
00279  err += theNDMaterial->revertToStart();
00280 
00281  // Revert the UniaxialMaterial to start
00282  if (the1DMaterial != 0)
00283   err += the1DMaterial->revertToStart();
00284 
00285  return err;
00286 }
00287 
00288 const Matrix &
00289 ZeroLengthND::getTangentStiff(void)
00290 {
00291  // Compute material strains
00292  this->computeStrain();
00293 
00294  // Set trial strain for NDMaterial
00295  theNDMaterial->setTrialStrain(*v);
00296 
00297  // Get NDMaterial tangent, the element basic stiffness
00298  const Matrix &kb = theNDMaterial->getTangent();
00299 
00300  // Set some references to make the syntax nicer
00301  Matrix &stiff = *K;
00302  const Matrix &tran = *A;
00303 
00304  stiff.Zero();
00305 
00306  double E;
00307 
00308  // Compute element stiffness ... K = A^*kb*A
00309  for (int k = 0; k < order; k++) {
00310   for (int l = 0; l < order; l++) {
00311    E = kb(k,l);
00312    for (int i = 0; i < numDOF; i++)
00313     for (int j = 0; j < i+1; j++)
00314      stiff(i,j) +=  tran(k,i) * E * tran(l,j);
00315   }
00316  }
00317 
00318  if (the1DMaterial != 0) {
00319 
00320   // Set trial strain for UniaxialMaterial
00321   the1DMaterial->setTrialStrain(e);
00322 
00323   // Get UniaxialMaterial tangent, the element basic stiffness
00324   E = the1DMaterial->getTangent();
00325 
00326   // Compute element stiffness ... K = A^*kb*A
00327   for (int i = 0; i < numDOF; i++)
00328    for (int j = 0; j < i+1; j++)
00329     stiff(i,j) +=  tran(2,i) * E * tran(2,j);
00330  }
00331 
00332     // Complete symmetric stiffness matrix
00333     for (int i = 0; i < numDOF; i++)
00334   for(int j = 0; j < i; j++)
00335       stiff(j,i) = stiff(i,j);
00336 
00337  return stiff;
00338 }
00339 
00340 const Matrix &
00341 ZeroLengthND::getSecantStiff(void)
00342 {
00343     // secant is not defined; use tangent
00344     return this->getTangentStiff();
00345 }
00346 
00347 const Matrix &
00348 ZeroLengthND::getDamp(void)
00349 {
00350  // Return zero damping
00351  K->Zero();
00352 
00353  return *K;
00354 }
00355 
00356 const Matrix &
00357 ZeroLengthND::getMass(void)
00358 {
00359  // Return zero mass
00360  K->Zero();
00361 
00362  return *K;
00363 }
00364 
00365 void 
00366 ZeroLengthND::zeroLoad(void)
00367 {
00368  // does nothing now
00369 }
00370 
00371 int
00372 ZeroLengthND::addLoad(const Vector &addP)
00373 {
00374  // does nothing now
00375  return 0;
00376 }
00377 
00378 int 
00379 ZeroLengthND::addInertiaLoadToUnbalance(const Vector &accel)
00380 {
00381  // does nothing as element has no mass yet!
00382  return 0;
00383 }
00384 
00385 const Vector &
00386 ZeroLengthND::getResistingForce()
00387 {
00388  // Compute material strains
00389  this->computeStrain();
00390 
00391  // Set trial strain for NDMaterial
00392  theNDMaterial->setTrialStrain(*v);
00393 
00394  // Get NDMaterial stress, the element basic force
00395  const Vector &q = theNDMaterial->getStress();
00396 
00397  // Set some references to make the syntax nicer
00398  Vector &force = *P;
00399  const Matrix &tran = *A;
00400 
00401  force.Zero();
00402 
00403  double s;
00404 
00405  // Compute element resisting force ... P = A^*q
00406  for (int k = 0; k < order; k++) {
00407   s = q(k);
00408   for (int i = 0; i < numDOF; i++)
00409    force(i) += tran(k,i) * s;
00410  }
00411 
00412  if (the1DMaterial != 0) {
00413 
00414   // Set trial strain for UniaxialMaterial
00415   the1DMaterial->setTrialStrain(e);
00416 
00417   // Get UniaxialMaterial stress, the element basic force
00418   s = the1DMaterial->getStress();
00419 
00420   // Compute element resisting force ... P = A^*q
00421   for (int i = 0; i < numDOF; i++)
00422    force(i) += tran(2,i) * s;
00423  }
00424 
00425  return force;
00426 }
00427 
00428 const Vector &
00429 ZeroLengthND::getResistingForceIncInertia()
00430 { 
00431     // There is no mass, so return
00432     return this->getResistingForce();
00433 }
00434 
00435 int
00436 ZeroLengthND::sendSelf(int commitTag, Channel &theChannel)
00437 {
00438  int res = 0;
00439 
00440  // note: we don't check for dataTag == 0 for Element
00441  // objects as that is taken care of in a commit by the Domain
00442  // object - don't want to have to do the check if sending data
00443  int dataTag = this->getDbTag();
00444 
00445  // ZeroLengthND packs its data into an ID and sends this to theChannel
00446  // along with its dbTag and the commitTag passed in the arguments
00447 
00448  static ID idData(11);
00449 
00450  idData(0) = this->getTag();
00451  idData(1) = dimension;
00452  idData(2) = numDOF;
00453  idData(3) = order;
00454  idData(4) = (the1DMaterial == 0) ? 0 : 1;
00455  idData(5) = connectedExternalNodes(0);
00456  idData(6) = connectedExternalNodes(1);
00457  idData(7) = theNDMaterial->getClassTag();
00458 
00459  int dbTag = theNDMaterial->getDbTag();
00460  if (dbTag == 0) {
00461   dbTag = theChannel.getDbTag();
00462   if (dbTag != 0)
00463    theNDMaterial->setDbTag(dbTag);
00464  }
00465  idData(8) = dbTag;
00466 
00467  if (the1DMaterial != 0) {
00468   idData(9) = the1DMaterial->getClassTag();
00469 
00470   dbTag = the1DMaterial->getDbTag();
00471   if (dbTag == 0) {
00472    dbTag = theChannel.getDbTag();
00473    if (dbTag != 0)
00474     the1DMaterial->setDbTag(dbTag);
00475   }
00476   idData(10) = dbTag;
00477  }
00478 
00479  res += theChannel.sendID(dataTag, commitTag, idData);
00480  if (res < 0) {
00481   g3ErrorHandler->warning("%s -- failed to send ID data",
00482    "ZeroLengthND::sendSelf");
00483   return res;
00484  }
00485 
00486  // Send the 3x3 direction cosine matrix, have to send it since it is only set
00487  // in the constructor and not setDomain()
00488  res += theChannel.sendMatrix(dataTag, commitTag, transformation);
00489  if (res < 0) {
00490   g3ErrorHandler->warning("%s -- failed to send transformation Matrix",
00491    "ZeroLengthND::sendSelf");
00492   return res;
00493  }
00494 
00495  // Send the NDMaterial
00496  res += theNDMaterial->sendSelf(commitTag, theChannel);
00497  if (res < 0) {
00498   g3ErrorHandler->warning("%s -- failed to send NDMaterial",
00499    "ZeroLengthND::sendSelf");
00500   return res;
00501  }
00502 
00503  // Send the UniaxialMaterial, if present
00504  if (the1DMaterial != 0) {
00505   res += the1DMaterial->sendSelf(commitTag, theChannel);
00506   if (res < 0) {
00507    g3ErrorHandler->warning("%s -- failed to send UniaxialMaterial",
00508     "ZeroLengthND::sendSelf");
00509    return res;
00510   }
00511  }
00512 
00513  return res;
00514 }
00515 
00516 int
00517 ZeroLengthND::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00518 {
00519  int res = 0;
00520   
00521  int dataTag = this->getDbTag();
00522 
00523  // ZeroLengthND creates an ID, receives the ID and then sets the 
00524  // internal data with the data in the ID
00525 
00526  static ID idData(11);
00527 
00528  res += theChannel.recvID(dataTag, commitTag, idData);
00529  if (res < 0) {
00530   g3ErrorHandler->warning("%s -- failed to receive ID data",
00531    "ZeroLengthND::recvSelf");
00532   return res;
00533  }
00534 
00535  res += theChannel.recvMatrix(dataTag, commitTag, transformation);
00536  if (res < 0) {
00537   g3ErrorHandler->warning("%s -- failed to receive transformation Matrix",
00538    "ZeroLengthND::recvSelf");
00539   return res;
00540  }
00541 
00542  this->setTag(idData(0));
00543  dimension = idData(1);
00544  numDOF = idData(2);
00545  connectedExternalNodes(0) = idData(5);
00546  connectedExternalNodes(1) = idData(6);
00547 
00548  if (order != idData(3)) {
00549 
00550   order = idData(3);
00551 
00552   // Allocate transformation matrix
00553   if (A != 0)
00554    delete A;
00555 
00556   A = new Matrix(order, numDOF);
00557 
00558   if (A == 0)
00559    g3ErrorHandler->fatal("%s -- failed to allocate transformation Matrix",
00560     "ZeroLengthND::recvSelf");
00561 
00562   if (numDOF == 6) {
00563    K = &K6;
00564    P = &P6;
00565   }
00566   else {
00567    K = &K12;
00568    P = &P12;
00569   }
00570 
00571   if (order == 2)
00572    v = &v2;
00573   else
00574    v = &v3;
00575  }
00576 
00577  int classTag = idData(7);
00578 
00579  // If null, get a new one from the broker
00580  if (theNDMaterial == 0)
00581   theNDMaterial = theBroker.getNewNDMaterial(classTag);
00582 
00583  // If wrong type, get a new one from the broker
00584  if (theNDMaterial->getClassTag() != classTag) {
00585   delete theNDMaterial;
00586   theNDMaterial = theBroker.getNewNDMaterial(classTag);
00587  }
00588 
00589  // Check if either allocation failed from broker
00590  if (theNDMaterial == 0) {
00591   g3ErrorHandler->warning("%s -- failed to allocate new NDMaterial",
00592    "ZeroLengthND::recvSelf");
00593   return -1;
00594  }
00595 
00596  // Receive the NDMaterial
00597  theNDMaterial->setDbTag(idData(8));
00598  res += theNDMaterial->recvSelf(commitTag, theChannel, theBroker);
00599  if (res < 0) {
00600   g3ErrorHandler->warning("%s -- failed to receive NDMaterial",
00601    "ZeroLengthND::recvSelf");
00602   return res;
00603  }
00604 
00605  // Receive the UniaxialMaterial, if present
00606  if (idData(4) == 1) {
00607   classTag = idData(9);
00608 
00609   // If null, get a new one from the broker
00610   if (the1DMaterial == 0)
00611    the1DMaterial = theBroker.getNewUniaxialMaterial(classTag);
00612 
00613   // If wrong type, get a new one from the broker
00614   if (the1DMaterial->getClassTag() != classTag) {
00615    delete the1DMaterial;
00616    the1DMaterial = theBroker.getNewUniaxialMaterial(classTag);
00617   }
00618 
00619   // Check if either allocation failed from broker
00620   if (the1DMaterial == 0) {
00621    g3ErrorHandler->warning("%s -- failed to allocate new UniaxialMaterial",
00622     "ZeroLengthND::recvSelf");
00623    return -1;
00624   }
00625 
00626   // Receive the UniaxialMaterial
00627   the1DMaterial->setDbTag(idData(10));
00628   res += the1DMaterial->recvSelf(commitTag, theChannel, theBroker);
00629   if (res < 0) {
00630    g3ErrorHandler->warning("%s -- failed to receive UniaxialMaterial",
00631     "ZeroLengthND::recvSelf");
00632    return res;
00633   }
00634  }
00635 
00636  return res;
00637 }
00638 
00639 int
00640 ZeroLengthND::displaySelf(Renderer &theViewer, int displayMode, float fact)
00641 {
00642     // ensure setDomain() worked
00643     if (end1Ptr == 0 || end2Ptr == 0)
00644   return 0;
00645 
00646     // first determine the two end points of the ZeroLengthND based on
00647     // the display factor (a measure of the distorted image)
00648     // store this information in 2 3d vectors v1 and v2
00649     const Vector &end1Crd = end1Ptr->getCrds();
00650     const Vector &end2Crd = end2Ptr->getCrds(); 
00651     const Vector &end1Disp = end1Ptr->getDisp();
00652     const Vector &end2Disp = end2Ptr->getDisp();    
00653 
00654     if (displayMode == 1 || displayMode == 2) {
00655   static Vector v1(3);
00656   static Vector v2(3);
00657   for (int i = 0; i < dimension; i++) {
00658    v1(i) = end1Crd(i)+end1Disp(i)*fact;
00659    v2(i) = end2Crd(i)+end2Disp(i)*fact;    
00660   }
00661   
00662   return theViewer.drawLine(v1, v2, 0.0, 0.0);
00663     }
00664 
00665     return 0;
00666 }
00667 
00668 void
00669 ZeroLengthND::Print(ostream &s, int flag)
00670 {
00671  s << "ZeroLengthND, tag: " << this->getTag() << endl;
00672  s << "\tConnected Nodes: " << connectedExternalNodes << endl;
00673  s << "\tNDMaterial, tag: " << theNDMaterial->getTag() << endl;
00674  if (the1DMaterial != 0)
00675   s << "\tUniaxialMaterial, tag: " << the1DMaterial->getTag() << endl;
00676 }
00677 
00678 Response*
00679 ZeroLengthND::setResponse(char **argv, int argc, Information &eleInformation)
00680 {
00681  // element forces
00682     if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0)
00683   return new ElementResponse(this, 1, *P);
00684 
00685     // element stiffness matrix
00686     else if (strcmp(argv[0],"stiff") == 0 || strcmp(argv[0],"stiffness") == 0)
00687   return new ElementResponse(this, 2, *K);
00688 
00689     else if (strcmp(argv[0],"defo") == 0 || strcmp(argv[0],"deformations") == 0 ||
00690   strcmp(argv[0],"deformation") == 0) {
00691   if (the1DMaterial != 0)
00692    return new ElementResponse(this, 3, Vector(3));
00693   else
00694    return new ElementResponse(this, 3, Vector(order));
00695    }     
00696 
00697  else if (strcmp(argv[0],"material") == 0) {
00698   // See if NDMaterial can handle request ...
00699   Response *res = theNDMaterial->setResponse(&argv[1], argc-1, eleInformation);
00700   if (res != 0)
00701    return res;
00702 
00703   // If not, send request to UniaxialMaterial, if present
00704   if (the1DMaterial != 0)
00705    return the1DMaterial->setResponse(&argv[1], argc-1, eleInformation);
00706   
00707   // If neither material can handle request, return 0
00708   else
00709    return 0;
00710  }
00711 
00712  else 
00713   return 0;
00714 }
00715 
00716 int 
00717 ZeroLengthND::getResponse(int responseID, Information &eleInfo)
00718 {
00719   switch (responseID) {
00720  case 1:
00721   return eleInfo.setVector(this->getResistingForce());
00722   
00723     case 2:
00724   return eleInfo.setMatrix(this->getTangentStiff());
00725 
00726  case 3:
00727   if (eleInfo.theVector != 0) {
00728    this->computeStrain();
00729    const Vector &tmp = *v; // NDMaterial strains
00730    Vector &def = *(eleInfo.theVector);
00731    for (int i = 0; i < order; i++)
00732     def(i) = tmp(i);
00733    if (the1DMaterial != 0)
00734     def(order) = e; // UniaxialMaterial strain
00735   }
00736   return 0;
00737 
00738     default:
00739   return -1;
00740   }
00741 }
00742 
00743 // Private methods
00744 
00745 
00746 // Establish the external nodes and set up the transformation matrix
00747 // for orientation
00748 void
00749 ZeroLengthND::setUp(int Nd1, int Nd2, const Vector &x, const Vector &yp)
00750 { 
00751     // ensure the connectedExternalNode ID is of correct size & set values
00752     if (connectedExternalNodes.Size() != 2)
00753   g3ErrorHandler->fatal("%s -- failed to create an ID of correct size",
00754    "ZeroLengthND::setUp");
00755     
00756     connectedExternalNodes(0) = Nd1;
00757     connectedExternalNodes(1) = Nd2;
00758     
00759     // check that vectors for orientation are correct size
00760     if ( x.Size() != 3 || yp.Size() != 3 )
00761   g3ErrorHandler->fatal("%s -- incorrect dimension of orientation vectors",
00762    "ZeroLengthND::setUp");
00763 
00764     // establish orientation of element for the tranformation matrix
00765     // z = x cross yp
00766     static Vector z(3);
00767     z(0) = x(1)*yp(2) - x(2)*yp(1);
00768     z(1) = x(2)*yp(0) - x(0)*yp(2);
00769     z(2) = x(0)*yp(1) - x(1)*yp(0);
00770 
00771     // y = z cross x
00772     static Vector y(3);
00773     y(0) = z(1)*x(2) - z(2)*x(1);
00774     y(1) = z(2)*x(0) - z(0)*x(2);
00775     y(2) = z(0)*x(1) - z(1)*x(0);
00776 
00777     // compute length(norm) of vectors
00778     double xn = x.Norm();
00779     double yn = y.Norm();
00780     double zn = z.Norm();
00781 
00782     // check valid x and y vectors, i.e. not parallel and of zero length
00783     if (xn == 0 || yn == 0 || zn == 0)
00784   g3ErrorHandler->fatal("%s -- invalid vectors to constructor",
00785    "ZeroLengthND::setUp");
00786     
00787     // create transformation matrix of direction cosines
00788     for (int i = 0; i < 3; i++) {
00789   transformation(0,i) = x(i)/xn;
00790   transformation(1,i) = y(i)/yn;
00791   transformation(2,i) = z(i)/zn;
00792  }
00793 }
00794 
00795 // Set basic deformation-displacement transformation matrix for the materials
00796 void 
00797 ZeroLengthND::setTransformation(void)
00798 {
00799  // Allocate transformation matrix
00800  if (A != 0)
00801   delete A;
00802 
00803  A = (the1DMaterial == 0) ? new Matrix(order, numDOF) : new Matrix(order+1, numDOF);
00804 
00805  if (A == 0)
00806   g3ErrorHandler->fatal("%s -- failed to allocate transformation Matrix",
00807    "ZeroLengthND::setTransformation");
00808 
00809  if (numDOF == 6) {
00810   K = &K6;
00811   P = &P6;
00812  }
00813  else {
00814   K = &K12;
00815   P = &P12;
00816  }
00817 
00818  if (order == 2)
00819   v = &v2;
00820  else
00821   v = &v3;
00822 
00823  // Set a reference to make the syntax nicer
00824  Matrix &tran = *A;
00825  
00826  // Loop over the NDMaterial order
00827  for (int i = 0; i < order; i++) {
00828 
00829   if (numDOF == 6) {
00830    tran(i,3) = transformation(i,0);
00831    tran(i,4) = transformation(i,1);
00832    tran(i,5) = 0.0;
00833   }
00834   else if (numDOF == 12) {
00835    tran(i,6) = transformation(i,0);
00836    tran(i,7) = transformation(i,1);
00837    tran(i,8) = transformation(i,2);
00838   }
00839 
00840   // Fill in first half of transformation matrix with negative sign
00841   for (int j = 0; j < numDOF/2; j++ )
00842    tran(i,j) = -tran(i,j+numDOF/2);
00843  }
00844 
00845  // Fill in transformation for UniaxialMaterial
00846  if (the1DMaterial != 0) {
00847 
00848   if (numDOF == 6) {
00849    tran(2,3) = transformation(2,0);
00850    tran(2,4) = transformation(2,1);
00851    tran(2,5) = 0.0;
00852   }
00853   else if (numDOF == 12) {
00854    tran(2,6) = transformation(2,0);
00855    tran(2,7) = transformation(2,1);
00856    tran(2,8) = transformation(2,2);
00857   }
00858 
00859   // Fill in first half of transformation matrix with negative sign
00860   for (int j = 0; j < numDOF/2; j++ )
00861    tran(2,j) = -tran(2,j+numDOF/2);
00862  }
00863 }
00864        
00865 void
00866 ZeroLengthND::computeStrain(void)
00867 {
00868  // Get nodal displacements
00869  const Vector &u1 = end1Ptr->getTrialDisp();
00870  const Vector &u2 = end2Ptr->getTrialDisp();
00871 
00872  // Compute differential displacements
00873  const Vector diff = u2 - u1;
00874 
00875  // Set some references to make the syntax nicer
00876  Vector &def = *v;
00877  const Matrix &tran = *A;
00878 
00879  def.Zero();
00880 
00881  // Compute element basic deformations ... v = A*(u2-u1)
00882  for (int i = 0; i < order; i++)
00883   for (int j = 0; j < numDOF/2; j++)
00884    def(i) += -diff(j)*tran(i,j);
00885 
00886  if (the1DMaterial != 0) {
00887   e = 0.0;
00888   for (int j = 0; j < numDOF/2; j++)
00889    e += -diff(j)*tran(2,j);
00890  }
00891 }
Copyright Contact Us