00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <ZeroLengthSection.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 <SectionForceDeformation.h>
00039 #include <Renderer.h>
00040 #include <ElementResponse.h>
00041
00042 #include <math.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045
00046 Matrix ZeroLengthSection::K6(6,6);
00047 Matrix ZeroLengthSection::K12(12,12);
00048
00049 Vector ZeroLengthSection::P6(6);
00050 Vector ZeroLengthSection::P12(12);
00051
00052
00053
00054
00055
00056 ZeroLengthSection::ZeroLengthSection(int tag, int dim, int Nd1, int Nd2,
00057 const Vector& x, const Vector& yprime,
00058 SectionForceDeformation& sec) :
00059 Element(tag, ELE_TAG_ZeroLengthSection),
00060 connectedExternalNodes(2),
00061 dimension(dim), numDOF(0),
00062 transformation(3,3), A(0), v(0), K(0), P(0),
00063 theSection(0), order(0)
00064 {
00065
00066 theSection = sec.getCopy();
00067
00068 if (theSection == 0) {
00069 opserr << "ZeroLengthSection::ZeroLengthSection -- failed to get copy of section\n";
00070 exit(-1);
00071 }
00072
00073
00074 order = theSection->getOrder();
00075
00076
00077 this->setUp(Nd1, Nd2, x, yprime);
00078 }
00079
00080 ZeroLengthSection::ZeroLengthSection() :
00081 Element(0, ELE_TAG_ZeroLengthSection),
00082 connectedExternalNodes(2),
00083 dimension(0), numDOF(0),
00084 transformation(3,3), A(0), v(0), K(0), P(0),
00085 theSection(0), order(0)
00086 {
00087
00088 }
00089
00090 ZeroLengthSection::~ZeroLengthSection()
00091 {
00092
00093
00094
00095 if (theSection != 0)
00096 delete theSection;
00097 if (A != 0)
00098 delete A;
00099 if (v != 0)
00100 delete v;
00101 }
00102
00103 int
00104 ZeroLengthSection::getNumExternalNodes(void) const
00105 {
00106 return 2;
00107 }
00108
00109 const ID &
00110 ZeroLengthSection::getExternalNodes(void)
00111 {
00112 return connectedExternalNodes;
00113 }
00114
00115 Node **
00116 ZeroLengthSection::getNodePtrs(void)
00117 {
00118 return theNodes;
00119 }
00120
00121 int
00122 ZeroLengthSection::getNumDOF(void)
00123 {
00124 return numDOF;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133 void
00134 ZeroLengthSection::setDomain(Domain *theDomain)
00135 {
00136
00137 if (theDomain == 0) {
00138 theNodes[0] = 0;
00139 theNodes[1] = 0;
00140 return;
00141 }
00142
00143
00144 int Nd1 = connectedExternalNodes(0);
00145 int Nd2 = connectedExternalNodes(1);
00146 theNodes[0] = theDomain->getNode(Nd1);
00147 theNodes[1] = theDomain->getNode(Nd2);
00148
00149
00150 if (theNodes[0] == 0 || theNodes[1] == 0) {
00151 if (theNodes[0] == 0)
00152 opserr << "ZeroLengthSection::setDomain() -- Nd2: " << Nd2 << " does not exist in ";
00153 else
00154 opserr << "ZeroLengthSection::setDomain() -- Nd2: " << Nd2 << " does not exist in ";
00155
00156 opserr << "model for ZeroLengthSection with id " << this->getTag() << endln;
00157
00158 return;
00159 }
00160
00161
00162 int dofNd1 = theNodes[0]->getNumberDOF();
00163 int dofNd2 = theNodes[1]->getNumberDOF();
00164
00165
00166 if (dofNd1 != dofNd2) {
00167 opserr << "ZeroLengthSection::setDomain() -- nodes " << Nd1 << " and " << Nd2 <<
00168 "have differing dof at ends for ZeroLengthSection " << this->getTag() << endln;
00169 return;
00170 }
00171
00172 numDOF = 2*dofNd1;
00173
00174 if (numDOF != 6 && numDOF != 12)
00175 opserr << "ZeroLengthSection::setDomain() -- element only works for 3 (2d) or 6 (3d) dof per node\n";
00176
00177
00178 if (numDOF == 6) {
00179 P = &P6;
00180 K = &K6;
00181 }
00182 else {
00183 P = &P12;
00184 K = &K12;
00185 }
00186
00187
00188 const Vector &end1Crd = theNodes[0]->getCrds();
00189 const Vector &end2Crd = theNodes[1]->getCrds();
00190 const Vector diff = end1Crd - end2Crd;
00191 double L = diff.Norm();
00192 double v1 = end1Crd.Norm();
00193 double v2 = end2Crd.Norm();
00194 double vm;
00195
00196 vm = (v1<v2) ? v2 : v1;
00197
00198 if (L > LENTOL*vm)
00199 opserr << "ZeroLengthSection::setDomain() -- Element " << this->getTag() <<
00200 "has L= " << L << ", which is greater than the tolerance\n";
00201
00202
00203
00204 this->DomainComponent::setDomain(theDomain);
00205
00206
00207 this->setTransformation();
00208 }
00209
00210 int
00211 ZeroLengthSection::commitState()
00212 {
00213 int retVal=0;
00214
00215
00216 if ((retVal = this->Element::commitState()) != 0) {
00217 opserr << "ZeroLength::commitState () - failed in base class\n";
00218 }
00219
00220 retVal += theSection->commitState();
00221 return retVal;
00222 }
00223
00224 int
00225 ZeroLengthSection::revertToLastCommit()
00226 {
00227
00228 return theSection->revertToLastCommit();
00229 }
00230
00231 int
00232 ZeroLengthSection::revertToStart()
00233 {
00234
00235 return theSection->revertToStart();
00236 }
00237
00238 const Matrix &
00239 ZeroLengthSection::getTangentStiff(void)
00240 {
00241
00242 this->computeSectionDefs();
00243
00244
00245 theSection->setTrialSectionDeformation(*v);
00246
00247
00248 const Matrix &kb = theSection->getSectionTangent();
00249
00250
00251 K->addMatrixTripleProduct(0.0, *A, kb, 1.0);
00252
00253 return *K;
00254 }
00255
00256 const Matrix &
00257 ZeroLengthSection::getInitialStiff(void)
00258 {
00259
00260 const Matrix &kb = theSection->getInitialTangent();
00261
00262
00263 K->addMatrixTripleProduct(0.0, *A, kb, 1.0);
00264
00265 return *K;
00266 }
00267
00268 void
00269 ZeroLengthSection::zeroLoad(void)
00270 {
00271
00272 }
00273
00274 int
00275 ZeroLengthSection::addLoad(ElementalLoad *theLoad, double loadFactor)
00276 {
00277 opserr << "ZeroLengthSection::addLoad - load type unknown for truss with tag: " << this->getTag() << endln;
00278 return -1;
00279 }
00280
00281
00282 int
00283 ZeroLengthSection::addInertiaLoadToUnbalance(const Vector &accel)
00284 {
00285
00286 return 0;
00287 }
00288
00289 const Vector &
00290 ZeroLengthSection::getResistingForce()
00291 {
00292
00293 this->computeSectionDefs();
00294
00295
00296 theSection->setTrialSectionDeformation(*v);
00297
00298
00299 const Vector &q = theSection->getStressResultant();
00300
00301
00302 P->addMatrixTransposeVector(0.0, *A, q, 1.0);
00303
00304 return *P;
00305 }
00306
00307
00308 const Vector &
00309 ZeroLengthSection::getResistingForceIncInertia()
00310 {
00311 this->getResistingForce();
00312
00313
00314 if (betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00315 *P += this->getRayleighDampingForces();
00316
00317 return *P;
00318 }
00319
00320
00321 int
00322 ZeroLengthSection::sendSelf(int commitTag, Channel &theChannel)
00323 {
00324 int res = 0;
00325
00326
00327
00328
00329 int dataTag = this->getDbTag();
00330
00331
00332
00333 static ID idData(8);
00334
00335 idData(0) = this->getTag();
00336 idData(1) = dimension;
00337 idData(2) = numDOF;
00338 idData(3) = order;
00339 idData(4) = connectedExternalNodes(0);
00340 idData(5) = connectedExternalNodes(1);
00341 idData(6) = theSection->getClassTag();
00342
00343 int secDbTag = theSection->getDbTag();
00344 if (secDbTag == 0) {
00345 secDbTag = theChannel.getDbTag();
00346 if (secDbTag != 0)
00347 theSection->setDbTag(secDbTag);
00348 }
00349 idData(7) = secDbTag;
00350
00351 res += theChannel.sendID(dataTag, commitTag, idData);
00352 if (res < 0) {
00353 opserr << "ZeroLengthSection::sendSelf -- failed to send ID data\n";
00354
00355 return res;
00356 }
00357
00358
00359
00360 res += theChannel.sendMatrix(dataTag, commitTag, transformation);
00361 if (res < 0) {
00362 opserr << "ZeroLengthSection::sendSelf -- failed to send transformation Matrix\n";
00363 return res;
00364 }
00365
00366
00367 res += theSection->sendSelf(commitTag, theChannel);
00368 if (res < 0) {
00369 opserr << "ZeroLengthSection::sendSelf -- failed to send Section\n";
00370 return res;
00371 }
00372
00373 return res;
00374 }
00375
00376 int
00377 ZeroLengthSection::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00378 {
00379 int res = 0;
00380
00381 int dataTag = this->getDbTag();
00382
00383
00384
00385
00386 static ID idData(8);
00387
00388 res += theChannel.recvID(dataTag, commitTag, idData);
00389 if (res < 0) {
00390 opserr << "ZeroLengthSection::recvSelf -- failed to receive ID data\n";
00391 return res;
00392 }
00393
00394 res += theChannel.recvMatrix(dataTag, commitTag, transformation);
00395 if (res < 0) {
00396 opserr << "ZeroLengthSection::recvSelf -- failed to receive transformation Matrix\n";
00397 return res;
00398 }
00399
00400 this->setTag(idData(0));
00401 dimension = idData(1);
00402 numDOF = idData(2);
00403 connectedExternalNodes(0) = idData(4);
00404 connectedExternalNodes(1) = idData(5);
00405
00406
00407 if (order != idData(3)) {
00408
00409 order = idData(3);
00410
00411
00412 if (A != 0)
00413 delete A;
00414
00415 A = new Matrix(order, numDOF);
00416
00417 if (A == 0) {
00418 opserr << "ZeroLengthSection::recvSelf -- failed to allocate transformation Matrix\n";
00419 exit(-1);
00420 }
00421
00422
00423 if (v != 0)
00424 delete v;
00425
00426 v = new Vector(order);
00427
00428 if (v == 0) {
00429 opserr << "ZeroLengthSection::recvSelf -- failed to allocate deformation Vector\n";
00430 exit(-1);
00431 }
00432
00433 if (numDOF == 6) {
00434 P = &P6;
00435 K = &K6;
00436 }
00437 else {
00438 P = &P12;
00439 K = &K12;
00440 }
00441 }
00442
00443 int secClassTag = idData(6);
00444
00445
00446 if (theSection == 0)
00447 theSection = theBroker.getNewSection(secClassTag);
00448
00449
00450 if (theSection->getClassTag() != secClassTag) {
00451 delete theSection;
00452 theSection = theBroker.getNewSection(secClassTag);
00453 }
00454
00455
00456 if (theSection == 0) {
00457 opserr << "ZeroLengthSection::recvSelf -- failed to allocate new Section\n";
00458 return -1;
00459 }
00460
00461
00462 theSection->setDbTag(idData(7));
00463 res += theSection->recvSelf(commitTag, theChannel, theBroker);
00464 if (res < 0) {
00465 opserr << "ZeroLengthSection::recvSelf -- failed to receive Section\n";
00466 return res;
00467 }
00468
00469 return res;
00470 }
00471
00472 int
00473 ZeroLengthSection::displaySelf(Renderer &theViewer, int displayMode, float fact)
00474 {
00475
00476 if (theNodes[0] == 0 || theNodes[1] == 0)
00477 return 0;
00478
00479
00480
00481
00482 const Vector &end1Crd = theNodes[0]->getCrds();
00483 const Vector &end2Crd = theNodes[1]->getCrds();
00484 const Vector &end1Disp = theNodes[0]->getDisp();
00485 const Vector &end2Disp = theNodes[1]->getDisp();
00486
00487 if (displayMode == 1 || displayMode == 2) {
00488 static Vector v1(3);
00489 static Vector v2(3);
00490 for (int i = 0; i < dimension; i++) {
00491 v1(i) = end1Crd(i)+end1Disp(i)*fact;
00492 v2(i) = end2Crd(i)+end2Disp(i)*fact;
00493 }
00494
00495 return theViewer.drawLine(v1, v2, 0.0, 0.0);
00496 }
00497
00498 return 0;
00499 }
00500
00501 void
00502 ZeroLengthSection::Print(OPS_Stream &s, int flag)
00503 {
00504 s << "ZeroLengthSection, tag: " << this->getTag() << endln;
00505 s << "\tConnected Nodes: " << connectedExternalNodes << endln;
00506 s << "\tSection, tag: " << theSection->getTag() << endln;
00507 }
00508
00509 Response*
00510 ZeroLengthSection::setResponse(const char **argv, int argc, Information &eleInformation, OPS_Stream &output)
00511 {
00512 Response *theResponse = 0;
00513
00514 output.tag("ElementOutput");
00515 output.attr("eleType","ZeroLengthSection");
00516 output.attr("eleTag",this->getTag());
00517 output.attr("node1",connectedExternalNodes[0]);
00518 output.attr("node2",connectedExternalNodes[1]);
00519
00520 char outputData[5];
00521
00522 if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0) {
00523
00524 for (int i=0; i<P->Size(); i++) {
00525 sprintf(outputData,"P%d",i+1);
00526 output.tag("ResponseType",outputData);
00527 }
00528 theResponse = new ElementResponse(this, 1, *P);
00529
00530 } else if (strcmp(argv[0],"defo") == 0 || strcmp(argv[0],"deformations") == 0 ||
00531 strcmp(argv[0],"deformation") == 0) {
00532
00533 for (int i=0; i<order; i++) {
00534 sprintf(outputData,"e%d",i+1);
00535 output.tag("ResponseType",outputData);
00536 }
00537
00538 theResponse = new ElementResponse(this, 3, Vector(order));
00539
00540 } else if (strcmp(argv[0],"section") == 0) {
00541 theResponse = theSection->setResponse(&argv[1], argc-1, eleInformation, output);
00542 }
00543
00544 output.endTag();
00545 return theResponse;
00546
00547 }
00548
00549 int
00550 ZeroLengthSection::getResponse(int responseID, Information &eleInfo)
00551 {
00552 switch (responseID) {
00553 case 1:
00554 return eleInfo.setVector(this->getResistingForce());
00555
00556 case 2:
00557 return eleInfo.setMatrix(this->getTangentStiff());
00558
00559 case 3:
00560 this->computeSectionDefs();
00561 return eleInfo.setVector(*v);
00562
00563 default:
00564 return -1;
00565 }
00566 }
00567
00568
00569
00570
00571
00572
00573 void
00574 ZeroLengthSection::setUp(int Nd1, int Nd2, const Vector &x, const Vector &yp)
00575 {
00576
00577 if (connectedExternalNodes.Size() != 2) {
00578 opserr << "ZeroLengthSection::setUp -- failed to create an ID of correct size\n";
00579 exit(-1);
00580 }
00581
00582 connectedExternalNodes(0) = Nd1;
00583 connectedExternalNodes(1) = Nd2;
00584
00585 int i;
00586 for (i=0; i<2; i++)
00587 theNodes[i] = 0;
00588
00589
00590 if ( x.Size() != 3 || yp.Size() != 3 )
00591 opserr << "ZeroLengthSection::setUp -- incorrect dimension of orientation vectors\n";
00592
00593
00594
00595
00596 static Vector z(3);
00597 z(0) = x(1)*yp(2) - x(2)*yp(1);
00598 z(1) = x(2)*yp(0) - x(0)*yp(2);
00599 z(2) = x(0)*yp(1) - x(1)*yp(0);
00600
00601
00602 static Vector y(3);
00603 y(0) = z(1)*x(2) - z(2)*x(1);
00604 y(1) = z(2)*x(0) - z(0)*x(2);
00605 y(2) = z(0)*x(1) - z(1)*x(0);
00606
00607
00608 double xn = x.Norm();
00609 double yn = y.Norm();
00610 double zn = z.Norm();
00611
00612
00613 if (xn == 0 || yn == 0 || zn == 0)
00614 opserr << "ZeroLengthSection::setUp -- invalid vectors to constructor\n";
00615
00616
00617 for (i = 0; i < 3; i++) {
00618 transformation(0,i) = x(i)/xn;
00619 transformation(1,i) = y(i)/yn;
00620 transformation(2,i) = z(i)/zn;
00621 }
00622 }
00623
00624
00625 void
00626 ZeroLengthSection::setTransformation(void)
00627 {
00628
00629 if (A != 0)
00630 delete A;
00631
00632 A = new Matrix(order, numDOF);
00633
00634 if (A == 0)
00635 opserr << "ZeroLengthSection::setTransformation -- failed to allocate transformation Matrix\n";
00636
00637
00638
00639 if (v != 0)
00640 delete v;
00641
00642 v = new Vector(order);
00643
00644
00645 const ID &code = theSection->getType();
00646
00647
00648 Matrix &tran = *A;
00649
00650 tran.Zero();
00651
00652
00653 for (int i = 0; i < order; i++) {
00654
00655
00656 switch(code(i)) {
00657
00658
00659 case SECTION_RESPONSE_MZ:
00660 if (numDOF == 6) {
00661 tran(i,3) = 0.0;
00662 tran(i,4) = 0.0;
00663 tran(i,5) = transformation(2,2);
00664 }
00665 else if (numDOF == 12) {
00666 tran(i,9) = transformation(2,0);
00667 tran(i,10) = transformation(2,1);
00668 tran(i,11) = transformation(2,2);
00669 }
00670 break;
00671 case SECTION_RESPONSE_P:
00672 if (numDOF == 6) {
00673 tran(i,3) = transformation(0,0);
00674 tran(i,4) = transformation(0,1);
00675 tran(i,5) = 0.0;
00676 }
00677 else if (numDOF == 12) {
00678 tran(i,6) = transformation(0,0);
00679 tran(i,7) = transformation(0,1);
00680 tran(i,8) = transformation(0,2);
00681 }
00682 break;
00683 case SECTION_RESPONSE_VY:
00684 if (numDOF == 6) {
00685 tran(i,3) = transformation(1,0);
00686 tran(i,4) = transformation(1,1);
00687 tran(i,5) = 0.0;
00688 }
00689 else if (numDOF == 12) {
00690 tran(i,6) = transformation(1,0);
00691 tran(i,7) = transformation(1,1);
00692 tran(i,8) = transformation(1,2);
00693 }
00694 break;
00695
00696
00697 case SECTION_RESPONSE_MY:
00698 if (numDOF == 12) {
00699 tran(i,9) = transformation(1,0);
00700 tran(i,10) = transformation(1,1);
00701 tran(i,11) = transformation(1,2);
00702 }
00703 break;
00704 case SECTION_RESPONSE_VZ:
00705 if (numDOF == 12) {
00706 tran(i,6) = transformation(2,0);
00707 tran(i,7) = transformation(2,1);
00708 tran(i,8) = transformation(2,2);
00709 }
00710 break;
00711 case SECTION_RESPONSE_T:
00712 if (numDOF == 12) {
00713 tran(i,9) = transformation(0,0);
00714 tran(i,10) = transformation(0,1);
00715 tran(i,11) = transformation(0,2);
00716 }
00717 break;
00718 default:
00719 break;
00720 }
00721
00722
00723 for (int j = 0; j < numDOF/2; j++ )
00724 tran(i,j) = -tran(i,j+numDOF/2);
00725 }
00726 }
00727
00728 void
00729 ZeroLengthSection::computeSectionDefs(void)
00730 {
00731
00732 const Vector &u1 = theNodes[0]->getTrialDisp();
00733 const Vector &u2 = theNodes[1]->getTrialDisp();
00734
00735
00736 const Vector diff = u2 - u1;
00737
00738
00739 Vector &def = *v;
00740 const Matrix &tran = *A;
00741
00742 def.Zero();
00743
00744
00745 for (int i = 0; i < order; i++)
00746 for (int j = 0; j < numDOF/2; j++)
00747 def(i) += -diff(j)*tran(i,j);
00748 }