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 <stdlib.h>
00035 #include <HystereticMaterial.h>
00036 #include <OPS_Globals.h>
00037 #include <math.h>
00038 #include <float.h>
00039 #include <Channel.h>
00040
00041 HystereticMaterial::HystereticMaterial(int tag,
00042 double m1p, double r1p, double m2p, double r2p, double m3p, double r3p,
00043 double m1n, double r1n, double m2n, double r2n, double m3n, double r3n,
00044 double px, double py, double d1, double d2, double b):
00045 UniaxialMaterial(tag, MAT_TAG_Hysteretic),
00046 pinchX(px), pinchY(py), damfc1(d1), damfc2(d2), beta(b),
00047 mom1p(m1p), rot1p(r1p), mom2p(m2p), rot2p(r2p), mom3p(m3p), rot3p(r3p),
00048 mom1n(m1n), rot1n(r1n), mom2n(m2n), rot2n(r2n), mom3n(m3n), rot3n(r3n)
00049 {
00050 bool error = false;
00051
00052 if (rot1p <= 0.0)
00053 error = true;
00054
00055 if (rot2p <= rot1p)
00056 error = true;
00057
00058 if (rot3p <= rot2p)
00059 error = true;
00060
00061
00062 if (rot1n >= 0.0)
00063 error = true;
00064
00065 if (rot2n >= rot1n)
00066 error = true;
00067
00068 if (rot3n >= rot2n)
00069 error = true;
00070
00071 if (error) {
00072 opserr << "HystereticMaterial::HystereticMaterial -- input backbone is not unique (one-to-one)\n";
00073 exit(-1);
00074 }
00075
00076 energyA = 0.5 * (rot1p*mom1p + (rot2p-rot1p)*(mom2p+mom1p) + (rot3p-rot2p)*(mom3p+mom2p) +
00077 rot1n*mom1n + (rot2n-rot1n)*(mom2n+mom1n) + (rot3n-rot2n)*(mom3n+mom2n));
00078
00079
00080 this->setEnvelope();
00081
00082
00083 this->revertToStart();
00084 this->revertToLastCommit();
00085 }
00086
00087 HystereticMaterial::HystereticMaterial(int tag,
00088 double m1p, double r1p, double m2p, double r2p,
00089 double m1n, double r1n, double m2n, double r2n,
00090 double px, double py, double d1, double d2, double b):
00091 UniaxialMaterial(tag, MAT_TAG_Hysteretic),
00092 pinchX(px), pinchY(py), damfc1(d1), damfc2(d2), beta(b),
00093 mom1p(m1p), rot1p(r1p), mom3p(m2p), rot3p(r2p),
00094 mom1n(m1n), rot1n(r1n), mom3n(m2n), rot3n(r2n)
00095 {
00096 bool error = false;
00097
00098
00099 if (rot1p <= 0.0)
00100 error = true;
00101
00102 if (rot3p <= rot1p)
00103 error = true;
00104
00105
00106 if (rot1n >= 0.0)
00107 error = true;
00108
00109 if (rot3n >= rot1n)
00110 error = true;
00111
00112 if (error) {
00113 opserr << "HystereticMaterial::HystereticMaterial -- input backbone is not unique (one-to-one)\n";
00114 exit(-1);
00115 }
00116
00117
00118
00119 energyA = 0.5 * (rot1p*mom1p + (rot3p-rot1p)*(mom3p+mom1p) +
00120 rot1n*mom1n + (rot3n-rot1n)*(mom3n+mom1n));
00121
00122 mom2p = 0.5*(mom1p+mom3p);
00123 mom2n = 0.5*(mom1n+mom3n);
00124
00125 rot2p = 0.5*(rot1p+rot3p);
00126 rot2n = 0.5*(rot1n+rot3n);
00127
00128 opserr << mom1p << " " << mom2p << " " << mom3p << " " << rot1p << " " << rot2p << " " << rot3p << endln;
00129
00130
00131 this->setEnvelope();
00132
00133
00134 this->revertToStart();
00135 this->revertToLastCommit();
00136 }
00137
00138 HystereticMaterial::HystereticMaterial():
00139 UniaxialMaterial(0, MAT_TAG_Hysteretic),
00140 pinchX(0.0), pinchY(0.0), damfc1(0.0), damfc2(0.0), beta(0.0),
00141 mom1p(0.0), rot1p(0.0), mom2p(0.0), rot2p(0.0), mom3p(0.0), rot3p(0.0),
00142 mom1n(0.0), rot1n(0.0), mom2n(0.0), rot2n(0.0), mom3n(0.0), rot3n(0.0)
00143 {
00144
00145 }
00146
00147 HystereticMaterial::~HystereticMaterial()
00148 {
00149
00150 }
00151
00152 int
00153 HystereticMaterial::setTrialStrain(double strain, double strainRate)
00154 {
00155 if (TloadIndicator == 0 && strain == 0.0)
00156 return 0;
00157
00158 TrotMax = CrotMax;
00159 TrotMin = CrotMin;
00160 TenergyD = CenergyD;
00161 TrotPu = CrotPu;
00162 TrotNu = CrotNu;
00163
00164 Tstrain = strain;
00165 double dStrain = Tstrain - Cstrain;
00166
00167 TloadIndicator = CloadIndicator;
00168
00169 if (TloadIndicator == 0)
00170 TloadIndicator = (dStrain < 0.0) ? 2 : 1;
00171
00172 if (Tstrain >= CrotMax) {
00173 TrotMax = Tstrain;
00174 Ttangent = posEnvlpTangent(Tstrain);
00175 Tstress = posEnvlpStress(Tstrain);
00176 }
00177 else if (Tstrain <= CrotMin) {
00178 TrotMin = Tstrain;
00179 Ttangent = negEnvlpTangent(Tstrain);
00180 Tstress = negEnvlpStress(Tstrain);
00181 }
00182 else {
00183 if (dStrain < 0.0)
00184 negativeIncrement(dStrain);
00185 else if (dStrain > 0.0)
00186 positiveIncrement(dStrain);
00187 }
00188
00189 TenergyD = CenergyD + 0.5*(Cstress+Tstress)*dStrain;
00190
00191 return 0;
00192 }
00193
00194
00195 double
00196 HystereticMaterial::getStrain(void)
00197 {
00198 return Tstrain;
00199 }
00200
00201 double
00202 HystereticMaterial::getStress(void)
00203 {
00204 return Tstress;
00205 }
00206
00207 double
00208 HystereticMaterial::getTangent(void)
00209 {
00210 return Ttangent;
00211 }
00212
00213 void
00214 HystereticMaterial::positiveIncrement(double dStrain)
00215 {
00216 double kn = pow(CrotMin/rot1n,beta);
00217 kn = (kn < 1.0) ? 1.0 : 1.0/kn;
00218 double kp = pow(CrotMax/rot1p,beta);
00219 kp = (kp < 1.0) ? 1.0 : 1.0/kp;
00220
00221 if (TloadIndicator == 2) {
00222 TloadIndicator = 1;
00223 if (Cstress <= 0.0) {
00224 TrotNu = Cstrain - Cstress/(E1n*kn);
00225 double energy = CenergyD - 0.5*Cstress/(E1n*kn)*Cstress;
00226 double damfc = 0.0;
00227 if (CrotMin < rot1n) {
00228 damfc = damfc2*energy/energyA;
00229 damfc += damfc1*(CrotMin-rot1n)/rot1n;
00230 }
00231
00232 TrotMax = CrotMax*(1.0+damfc);
00233 }
00234 }
00235
00236 TloadIndicator = 1;
00237
00238 TrotMax = (TrotMax > rot1p) ? TrotMax : rot1p;
00239
00240 double maxmom = posEnvlpStress(TrotMax);
00241 double rotlim = negEnvlpRotlim(CrotMin);
00242 double rotrel = (rotlim > TrotNu) ? rotlim : TrotNu;
00243
00244
00245
00246
00247
00248
00249
00250 double rotmp2 = TrotMax - (1.0-pinchY)*maxmom/(E1p*kp);
00251
00252
00253 double rotch = rotrel + (rotmp2-rotrel)*pinchX;
00254
00255 double tmpmo1;
00256 double tmpmo2;
00257
00258 if (Tstrain < TrotNu) {
00259 Ttangent = E1n*kn;
00260 Tstress = Cstress + Ttangent*dStrain;
00261 if (Tstress >= 0.0) {
00262 Tstress = 0.0;
00263 Ttangent = E1n*1.0e-9;
00264 }
00265 }
00266
00267 else if (Tstrain >= TrotNu && Tstrain < rotch) {
00268 if (Tstrain <= rotrel) {
00269 Tstress = 0.0;
00270 Ttangent = E1p*1.0e-9;
00271 }
00272 else {
00273 Ttangent = maxmom*pinchY/(rotch-rotrel);
00274 tmpmo1 = Cstress + E1p*kp*dStrain;
00275 tmpmo2 = (Tstrain-rotrel)*Ttangent;
00276 if (tmpmo1 < tmpmo2) {
00277 Tstress = tmpmo1;
00278 Ttangent = E1p*kp;
00279 }
00280 else
00281 Tstress = tmpmo2;
00282 }
00283 }
00284
00285 else {
00286 Ttangent = (1.0-pinchY)*maxmom/(TrotMax-rotch);
00287 tmpmo1 = Cstress + E1p*kp*dStrain;
00288 tmpmo2 = pinchY*maxmom + (Tstrain-rotch)*Ttangent;
00289 if (tmpmo1 < tmpmo2) {
00290 Tstress = tmpmo1;
00291 Ttangent = E1p*kp;
00292 }
00293 else
00294 Tstress = tmpmo2;
00295 }
00296 }
00297
00298 void
00299 HystereticMaterial::negativeIncrement(double dStrain)
00300 {
00301 double kn = pow(CrotMin/rot1n,beta);
00302 kn = (kn < 1.0) ? 1.0 : 1.0/kn;
00303 double kp = pow(CrotMax/rot1p,beta);
00304 kp = (kp < 1.0) ? 1.0 : 1.0/kp;
00305
00306 if (TloadIndicator == 1) {
00307 TloadIndicator = 2;
00308 if (Cstress >= 0.0) {
00309 TrotPu = Cstrain - Cstress/(E1p*kp);
00310 double energy = CenergyD - 0.5*Cstress/(E1p*kp)*Cstress;
00311 double damfc = 0.0;
00312 if (CrotMax > rot1p) {
00313 damfc = damfc2*energy/energyA;
00314 damfc += damfc1*(CrotMax-rot1p)/rot1p;
00315 }
00316
00317 TrotMin = CrotMin*(1.0+damfc);
00318 }
00319 }
00320
00321 TloadIndicator = 2;
00322
00323 TrotMin = (TrotMin < rot1n) ? TrotMin : rot1n;
00324
00325 double minmom = negEnvlpStress(TrotMin);
00326 double rotlim = posEnvlpRotlim(CrotMax);
00327 double rotrel = (rotlim < TrotPu) ? rotlim : TrotPu;
00328
00329
00330
00331
00332
00333
00334 double rotmp2 = TrotMin - (1.0-pinchY)*minmom/(E1n*kn);
00335
00336
00337 double rotch = rotrel + (rotmp2-rotrel)*pinchX;
00338
00339 double tmpmo1;
00340 double tmpmo2;
00341
00342 if (Tstrain > TrotPu) {
00343 Ttangent = E1p*kp;
00344 Tstress = Cstress + Ttangent*dStrain;
00345 if (Tstress <= 0.0) {
00346 Tstress = 0.0;
00347 Ttangent = E1p*1.0e-9;
00348 }
00349 }
00350
00351 else if (Tstrain <= TrotPu && Tstrain > rotch) {
00352 if (Tstrain >= rotrel) {
00353 Tstress = 0.0;
00354 Ttangent = E1n*1.0e-9;
00355 }
00356 else {
00357 Ttangent = minmom*pinchY/(rotch-rotrel);
00358 tmpmo1 = Cstress + E1n*kn*dStrain;
00359 tmpmo2 = (Tstrain-rotrel)*Ttangent;
00360 if (tmpmo1 > tmpmo2) {
00361 Tstress = tmpmo1;
00362 Ttangent = E1n*kn;
00363 }
00364 else
00365 Tstress = tmpmo2;
00366 }
00367 }
00368
00369 else {
00370 Ttangent = (1.0-pinchY)*minmom/(TrotMin-rotch);
00371 tmpmo1 = Cstress + E1n*kn*dStrain;
00372 tmpmo2 = pinchY*minmom + (Tstrain-rotch)*Ttangent;
00373 if (tmpmo1 > tmpmo2) {
00374 Tstress = tmpmo1;
00375 Ttangent = E1n*kn;
00376 }
00377 else
00378 Tstress = tmpmo2;
00379 }
00380 }
00381
00382 int
00383 HystereticMaterial::commitState(void)
00384 {
00385 CrotMax = TrotMax;
00386 CrotMin = TrotMin;
00387 CrotPu = TrotPu;
00388 CrotNu = TrotNu;
00389 CenergyD = TenergyD;
00390 CloadIndicator = TloadIndicator;
00391
00392 Cstress = Tstress;
00393 Cstrain = Tstrain;
00394 return 0;
00395 }
00396
00397 int
00398 HystereticMaterial::revertToLastCommit(void)
00399 {
00400 TrotMax = CrotMax;
00401 TrotMin = CrotMin;
00402 TrotPu = CrotPu;
00403 TrotNu = CrotNu;
00404 TenergyD = CenergyD;
00405 TloadIndicator = CloadIndicator;
00406
00407 Tstress = Cstress;
00408 Tstrain = Cstrain;
00409
00410 return 0;
00411 }
00412
00413 int
00414 HystereticMaterial::revertToStart(void)
00415 {
00416 CrotMax = 0.0;
00417 CrotMin = 0.0;
00418 CrotPu = 0.0;
00419 CrotNu = 0.0;
00420 CenergyD = 0.0;
00421 CloadIndicator = 0;
00422
00423 Cstress = 0.0;
00424 Cstrain = 0.0;
00425
00426 Tstrain = 0;
00427 Tstress = 0;
00428 Ttangent = E1p;
00429
00430 return 0;
00431 }
00432
00433 UniaxialMaterial*
00434 HystereticMaterial::getCopy(void)
00435 {
00436 HystereticMaterial *theCopy = new HystereticMaterial (this->getTag(),
00437 mom1p, rot1p, mom2p, rot2p, mom3p, rot3p,
00438 mom1n, rot1n, mom2n, rot2n, mom3n, rot3n,
00439 pinchX, pinchY, damfc1, damfc2, beta);
00440
00441 theCopy->CrotMax = CrotMax;
00442 theCopy->CrotMin = CrotMin;
00443 theCopy->CrotPu = CrotPu;
00444 theCopy->CrotNu = CrotNu;
00445 theCopy->CenergyD = CenergyD;
00446 theCopy->CloadIndicator = CloadIndicator;
00447 theCopy->Cstress = Cstress;
00448 theCopy->Cstrain = Cstrain;
00449 theCopy->Ttangent = Ttangent;
00450
00451 return theCopy;
00452 }
00453
00454 int
00455 HystereticMaterial::sendSelf(int commitTag, Channel &theChannel)
00456 {
00457 int res = 0;
00458
00459 static Vector data(27);
00460
00461 data(0) = this->getTag();
00462 data(1) = mom1p;
00463 data(2) = rot1p;
00464 data(3) = mom2p;
00465 data(4) = rot2p;
00466 data(5) = mom3p;
00467 data(6) = rot3p;
00468 data(7) = mom1n;
00469 data(8) = rot1n;
00470 data(9) = mom2n;
00471 data(10) = rot2n;
00472 data(11) = mom3n;
00473 data(12) = rot3n;
00474 data(13) = pinchX;
00475 data(14) = pinchY;
00476 data(15) = damfc1;
00477 data(16) = damfc2;
00478 data(17) = beta;
00479 data(18) = CrotMax;
00480 data(19) = CrotMin;
00481 data(20) = CrotPu;
00482 data(21) = CrotNu;
00483 data(22) = CenergyD;
00484 data(23) = CloadIndicator;
00485 data(24) = Cstress;
00486 data(25) = Cstrain;
00487 data(26) = Ttangent;
00488
00489 res = theChannel.sendVector(this->getDbTag(), commitTag, data);
00490 if (res < 0)
00491 opserr << "HystereticMaterial::sendSelf() - failed to send data\n";
00492
00493
00494 return res;
00495 }
00496
00497 int
00498 HystereticMaterial::recvSelf(int commitTag, Channel &theChannel,
00499 FEM_ObjectBroker &theBroker)
00500 {
00501 int res = 0;
00502
00503 static Vector data(27);
00504 res = theChannel.recvVector(this->getDbTag(), commitTag, data);
00505
00506 if (res < 0) {
00507 opserr << "HystereticMaterial::recvSelf() - failed to receive data\n";
00508 return res;
00509 }
00510 else {
00511 this->setTag((int)data(0));
00512 mom1p = data(1);
00513 rot1p = data(2);
00514 mom2p = data(3);
00515 rot2p = data(4);
00516 mom3p = data(5);
00517 rot3p = data(6);
00518 mom1n = data(7);
00519 rot1n = data(8);
00520 mom2n = data(9);
00521 rot2n = data(10);
00522 mom3n = data(11);
00523 rot3n = data(12);
00524 pinchX = data(13);
00525 pinchY = data(14);
00526 damfc1 = data(15);
00527 damfc2 = data(16);
00528 beta = data(17);
00529 CrotMax = data(18);
00530 CrotMin = data(19);
00531 CrotPu = data(20);
00532 CrotNu = data(21);
00533 CenergyD = data(22);
00534 CloadIndicator = int(data(23));
00535 Cstress = data(24);
00536 Cstrain = data(25);
00537 Ttangent = data(26);
00538
00539
00540 TrotMax = CrotMax;
00541 TrotMin = CrotMin;
00542 TrotPu = CrotPu;
00543 TrotNu = CrotNu;
00544 TenergyD = CenergyD;
00545 TloadIndicator = CloadIndicator;
00546 Tstress = Cstress;
00547 Tstrain = Cstrain;
00548
00549 }
00550
00551 return 0;
00552 }
00553
00554 void
00555 HystereticMaterial::Print(OPS_Stream &s, int flag)
00556 {
00557 s << "Hysteretic Material, tag: " << this->getTag() << endln;
00558 s << "mom1p: " << mom1p << endln;
00559 s << "rot1p: " << rot1p << endln;
00560 s << "E1p: " << E1p << endln;
00561 s << "mom2p: " << mom2p << endln;
00562 s << "rot2p: " << rot2p << endln;
00563 s << "E2p: " << E2p << endln;
00564 s << "mom3p: " << mom3p << endln;
00565 s << "rot3p: " << rot3p << endln;
00566 s << "E3p: " << E3p << endln;
00567
00568 s << "mom1n: " << mom1n << endln;
00569 s << "rot1n: " << rot1n << endln;
00570 s << "E1n: " << E1n << endln;
00571 s << "mom2n: " << mom2n << endln;
00572 s << "rot2n: " << rot2n << endln;
00573 s << "E2n: " << E2n << endln;
00574 s << "mom3n: " << mom3n << endln;
00575 s << "rot3n: " << rot3n << endln;
00576 s << "E3n: " << E3n << endln;
00577
00578 s << "pinchX: " << pinchX << endln;
00579 s << "pinchY: " << pinchY << endln;
00580 s << "damfc1: " << damfc1 << endln;
00581 s << "damfc2: " << damfc2 << endln;
00582 s << "energyA: " << energyA << endln;
00583 s << "beta: " << beta << endln;
00584 }
00585
00586 void
00587 HystereticMaterial::setEnvelope(void)
00588 {
00589 E1p = mom1p/rot1p;
00590 E2p = (mom2p-mom1p)/(rot2p-rot1p);
00591 E3p = (mom3p-mom2p)/(rot3p-rot2p);
00592
00593 E1n = mom1n/rot1n;
00594 E2n = (mom2n-mom1n)/(rot2n-rot1n);
00595 E3n = (mom3n-mom2n)/(rot3n-rot2n);
00596 }
00597
00598 double
00599 HystereticMaterial::posEnvlpStress(double strain)
00600 {
00601 if (strain <= 0.0)
00602 return 0.0;
00603 else if (strain <= rot1p)
00604 return E1p*strain;
00605 else if (strain <= rot2p)
00606 return mom1p + E2p*(strain-rot1p);
00607 else if (strain <= rot3p || E3p > 0.0)
00608 return mom2p + E3p*(strain-rot2p);
00609 else
00610 return mom3p;
00611 }
00612
00613 double
00614 HystereticMaterial::negEnvlpStress(double strain)
00615 {
00616 if (strain >= 0.0)
00617 return 0.0;
00618 else if (strain >= rot1n)
00619 return E1n*strain;
00620 else if (strain >= rot2n)
00621 return mom1n + E2n*(strain-rot1n);
00622 else if (strain >= rot3n || E3n > 0.0)
00623 return mom2n + E3n*(strain-rot2n);
00624 else
00625 return mom3n;
00626 }
00627
00628 double
00629 HystereticMaterial::posEnvlpTangent(double strain)
00630 {
00631 if (strain < 0.0)
00632 return E1p*1.0e-9;
00633 else if (strain <= rot1p)
00634 return E1p;
00635 else if (strain <= rot2p)
00636 return E2p;
00637 else if (strain <= rot3p || E3p > 0.0)
00638 return E3p;
00639 else
00640 return E1p*1.0e-9;
00641 }
00642
00643 double
00644 HystereticMaterial::negEnvlpTangent(double strain)
00645 {
00646 if (strain > 0.0)
00647 return E1n*1.0e-9;
00648 else if (strain >= rot1n)
00649 return E1n;
00650 else if (strain >= rot2n)
00651 return E2n;
00652 else if (strain >= rot3n || E3n > 0.0)
00653 return E3n;
00654 else
00655 return E1n*1.0e-9;
00656 }
00657
00658 double
00659 HystereticMaterial::posEnvlpRotlim(double strain)
00660 {
00661 double strainLimit = POS_INF_STRAIN;
00662
00663 if (strain <= rot1p)
00664 return POS_INF_STRAIN;
00665 if (strain > rot1p && strain <= rot2p && E2p < 0.0)
00666 strainLimit = rot1p - mom1p/E2p;
00667 if (strain > rot2p && E3p < 0.0)
00668 strainLimit = rot2p - mom2p/E3p;
00669
00670 if (strainLimit == POS_INF_STRAIN)
00671 return POS_INF_STRAIN;
00672 else if (posEnvlpStress(strainLimit) > 0)
00673 return POS_INF_STRAIN;
00674 else
00675 return strainLimit;
00676 }
00677
00678 double
00679 HystereticMaterial::negEnvlpRotlim(double strain)
00680 {
00681 double strainLimit = NEG_INF_STRAIN;
00682
00683 if (strain >= rot1n)
00684 return NEG_INF_STRAIN;
00685 if (strain < rot1n && strain >= rot2n && E2n < 0.0)
00686 strainLimit = rot1n - mom1n/E2n;
00687 if (strain < rot2n && E3n < 0.0)
00688 strainLimit = rot2n - mom2n/E3n;
00689
00690 if (strainLimit == NEG_INF_STRAIN)
00691 return NEG_INF_STRAIN;
00692 else if (negEnvlpStress(strainLimit) < 0)
00693 return NEG_INF_STRAIN;
00694 else
00695 return strainLimit;
00696 }