00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <TzLiq1.h>
00023 #include <NDMaterial.h>
00024 #include <Vector.h>
00025 #include <Channel.h>
00026 #include <math.h>
00027
00028
00029 const int TZmaxIterations = 20;
00030 const double TZtolerance = 1.0e-12;
00031
00032 int TzLiq1::loadStage = 0;
00033 Vector TzLiq1::stressV3(3);
00034
00036
00037
00038 TzLiq1::TzLiq1(int tag, int classtag, int tz_type, double t_ult, double z_50,
00039 double dash_pot, int solid_elem1, int solid_elem2, Domain *the_Domain)
00040 :TzSimple1(tag, classtag, tz_type, t_ult, z_50, dash_pot),
00041 solidElem1(solid_elem1), solidElem2(solid_elem2), theDomain(the_Domain)
00042 {
00043
00044
00045 this->revertToStart();
00046 initialTangent = Tangent;
00047 }
00048
00050
00051
00052 TzLiq1::TzLiq1()
00053 :TzSimple1(), solidElem1(0), solidElem2(0), theDomain(0)
00054 {
00055 }
00057
00058 TzLiq1::~TzLiq1()
00059 {
00060
00061
00062
00063 }
00064
00066 int
00067 TzLiq1::setTrialStrain (double newz, double zRate)
00068 {
00069
00070
00071 TzSimple1::setTrialStrain(newz, zRate);
00072 Tz = newz;
00073
00074
00075
00076
00077
00078 if(lastLoadStage ==0 && loadStage ==1){
00079
00080 meanConsolStress = getEffectiveStress();
00081 if(meanConsolStress == 0.0){
00082 opserr << "WARNING meanConsolStress is 0 in solid elements, ru will divide by zero";
00083 opserr << "TzLiq1: " << endln;
00084 opserr << "Adjacent solidElems: " << solidElem1 << ", " << solidElem2 << endln;
00085 exit(-1);
00086 }
00087 }
00088 lastLoadStage = loadStage;
00089
00090
00091
00092
00093 if(loadStage == 1) {
00094 double meanStress = getEffectiveStress();
00095 Tru = 1.0 - meanStress/meanConsolStress;
00096 if(Tru > 0.999) Tru = 0.999;
00097 }
00098 else {
00099 Tru = 0.0;
00100 }
00101
00102
00103
00104 double baseT = TzSimple1::getStress();
00105 double baseTangent = TzSimple1::getTangent();
00106
00107
00108
00109 if(Tz !=Cz || Tt !=Ct) Hru = Tru;
00110
00111
00112
00113
00114
00115 if (Tru < Cru){
00116
00117 maxTangent = (TzSimple1::tult/TzSimple1::z50)*(1.0-Cru);
00118
00119
00120
00121 if(Cz>0.0 && Tz<Cz && baseT>0.0){
00122 Hru = Cru;
00123 }
00124 if(Cz<0.0 && Tz>Cz && baseT<0.0){
00125 Hru = Cru;
00126 }
00127
00128
00129
00130 double zref = Cz + baseT*(Cru-Tru)/maxTangent;
00131 if(Cz>0.0 && Tz>Cz && Tz<zref){
00132 Hru = 1.0 - (Ct + (Tz-Cz)*maxTangent)/baseT;
00133 }
00134 if(Cz<0.0 && Tz<Cz && Tz>zref){
00135 Hru = 1.0 - (Ct + (Tz-Cz)*maxTangent)/baseT;
00136 }
00137 }
00138
00139
00140
00141
00142 Tt = baseT*(1.0-Hru);
00143 if(Hru==Cru || Hru==Tru){
00144 Tangent = (1.0-Hru)*baseTangent;
00145 }
00146 else {
00147 Tangent = maxTangent;
00148 }
00149
00150 return 0;
00151 }
00153 double
00154 TzLiq1::getStress(void)
00155 {
00156 double dashForce = getStrainRate()*this->getDampTangent();
00157
00158
00159
00160 double tmax = (1.0-TZtolerance)*TzSimple1::tult*(1.0-Hru);
00161 if(fabs(Tt + dashForce) >= tmax)
00162 return tmax*(Tt+dashForce)/fabs(Tt+dashForce);
00163 else return Tt + dashForce;
00164
00165 }
00167 double
00168 TzLiq1::getTangent(void)
00169 {
00170 return this->Tangent;
00171
00172 }
00174 double
00175 TzLiq1::getInitialTangent(void)
00176 {
00177 return this->initialTangent;
00178 }
00180 double
00181 TzLiq1::getDampTangent(void)
00182 {
00183
00184
00185
00186 double dampTangent = TzSimple1::getDampTangent();
00187 return dampTangent*(1.0-Hru);
00188 }
00190 double
00191 TzLiq1::getStrain(void)
00192 {
00193 double strain = TzSimple1::getStrain();
00194 return strain;
00195 }
00197 double
00198 TzLiq1::getStrainRate(void)
00199 {
00200 double strainrate = TzSimple1::getStrainRate();
00201 return strainrate;
00202 }
00204 int
00205 TzLiq1::commitState(void)
00206 {
00207
00208
00209 TzSimple1::commitState();
00210 Cz = Tz;
00211 Ct = Tt;
00212 Cru= Hru;
00213
00214 return 0;
00215 }
00216
00218 int
00219 TzLiq1::revertToLastCommit(void)
00220 {
00221
00222
00223 TzSimple1::revertToLastCommit();
00224 Tz = Cz;
00225 Tt = Ct;
00226 Hru= Cru;
00227
00228 return 0;
00229 }
00230
00232 int
00233 TzLiq1::revertToStart(void)
00234 {
00235
00236
00237 TzSimple1::revertToStart();
00238 Tz = 0.0;
00239 Tt = 0.0;
00240 maxTangent = (TzSimple1::tult/TzSimple1::z50);
00241
00242
00243
00244 Tru = 0.0;
00245 Hru = 0.0;
00246 meanConsolStress = -TzSimple1::tult;
00247 lastLoadStage = 0;
00248 loadStage = 0;
00249 elemFlag.assign("NONE");
00250
00251
00252
00253 commitState();
00254
00255 return 0;
00256 }
00257
00259 double
00260 TzLiq1::getEffectiveStress(void)
00261 {
00262
00263 double meanStress = meanConsolStress;
00264
00265
00266
00267 if(elemFlag.compare("NONE") == 0) {
00268
00269
00270
00271 if(theDomain != 0)
00272 {
00273 Element *theElement1 = theDomain->getElement(solidElem1);
00274 Element *theElement2 = theDomain->getElement(solidElem2);
00275 if (theElement1 == 0 || theElement2 == 0) {
00276 opserr << "WARNING solid element not found in getEffectiveStress" << endln;
00277 opserr << "TzLiq1: " << endln;
00278 opserr << "Adjacent solidElems: " << solidElem1 << ", " << solidElem2 << endln;
00279 exit(-1);
00280 }
00281
00282
00283 theQuad1 = dynamic_cast<FourNodeQuad*>(theElement1);
00284 theQuad2 = dynamic_cast<FourNodeQuad*>(theElement2);
00285 if(theQuad1 != 0 && theQuad2 != 0) {
00286 elemFlag.assign("4NodeQuad");
00287 }
00288
00289
00290 if(elemFlag.compare("NONE") == 0) {
00291
00292
00293 elemFlag.assign("NONE");
00294 }
00295
00296
00297
00298 if(elemFlag.compare("4NodeQuad") == 0) {
00299 NDMaterial *theNDM1[4];
00300 NDMaterial *theNDM2[4];
00301 FluidSolidPorousMaterial *theFSPM1[4];
00302 FluidSolidPorousMaterial *theFSPM2[4];
00303 int dummy = 0;
00304 for (int i=0; i<4; i++) {
00305 theNDM1[i] = theQuad1->theMaterial[i];
00306 theNDM2[i] = theQuad2->theMaterial[i];
00307 theFSPM1[i] = dynamic_cast<FluidSolidPorousMaterial*>(theNDM1[i]);
00308 theFSPM2[i] = dynamic_cast<FluidSolidPorousMaterial*>(theNDM2[i]);
00309 if(theFSPM1 == 0 || theFSPM2 == 0) dummy = dummy + 1;
00310 }
00311 if(dummy == 0) elemFlag.append("-FSPM");
00312
00313
00314 }
00315
00316 if(elemFlag.compare("NONE") == 0) {
00317 opserr << "WARNING: Adjoining solid elements did not return valid pointers";
00318 opserr << "TzLiq1: " << endln;
00319 opserr << "Adjacent solidElems: " << solidElem1 << ", " << solidElem2 << endln;
00320 exit(-1);
00321 return meanStress;
00322 }
00323
00324 }
00325 }
00326
00327
00328
00329 if(elemFlag.compare("NONE") != 0) {
00330
00331 if(elemFlag.compare("4NodeQuad-FSPM") == 0) {
00332 meanStress = 0.0;
00333 Vector *theStressVector = &stressV3;
00334 double excessPorePressure = 0.0;
00335 NDMaterial *theNDM;
00336 FluidSolidPorousMaterial *theFSPM;
00337
00338 for(int i=0; i < 4; i++) {
00339 *theStressVector = theQuad1->theMaterial[i]->getStress();
00340 meanStress += 2.0*(*theStressVector)[0] + (*theStressVector)[1];
00341 *theStressVector = theQuad2->theMaterial[i]->getStress();
00342 meanStress += 2.0*(*theStressVector)[0] + (*theStressVector)[1];
00343
00344 theNDM = theQuad1->theMaterial[i];
00345 theFSPM= dynamic_cast<FluidSolidPorousMaterial*>(theNDM);
00346 excessPorePressure += (theFSPM->trialExcessPressure);
00347 theNDM = theQuad2->theMaterial[i];
00348 theFSPM= dynamic_cast<FluidSolidPorousMaterial*>(theNDM);
00349 excessPorePressure += (theFSPM->trialExcessPressure);
00350 }
00351 meanStress = meanStress/(2.0*4.0*3.0);
00352 excessPorePressure = excessPorePressure/(2.0*4.0);
00353 meanStress = meanStress - excessPorePressure;
00354
00355 return meanStress;
00356 }
00357
00358 else if(elemFlag.compare("4NodeQuadUP-FSPM") == 0) {
00359
00360
00361
00362 return meanStress;
00363 }
00364
00365 else {
00366 opserr << "WARNING: Something wrong with specification of elemFlag in getEffectiveStress";
00367 opserr << "TzLiq1: " << endln;
00368 opserr << "Adjacent solidElems: " << solidElem1 << ", " << solidElem2 << endln;
00369 exit(-1);
00370 return meanStress;
00371 }
00372 }
00373
00374 return meanStress;
00375 }
00376
00378 int
00379 TzLiq1::updateParameter(int snum,Information &eleInformation)
00380 {
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 if(snum !=0 && snum !=1){
00392 opserr << "WARNING updateMaterialStage for TzLiq1 material must be 0 or 1";
00393 opserr << endln;
00394 exit(-1);
00395 }
00396 loadStage = snum;
00397
00398 return 0;
00399 }
00400
00402 UniaxialMaterial *
00403 TzLiq1::getCopy(void)
00404 {
00405
00406
00407 TzLiq1 *clone;
00408 clone = new TzLiq1();
00409 *clone = *this;
00410
00411 return clone;
00412 }
00413
00415 int
00416 TzLiq1::sendSelf(int cTag, Channel &theChannel)
00417 {
00418
00419
00420 int res =0;
00421
00422 static Vector data(16);
00423
00424 TzSimple1::sendSelf(cTag, theChannel);
00425
00426 data(0) = this->getTag();
00427 data(1) = Tz;
00428 data(2) = Cz;
00429 data(3) = Tt;
00430 data(4) = Ct;
00431 data(5) = Tangent;
00432 data(6) = maxTangent;
00433 data(7) = Tru;
00434 data(8) = Cru;
00435 data(9) = Hru;
00436 data(10) = solidElem1;
00437 data(11) = solidElem2;
00438 data(12) = meanConsolStress;
00439 data(13) = loadStage;
00440 data(14) = lastLoadStage;
00441 data(15) = initialTangent;
00442
00443 res = theChannel.sendVector(this->getDbTag(), cTag, data);
00444 if (res < 0)
00445 opserr << "TzLiq1::sendSelf() - failed to send data\n";
00446
00447 return res;
00448 }
00449
00451 int
00452 TzLiq1::recvSelf(int cTag, Channel &theChannel,
00453 FEM_ObjectBroker &theBroker)
00454 {
00455 int res = 0;
00456
00457 static Vector data(16);
00458 res = theChannel.recvVector(this->getDbTag(), cTag, data);
00459
00460 if (res < 0) {
00461 opserr << "TzLiq1::recvSelf() - failed to receive data\n";
00462 this->setTag(0);
00463 }
00464 else {
00465 this->setTag((int)data(0));
00466
00467 TzSimple1::recvSelf(cTag, theChannel, theBroker);
00468
00469 Tz = data(1);
00470 Cz = data(2);
00471 Tt = data(3);
00472 Ct = data(4);
00473 Tangent = data(5);
00474 maxTangent =data(6);
00475 Tru = data(7);
00476 Cru = data(8);
00477 Hru = data(9);
00478 solidElem1 = (int)data(10);
00479 solidElem2 = (int)data(11);
00480 meanConsolStress = data(12);
00481 loadStage = (int)data(13);
00482 lastLoadStage = (int)data(14);
00483 initialTangent = data(15);
00484
00485
00486 this->revertToLastCommit();
00487 }
00488
00489 return res;
00490 }
00491
00493 void
00494 TzLiq1::Print(OPS_Stream &s, int flag)
00495 {
00496 s << "TzLiq1, tag: " << this->getTag() << endln;
00497 s << " tzType: " << tzType << endln;
00498 s << " tult: " << tult << endln;
00499 s << " z50: " << z50 << endln;
00500 s << " dashpot: " << dashpot << endln;
00501 s << " solidElem1: " << solidElem1 << endln;
00502 s << " solidElem2: " << solidElem2 << endln;
00503 }
00504