BeamWithHinges2d.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.21 $
00022 // $Date: 2004/06/07 23:20:55 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/element/beamWithHinges/BeamWithHinges2d.cpp,v $
00024 
00025 #include <BeamWithHinges2d.h>
00026 #include <Element.h>
00027 #include <Domain.h>
00028 #include <Channel.h>
00029 #include <FEM_ObjectBroker.h>
00030 #include <Matrix.h>
00031 #include <Vector.h>                                             
00032 #include <Node.h>
00033 #include <MatrixUtil.h>
00034 #include <math.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <stdio.h>
00038 
00039 #include <SectionForceDeformation.h>
00040 #include <CrdTransf2d.h>
00041 #include <ElementalLoad.h>
00042 
00043 #include <Information.h>
00044 #include <ElementResponse.h>
00045 #include <Renderer.h>
00046 
00047 Matrix BeamWithHinges2d::theMatrix(6,6);
00048 Vector BeamWithHinges2d::theVector(6);
00049 double BeamWithHinges2d::workArea[100];
00050 
00051 BeamWithHinges2d::BeamWithHinges2d(void)
00052   :Element(0, ELE_TAG_BeamWithHinges2d),
00053    E(0.0), A(0.0), I(0.0),
00054    beta1(0.0), beta2(0.0), rho(0.0),
00055    theCoordTransf(0),
00056    connectedExternalNodes(2),
00057    kb(3,3), q(3), load(6),
00058    kbCommit(3,3), qCommit(3),
00059    initialFlag(0), maxIter(0), tolerance(0.0), sp(0)
00060 {
00061   section[0] = 0;
00062   section[1] = 0;
00063 
00064   p0[0] = 0.0;
00065   p0[1] = 0.0;
00066   p0[2] = 0.0;
00067 
00068   v0[0] = 0.0;
00069   v0[1] = 0.0;
00070   v0[2] = 0.0;
00071 
00072   theNodes[0] = 0;
00073   theNodes[1] = 0;
00074 }
00075 
00076 BeamWithHinges2d::BeamWithHinges2d(int tag, int nodeI, int nodeJ,
00077                                    double e, double a, double i,
00078                                    SectionForceDeformation &sectionRefI, double lpi,
00079                                    SectionForceDeformation &sectionRefJ, double lpj,
00080                                    CrdTransf2d &coordTransf,
00081                                    double r, int max, double tol)
00082   :Element(tag, ELE_TAG_BeamWithHinges2d),
00083    E(e), A(a), I(i),
00084    beta1(lpi), beta2(lpj), rho(r),
00085    theCoordTransf(0),
00086    connectedExternalNodes(2),
00087    kb(3,3), q(3), load(6),
00088    kbCommit(3,3), qCommit(3),
00089    initialFlag(0), maxIter(max), tolerance(tol), sp(0)
00090 {
00091   if (E <= 0.0)  {
00092     opserr << "BeamWithHinges2d::BeamWithHinges2d -- input parameter E is <= 0.0\n";
00093     exit(-1);
00094   }
00095   
00096   if (I <= 0.0)  {
00097     opserr << "BeamWithHinges2d::BeamWithHinges2d -- input parameter I is <= 0.0\n";
00098     exit(-1);
00099   }
00100   
00101   if (A <= 0.0)  {
00102     opserr << "BeamWithHinges2d::BeamWithHinges2d -- input parameter A is <= 0.0\n";
00103     exit(-1);
00104   }
00105   
00106   // Get copies of sections
00107   section[0] = sectionRefI.getCopy();
00108   
00109   if (section[0] == 0) {
00110     opserr << "BeamWithHinges2d::BeamWithHinges2d -- failed to get copy of section I\n";
00111     exit(-1);
00112   }
00113   
00114   section[1] = sectionRefJ.getCopy();
00115   
00116   if (section[1] == 0) {
00117     opserr << "BeamWithHinges2d::BeamWithHinges2d -- failed to get copy of section J\n";
00118     exit(-1);
00119   }
00120   
00121   theCoordTransf = coordTransf.getCopy();
00122   
00123   if (theCoordTransf == 0) {
00124     opserr << "BeamWithHinges2d::BeamWithHinges2d -- failed to get copy of coordinate transformation\n";
00125     exit(-1);
00126   }
00127 
00128   connectedExternalNodes(0) = nodeI;
00129   connectedExternalNodes(1) = nodeJ;
00130 
00131   theNodes[0] = 0;
00132   theNodes[1] = 0;
00133 
00134   // Set up section interpolation and hinge lengths
00135   this->setHinges();
00136 
00137   p0[0] = 0.0;
00138   p0[1] = 0.0;
00139   p0[2] = 0.0;
00140 
00141   v0[0] = 0.0;
00142   v0[1] = 0.0;
00143   v0[2] = 0.0;
00144 }
00145 
00146 BeamWithHinges2d::~BeamWithHinges2d(void)
00147 {
00148   for (int i = 0; i < 2; i++)
00149     if (section[i] != 0)
00150       delete section[i];
00151   
00152   if (theCoordTransf)
00153     delete theCoordTransf;
00154 
00155   if (sp != 0)
00156     delete sp;
00157 }
00158 
00159 int 
00160 BeamWithHinges2d::getNumExternalNodes(void) const
00161 {
00162   return 2;
00163 }
00164 
00165 const ID &
00166 BeamWithHinges2d::getExternalNodes(void)
00167 {
00168   return connectedExternalNodes;
00169 }
00170 
00171 Node **
00172 BeamWithHinges2d::getNodePtrs()
00173 {
00174     return theNodes;
00175 }
00176 
00177 int 
00178 BeamWithHinges2d::getNumDOF(void)
00179 {
00180   return 6;
00181 }
00182 
00183 void
00184 BeamWithHinges2d::setDomain(Domain *theDomain)
00185 {
00186   //This function may be called after a beam is constructed, so
00187   //geometry may change.  Therefore calculate all beam geometry here.
00188   
00189   if(theDomain == 0) {
00190     theNodes[0] = 0;
00191     theNodes[1] = 0;
00192     return;
00193   }
00194   
00195   // set the node pointers and verify them
00196   this->setNodePtrs(theDomain);
00197   
00198   // call the DomainComponent version of the function
00199   this->DomainComponent::setDomain(theDomain);
00200   
00201   if (theCoordTransf->initialize(theNodes[0], theNodes[1]) != 0) {
00202     opserr << "BeamWithHinges2d::setDomain() -- failed to initialize coordinate transformation\n";
00203     exit(-1);
00204   }
00205   
00206   // get element length
00207   double L = theCoordTransf->getInitialLength();
00208   if (L == 0.0) {
00209     opserr << "BeamWithHinges2d::setDomain() -- element has zero length\n";
00210     exit(-1);
00211   }
00212 
00213   if (initialFlag == 2)
00214     theCoordTransf->update();
00215   else
00216     this->update();
00217 }
00218 
00219 int
00220 BeamWithHinges2d::commitState(void)
00221 {
00222   int err = 0;
00223 
00224   // call element commitState to do any base class stuff
00225   if ((err = this->Element::commitState()) != 0) {
00226     opserr << "BeamWithHinges2d::commitState () - failed in base class";
00227   }    
00228   
00229   for (int i = 0; i < 2; i++) {
00230     if (section[i] != 0)
00231       err += section[i]->commitState();
00232   }
00233   
00234   err += theCoordTransf->commitState();
00235   
00236   kbCommit = kb;
00237   qCommit = q;
00238 
00239 
00240   eCommit[0] = e[0];
00241   eCommit[1] = e[1];
00242   
00243   //initialFlag = 0;
00244   
00245   return err;
00246 }
00247 
00248 int
00249 BeamWithHinges2d::revertToLastCommit(void)
00250 {
00251   int err = 0;
00252   
00253   // Revert the sections and then get their last commited
00254   // deformations, stress resultants, and flexibilities
00255   for (int i = 0; i < 2; i++) {
00256     if (section[i] != 0) {
00257       err += section[i]->revertToLastCommit();
00258       section[i]->setTrialSectionDeformation(eCommit[i]);
00259 
00260       e[i] = eCommit[i];
00261       sr[i] = section[i]->getStressResultant();
00262       fs[i] = section[i]->getSectionFlexibility();
00263     }
00264   }
00265   
00266   // Commit the coordinate transformation
00267   err += theCoordTransf->revertToLastCommit();
00268   
00269   kb = kbCommit;
00270   q = qCommit;
00271   
00272   initialFlag = 0;
00273   //   this->update();
00274 
00275   return err;
00276 }
00277 
00278 int
00279 BeamWithHinges2d::revertToStart(void)
00280 {
00281   int err = 0;
00282   
00283   for (int i = 0; i < 2; i++) {
00284     if (section[i] != 0) {
00285       err += section[i]->revertToStart();
00286       fs[i].Zero();
00287       e[i].Zero();
00288       sr[i].Zero();
00289       eCommit[i].Zero();
00290     }
00291   }
00292   
00293   err += theCoordTransf->revertToStart();
00294   
00295   kb.Zero();
00296   q.Zero();
00297   
00298   initialFlag = 0;
00299   // this->update();
00300 
00301   return err;
00302 }
00303 
00304 const Matrix &
00305 BeamWithHinges2d::getTangentStiff(void)
00306 {
00307   return theCoordTransf->getGlobalStiffMatrix(kb, q);
00308 }
00309 
00310 
00311 const Matrix &
00312 BeamWithHinges2d::getInitialStiff(void)
00313 {
00314   double L = theCoordTransf->getInitialLength();
00315   double oneOverL = 1.0/L;
00316 
00317   // Section locations along element length ...
00318   double xi[2];
00319 
00320   // and their integration weights
00321   double lp[2];
00322   
00323   lp[0] = beta1*L;
00324   lp[1] = beta2*L;
00325 
00326   xi[0] = 0.5*lp[0];
00327   xi[1] = L-0.5*lp[1];
00328   
00329   // element properties
00330   static Matrix f(3,3); // element flexibility
00331   static Vector vr(3);  // Residual element deformations
00332   
00333   static Matrix Iden(3,3);   // an identity matrix for matrix inverse
00334   Iden.Zero();
00335   int i;
00336   for (i = 0; i < 3; i++)
00337     Iden(i,i) = 1.0;
00338 
00339   // Length of elastic interior
00340   double Le = L-lp[0]-lp[1];
00341   double LoverEA  = Le/(E*A);
00342   double Lover3EI = Le/(3*E*I);
00343   double Lover6EI = 0.5*Lover3EI;
00344   
00345   // Elastic flexibility of element interior
00346   static Matrix fe(2,2);
00347   fe(0,0) = fe(1,1) =  Lover3EI;
00348   fe(0,1) = fe(1,0) = -Lover6EI;
00349   
00350   // Equilibrium transformation matrix
00351   static Matrix B(2,2);
00352   B(0,0) = 1.0 - beta1;
00353   B(1,1) = 1.0 - beta2;
00354   B(0,1) = -beta1;
00355   B(1,0) = -beta2;
00356   
00357   // Transform the elastic flexibility of the element
00358   // interior to the basic system
00359   static Matrix fElastic(2,2);
00360   fElastic.addMatrixTripleProduct(0.0, B, fe, 1.0);
00361 
00362   // Set element flexibility to flexibility of elastic region
00363   f(0,0) = LoverEA;
00364   f(1,1) = fElastic(0,0);
00365   f(2,2) = fElastic(1,1);
00366   f(1,2) = fElastic(0,1);
00367   f(2,1) = fElastic(1,0);
00368   f(0,1) = f(1,0) = f(0,2) = f(2,0) = 0.0;
00369     
00370   for (i = 0; i < 2; i++) {
00371       
00372     if (section[i] == 0 || lp[i] <= 0.0)
00373       continue;
00374       
00375     // Get section information
00376     int order = section[i]->getOrder();
00377     const ID &code = section[i]->getType();
00378     
00379     Vector s(workArea, order);
00380     Vector ds(&workArea[order], order);
00381     Vector de(&workArea[2*order], order);
00382     
00383     Matrix fb(&workArea[3*order], order, 3);
00384     
00385     double x   = xi[i];
00386     double xL  = x*oneOverL;
00387     double xL1 = xL-1.0;
00388       
00389     // get section flexibility matrix
00390     const Matrix &fSec = section[i]->getInitialFlexibility();
00391             
00392     // integrate section flexibility matrix
00393     // f += (b^ fs * b) * lp[i];
00394     //f.addMatrixTripleProduct(1.0, b, fSec, lp[i]);
00395     int ii, jj;
00396     fb.Zero();
00397     double tmp;
00398     for (ii = 0; ii < order; ii++) {
00399       switch(code(ii)) {
00400       case SECTION_RESPONSE_P:
00401         for (jj = 0; jj < order; jj++)
00402           fb(jj,0) += fSec(jj,ii)*lp[i];
00403         break;
00404       case SECTION_RESPONSE_MZ:
00405         for (jj = 0; jj < order; jj++) {
00406           tmp = fSec(jj,ii)*lp[i];
00407           fb(jj,1) += xL1*tmp;
00408           fb(jj,2) += xL*tmp;
00409         }
00410         break;
00411       case SECTION_RESPONSE_VY:
00412         for (jj = 0; jj < order; jj++) {
00413           //tmp = oneOverL*fSec(jj,ii)*lp[i]*L/lp[i];
00414           tmp = fSec(jj,ii);
00415           fb(jj,1) += tmp;
00416           fb(jj,2) += tmp;
00417           }
00418         break;
00419       default:
00420         break;
00421       }
00422     }
00423     for (ii = 0; ii < order; ii++) {
00424       switch (code(ii)) {
00425       case SECTION_RESPONSE_P:
00426         for (jj = 0; jj < 3; jj++)
00427           f(0,jj) += fb(ii,jj);
00428         break;
00429       case SECTION_RESPONSE_MZ:
00430         for (jj = 0; jj < 3; jj++) {
00431           tmp = fb(ii,jj);
00432           f(1,jj) += xL1*tmp;
00433           f(2,jj) += xL*tmp;
00434         }
00435         break;
00436       case SECTION_RESPONSE_VY:
00437         for (jj = 0; jj < 3; jj++) {
00438           tmp = oneOverL*fb(ii,jj);
00439           f(1,jj) += tmp;
00440           f(2,jj) += tmp;
00441         }
00442         break;
00443       default:
00444         break;
00445       }
00446     }
00447   }
00448 
00449   // calculate element stiffness matrix
00450   //invert3by3Matrix(f, kb);
00451   static Matrix kbInit(3,3);
00452   if (f.Solve(Iden,kbInit) < 0)
00453     opserr << "BeamWithHinges2d::update() -- could not invert flexibility\n";
00454   
00455   return theCoordTransf->getInitialGlobalStiffMatrix(kbInit);
00456 }
00457 
00458 
00459 const Matrix &
00460 BeamWithHinges2d::getMass(void)
00461 {
00462   theMatrix.Zero();
00463 
00464   if (rho != 0.0) {
00465     double L = theCoordTransf->getInitialLength();  
00466     theMatrix(0,0) = theMatrix(1,1) = theMatrix(3,3) = theMatrix(4,4) = 0.5*L*rho;
00467   }
00468   
00469   return theMatrix;
00470 }
00471 
00472 void 
00473 BeamWithHinges2d::zeroLoad(void)
00474 {
00475   if (sp != 0)
00476     sp->Zero();
00477 
00478   p0[0] = 0.0;
00479   p0[1] = 0.0;
00480   p0[2] = 0.0;
00481   
00482   v0[0] = 0.0;
00483   v0[1] = 0.0;
00484   v0[2] = 0.0;
00485 
00486   load.Zero();
00487 }
00488 
00489 int
00490 BeamWithHinges2d::addLoad(ElementalLoad *theLoad, double loadFactor)
00491 {
00492   int type;
00493   const Vector &data = theLoad->getData(type, loadFactor);
00494   
00495   if (sp == 0) {
00496     sp = new Matrix(3,2);
00497     if (sp == 0) {
00498       opserr << "BeamWithHinges2d::addLoad  -- out of memory\n";
00499       exit(-1);
00500     }
00501   }
00502 
00503   double L = theCoordTransf->getInitialLength();
00504   double oneOverL = 1.0/L;
00505 
00506   double lp1 = beta1*L;
00507   double lp2 = beta2*L;
00508   double Le = L-lp1-lp2;
00509 
00510   // Section locations along element length ...
00511   double xi[2];
00512   xi[0] = 0.5*lp1;
00513   xi[1] = L-0.5*lp2;
00514 
00515   if (type == LOAD_TAG_Beam2dUniformLoad) {
00516     double wa = data(1)*loadFactor;  // Axial
00517     double wy = data(0)*loadFactor;  // Transverse
00518 
00519     Matrix &s_p = *sp;
00520 
00521     // Accumulate applied section forces due to uniform load
00522     for (int i = 0; i < 2; i++) {
00523       double x = xi[i];
00524       // Axial
00525       s_p(0,i) += wa*(L-x);
00526       // Moment
00527       s_p(1,i) += wy*0.5*x*(x-L);
00528       // Shear
00529       s_p(2,i) += wy*(x-0.5*L);
00530     }
00531 
00532     // Accumulate reactions in basic system
00533     p0[0] -= wa*L;
00534     double V = 0.5*wy*L;
00535     p0[1] -= V;
00536     p0[2] -= V;
00537 
00538     // Quick return
00539     if (Le == 0.0)
00540       return 0;
00541 
00542     // Accumulate basic deformations due to uniform load on interior
00543     // Midpoint rule for axial
00544     v0[0] += wa*0.5*(L-lp1+lp2)/(E*A)*Le;
00545 
00546     // Two point Gauss for bending ... will not be exact when
00547     // hinge lengths are not equal, but this is not a big deal!!!
00548     double x1 = lp1 + 0.5*Le*(1.0-1.0/sqrt(3.0));
00549     double x2 = lp1 + 0.5*Le*(1.0+1.0/sqrt(3.0));
00550 
00551     double M1 = 0.5*wy*x1*(x1-L);
00552     double M2 = 0.5*wy*x2*(x2-L);
00553 
00554     double b1, b2;
00555     double Le2EI = Le/(2*E*I);
00556     b1 = x1*oneOverL;
00557     b2 = x2*oneOverL;
00558     v0[2] += Le2EI*(b1*M1+b2*M2);
00559 
00560     b1 -= 1.0;
00561     b2 -= 1.0;
00562     v0[1] += Le2EI*(b1*M1+b2*M2);
00563   }
00564 
00565   else if (type == LOAD_TAG_Beam2dPointLoad) {
00566     double P = data(0)*loadFactor;
00567     double N = data(1)*loadFactor;
00568     double aOverL = data(2);
00569     double a = aOverL*L;
00570 
00571     double V1 = P*(1.0-aOverL);
00572     double V2 = P*aOverL;
00573 
00574     Matrix &s_p = *sp;
00575 
00576     // Accumulate applied section forces due to point load
00577     for (int i = 0; i < 2; i++) {
00578       double x = xi[i];
00579       if (x <= a) {
00580         s_p(0,i) += N;
00581         s_p(1,i) -= x*V1;
00582         s_p(2,i) -= V1;
00583       }
00584       else {
00585         s_p(1,i) -= (L-x)*V2;
00586         s_p(2,i) += V2;
00587       }
00588     }
00589 
00590     // Accumulate reactions in basic system
00591     p0[0] -= N;
00592     p0[1] -= V1;
00593     p0[2] -= V2;
00594 
00595     // Quick return
00596     if (Le == 0.0)
00597       return 0;
00598 
00599     // Accumulate basic deformations of interior due to point load
00600     double M1, M2, M3;
00601     double b1, b2, b3;
00602 
00603     // Point load is on left hinge
00604     if (a < lp1) {
00605       M1 = (lp1-L)*V2;
00606       M2 = -lp2*V2;
00607 
00608       double Le_6EI = Le/(6*E*I);
00609 
00610       b1 = lp1*oneOverL;
00611       b2 = 1.0-lp2*oneOverL;
00612       v0[2] += Le_6EI*(M1*(2*b1+b2)+M2*(b1+2*b2));
00613 
00614       b1 -= 1.0;
00615       b2 -= 1.0;
00616       v0[1] += Le_6EI*(M1*(2*b1+b2)+M2*(b1+2*b2));
00617 
00618       // Nothing to do for axial
00619       //v0[0] += 0.0;
00620     }
00621     // Point load is on right hinge
00622     else if (a > L-lp2) {
00623       M1 = -lp1*V1;
00624       M2 = (lp2-L)*V1;
00625 
00626       double Le_6EI = Le/(6*E*I);
00627 
00628       b1 = lp1*oneOverL;
00629       b2 = 1.0-lp2*oneOverL;
00630       v0[2] += Le_6EI*(M1*(2*b1+b2)+M2*(b1+2*b2));
00631 
00632       b1 -= 1.0;
00633       b2 -= 1.0;
00634       v0[1] += Le_6EI*(M1*(2*b1+b2)+M2*(b1+2*b2));
00635 
00636       v0[0] += N*Le/(E*A);      
00637     }
00638     // Point load is on elastic interior
00639     else {
00640       M1 = -lp1*V1;
00641       M2 = -lp2*V2;
00642       M3 = -a*V1;
00643 
00644       double L1_6EI = (a-lp1)/(6*E*I);
00645       double L2_6EI = (Le-a+lp1)/(6*E*I);
00646 
00647       b1 = lp1*oneOverL;
00648       b2 = 1.0-lp2*oneOverL;
00649       b3 = a*oneOverL;
00650       v0[2] += L1_6EI*(M1*(2*b1+b3)+M3*(b1+2*b3));
00651       v0[2] += L2_6EI*(M2*(2*b2+b3)+M3*(b2+2*b3));
00652 
00653       b1 -= 1.0;
00654       b2 -= 1.0;
00655       b3 -= 1.0;
00656       v0[1] += L1_6EI*(M1*(2*b1+b3)+M3*(b1+2*b3));
00657       v0[1] += L2_6EI*(M2*(2*b2+b3)+M3*(b2+2*b3));
00658 
00659       v0[0] += N*(a-lp1)/(E*A);
00660     }
00661   }
00662 
00663   else {
00664     opserr << "BeamWithHinges2d::addLoad() -- load type unknown for element with tag: " << this->getTag() << endln;
00665     return -1;
00666   }
00667 
00668   return 0;  
00669 }
00670 
00671 int
00672 BeamWithHinges2d::addInertiaLoadToUnbalance(const Vector &accel)
00673 {
00674   if (rho == 0.0)
00675     return 0;
00676   
00677   const Vector &Raccel1 = theNodes[0]->getRV(accel);
00678   const Vector &Raccel2 = theNodes[1]->getRV(accel);
00679   
00680   double L = theCoordTransf->getInitialLength();
00681   double mass = 0.5*L*rho;
00682   
00683   int i,j;
00684   for (i = 0, j = 3; i < 2; i++, j++) {
00685     load(i) += mass*Raccel1(i);
00686     load(j) += mass*Raccel2(i); // Yes, this should be 'i'
00687   }
00688   
00689   return 0;
00690 }
00691 
00692 const Vector &
00693 BeamWithHinges2d::getResistingForce(void)
00694 {
00695   Vector p0Vec(p0, 3);
00696 
00697   return theCoordTransf->getGlobalResistingForce(q, p0Vec);
00698 }
00699 
00700 const Vector &
00701 BeamWithHinges2d::getResistingForceIncInertia(void)
00702 {
00703   theVector =  this->getResistingForce();
00704 
00705   if (rho != 0.0) {
00706 
00707     double ag[6];
00708   
00709     const Vector &accel1 = theNodes[0]->getTrialAccel();
00710     const Vector &accel2 = theNodes[1]->getTrialAccel();
00711     
00712     ag[0] = accel1(0);
00713     ag[1] = accel1(1);
00714     //ag[2] = accel1(2); // no rotational element mass
00715     ag[3] = accel2(0);
00716     ag[4] = accel2(1);
00717     //ag[5] = accel2(2); // no rotational element mass
00718     
00719     theVector = this->getResistingForce();
00720     
00721     double L = theCoordTransf->getInitialLength();
00722     double mass = 0.5*L*rho;
00723     
00724     int i,j;
00725     for (i = 0, j = 3; i < 2; i++, j++) {
00726       theVector(i) += mass*ag[i];
00727       theVector(j) += mass*ag[j];
00728     }
00729 
00730     // add the damping forces if rayleigh damping
00731     if (alphaM != 0.0 || betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00732       theVector += this->getRayleighDampingForces();
00733 
00734   } else {
00735 
00736     // add the damping forces if rayleigh damping
00737     if (betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00738       theVector += this->getRayleighDampingForces();
00739   }
00740     
00741   return theVector;
00742 }
00743 
00744 int
00745 BeamWithHinges2d::sendSelf(int commitTag, Channel &theChannel)
00746 {
00747   // place the integer data into an ID
00748   int dbTag = this->getDbTag();
00749   int i, j , k;
00750   int loc = 0;
00751   
00752   static ID idData(11);  
00753   idData(0) = this->getTag();
00754   idData(1) = connectedExternalNodes(0);
00755   idData(2) = connectedExternalNodes(1);
00756   idData(3) = theCoordTransf->getClassTag();
00757   int theCoordTransfDbTag  = theCoordTransf->getDbTag();
00758   if (theCoordTransfDbTag  == 0) {
00759     theCoordTransfDbTag = theChannel.getDbTag();
00760     if (theCoordTransfDbTag  != 0) 
00761       theCoordTransf->setDbTag(theCoordTransfDbTag);
00762   }
00763   idData(4) = theCoordTransfDbTag;
00764 
00765   idData(5) = initialFlag;
00766   idData(6) = maxIter;
00767 
00768   loc = 5;
00769   for (i = 0; i<2; i++) {
00770     int sectClassTag = section[i]->getClassTag();
00771     int sectDbTag = section[i]->getDbTag();
00772     if (sectDbTag == 0) {
00773       sectDbTag = theChannel.getDbTag();
00774       section[i]->setDbTag(sectDbTag);
00775     }
00776 
00777     idData(loc) = sectClassTag;
00778     idData(loc+1) = sectDbTag;
00779     loc += 2;
00780   }  
00781 
00782   if (theChannel.sendID(dbTag, commitTag, idData) < 0) {
00783     opserr << "NLBeamColumn2d::sendSelf() - failed to send ID data\n";
00784     return -1;
00785   }    
00786 
00787   // send the coordinate transformation
00788   
00789   if (theCoordTransf->sendSelf(commitTag, theChannel) < 0) {
00790     opserr << "NLBeamColumn2d::sendSelf() - failed to send crdTranf\n";
00791     return -1;
00792   }      
00793 
00794   //
00795   // send the sections
00796   //
00797   
00798   for (j = 0; j<2; j++) {
00799     if (section[j]->sendSelf(commitTag, theChannel) < 0) {
00800       opserr << "NLBeamColumn2d::sendSelf() - section " << j << "failed to send itself\n";
00801       return -1;
00802     }
00803   }
00804   
00805   // into a vector place distrLoadCommit, rho, UeCommit, Secommit and kvcommit
00806   int secDefSize = 0;
00807   for (i = 0; i < 2; i++)
00808   {
00809      int size = section[i]->getOrder();
00810      secDefSize   += size;
00811   }
00812 
00813   Vector dData(7+3+9+secDefSize); 
00814   loc = 0;
00815 
00816   // place double variables into Vector
00817   dData(loc++) = E;
00818   dData(loc++) = A;
00819   dData(loc++) = I;
00820   dData(loc++) = beta1;
00821   dData(loc++) = beta2;
00822   dData(loc++) = rho;
00823   dData(loc++) = tolerance;
00824   
00825   // put  distrLoadCommit into the Vector
00826   //  for (i=0; i<NL; i++) 
00827   //dData(loc++) = distrLoadcommit(i);
00828 
00829   // place kvcommit into vector
00830   for (i=0; i<3; i++) 
00831     dData(loc++) = qCommit(i);
00832 
00833   // place kvcommit into vector
00834   for (i=0; i<3; i++) 
00835      for (j=0; j<3; j++)
00836         dData(loc++) = kbCommit(i,j);
00837   
00838   // place vscommit into vector
00839   for (k=0; k<2; k++)
00840      for (i=0; i<section[k]->getOrder(); i++)
00841         dData(loc++) = (eCommit[k])(i);
00842 
00843   if (theChannel.sendVector(dbTag, commitTag, dData) < 0) {
00844     opserr << "NLBeamColumn2d::sendSelf() - failed to send Vector data\n";
00845     return -1;
00846   }    
00847 
00848   return 0;
00849 }
00850 
00851 int 
00852 BeamWithHinges2d::recvSelf(int commitTag, Channel &theChannel,
00853                                FEM_ObjectBroker &theBroker)
00854 {
00855   // place the integer data into an ID
00856   int dbTag = this->getDbTag();
00857   int i, j , k;
00858   int loc = 0;
00859   
00860   static ID idData(11);  
00861 
00862   if (theChannel.recvID(dbTag, commitTag, idData) < 0)  {
00863     opserr << "NLBeamColumn2d::recvSelf() - failed to recv ID data\n";
00864     return -1;
00865   }    
00866 
00867   this->setTag(idData(0));
00868   connectedExternalNodes(0) = idData(1);
00869   connectedExternalNodes(1) = idData(2);
00870 
00871   maxIter = idData(5);
00872   initialFlag = idData(6);
00873   
00874   int crdTransfClassTag = idData(3);
00875   int crdTransfDbTag = idData(4);
00876 
00877   // create a new crdTransf object if one needed
00878   if (theCoordTransf == 0 || theCoordTransf->getClassTag() != crdTransfClassTag) {
00879       if (theCoordTransf != 0)
00880           delete theCoordTransf;
00881 
00882       theCoordTransf = theBroker.getNewCrdTransf2d(crdTransfClassTag);
00883 
00884       if (theCoordTransf == 0) {
00885         opserr << "NLBeamColumn2d::recvSelf() - " << 
00886           "failed to obtain a CrdTrans object with classTag" << crdTransfClassTag << endln;
00887       return -2;          
00888       }
00889   }
00890 
00891   theCoordTransf->setDbTag(crdTransfDbTag);
00892 
00893   // invoke recvSelf on the crdTransf obkject
00894   if (theCoordTransf->recvSelf(commitTag, theChannel, theBroker) < 0)  
00895   {
00896     opserr << "NLBeamColumn2d::sendSelf() - failed to recv crdTranf\n";
00897     return -3;
00898   }      
00899 
00900   //
00901   // receive the sections
00902   //
00903 
00904   loc = 5;
00905   if (section[0] == 0) {
00906 
00907     // if no sections yet created, we create new ones and then do a recvSelf
00908     for (i=0; i<2; i++) {
00909       int sectClassTag = idData(loc);
00910       int sectDbTag = idData(loc+1);
00911       loc += 2;
00912       section[i] = theBroker.getNewSection(sectClassTag);
00913       if (section[i] == 0) {
00914         opserr << "NLBeamColumn2d::recvSelf() - " << 
00915           "Broker could not create Section of class type" << sectClassTag << endln;
00916         exit(-1);
00917       }
00918       section[i]->setDbTag(sectDbTag);
00919       if (section[i]->recvSelf(commitTag, theChannel, theBroker) < 0) {
00920         opserr << "NLBeamColumn2d::recvSelf() - section " << i << "failed to recv itself\n";
00921         return -1;
00922       }     
00923     }
00924 
00925     this->setHinges();
00926 
00927   } else {
00928 
00929     // if sections exist, we ensure of correct type and then do a recvSelf
00930     for (i=0; i<2; i++) {
00931 
00932       int sectClassTag = idData(loc);
00933       int sectDbTag = idData(loc+1);
00934       loc += 2;
00935 
00936       // check of correct type
00937       if (section[i]->getClassTag() !=  sectClassTag) {
00938         // delete the old section[i] and create a new one
00939         delete section[i];
00940         section[i] = theBroker.getNewSection(sectClassTag);
00941         if (section[i] == 0) {
00942           opserr << "NLBeamColumn2d::recvSelf() - " <<
00943             "Broker could not create Section of class type" << sectClassTag << endln;
00944           exit(-1);
00945         }
00946       }
00947     
00948       // recvvSelf on it
00949       section[i]->setDbTag(sectDbTag);
00950       if (section[i]->recvSelf(commitTag, theChannel, theBroker) < 0) {
00951         opserr << "NLBeamColumn2d::recvSelf() - section " <<  i << "failed to recv itself\n";
00952         return -1;
00953       }     
00954     }
00955   }
00956 
00957   // into a vector place distrLoadCommit, rho, UeCommit, Secommit and kvcommit
00958   int secDefSize = 0;
00959   for (i = 0; i < 2; i++)
00960   {
00961      int size = section[i]->getOrder();
00962      secDefSize   += size;
00963   }
00964 
00965   Vector dData(7+3+9+secDefSize); 
00966   loc = 0;
00967 
00968   if (theChannel.recvVector(dbTag, commitTag, dData) < 0) {
00969      opserr << "NLBeamColumn2d::sendSelf() - failed to send Vector data\n";
00970      return -1;
00971   }    
00972 
00973   // place double variables into Vector
00974    E = dData(loc++);
00975    A = dData(loc++);
00976    I = dData(loc++);
00977    beta1 = dData(loc++);
00978    beta2 = dData(loc++);
00979    rho = dData(loc++);
00980    tolerance = dData(loc++);
00981   
00982   // place kvcommit into vector
00983   for (i=0; i<3; i++) 
00984     qCommit(i) = dData(loc++);
00985 
00986   // place kvcommit into vector
00987   for (i=0; i<3; i++) 
00988      for (j=0; j<3; j++)
00989         kbCommit(i,j) = dData(loc++);;
00990 
00991   // place vscommit into vector
00992   for (k=0; k<2; k++) 
00993     for (i=0; i<section[k]->getOrder(); i++) 
00994        (eCommit[k])(i) = dData(loc++);
00995 
00996   initialFlag = 2;
00997 
00998   return 0;
00999 }
01000 
01001 void 
01002 BeamWithHinges2d::Print(OPS_Stream &s, int flag)
01003 {
01004   s << "\nBeamWithHinges2d, tag: " << this->getTag() << endln;
01005   s << "\tConnected Nodes: " << connectedExternalNodes;
01006   s << "\tE: " << E << endln;
01007   s << "\tA: " << A << endln;
01008   s << "\tI: " << I << endln;
01009   
01010   double P, V, M1, M2;
01011   double L = theCoordTransf->getInitialLength();
01012   P = qCommit(0);
01013   M1 = qCommit(1);
01014   M2 = qCommit(2);
01015   V = (M1+M2)/L;
01016 
01017   s << "\tEnd 1 Forces (P V M): "
01018     << -P+p0[0] << ' ' <<  V+p0[1] << ' ' << M1 << endln;
01019   s << "\tEnd 2 Forces (P V M): "
01020     <<  P << ' ' << -V+p0[2] << ' ' << M2 << endln;
01021   
01022   if (section[0] != 0) {
01023     s << "Hinge 1, section tag: " << section[0]->getTag() << 
01024       ", length: " << beta1*L << endln;
01025     section[0]->Print(s,flag);
01026   }
01027   
01028   if (section[1] != 0) {
01029     s << "Hinge 2, section tag: " << section[2]->getTag() << 
01030       ", length: " << beta2*L << endln;
01031     section[1]->Print(s,flag);
01032   }
01033 }
01034 
01036 //Private Function Definitions
01037 
01038 void 
01039 BeamWithHinges2d::setNodePtrs(Domain *theDomain)
01040 {
01041   theNodes[0] = theDomain->getNode(connectedExternalNodes(0));
01042   theNodes[1] = theDomain->getNode(connectedExternalNodes(1));
01043   
01044   if(theNodes[0] == 0) {
01045     opserr << "BeamWithHinges2d::setNodePtrs() -- node 1 does not exist\n";
01046     exit(-1);
01047   }
01048   
01049   if(theNodes[1] == 0) {
01050     opserr << "BeamWithHinges2d::setNodePtrs() -- node 2 does not exist\n";
01051     exit(-1);
01052   }
01053   
01054   // check for correct # of DOF's
01055   int dofNd1 = theNodes[0]->getNumberDOF();
01056   int dofNd2 = theNodes[1]->getNumberDOF();
01057   if ((dofNd1 != 3) || (dofNd2 != 3))  {
01058     opserr << "BeamWithHinges2d::setNodePtrs() -- nodal dof is not three";
01059     exit(-1);
01060   }
01061 }
01062 
01063 int
01064 BeamWithHinges2d::update(void)
01065 {
01066   // if have completed a recvSelf() - do a revertToLastCommit
01067   // to get e, kb, etc. set correctly
01068   if (initialFlag == 2)
01069     this->revertToLastCommit();
01070 
01071   // Update the coordinate transformation
01072   theCoordTransf->update();
01073   
01074   // Convert to basic system from local coord's (eliminate rb-modes)
01075   static Vector v(3);                           // basic system deformations
01076   v = theCoordTransf->getBasicTrialDisp();
01077 
01078   static Vector dv(3);
01079   dv = theCoordTransf->getBasicIncrDeltaDisp();
01080 
01081   double L = theCoordTransf->getInitialLength();
01082   double oneOverL = 1.0/L;
01083 
01084   // Section locations along element length ...
01085   double xi[2];
01086 
01087   // and their integration weights
01088   double lp[2];
01089   
01090   lp[0] = beta1*L;
01091   lp[1] = beta2*L;
01092 
01093   xi[0] = 0.5*lp[0];
01094   xi[1] = L-0.5*lp[1];
01095   
01096   // element properties
01097   static Matrix f(3,3); // element flexibility
01098   static Vector vr(3);  // Residual element deformations
01099   
01100   static Matrix Iden(3,3);   // an identity matrix for matrix inverse
01101   Iden.Zero();
01102   for (int i = 0; i < 3; i++)
01103     Iden(i,i) = 1.0;
01104 
01105   // Length of elastic interior
01106   double Le = L-lp[0]-lp[1];
01107   double LoverEA  = Le/(E*A);
01108   double Lover3EI = Le/(3*E*I);
01109   double Lover6EI = 0.5*Lover3EI;
01110   
01111   // Elastic flexibility of element interior
01112   static Matrix fe(2,2);
01113   fe(0,0) = fe(1,1) =  Lover3EI;
01114   fe(0,1) = fe(1,0) = -Lover6EI;
01115   
01116   // Equilibrium transformation matrix
01117   static Matrix B(2,2);
01118   B(0,0) = 1.0 - beta1;
01119   B(1,1) = 1.0 - beta2;
01120   B(0,1) = -beta1;
01121   B(1,0) = -beta2;
01122   
01123   // Transform the elastic flexibility of the element
01124   // interior to the basic system
01125   static Matrix fElastic(2,2);
01126   fElastic.addMatrixTripleProduct(0.0, B, fe, 1.0);
01127 
01128   // calculate nodal force increments and update nodal forces
01129   static Vector dq(3);
01130   //dq = kb * dv;   // using previous stiff matrix k,i
01131   dq.addMatrixVector(0.0, kb, dv, 1.0);
01132 
01133   int converged = 0;
01134   
01135   for (int j = 0; j < maxIter; j++) {
01136     
01137     // q += dq;
01138     q.addVector(1.0, dq, 1.0);
01139     
01140     // Set element flexibility to flexibility of elastic region
01141     f(0,0) = LoverEA;
01142     f(1,1) = fElastic(0,0);
01143     f(2,2) = fElastic(1,1);
01144     f(1,2) = fElastic(0,1);
01145     f(2,1) = fElastic(1,0);
01146     f(0,1) = f(1,0) = f(0,2) = f(2,0) = 0.0;
01147 
01148     // vr = fElastic*q + v0;
01149     vr(0) = LoverEA*q(0) + v0[0];
01150     vr(1) = fElastic(0,0)*q(1) + fElastic(0,1)*q(2) + v0[1];
01151     vr(2) = fElastic(1,0)*q(1) + fElastic(1,1)*q(2) + v0[2];
01152     
01153     for (int i = 0; i < 2; i++) {
01154       
01155       if (section[i] == 0 || lp[i] <= 0.0)
01156         continue;
01157       
01158       // Get section information
01159       int order = section[i]->getOrder();
01160       const ID &code = section[i]->getType();
01161       
01162       Vector s(workArea, order);
01163       Vector ds(&workArea[order], order);
01164       Vector de(&workArea[2*order], order);
01165       
01166       Matrix fb(&workArea[3*order], order, 3);
01167       
01168       double x   = xi[i];
01169       double xL  = x*oneOverL;
01170       double xL1 = xL-1.0;
01171       
01172       int ii;
01173       // Section forces
01174       // s = b*q + bp*w;
01175       //this->getForceInterpMatrix(b, xi[i], code);
01176       //s.addMatrixVector(0.0, b, q, 1.0);
01177       for (ii = 0; ii < order; ii++) {
01178         switch(code(ii)) {
01179         case SECTION_RESPONSE_P:
01180           s(ii) = q(0);
01181           break;
01182         case SECTION_RESPONSE_MZ:
01183           s(ii) = xL1*q(1) + xL*q(2);
01184           break;
01185         case SECTION_RESPONSE_VY:
01186           s(ii) = oneOverL*(q(1)+q(2));
01187           break;
01188         default:
01189           s(ii) = 0.0;
01190           break;
01191         }
01192       }
01193       
01194       // Add the effects of element loads, if present
01195       if (sp != 0) {
01196         const Matrix &s_p = *sp;
01197         for (ii = 0; ii < order; ii++) {
01198           switch(code(ii)) {
01199           case SECTION_RESPONSE_P:
01200             s(ii) += s_p(0,i);
01201             break;
01202           case SECTION_RESPONSE_MZ:
01203             s(ii) += s_p(1,i);
01204             break;
01205           case SECTION_RESPONSE_VY:
01206             s(ii) += s_p(2,i);
01207             break;
01208           default:
01209             break;
01210           }
01211         }
01212       }
01213 
01214       // Increment in section forces
01215       // ds = s - sr
01216       ds = s;
01217       ds.addVector(1.0, sr[i], -1.0);
01218       
01219       // compute section deformation increments and update current deformations
01220       // e += fs * ds;
01221       de.addMatrixVector(0.0, fs[i], ds, 1.0);
01222       if (initialFlag != 0)
01223         e[i].addVector(1.0, de, 1.0);
01224       
01225       // set section deformations
01226       section[i]->setTrialSectionDeformation(e[i]);
01227       
01228       // get section resisting forces
01229       sr[i] = section[i]->getStressResultant();
01230       
01231       // get section flexibility matrix
01232       fs[i] = section[i]->getSectionFlexibility();
01233       
01234       // ds = s - sr;
01235       ds = s;
01236       ds.addVector(1.0, sr[i], -1.0);
01237       
01238       de.addMatrixVector(0.0, fs[i], ds, 1.0);
01239       
01240       // integrate section flexibility matrix
01241       // f += (b^ fs * b) * lp[i];
01242       //f.addMatrixTripleProduct(1.0, b, fSec, lp[i]);
01243       int jj;
01244       fb.Zero();
01245       double tmp;
01246       const Matrix &fSec = fs[i];
01247       for (ii = 0; ii < order; ii++) {
01248         switch(code(ii)) {
01249         case SECTION_RESPONSE_P:
01250           for (jj = 0; jj < order; jj++)
01251             fb(jj,0) += fSec(jj,ii)*lp[i];
01252           break;
01253         case SECTION_RESPONSE_MZ:
01254           for (jj = 0; jj < order; jj++) {
01255             tmp = fSec(jj,ii)*lp[i];
01256             fb(jj,1) += xL1*tmp;
01257             fb(jj,2) += xL*tmp;
01258           }
01259           break;
01260         case SECTION_RESPONSE_VY:
01261           for (jj = 0; jj < order; jj++) {
01262             //tmp = oneOverL*fSec(jj,ii)*lp[i]*L/lp[i];
01263             tmp = fSec(jj,ii);
01264             fb(jj,1) += tmp;
01265             fb(jj,2) += tmp;
01266           }
01267           break;
01268         default:
01269           break;
01270         }
01271       }
01272       for (ii = 0; ii < order; ii++) {
01273         switch (code(ii)) {
01274         case SECTION_RESPONSE_P:
01275           for (jj = 0; jj < 3; jj++)
01276             f(0,jj) += fb(ii,jj);
01277           break;
01278         case SECTION_RESPONSE_MZ:
01279           for (jj = 0; jj < 3; jj++) {
01280             tmp = fb(ii,jj);
01281             f(1,jj) += xL1*tmp;
01282             f(2,jj) += xL*tmp;
01283           }
01284           break;
01285         case SECTION_RESPONSE_VY:
01286           for (jj = 0; jj < 3; jj++) {
01287             tmp = oneOverL*fb(ii,jj);
01288             f(1,jj) += tmp;
01289             f(2,jj) += tmp;
01290           }
01291           break;
01292         default:
01293           break;
01294         }
01295       }
01296            
01297       // UNCOMMENT WHEN DISTRIBUTED LOADS ARE ADDED TO INTERFACE
01298       // vr.addMatrixVector(1.0, vElastic, currDistrLoad, 1.0);
01299       
01300       // vr += (b^ (e+de)) * lp[i];
01301       de.addVector(1.0, e[i], 1.0);
01302       //vr.addMatrixTransposeVector(1.0, b, de, lp[i]);
01303       for (ii = 0; ii < order; ii++) {
01304         switch(code(ii)) {
01305         case SECTION_RESPONSE_P:
01306           vr(0) += de(ii)*lp[i]; break;
01307         case SECTION_RESPONSE_MZ:
01308           tmp = de(ii)*lp[i];
01309           vr(1) += xL1*tmp; vr(2) += xL*tmp; break;
01310         case SECTION_RESPONSE_VY:
01311           //tmp = oneOverL*de(ii)*lp[i]*L/lp[i];
01312           tmp = de(ii);
01313           vr(1) += tmp; vr(2) += tmp; break;
01314         default:
01315           break;
01316         }
01317       }
01318     }
01319   
01320     // calculate element stiffness matrix
01321     //invert3by3Matrix(f, kb);
01322     if (f.Solve(Iden,kb) < 0)
01323       opserr << "BeamWithHinges2d::update() -- could not invert flexibility\n";
01324                               
01325 
01326     // dv = v - vr;
01327     dv = v;
01328     dv.addVector(1.0, vr, -1.0);
01329 
01330     
01331     // determine resisting forces
01332     // dq = kb * dv;
01333     dq.addMatrixVector(0.0, kb, dv, 1.0);
01334 
01335     double dW = dv^ dq;
01336 
01337     if (fabs(dW) < tolerance) 
01338       break;
01339     
01340     if ((maxIter != 1) && (j == (maxIter - 1))) {
01341       converged = -1;
01342     }
01343   }
01344 
01345   // q += dq;
01346   q.addVector(1.0, dq, 1.0);
01347 
01348   initialFlag = 1;
01349   
01350   return 0;
01351 }
01352 
01353 void
01354 BeamWithHinges2d::setHinges(void)
01355 {
01356   for (int i = 0; i < 2; i++) {
01357     if (section[i] == 0)
01358       continue;
01359     
01360     // Get the number of section response quantities
01361     int order = section[i]->getOrder();
01362     
01363     fs[i] = Matrix(order,order);
01364     e[i]  = Vector(order);
01365     sr[i] = Vector(order);
01366     eCommit[i] = Vector(order);    
01367   }
01368 }
01369 
01370 void
01371 BeamWithHinges2d::getForceInterpMatrix(Matrix &b, double x, const ID &code)
01372 {                       
01373   b.Zero();
01374   
01375   double L = theCoordTransf->getInitialLength();
01376   double xi = x/L;
01377   
01378   for (int i = 0; i < code.Size(); i++) {
01379     switch (code(i)) {
01380     case SECTION_RESPONSE_MZ:           // Moment, Mz, interpolation
01381       b(i,1) = xi - 1.0;
01382       b(i,2) = xi;
01383       break;
01384     case SECTION_RESPONSE_P:            // Axial, P, interpolation
01385       b(i,0) = 1.0;
01386       break;
01387     case SECTION_RESPONSE_VY:           // Shear, Vy, interpolation
01388       b(i,1) = b(i,2) = 1.0/L;
01389       break;
01390     default:
01391       break;
01392     }
01393   }
01394 }
01395 
01396 void
01397 BeamWithHinges2d::getDistrLoadInterpMatrix(Matrix &bp, double x, const ID & code)
01398 {
01399   bp.Zero();
01400 
01401   double L = theCoordTransf->getInitialLength();
01402   double xi = x/L;
01403   
01404   for (int i = 0; i < code.Size(); i++) {
01405     switch (code(i)) {
01406     case SECTION_RESPONSE_MZ:           // Moment, Mz, interpolation
01407       bp(i,1) = 0.5*xi*(xi-1);
01408       break;
01409     case SECTION_RESPONSE_P:            // Axial, P, interpolation
01410       bp(i,0) = 1.0-xi;
01411       break;
01412     case SECTION_RESPONSE_VY:           // Shear, Vy, interpolation
01413       bp(i,1) = xi-0.5;
01414       break;
01415     default:
01416       break;
01417     }
01418   }
01419 }
01420 
01421 Response*
01422 BeamWithHinges2d::setResponse(const char **argv, int argc, Information &info)
01423 {
01424   // hinge rotations
01425   if (strcmp(argv[0],"plasticDeformation") == 0 ||
01426       strcmp(argv[0],"plasticRotation") == 0)
01427     return new ElementResponse(this, 1, Vector(3));
01428   
01429   // global forces
01430   else if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0 ||
01431            strcmp(argv[0],"globalForce") == 0 || strcmp(argv[0],"globalForces") == 0)
01432     return new ElementResponse(this, 2, theVector);
01433   
01434   // stiffness
01435   else if (strcmp(argv[0],"stiffness") == 0)
01436     return new ElementResponse(this, 3, theMatrix);
01437   
01438   // local forces
01439   else if (strcmp(argv[0],"localForce") == 0 || strcmp(argv[0],"localForces") == 0)
01440     return new ElementResponse(this, 4, theVector);
01441   
01442   // section response
01443   else if (strcmp(argv[0],"section") == 0) {
01444     int sectionNum = atoi(argv[1]) - 1;
01445     
01446     if (sectionNum >= 0 && sectionNum < 2)
01447       if (section[sectionNum] != 0)
01448         return section[sectionNum]->setResponse(&argv[2], argc-2, info);
01449     return 0;
01450   }
01451   else
01452     return 0;
01453 }
01454 
01455 int
01456 BeamWithHinges2d::getResponse(int responseID, Information &eleInfo)
01457 {
01458   double V;
01459   double L = theCoordTransf->getInitialLength();
01460   static Vector force(6);
01461   static Vector def(3);
01462   
01463   switch (responseID) {
01464   case 1: {
01465     const Vector &v = theCoordTransf->getBasicTrialDisp();
01466     double LoverEA  = L/(E*A);
01467     double Lover3EI = L/(3*E*I);
01468     double Lover6EI = 0.5*Lover3EI;
01469 
01470     double q1 = qCommit(1);
01471     double q2 = qCommit(2);
01472 
01473     def(0) = v(0) - LoverEA*qCommit(0);
01474     def(1) = v(1) - Lover3EI*q1 + Lover6EI*q2;
01475     def(2) = v(2) + Lover6EI*q1 - Lover3EI*q2;
01476     
01477     return eleInfo.setVector(def);
01478   }
01479   
01480   case 2: // global forces
01481     return eleInfo.setVector(this->getResistingForce());
01482     
01483   case 3: // stiffness
01484     return eleInfo.setMatrix(this->getTangentStiff());
01485     
01486   case 4: // local forces
01487     // Axial
01488     force(3) =  q(0);
01489     force(0) = -q(0)+p0[0];
01490     // Moment
01491     force(2) = q(1);
01492     force(5) = q(2);
01493     // Shear
01494     V = (q(1)+q(2))/L;
01495     force(1) =  V+p0[1];
01496     force(4) = -V+p0[2];
01497     return eleInfo.setVector(force);
01498     
01499   default:
01500     return -1;
01501   }
01502 }
01503 
01504 int
01505 BeamWithHinges2d::displaySelf(Renderer &theViewer, int displayMode, float fact)
01506 {
01507   // first determine the end points of the quad based on
01508   // the display factor (a measure of the distorted image)
01509   const Vector &end1Crd = theNodes[0]->getCrds();
01510   const Vector &end2Crd = theNodes[1]->getCrds();       
01511   
01512   const Vector &end1Disp = theNodes[0]->getDisp();
01513   const Vector &end2Disp = theNodes[1]->getDisp();
01514   
01515   static Vector v1(3);
01516   static Vector v2(3);
01517   
01518   for (int i = 0; i < 2; i++) {
01519     v1(i) = end1Crd(i) + end1Disp(i)*fact;
01520     v2(i) = end2Crd(i) + end2Disp(i)*fact;    
01521   }
01522   
01523   return theViewer.drawLine (v1, v2, 1.0, 1.0);
01524 }
01525 
01526 int
01527 BeamWithHinges2d::setParameter(const char **argv, int argc, Information &info)
01528 {
01529   // E of the beam interior
01530   if (strcmp(argv[0],"E") == 0) {
01531     info.theType = DoubleType;
01532     return 1;
01533   }
01534   
01535   // A of the beam interior
01536   else if (strcmp(argv[0],"A") == 0) {
01537     info.theType = DoubleType;
01538     return 3;
01539   }
01540   
01541   // I of the beam interior
01542   else if (strcmp(argv[0],"I") == 0) {
01543     info.theType = DoubleType;
01544     return 4;
01545   }
01546   
01547   // Section parameter
01548   else if (strcmp(argv[0],"section") ==0) {
01549     if (argc <= 2)
01550       return -1;
01551     
01552     int sectionNum = atoi(argv[1]);
01553     
01554     int ok = -1;
01555     
01556     if (sectionNum == 1)
01557       ok = section[0]->setParameter (&argv[2], argc-2, info);
01558     if (sectionNum == 2)
01559       ok = section[1]->setParameter (&argv[2], argc-2, info);
01560     
01561     if (ok < 0)
01562       return -1;
01563     else if (ok < 100)
01564       return sectionNum*100 + ok;
01565     else 
01566       return -1;
01567   }
01568   
01569   // Unknown parameter
01570   else
01571     return -1;
01572 }       
01573 
01574 int
01575 BeamWithHinges2d::updateParameter(int parameterID, Information &info)
01576 {
01577   switch (parameterID) {
01578   case 1:
01579     this->E = info.theDouble;
01580     return 0;
01581   case 3:
01582     this->A = info.theDouble;
01583     return 0;
01584   case 4:
01585     this->I = info.theDouble;
01586     return 0;
01587   default:
01588     if (parameterID >= 100) { // section quantity
01589       int sectionNum = parameterID/100; 
01590       if (sectionNum == 1)
01591         return section[0]->updateParameter (parameterID-100, info);
01592       if (sectionNum == 2)
01593         return section[1]->updateParameter (parameterID-2*100, info);
01594       else
01595         return -1;
01596     }
01597     else // unknown
01598       return -1;
01599   }     
01600 }       

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