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