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