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