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
00032
00033
00034 #include <Truss.h>
00035 #include <Information.h>
00036 #include <Parameter.h>
00037
00038 #include <Domain.h>
00039 #include <Node.h>
00040 #include <Channel.h>
00041 #include <FEM_ObjectBroker.h>
00042 #include <UniaxialMaterial.h>
00043 #include <Renderer.h>
00044
00045 #include <math.h>
00046 #include <stdlib.h>
00047 #include <string.h>
00048
00049 #include <ElementResponse.h>
00050
00051
00052
00053
00054 Matrix Truss::trussM2(2,2);
00055 Matrix Truss::trussM4(4,4);
00056 Matrix Truss::trussM6(6,6);
00057 Matrix Truss::trussM12(12,12);
00058 Vector Truss::trussV2(2);
00059 Vector Truss::trussV4(4);
00060 Vector Truss::trussV6(6);
00061 Vector Truss::trussV12(12);
00062
00063
00064
00065
00066 Truss::Truss(int tag,
00067 int dim,
00068 int Nd1, int Nd2,
00069 UniaxialMaterial &theMat,
00070 double a, double r)
00071 :Element(tag,ELE_TAG_Truss),
00072 theMaterial(0), connectedExternalNodes(2),
00073 dimension(dim), numDOF(0), theLoad(0),
00074 theMatrix(0), theVector(0),
00075 L(0.0), A(a), rho(r)
00076 {
00077
00078 theMaterial = theMat.getCopy();
00079 if (theMaterial == 0) {
00080 opserr << "FATAL Truss::Truss - " << tag <<
00081 "failed to get a copy of material with tag " << theMat.getTag() << endln;
00082 exit(-1);
00083 }
00084
00085
00086 if (connectedExternalNodes.Size() != 2) {
00087 opserr << "FATAL Truss::Truss - " << tag << "failed to create an ID of size 2\n";
00088 exit(-1);
00089 }
00090
00091 connectedExternalNodes(0) = Nd1;
00092 connectedExternalNodes(1) = Nd2;
00093
00094
00095 for (int i=0; i<2; i++)
00096 theNodes[i] = 0;
00097
00098 cosX[0] = 0.0;
00099 cosX[1] = 0.0;
00100 cosX[2] = 0.0;
00101
00102
00103 parameterID = 0;
00104 theLoadSens = 0;
00105
00106 }
00107
00108
00109
00110
00111 Truss::Truss()
00112 :Element(0,ELE_TAG_Truss),
00113 theMaterial(0),connectedExternalNodes(2),
00114 dimension(0), numDOF(0), theLoad(0),
00115 theMatrix(0), theVector(0),
00116 L(0.0), A(0.0), rho(0.0)
00117 {
00118
00119 if (connectedExternalNodes.Size() != 2) {
00120 opserr << "FATAL Truss::Truss - failed to create an ID of size 2\n";
00121 exit(-1);
00122 }
00123
00124 for (int i=0; i<2; i++)
00125 theNodes[i] = 0;
00126
00127 cosX[0] = 0.0;
00128 cosX[1] = 0.0;
00129 cosX[2] = 0.0;
00130
00131
00132 parameterID = 0;
00133 theLoadSens = 0;
00134
00135 }
00136
00137
00138
00139
00140 Truss::~Truss()
00141 {
00142
00143
00144 if (theMaterial != 0)
00145 delete theMaterial;
00146 if (theLoad != 0)
00147 delete theLoad;
00148 if (theLoadSens != 0)
00149 delete theLoadSens;
00150 }
00151
00152
00153 int
00154 Truss::getNumExternalNodes(void) const
00155 {
00156 return 2;
00157 }
00158
00159 const ID &
00160 Truss::getExternalNodes(void)
00161 {
00162 return connectedExternalNodes;
00163 }
00164
00165 Node **
00166 Truss::getNodePtrs(void)
00167 {
00168 return theNodes;
00169 }
00170
00171 int
00172 Truss::getNumDOF(void)
00173 {
00174 return numDOF;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184 void
00185 Truss::setDomain(Domain *theDomain)
00186 {
00187
00188 if (theDomain == 0) {
00189 theNodes[0] = 0;
00190 theNodes[1] = 0;
00191 L = 0;
00192 return;
00193 }
00194
00195
00196 int Nd1 = connectedExternalNodes(0);
00197 int Nd2 = connectedExternalNodes(1);
00198 theNodes[0] = theDomain->getNode(Nd1);
00199 theNodes[1] = theDomain->getNode(Nd2);
00200
00201
00202 if ((theNodes[0] == 0) || (theNodes[1] == 0)) {
00203 if (theNodes[0] == 0)
00204 opserr <<"Truss::setDomain() - truss" << this->getTag() << " node " << Nd1 <<
00205 "does not exist in the model\n";
00206 else
00207 opserr <<"Truss::setDomain() - truss" << this->getTag() << " node " << Nd2 <<
00208 "does not exist in the model\n";
00209
00210
00211 numDOF = 2;
00212 theMatrix = &trussM2;
00213 theVector = &trussV2;
00214
00215 return;
00216 }
00217
00218
00219 int dofNd1 = theNodes[0]->getNumberDOF();
00220 int dofNd2 = theNodes[1]->getNumberDOF();
00221
00222
00223 if (dofNd1 != dofNd2) {
00224 opserr <<"WARNING Truss::setDomain(): nodes " << Nd1 << " and " << Nd2 <<
00225 "have differing dof at ends for truss " << this->getTag() << endln;
00226
00227
00228 numDOF = 2;
00229 theMatrix = &trussM2;
00230 theVector = &trussV2;
00231
00232 return;
00233 }
00234
00235
00236 this->DomainComponent::setDomain(theDomain);
00237
00238
00239 if (dimension == 1 && dofNd1 == 1) {
00240 numDOF = 2;
00241 theMatrix = &trussM2;
00242 theVector = &trussV2;
00243 }
00244 else if (dimension == 2 && dofNd1 == 2) {
00245 numDOF = 4;
00246 theMatrix = &trussM4;
00247 theVector = &trussV4;
00248 }
00249 else if (dimension == 2 && dofNd1 == 3) {
00250 numDOF = 6;
00251 theMatrix = &trussM6;
00252 theVector = &trussV6;
00253 }
00254 else if (dimension == 3 && dofNd1 == 3) {
00255 numDOF = 6;
00256 theMatrix = &trussM6;
00257 theVector = &trussV6;
00258 }
00259 else if (dimension == 3 && dofNd1 == 6) {
00260 numDOF = 12;
00261 theMatrix = &trussM12;
00262 theVector = &trussV12;
00263 }
00264 else {
00265 opserr <<"WARNING Truss::setDomain cannot handle " << dimension << " dofs at nodes in " <<
00266 dofNd1 << " problem\n";
00267
00268 numDOF = 2;
00269 theMatrix = &trussM2;
00270 theVector = &trussV2;
00271 return;
00272 }
00273
00274 if (theLoad == 0)
00275 theLoad = new Vector(numDOF);
00276 else if (theLoad->Size() != numDOF) {
00277 delete theLoad;
00278 theLoad = new Vector(numDOF);
00279 }
00280
00281 if (theLoad == 0) {
00282 opserr << "Truss::setDomain - truss " << this->getTag() <<
00283 "out of memory creating vector of size" << numDOF << endln;
00284 exit(-1);
00285 return;
00286 }
00287
00288
00289
00290 const Vector &end1Crd = theNodes[0]->getCrds();
00291 const Vector &end2Crd = theNodes[1]->getCrds();
00292
00293 if (dimension == 1) {
00294 double dx = end2Crd(0)-end1Crd(0);
00295
00296 L = sqrt(dx*dx);
00297
00298 if (L == 0.0) {
00299 opserr <<"WARNING Truss::setDomain() - truss " << this->getTag() << " has zero length\n";
00300 return;
00301 }
00302
00303 cosX[0] = 1.0;
00304 }
00305 else if (dimension == 2) {
00306 double dx = end2Crd(0)-end1Crd(0);
00307 double dy = end2Crd(1)-end1Crd(1);
00308
00309 L = sqrt(dx*dx + dy*dy);
00310
00311 if (L == 0.0) {
00312 opserr <<"WARNING Truss::setDomain() - truss " << this->getTag() << " has zero length\n";
00313 return;
00314 }
00315
00316 cosX[0] = dx/L;
00317 cosX[1] = dy/L;
00318 }
00319 else {
00320 double dx = end2Crd(0)-end1Crd(0);
00321 double dy = end2Crd(1)-end1Crd(1);
00322 double dz = end2Crd(2)-end1Crd(2);
00323
00324 L = sqrt(dx*dx + dy*dy + dz*dz);
00325
00326 if (L == 0.0) {
00327 opserr <<"WARNING Truss::setDomain() - truss " << this->getTag() << " has zero length\n";
00328 return;
00329 }
00330
00331 cosX[0] = dx/L;
00332 cosX[1] = dy/L;
00333 cosX[2] = dz/L;
00334 }
00335 }
00336
00337
00338 int
00339 Truss::commitState()
00340 {
00341 int retVal = 0;
00342
00343 if ((retVal = this->Element::commitState()) != 0) {
00344 opserr << "Truss::commitState () - failed in base class";
00345 }
00346 retVal = theMaterial->commitState();
00347 return retVal;
00348 }
00349
00350 int
00351 Truss::revertToLastCommit()
00352 {
00353 return theMaterial->revertToLastCommit();
00354 }
00355
00356 int
00357 Truss::revertToStart()
00358 {
00359 return theMaterial->revertToStart();
00360 }
00361
00362 int
00363 Truss::update(void)
00364 {
00365
00366 double strain = this->computeCurrentStrain();
00367 double rate = this->computeCurrentStrainRate();
00368 return theMaterial->setTrialStrain(strain, rate);
00369 }
00370
00371
00372 const Matrix &
00373 Truss::getTangentStiff(void)
00374 {
00375 if (L == 0.0) {
00376 theMatrix->Zero();
00377 return *theMatrix;
00378 }
00379
00380 double E = theMaterial->getTangent();
00381
00382
00383 Matrix &stiff = *theMatrix;
00384
00385 int numDOF2 = numDOF/2;
00386 double temp;
00387 double EAoverL = E*A/L;
00388 for (int i = 0; i < dimension; i++) {
00389 for (int j = 0; j < dimension; j++) {
00390 temp = cosX[i]*cosX[j]*EAoverL;
00391 stiff(i,j) = temp;
00392 stiff(i+numDOF2,j) = -temp;
00393 stiff(i,j+numDOF2) = -temp;
00394 stiff(i+numDOF2,j+numDOF2) = temp;
00395 }
00396 }
00397
00398 return stiff;
00399 }
00400
00401
00402 const Matrix &
00403 Truss::getInitialStiff(void)
00404 {
00405 if (L == 0.0) {
00406 theMatrix->Zero();
00407 return *theMatrix;
00408 }
00409
00410 double E = theMaterial->getInitialTangent();
00411
00412
00413 Matrix &stiff = *theMatrix;
00414
00415 int numDOF2 = numDOF/2;
00416 double temp;
00417 double EAoverL = E*A/L;
00418 for (int i = 0; i < dimension; i++) {
00419 for (int j = 0; j < dimension; j++) {
00420 temp = cosX[i]*cosX[j]*EAoverL;
00421 stiff(i,j) = temp;
00422 stiff(i+numDOF2,j) = -temp;
00423 stiff(i,j+numDOF2) = -temp;
00424 stiff(i+numDOF2,j+numDOF2) = temp;
00425 }
00426 }
00427
00428 return *theMatrix;
00429 }
00430
00431 const Matrix &
00432 Truss::getDamp(void)
00433 {
00434 if (L == 0.0) {
00435 theMatrix->Zero();
00436 return *theMatrix;
00437 }
00438
00439 double eta = theMaterial->getDampTangent();
00440
00441
00442 Matrix &damp = *theMatrix;
00443
00444 int numDOF2 = numDOF/2;
00445 double temp;
00446 double etaAoverL = eta*A/L;
00447 for (int i = 0; i < dimension; i++) {
00448 for (int j = 0; j < dimension; j++) {
00449 temp = cosX[i]*cosX[j]*etaAoverL;
00450 damp(i,j) = temp;
00451 damp(i+numDOF2,j) = -temp;
00452 damp(i,j+numDOF2) = -temp;
00453 damp(i+numDOF2,j+numDOF2) = temp;
00454 }
00455 }
00456
00457 return damp;
00458 }
00459
00460
00461 const Matrix &
00462 Truss::getMass(void)
00463 {
00464
00465 Matrix &mass = *theMatrix;
00466 mass.Zero();
00467
00468
00469 if (L == 0.0 || rho == 0.0) {
00470 return mass;
00471 }
00472
00473 double M = 0.5*rho*L;
00474 int numDOF2 = numDOF/2;
00475 for (int i = 0; i < dimension; i++) {
00476 mass(i,i) = M;
00477 mass(i+numDOF2,i+numDOF2) = M;
00478 }
00479
00480 return mass;
00481 }
00482
00483 void
00484 Truss::zeroLoad(void)
00485 {
00486 theLoad->Zero();
00487 }
00488
00489 int
00490 Truss::addLoad(ElementalLoad *theLoad, double loadFactor)
00491
00492 {
00493 opserr <<"Truss::addLoad - load type unknown for truss with tag: " << this->getTag() << endln;
00494
00495 return -1;
00496 }
00497
00498 int
00499 Truss::addInertiaLoadToUnbalance(const Vector &accel)
00500 {
00501
00502 if (L == 0.0 || rho == 0.0)
00503 return 0;
00504
00505
00506 const Vector &Raccel1 = theNodes[0]->getRV(accel);
00507 const Vector &Raccel2 = theNodes[1]->getRV(accel);
00508
00509 int nodalDOF = numDOF/2;
00510
00511 #ifdef _G3DEBUG
00512 if (nodalDOF != Raccel1.Size() || nodalDOF != Raccel2.Size()) {
00513 opserr <<"Truss::addInertiaLoadToUnbalance " <<
00514 "matrix and vector sizes are incompatable\n";
00515 return -1;
00516 }
00517 #endif
00518
00519 double M = 0.5*rho*L;
00520
00521 for (int i=0; i<dimension; i++) {
00522 double val1 = Raccel1(i);
00523 double val2 = Raccel2(i);
00524
00525
00526 val1 *= -M;
00527 val2 *= -M;
00528
00529 (*theLoad)(i) += val1;
00530 (*theLoad)(i+nodalDOF) += val2;
00531 }
00532
00533 return 0;
00534 }
00535
00536
00537 int
00538 Truss::addInertiaLoadSensitivityToUnbalance(const Vector &accel, bool somethingRandomInMotions)
00539 {
00540
00541 if (theLoadSens == 0) {
00542 theLoadSens = new Vector(numDOF);
00543 }
00544 else {
00545 theLoadSens->Zero();
00546 }
00547
00548
00549 if (somethingRandomInMotions) {
00550
00551
00552
00553 if (L == 0.0 || rho == 0.0)
00554 return 0;
00555
00556
00557 const Vector &Raccel1 = theNodes[0]->getRV(accel);
00558 const Vector &Raccel2 = theNodes[1]->getRV(accel);
00559
00560 int nodalDOF = numDOF/2;
00561
00562 #ifdef _G3DEBUG
00563 if (nodalDOF != Raccel1.Size() || nodalDOF != Raccel2.Size()) {
00564 opserr << "Truss::addInertiaLoadToUnbalance " <<
00565 "matrix and vector sizes are incompatable\n";
00566 return -1;
00567 }
00568 #endif
00569
00570 double M = 0.5*rho*L;
00571
00572 for (int i=0; i<dimension; i++) {
00573 double val1 = Raccel1(i);
00574 double val2 = Raccel2(i);
00575
00576
00577 val1 *= M;
00578 val2 *= M;
00579
00580 (*theLoadSens)(i) = val1;
00581 (*theLoadSens)(i+nodalDOF) = val2;
00582 }
00583 }
00584 else {
00585
00586
00587 if (L == 0.0 || rho == 0.0)
00588 return 0;
00589
00590
00591 const Vector &Raccel1 = theNodes[0]->getRV(accel);
00592 const Vector &Raccel2 = theNodes[1]->getRV(accel);
00593
00594 int nodalDOF = numDOF/2;
00595
00596 #ifdef _G3DEBUG
00597 if (nodalDOF != Raccel1.Size() || nodalDOF != Raccel2.Size()) {
00598 opserr << "Truss::addInertiaLoadToUnbalance " <<
00599 "matrix and vector sizes are incompatable\n";
00600 return -1;
00601 }
00602 #endif
00603
00604 double massDerivative = 0.0;
00605 if (parameterID == 2) {
00606 massDerivative = 0.5*L;
00607 }
00608
00609
00610 for (int i=0; i<dimension; i++) {
00611 double val1 = Raccel1(i);
00612 double val2 = Raccel2(i);
00613
00614
00615
00616 val1 *= massDerivative;
00617 val2 *= massDerivative;
00618
00619 (*theLoadSens)(i) = val1;
00620 (*theLoadSens)(i+nodalDOF) = val2;
00621 }
00622 }
00623 return 0;
00624 }
00625
00626 const Vector &
00627 Truss::getResistingForce()
00628 {
00629 if (L == 0.0) {
00630 theVector->Zero();
00631 return *theVector;
00632 }
00633
00634
00635
00636 double force = A*theMaterial->getStress();
00637 int numDOF2 = numDOF/2;
00638 double temp;
00639 for (int i = 0; i < dimension; i++) {
00640 temp = cosX[i]*force;
00641 (*theVector)(i) = -temp;
00642 (*theVector)(i+numDOF2) = temp;
00643 }
00644
00645
00646 (*theVector) -= *theLoad;
00647
00648 return *theVector;
00649 }
00650
00651
00652 const Vector &
00653 Truss::getResistingForceIncInertia()
00654 {
00655 this->getResistingForce();
00656
00657
00658 if (L != 0.0 && rho != 0.0) {
00659
00660 const Vector &accel1 = theNodes[0]->getTrialAccel();
00661 const Vector &accel2 = theNodes[1]->getTrialAccel();
00662
00663 int numDOF2 = numDOF/2;
00664 double M = 0.5*rho*L;
00665 for (int i = 0; i < dimension; i++) {
00666 (*theVector)(i) += M*accel1(i);
00667 (*theVector)(i+numDOF2) += M*accel2(i);
00668 }
00669
00670
00671 if (alphaM != 0.0 || betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00672 (*theVector) += this->getRayleighDampingForces();
00673 } else {
00674
00675
00676 if (betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00677 (*theVector) += this->getRayleighDampingForces();
00678 }
00679
00680 return *theVector;
00681 }
00682
00683 int
00684 Truss::sendSelf(int commitTag, Channel &theChannel)
00685 {
00686 int res;
00687
00688
00689
00690
00691 int dataTag = this->getDbTag();
00692
00693
00694
00695
00696 static Vector data(7);
00697 data(0) = this->getTag();
00698 data(1) = dimension;
00699 data(2) = numDOF;
00700 data(3) = A;
00701 data(6) = rho;
00702
00703 data(4) = theMaterial->getClassTag();
00704 int matDbTag = theMaterial->getDbTag();
00705
00706
00707
00708 if (matDbTag == 0) {
00709 matDbTag = theChannel.getDbTag();
00710 if (matDbTag != 0)
00711 theMaterial->setDbTag(matDbTag);
00712 }
00713 data(5) = matDbTag;
00714
00715 res = theChannel.sendVector(dataTag, commitTag, data);
00716 if (res < 0) {
00717 opserr <<"WARNING Truss::sendSelf() - " << this->getTag() << " failed to send Vector\n";
00718 return -1;
00719 }
00720
00721
00722
00723 res = theChannel.sendID(dataTag, commitTag, connectedExternalNodes);
00724 if (res < 0) {
00725 opserr <<"WARNING Truss::sendSelf() - " << this->getTag() << " failed to send Vector\n";
00726 return -2;
00727 }
00728
00729
00730 res = theMaterial->sendSelf(commitTag, theChannel);
00731 if (res < 0) {
00732 opserr <<"WARNING Truss::sendSelf() - " << this->getTag() << " failed to send its Material\n";
00733 return -3;
00734 }
00735
00736 return 0;
00737 }
00738
00739 int
00740 Truss::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00741 {
00742 int res;
00743 int dataTag = this->getDbTag();
00744
00745
00746
00747
00748 static Vector data(7);
00749 res = theChannel.recvVector(dataTag, commitTag, data);
00750 if (res < 0) {
00751 opserr <<"WARNING Truss::recvSelf() - failed to receive Vector\n";
00752 return -1;
00753 }
00754
00755 this->setTag((int)data(0));
00756 dimension = (int)data(1);
00757 numDOF = (int)data(2);
00758 A = data(3);
00759 rho = data(6);
00760
00761
00762 res = theChannel.recvID(dataTag, commitTag, connectedExternalNodes);
00763 if (res < 0) {
00764 opserr <<"WARNING Truss::recvSelf() - " << this->getTag() << " failed to receive ID\n";
00765 return -2;
00766 }
00767
00768
00769
00770
00771 int matClass = (int)data(4);
00772 int matDb = (int)data(5);
00773
00774
00775 if ((theMaterial == 0) || (theMaterial->getClassTag() != matClass)) {
00776
00777
00778 if (theMaterial != 0)
00779 delete theMaterial;
00780
00781
00782 theMaterial = theBroker.getNewUniaxialMaterial(matClass);
00783 if (theMaterial == 0) {
00784 opserr <<"WARNING Truss::recvSelf() - " << this->getTag()
00785 << " failed to get a blank Material of type " << matClass << endln;
00786 return -3;
00787 }
00788 }
00789
00790 theMaterial->setDbTag(matDb);
00791 res = theMaterial->recvSelf(commitTag, theChannel, theBroker);
00792 if (res < 0) {
00793 opserr <<"WARNING Truss::recvSelf() - "<< this->getTag() << "failed to receive its Material\n";
00794 return -3;
00795 }
00796
00797 return 0;
00798 }
00799
00800
00801 int
00802 Truss::displaySelf(Renderer &theViewer, int displayMode, float fact)
00803 {
00804
00805 if (L == 0.0)
00806 return 0;
00807
00808
00809
00810
00811 const Vector &end1Crd = theNodes[0]->getCrds();
00812 const Vector &end2Crd = theNodes[1]->getCrds();
00813
00814 static Vector v1(3);
00815 static Vector v2(3);
00816
00817 if (displayMode == 1 || displayMode == 2) {
00818 const Vector &end1Disp = theNodes[0]->getDisp();
00819 const Vector &end2Disp = theNodes[1]->getDisp();
00820
00821 for (int i=0; i<dimension; i++) {
00822 v1(i) = end1Crd(i)+end1Disp(i)*fact;
00823 v2(i) = end2Crd(i)+end2Disp(i)*fact;
00824 }
00825
00826
00827 double strain, force;
00828 if (L == 0.0) {
00829 strain = 0.0;
00830 force = 0.0;
00831 } else {
00832 strain = this->computeCurrentStrain();
00833 theMaterial->setTrialStrain(strain);
00834 force = A*theMaterial->getStress();
00835 }
00836
00837 if (displayMode == 2)
00838 return theViewer.drawLine(v1, v2, strain, strain);
00839 else {
00840 return theViewer.drawLine(v1,v2, force, force);
00841 }
00842 } else if (displayMode < 0) {
00843 int mode = displayMode * -1;
00844 const Matrix &eigen1 = theNodes[0]->getEigenvectors();
00845 const Matrix &eigen2 = theNodes[1]->getEigenvectors();
00846 if (eigen1.noCols() >= mode) {
00847 for (int i = 0; i < dimension; i++) {
00848 v1(i) = end1Crd(i) + eigen1(i,mode-1)*fact;
00849 v2(i) = end2Crd(i) + eigen2(i,mode-1)*fact;
00850 }
00851 } else {
00852 for (int i = 0; i < dimension; i++) {
00853 v1(i) = end1Crd(i);
00854 v2(i) = end2Crd(i);
00855 }
00856 }
00857 }
00858 return 0;
00859 }
00860
00861
00862 void
00863 Truss::Print(OPS_Stream &s, int flag)
00864 {
00865
00866 double strain, force;
00867 strain = theMaterial->getStrain();
00868 force = A * theMaterial->getStress();
00869
00870 if (flag == 0) {
00871 s << "Element: " << this->getTag();
00872 s << " type: Truss iNode: " << connectedExternalNodes(0);
00873 s << " jNode: " << connectedExternalNodes(1);
00874 s << " Area: " << A << " Mass/Length: " << rho;
00875
00876 s << " \n\t strain: " << strain;
00877 s << " axial load: " << force;
00878 if (L != 0.0) {
00879 int numDOF2 = numDOF/2;
00880 double temp;
00881 for (int i = 0; i < dimension; i++) {
00882 temp = cosX[i]*force;
00883 (*theVector)(i) = -temp;
00884 (*theVector)(i+numDOF2) = temp;
00885 }
00886 s << " \n\t unbalanced load: " << *theVector;
00887 }
00888
00889 s << " \t Material: " << *theMaterial;
00890 s << endln;
00891 } else if (flag == 1) {
00892 s << this->getTag() << " " << strain << " ";
00893 s << force << endln;
00894 }
00895 }
00896
00897 double
00898 Truss::computeCurrentStrain(void) const
00899 {
00900
00901
00902
00903 const Vector &disp1 = theNodes[0]->getTrialDisp();
00904 const Vector &disp2 = theNodes[1]->getTrialDisp();
00905
00906 double dLength = 0.0;
00907 for (int i = 0; i < dimension; i++)
00908 dLength += (disp2(i)-disp1(i))*cosX[i];
00909
00910
00911 return dLength/L;
00912 }
00913
00914 double
00915 Truss::computeCurrentStrainRate(void) const
00916 {
00917
00918
00919
00920 const Vector &vel1 = theNodes[0]->getTrialVel();
00921 const Vector &vel2 = theNodes[1]->getTrialVel();
00922
00923 double dLength = 0.0;
00924 for (int i = 0; i < dimension; i++){
00925 dLength += (vel2(i)-vel1(i))*cosX[i];
00926 }
00927
00928
00929 return dLength/L;
00930 }
00931
00932 Response*
00933 Truss::setResponse(const char **argv, int argc, Information &eleInfo, OPS_Stream &output)
00934 {
00935
00936 Response *theResponse = 0;
00937
00938 output.tag("ElementOutput");
00939 output.attr("eleType","Truss");
00940 output.attr("eleTag",this->getTag());
00941 output.attr("node1",connectedExternalNodes[0]);
00942 output.attr("node2",connectedExternalNodes[1]);
00943
00944
00945
00946
00947
00948 if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0 || strcmp(argv[0],"axialForce") == 0) {
00949 opserr << "HELLO\n";
00950 output.tag("ResponseType", "N");
00951 theResponse = new ElementResponse(this, 1, 0.0);
00952
00953 } else if (strcmp(argv[0],"defo") == 0 || strcmp(argv[0],"deformations") == 0 ||
00954 strcmp(argv[0],"deformation") == 0) {
00955
00956 output.tag("ResponseType", "eps");
00957 theResponse = new ElementResponse(this, 2, 0.0);
00958
00959
00960 } else if (strcmp(argv[0],"material") == 0 || strcmp(argv[0],"-material") == 0) {
00961
00962 theResponse = theMaterial->setResponse(&argv[1], argc-1, eleInfo, output);
00963 }
00964
00965 output.endTag();
00966 return theResponse;
00967 }
00968
00969 int
00970 Truss::getResponse(int responseID, Information &eleInfo)
00971 {
00972 switch (responseID) {
00973 case 1:
00974 return eleInfo.setDouble(A * theMaterial->getStress());
00975
00976 case 2:
00977 return eleInfo.setDouble(L * theMaterial->getStrain());
00978
00979 case 3:
00980 return eleInfo.setMatrix(this->getTangentStiff());
00981
00982 default:
00983 return 0;
00984 }
00985 }
00986
00987
00988 int
00989 Truss::setParameter(const char **argv, int argc, Parameter ¶m)
00990 {
00991 if (argc < 1)
00992 return -1;
00993
00994
00995 if (strcmp(argv[0],"A") == 0)
00996 return param.addObject(1, this);
00997
00998
00999 if (strcmp(argv[0],"rho") == 0)
01000 return param.addObject(2, this);
01001
01002
01003 if (strstr(argv[0],"material") != 0) {
01004
01005 if (argc < 2)
01006 return -1;
01007
01008 else
01009 return theMaterial->setParameter(&argv[1], argc-1, param);
01010 }
01011
01012
01013 else
01014 return theMaterial->setParameter(argv, argc, param);
01015 }
01016
01017 int
01018 Truss::updateParameter (int parameterID, Information &info)
01019 {
01020 switch (parameterID) {
01021 case 1:
01022 A = info.theDouble;
01023 return 0;
01024 case 2:
01025 rho = info.theDouble;
01026 return 0;
01027 default:
01028 return -1;
01029 }
01030 }
01031
01032 int
01033 Truss::activateParameter(int passedParameterID)
01034 {
01035 parameterID = passedParameterID;
01036
01037 return 0;
01038 }
01039
01040
01041 const Matrix &
01042 Truss::getKiSensitivity(int gradNumber)
01043 {
01044 Matrix &stiff = *theMatrix;
01045 stiff.Zero();
01046
01047 if (parameterID == 0) {
01048 }
01049 else if (parameterID == 1) {
01050
01051 double E = theMaterial->getInitialTangent();
01052
01053 int numDOF2 = numDOF/2;
01054 double temp;
01055 double EoverL = E/L;
01056 for (int i = 0; i < dimension; i++) {
01057 for (int j = 0; j < dimension; j++) {
01058 temp = cosX[i]*cosX[j]*EoverL;
01059 stiff(i,j) = temp;
01060 stiff(i+numDOF2,j) = -temp;
01061 stiff(i,j+numDOF2) = -temp;
01062 stiff(i+numDOF2,j+numDOF2) = temp;
01063 }
01064 }
01065 }
01066 else if (parameterID == 2) {
01067
01068 }
01069 else {
01070 double Esens = theMaterial->getInitialTangentSensitivity(gradNumber);
01071
01072 int numDOF2 = numDOF/2;
01073 double temp;
01074 double EAoverL = Esens*A/L;
01075 for (int i = 0; i < dimension; i++) {
01076 for (int j = 0; j < dimension; j++) {
01077 temp = cosX[i]*cosX[j]*EAoverL;
01078 stiff(i,j) = temp;
01079 stiff(i+numDOF2,j) = -temp;
01080 stiff(i,j+numDOF2) = -temp;
01081 stiff(i+numDOF2,j+numDOF2) = temp;
01082 }
01083 }
01084 }
01085
01086 return stiff;
01087 }
01088
01089 const Matrix &
01090 Truss::getMassSensitivity(int gradNumber)
01091 {
01092 Matrix &mass = *theMatrix;
01093 mass.Zero();
01094
01095 if (parameterID == 2) {
01096 double massDerivative = 0.5*L;
01097
01098 int numDOF2 = numDOF/2;
01099 for (int i = 0; i < dimension; i++) {
01100 mass(i,i) = massDerivative;
01101 mass(i+numDOF2,i+numDOF2) = massDerivative;
01102 }
01103 }
01104
01105 return mass;
01106 }
01107
01108 const Vector &
01109 Truss::getResistingForceSensitivity(int gradNumber)
01110 {
01111 theVector->Zero();
01112
01113
01114 int i;
01115 double stressSensitivity, temp1, temp2;
01116
01117
01118 double strain = this->computeCurrentStrain();
01119 double rate = this->computeCurrentStrainRate();
01120 theMaterial->setTrialStrain(strain,rate);
01121
01122
01123 stressSensitivity = theMaterial->getStressSensitivity(gradNumber,true);
01124
01125
01126 double dcosXdh[3];
01127 dcosXdh[0] = 0.0;
01128 dcosXdh[1] = 0.0;
01129 dcosXdh[2] = 0.0;
01130
01131 int nodeParameterID0 = theNodes[0]->getCrdsSensitivity();
01132 int nodeParameterID1 = theNodes[1]->getCrdsSensitivity();
01133 if (nodeParameterID0 != 0 || nodeParameterID1 != 0) {
01134
01135 double dx = L*cosX[0];
01136 double dy = L*cosX[1];
01137
01138
01139
01140 if (nodeParameterID0 == 1) {
01141 temp1 = (-L+dx*dx/L)/(L*L);
01142 temp2 = dx*dy/(L*L*L);
01143
01144
01145
01146
01147 dcosXdh[0] = temp1;
01148 dcosXdh[1] = temp2;
01149 dcosXdh[2] = 0.0;
01150 }
01151 if (nodeParameterID0 == 2) {
01152 temp1 = (-L+dy*dy/L)/(L*L);
01153 temp2 = dx*dy/(L*L*L);
01154
01155
01156
01157
01158 dcosXdh[0] = temp2;
01159 dcosXdh[1] = temp1;
01160 dcosXdh[2] = 0.0;
01161 }
01162 if (nodeParameterID1 == 1) {
01163 temp1 = (L-dx*dx/L)/(L*L);
01164 temp2 = -dx*dy/(L*L*L);
01165
01166
01167
01168
01169 dcosXdh[0] = temp1;
01170 dcosXdh[1] = temp2;
01171 dcosXdh[2] = 0.0;
01172 }
01173 if (nodeParameterID1 == 2) {
01174 temp1 = (L-dy*dy/L)/(L*L);
01175 temp2 = -dx*dy/(L*L*L);
01176
01177
01178
01179
01180 dcosXdh[0] = temp2;
01181 dcosXdh[1] = temp1;
01182 dcosXdh[2] = 0.0;
01183 }
01184
01185 const Vector &disp1 = theNodes[0]->getTrialDisp();
01186 const Vector &disp2 = theNodes[1]->getTrialDisp();
01187 double dLengthDerivative = 0.0;
01188 for (i = 0; i < dimension; i++) {
01189 dLengthDerivative += (disp2(i)-disp1(i))*dcosXdh[i];
01190 }
01191
01192 double materialTangent = theMaterial->getTangent();
01193 double strainSensitivity;
01194
01195 if (nodeParameterID0 == 1) {
01196 strainSensitivity = (dLengthDerivative*L+strain*dx)/(L*L);
01197 }
01198 if (nodeParameterID0 == 2) {
01199 strainSensitivity = (dLengthDerivative*L+strain*dy)/(L*L);
01200 }
01201 if (nodeParameterID1 == 1) {
01202 strainSensitivity = (dLengthDerivative*L-strain*dx)/(L*L);
01203 }
01204 if (nodeParameterID1 == 2) {
01205 strainSensitivity = (dLengthDerivative*L-strain*dy)/(L*L);
01206 }
01207 stressSensitivity += materialTangent * strainSensitivity;
01208 }
01209
01210
01211
01212 double stress = theMaterial->getStress();
01213 int numDOF2 = numDOF/2;
01214 double temp;
01215 if (parameterID == 1) {
01216 for (i = 0; i < dimension; i++) {
01217 temp = (stress + A*stressSensitivity)*cosX[i];
01218 (*theVector)(i) = -temp;
01219 (*theVector)(i+numDOF2) = temp;
01220 }
01221 }
01222 else {
01223 for (i = 0; i < dimension; i++) {
01224 temp = A*(stressSensitivity*cosX[i] + stress*dcosXdh[i]);
01225 (*theVector)(i) = -temp;
01226 (*theVector)(i+numDOF2) = temp;
01227 }
01228 }
01229
01230
01231 if (theLoadSens == 0) {
01232 theLoadSens = new Vector(numDOF);
01233 }
01234 (*theVector) -= *theLoadSens;
01235
01236 return *theVector;
01237 }
01238
01239 int
01240 Truss::commitSensitivity(int gradNumber, int numGrads)
01241 {
01242
01243 int i;
01244 double strainSensitivity, temp1, temp2;
01245
01246
01247 double strain = this->computeCurrentStrain();
01248 double dLength = strain*L;
01249
01250
01251 double sens1;
01252 double sens2;
01253 double dSensitivity = 0.0;
01254 for (i=0; i<dimension; i++){
01255 sens1 = theNodes[0]->getDispSensitivity(i+1, gradNumber);
01256 sens2 = theNodes[1]->getDispSensitivity(i+1, gradNumber);
01257 dSensitivity += (sens2-sens1)*cosX[i];
01258 }
01259
01260 strainSensitivity = dSensitivity/L;
01261
01262
01263 int nodeParameterID0 = theNodes[0]->getCrdsSensitivity();
01264 int nodeParameterID1 = theNodes[1]->getCrdsSensitivity();
01265 if (nodeParameterID0 != 0 || nodeParameterID1 != 0) {
01266
01267 double dx = L*cosX[0];
01268 double dy = L*cosX[1];
01269
01270
01271
01272 double dcosXdh[3];
01273
01274 if (nodeParameterID0 == 1) {
01275 temp1 = (-L+dx*dx/L)/(L*L);
01276 temp2 = dx*dy/(L*L*L);
01277
01278
01279
01280
01281 dcosXdh[0] = temp1;
01282 dcosXdh[1] = temp2;
01283 dcosXdh[2] = 0.0;
01284 }
01285 if (nodeParameterID0 == 2) {
01286 temp1 = (-L+dy*dy/L)/(L*L);
01287 temp2 = dx*dy/(L*L*L);
01288
01289
01290
01291
01292 dcosXdh[0] = temp2;
01293 dcosXdh[1] = temp1;
01294 dcosXdh[2] = 0.0;
01295 }
01296
01297 if (nodeParameterID1 == 1) {
01298 temp1 = (L-dx*dx/L)/(L*L);
01299 temp2 = -dx*dy/(L*L*L);
01300
01301
01302
01303
01304 dcosXdh[0] = temp1;
01305 dcosXdh[1] = temp2;
01306 dcosXdh[2] = 0.0;
01307 }
01308 if (nodeParameterID1 == 2) {
01309 temp1 = (L-dy*dy/L)/(L*L);
01310 temp2 = -dx*dy/(L*L*L);
01311
01312
01313
01314
01315 dcosXdh[0] = temp2;
01316 dcosXdh[1] = temp1;
01317 dcosXdh[2] = 0.0;
01318 }
01319
01320 const Vector &disp1 = theNodes[0]->getTrialDisp();
01321 const Vector &disp2 = theNodes[1]->getTrialDisp();
01322 double dLengthDerivative = 0.0;
01323 for (i = 0; i < dimension; i++){
01324 dLengthDerivative += (disp2(i)-disp1(i))*dcosXdh[i];
01325 }
01326
01327 strainSensitivity += dLengthDerivative/L;
01328
01329 if (nodeParameterID0 == 1) {
01330 strainSensitivity += dLength/(L*L*L)*dx;
01331 }
01332 if (nodeParameterID0 == 2) {
01333 strainSensitivity += dLength/(L*L*L)*dy;
01334 }
01335 if (nodeParameterID1 == 1) {
01336 strainSensitivity -= dLength/(L*L*L)*dx;
01337 }
01338 if (nodeParameterID1 == 2) {
01339 strainSensitivity -= dLength/(L*L*L)*dy;
01340 }
01341 }
01342
01343
01344 theMaterial->commitSensitivity(strainSensitivity, gradNumber, numGrads);
01345
01346 return 0;
01347 }
01348
01349