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 <G3Globals.h>
00041
00042 #include <math.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045
00046 #include <ElementResponse.h>
00047
00048 Matrix CorotTruss::M2(2,2);
00049 Matrix CorotTruss::M4(4,4);
00050 Matrix CorotTruss::M6(6,6);
00051 Matrix CorotTruss::M12(12,12);
00052
00053 Vector CorotTruss::V2(2);
00054 Vector CorotTruss::V4(4);
00055 Vector CorotTruss::V6(6);
00056 Vector CorotTruss::V12(12);
00057
00058
00059
00060
00061 CorotTruss::CorotTruss(int tag, int dim,
00062 int Nd1, int Nd2,
00063 UniaxialMaterial &theMat,
00064 double a, double rho)
00065 :Element(tag,ELE_TAG_CorotTruss),
00066 theMaterial(0), connectedExternalNodes(2),
00067 numDOF(0), numDIM(dim),
00068 Lo(0.0), Ln(0.0), R(3,3),
00069 A(a), M(rho), end1Ptr(0), end2Ptr(0),
00070 theMatrix(0), theVector(0)
00071 {
00072
00073 theMaterial = theMat.getCopy();
00074 if (theMaterial == 0)
00075 g3ErrorHandler->fatal("FATAL CorotTruss::CorotTruss - %d %s %d\n", tag,
00076 "failed to get a copy of material with tag ",
00077 theMat.getTag());
00078
00079
00080 if (connectedExternalNodes.Size() != 2)
00081 g3ErrorHandler->fatal("FATAL CorotTruss::CorotTruss - %d %s\n", tag,
00082 "failed to create an ID of size 2");
00083
00084 connectedExternalNodes(0) = Nd1;
00085 connectedExternalNodes(1) = Nd2;
00086 }
00087
00088
00089
00090
00091 CorotTruss::CorotTruss()
00092 :Element(0,ELE_TAG_CorotTruss),
00093 theMaterial(0),connectedExternalNodes(2),
00094 numDOF(0), numDIM(0),
00095 Lo(0.0), Ln(0.0), R(3,3),
00096 A(0.0), M(0.0), end1Ptr(0), end2Ptr(0),
00097 theMatrix(0), theVector(0)
00098 {
00099
00100 if (connectedExternalNodes.Size() != 2)
00101 g3ErrorHandler->fatal("FATAL CorotTruss::CorotTruss - %s\n",
00102 "failed to create an ID of size 2");
00103 }
00104
00105
00106
00107
00108 CorotTruss::~CorotTruss()
00109 {
00110
00111
00112 if (theMaterial != 0)
00113 delete theMaterial;
00114 }
00115
00116 int
00117 CorotTruss::getNumExternalNodes(void) const
00118 {
00119 return 2;
00120 }
00121
00122 const ID &
00123 CorotTruss::getExternalNodes(void)
00124 {
00125 return connectedExternalNodes;
00126 }
00127
00128 int
00129 CorotTruss::getNumDOF(void)
00130 {
00131 return numDOF;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140 void
00141 CorotTruss::setDomain(Domain *theDomain)
00142 {
00143
00144 if (theDomain == 0) {
00145 end1Ptr = 0;
00146 end2Ptr = 0;
00147 Lo = 0.0;
00148 Ln = 0.0;
00149 return;
00150 }
00151
00152
00153 int Nd1 = connectedExternalNodes(0);
00154 int Nd2 = connectedExternalNodes(1);
00155 end1Ptr = theDomain->getNode(Nd1);
00156 end2Ptr = theDomain->getNode(Nd2);
00157
00158
00159 if ((end1Ptr == 0) || (end2Ptr == 0)) {
00160 g3ErrorHandler->warning("CorotTruss::setDomain() - CorotTruss %d node %d %s\n",
00161 this->getTag(), Nd1,
00162 "does not exist in the model");
00163
00164
00165 numDOF = 6;
00166
00167 return;
00168 }
00169
00170
00171 int dofNd1 = end1Ptr->getNumberDOF();
00172 int dofNd2 = end2Ptr->getNumberDOF();
00173
00174
00175 if (dofNd1 != dofNd2) {
00176 g3ErrorHandler->warning("WARNING CorotTruss::setDomain(): nodes %d and %d %s %d\n",Nd1, Nd2,
00177 "have differing dof at ends for CorotTruss",this->getTag());
00178
00179
00180 numDOF = 6;
00181
00182 return;
00183 }
00184
00185 if (numDIM == 1 && dofNd1 == 1) {
00186 numDOF = 2;
00187 theMatrix = &M2;
00188 theVector = &V2;
00189 }
00190 else if (numDIM == 2 && dofNd1 == 2) {
00191 numDOF = 4;
00192 theMatrix = &M4;
00193 theVector = &V4;
00194 }
00195 else if (numDIM == 2 && dofNd1 == 3) {
00196 numDOF = 6;
00197 theMatrix = &M6;
00198 theVector = &V6;
00199 }
00200 else if (numDIM == 3 && dofNd1 == 3) {
00201 numDOF = 6;
00202 theMatrix = &M6;
00203 theVector = &V6;
00204 }
00205 else if (numDIM == 3 && dofNd1 == 6) {
00206 numDOF = 12;
00207 theMatrix = &M12;
00208 theVector = &V12;
00209 }
00210 else {
00211 g3ErrorHandler->warning("%s -- nodal DOF %d not compatible with element",
00212 "CorotTruss::setDomain", dofNd1);
00213
00214
00215 numDOF = 6;
00216
00217 return;
00218 }
00219
00220
00221 this->DomainComponent::setDomain(theDomain);
00222
00223
00224
00225 const Vector &end1Crd = end1Ptr->getCrds();
00226 const Vector &end2Crd = end2Ptr->getCrds();
00227
00228
00229 double cosX[3];
00230 cosX[0] = 0.0; cosX[1] = 0.0; cosX[2] = 0.0;
00231 int i;
00232 for (i = 0; i < numDIM; i++) {
00233 cosX[i] += end2Crd(i)-end1Crd(i);
00234 }
00235
00236
00237 Lo = cosX[0]*cosX[0] + cosX[1]*cosX[1] + cosX[2]*cosX[2];
00238 Lo = sqrt(Lo);
00239 Ln = Lo;
00240
00241
00242 d21[0] = Lo;
00243 d21[1] = 0.0;
00244 d21[2] = 0.0;
00245
00246
00247 cosX[0] /= Lo;
00248 cosX[1] /= Lo;
00249 cosX[2] /= Lo;
00250
00251 R(0,0) = cosX[0];
00252 R(0,1) = cosX[1];
00253 R(0,2) = cosX[2];
00254
00255
00256 if (fabs(cosX[0]) > 0.0) {
00257 R(1,0) = -cosX[1];
00258 R(1,1) = cosX[0];
00259 R(1,2) = 0.0;
00260
00261 R(2,0) = -cosX[0]*cosX[2];
00262 R(2,1) = -cosX[1]*cosX[2];
00263 R(2,2) = cosX[0]*cosX[0] + cosX[1]*cosX[1];
00264 }
00265
00266 else {
00267 R(1,0) = 0.0;
00268 R(1,1) = -cosX[2];
00269 R(1,2) = cosX[1];
00270
00271 R(2,0) = 1.0;
00272 R(2,1) = 0.0;
00273 R(2,2) = 0.0;
00274 }
00275
00276
00277 double norm;
00278 for (i = 1; i < 3; i++) {
00279 norm = sqrt(R(i,0)*R(i,0) + R(i,1)*R(i,1) + R(i,2)*R(i,2));
00280 R(i,0) /= norm;
00281 R(i,1) /= norm;
00282 R(i,2) /= norm;
00283 }
00284
00285
00286 M = M*Lo/2;
00287 }
00288
00289 int
00290 CorotTruss::commitState()
00291 {
00292
00293 return theMaterial->commitState();
00294 }
00295
00296 int
00297 CorotTruss::revertToLastCommit()
00298 {
00299
00300 return theMaterial->revertToLastCommit();
00301 }
00302
00303 int
00304 CorotTruss::revertToStart()
00305 {
00306
00307 return theMaterial->revertToStart();
00308 }
00309
00310 int
00311 CorotTruss::update(void)
00312 {
00313
00314 const Vector &end1Disp = end1Ptr->getTrialDisp();
00315 const Vector &end2Disp = end2Ptr->getTrialDisp();
00316
00317
00318 d21[0] = Lo;
00319 d21[1] = 0.0;
00320 d21[2] = 0.0;
00321
00322
00323 for (int i = 0; i < numDIM; i++) {
00324 d21[0] += R(0,i)*(end2Disp(i)-end1Disp(i));
00325 d21[1] += R(1,i)*(end2Disp(i)-end1Disp(i));
00326 d21[2] += R(2,i)*(end2Disp(i)-end1Disp(i));
00327 }
00328
00329
00330 Ln = d21[0]*d21[0] + d21[1]*d21[1] + d21[2]*d21[2];
00331 Ln = sqrt(Ln);
00332
00333
00334 double strain = (Ln-Lo)/Lo;
00335
00336
00337 return theMaterial->setTrialStrain(strain);
00338 }
00339
00340 const Matrix &
00341 CorotTruss::getTangentStiff(void)
00342 {
00343 static Matrix kl(3,3);
00344
00345
00346
00347
00348 double EA = A*theMaterial->getTangent();
00349 EA /= (Ln*Ln*Lo);
00350
00351 int i,j;
00352 for (i = 0; i < 3; i++)
00353 for (j = 0; j < 3; j++)
00354 kl(i,j) = EA*d21[i]*d21[j];
00355
00356
00357
00358
00359 double q = A*theMaterial->getStress();
00360 double SA = q/(Ln*Ln*Ln);
00361 double SL = q/Ln;
00362
00363 for (i = 0; i < 3; i++) {
00364 kl(i,i) += SL;
00365 for (j = 0; j < 3; j++)
00366 kl(i,j) -= SA*d21[i]*d21[j];
00367 }
00368
00369
00370 static Matrix kg(3,3);
00371 kg.addMatrixTripleProduct(0.0, R, kl, 1.0);
00372
00373 Matrix &K = *theMatrix;
00374 K.Zero();
00375
00376
00377 int numDOF2 = numDOF/2;
00378 for (i = 0; i < numDIM; i++) {
00379 for (j = 0; j < numDIM; j++) {
00380 K(i,j) = kg(i,j);
00381 K(i,j+numDOF2) = -kg(i,j);
00382 K(i+numDOF2,j) = -kg(i,j);
00383 K(i+numDOF2,j+numDOF2) = kg(i,j);
00384 }
00385 }
00386
00387 return *theMatrix;
00388 }
00389
00390 const Matrix &
00391 CorotTruss::getSecantStiff(void)
00392 {
00393 return this->getTangentStiff();
00394 }
00395
00396 const Matrix &
00397 CorotTruss::getDamp(void)
00398 {
00399 theMatrix->Zero();
00400
00401 return *theMatrix;
00402 }
00403
00404 const Matrix &
00405 CorotTruss::getMass(void)
00406 {
00407 Matrix &Mass = *theMatrix;
00408 Mass.Zero();
00409
00410 int numDOF2 = numDOF/2;
00411 for (int i = 0; i < numDIM; i++) {
00412 Mass(i,i) = M;
00413 Mass(i+numDOF2,i+numDOF2) = M;
00414 }
00415
00416 return *theMatrix;
00417 }
00418
00419 void
00420 CorotTruss::zeroLoad(void)
00421 {
00422 return;
00423 }
00424
00425 int
00426 CorotTruss::addLoad(const Vector &addP)
00427 {
00428 return 0;
00429 }
00430
00431 int
00432 CorotTruss::addInertiaLoadToUnbalance(const Vector &accel)
00433 {
00434 return 0;
00435 }
00436
00437 const Vector &
00438 CorotTruss::getResistingForce()
00439 {
00440
00441 double SA = A*theMaterial->getStress();
00442 SA /= Ln;
00443
00444 static Vector ql(3);
00445
00446 ql(0) = d21[0]*SA;
00447 ql(1) = d21[1]*SA;
00448 ql(2) = d21[2]*SA;
00449
00450 static Vector qg(3);
00451 qg.addMatrixTransposeVector(0.0, R, ql, 1.0);
00452
00453 Vector &P = *theVector;
00454 P.Zero();
00455
00456
00457 int numDOF2 = numDOF/2;
00458 for (int i = 0; i < numDIM; i++) {
00459 P(i) = -qg(i);
00460 P(i+numDOF2) = qg(i);
00461 }
00462
00463 return *theVector;
00464 }
00465
00466 const Vector &
00467 CorotTruss::getResistingForceIncInertia()
00468 {
00469 Vector &P = *theVector;
00470 P = this->getResistingForce();
00471
00472 if (M != 0.0) {
00473
00474 const Vector &accel1 = end1Ptr->getTrialAccel();
00475 const Vector &accel2 = end2Ptr->getTrialAccel();
00476
00477 int numDOF2 = numDOF/2;
00478 for (int i = 0; i < numDIM; i++) {
00479 P(i) += M*accel1(i);
00480 P(i+numDOF2) += M*accel2(i);
00481 }
00482 }
00483
00484 return *theVector;
00485 }
00486
00487 int
00488 CorotTruss::sendSelf(int commitTag, Channel &theChannel)
00489 {
00490 return -1;
00491 }
00492
00493 int
00494 CorotTruss::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00495 {
00496 return -1;
00497 }
00498
00499 int
00500 CorotTruss::displaySelf(Renderer &theViewer, int displayMode, float fact)
00501 {
00502
00503 if (Ln == 0.0)
00504 return 0;
00505
00506
00507
00508
00509 const Vector &end1Crd = end1Ptr->getCrds();
00510 const Vector &end2Crd = end2Ptr->getCrds();
00511 const Vector &end1Disp = end1Ptr->getDisp();
00512 const Vector &end2Disp = end2Ptr->getDisp();
00513
00514 static Vector v1(3);
00515 static Vector v2(3);
00516 for (int i = 0; i < numDIM; i++) {
00517 v1(i) = end1Crd(i)+end1Disp(i)*fact;
00518 v2(i) = end2Crd(i)+end2Disp(i)*fact;
00519 }
00520
00521 return theViewer.drawLine(v1, v2, 1.0, 1.0);
00522 }
00523
00524 void
00525 CorotTruss::Print(ostream &s, int flag)
00526 {
00527 s << "\nCorotTruss, tag: " << this->getTag() << endl;
00528 s << "\tConnected Nodes: " << connectedExternalNodes;
00529 s << "\tSection Area: " << A << endl;
00530 s << "\tUndeformed Length: " << Lo << endl;
00531 s << "\tCurrent Length: " << Ln << endl;
00532 s << "\tRotation matrix: " << endl;
00533
00534 if (theMaterial) {
00535 s << "\tAxial Force: " << A*theMaterial->getStress() << endl;
00536 s << "\tUniaxialMaterial, tag: " << theMaterial->getTag() << endl;
00537 theMaterial->Print(s,flag);
00538 }
00539 }
00540
00541 Response*
00542 CorotTruss::setResponse(char **argv, int argc, Information &eleInfo)
00543 {
00544
00545 if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0 || strcmp(argv[0],"axialForce") == 0)
00546 return new ElementResponse(this, 1, 0.0);
00547
00548 else if (strcmp(argv[0],"defo") == 0 || strcmp(argv[0],"deformations") == 0 ||
00549 strcmp(argv[0],"deformation") == 0)
00550 return new ElementResponse(this, 2, 0.0);
00551
00552
00553 else if (strcmp(argv[0],"material") == 0)
00554 return theMaterial->setResponse(&argv[1], argc-1, eleInfo);
00555
00556 else
00557 return 0;
00558 }
00559
00560 int
00561 CorotTruss::getResponse(int responseID, Information &eleInfo)
00562 {
00563 switch (responseID) {
00564 case 1:
00565 return eleInfo.setDouble(A * theMaterial->getStress());
00566
00567 case 2:
00568 return eleInfo.setDouble(Lo * theMaterial->getStrain());
00569
00570 default:
00571 return 0;
00572 }
00573 }