00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <math.h>
00014 #include <stdlib.h>
00015 #include <PressureDependMultiYield02.h>
00016 #include <Information.h>
00017 #include <ID.h>
00018 #include <MaterialResponse.h>
00019
00020 int PressureDependMultiYield02::matCount=0;
00021 int* PressureDependMultiYield02::loadStagex = 0;
00022 int* PressureDependMultiYield02::ndmx=0;
00023 double* PressureDependMultiYield02::rhox=0;
00024 double* PressureDependMultiYield02::refShearModulusx=0;
00025 double* PressureDependMultiYield02::refBulkModulusx=0;
00026 double* PressureDependMultiYield02::frictionAnglex=0;
00027 double* PressureDependMultiYield02::peakShearStrainx=0;
00028 double* PressureDependMultiYield02::refPressurex=0;
00029 double* PressureDependMultiYield02::cohesionx=0;
00030 double* PressureDependMultiYield02::pressDependCoeffx=0;
00031 int* PressureDependMultiYield02::numOfSurfacesx=0;
00032 double* PressureDependMultiYield02::phaseTransfAnglex=0;
00033 double* PressureDependMultiYield02::contractParam1x=0;
00034 double* PressureDependMultiYield02::contractParam2x=0;
00035 double* PressureDependMultiYield02::contractParam3x=0;
00036 double* PressureDependMultiYield02::dilateParam1x=0;
00037 double* PressureDependMultiYield02::dilateParam2x=0;
00038 double* PressureDependMultiYield02::liquefyParam1x=0;
00039 double* PressureDependMultiYield02::liquefyParam2x=0;
00040 double* PressureDependMultiYield02::dilateParam3x=0;
00041 double* PressureDependMultiYield02::einitx=0;
00042 double* PressureDependMultiYield02::volLimit1x=0;
00043 double* PressureDependMultiYield02::volLimit2x=0;
00044 double* PressureDependMultiYield02::volLimit3x=0;
00045 double* PressureDependMultiYield02::residualPressx=0;
00046 double* PressureDependMultiYield02::stressRatioPTx=0;
00047 double* PressureDependMultiYield02::Hvx=0;
00048 double* PressureDependMultiYield02::Pvx=0;
00049
00050 double PressureDependMultiYield02::pAtm = 101.;
00051 Matrix PressureDependMultiYield02::theTangent(6,6);
00052 T2Vector PressureDependMultiYield02::trialStrain;
00053 T2Vector PressureDependMultiYield02::subStrainRate;
00054 Vector PressureDependMultiYield02::workV6(6);
00055 T2Vector PressureDependMultiYield02::workT2V;
00056
00057 const double pi = 3.14159265358979;
00058
00059
00060
00061 PressureDependMultiYield02::PressureDependMultiYield02 (int tag, int nd,
00062 double r, double refShearModul,
00063 double refBulkModul, double frictionAng,
00064 double peakShearStra, double refPress,
00065 double pressDependCoe,
00066 double phaseTransformAng,
00067 double contractionParam1,
00068 double contractionParam3,
00069 double dilationParam1,
00070 double dilationParam3,
00071 int numberOfYieldSurf,
00072 double * gredu,
00073 double contractionParam2,
00074 double dilationParam2,
00075 double liquefactionParam1,
00076 double liquefactionParam2,
00077 double ei,
00078 double volLim1, double volLim2, double volLim3,
00079 double atm, double cohesi,
00080 double hv, double pv)
00081 : NDMaterial(tag,ND_TAG_PressureDependMultiYield02), currentStress(),
00082 trialStress(), updatedTrialStress(), currentStrain(), strainRate(),
00083 PPZPivot(), PPZCenter(), PPZPivotCommitted(), PPZCenterCommitted(),
00084 PivotStrainRate(6), PivotStrainRateCommitted(6), check(0)
00085 {
00086 if (nd !=2 && nd !=3) {
00087 opserr << "FATAL:PressureDependMultiYield02:: dimension error" << endln;
00088 opserr << "Dimension has to be 2 or 3, you give nd= " << nd << endln;
00089 exit(-1);
00090 }
00091 if (refShearModul <= 0) {
00092 opserr << "FATAL:PressureDependMultiYield02:: refShearModulus <= 0" << endln;
00093 exit(-1);
00094 }
00095 if (refBulkModul <= 0) {
00096 opserr << "FATAL:PressureDependMultiYield02:: refBulkModulus <= 0" << endln;
00097 exit(-1);
00098 }
00099 if (frictionAng <= 0.) {
00100 opserr << "FATAL:PressureDependMultiYield02:: frictionAngle <= 0" << endln;
00101 exit(-1);
00102 }
00103 if (frictionAng >= 90.) {
00104 opserr << "FATAL:PressureDependMultiYield02:: frictionAngle >= 90" << endln;
00105 exit(-1);
00106 }
00107 if (phaseTransformAng <= 0.) {
00108 opserr << "FATAL:PressureDependMultiYield02:: phaseTransformAng "<< phaseTransformAng << "<= 0" << endln;
00109 exit(-1);
00110 }
00111
00112
00113
00114
00115
00116 if (cohesi < 0) {
00117 opserr << "WARNING:PressureDependMultiYield02:: cohesion < 0" << endln;
00118 opserr << "Will reset cohesion to 0.3." << endln;
00119 cohesi = 0.3;
00120 }
00121 if (peakShearStra <= 0) {
00122 opserr << "FATAL:PressureDependMultiYield02:: peakShearStra <= 0" << endln;
00123 exit(-1);
00124 }
00125 if (refPress <= 0) {
00126 opserr << "FATAL:PressureDependMultiYield02:: refPress <= 0" << endln;
00127 exit(-1);
00128 }
00129 if (pressDependCoe < 0) {
00130 opserr << "WARNING:PressureDependMultiYield02:: pressDependCoe < 0" << endln;
00131 opserr << "Will reset pressDependCoe to 0.5." << endln;
00132 pressDependCoe = 0.5;
00133 }
00134 if (numberOfYieldSurf <= 0) {
00135 opserr << "WARNING:PressureDependMultiYield02:: numberOfSurfaces " <<numberOfYieldSurf << "<= 0" << endln;
00136 opserr << "Will use 10 yield surfaces." << endln;
00137 numberOfYieldSurf = 10;
00138 }
00139 if (numberOfYieldSurf > 100) {
00140 opserr << "WARNING:PressureDependMultiYield02::PressureDependMultiYield02: numberOfSurfaces > 100" << endln;
00141 opserr << "Will use 100 yield surfaces." << endln;
00142 numberOfYieldSurf = 100;
00143 }
00144 if (volLim1 < 0) {
00145 opserr << "WARNING:PressureDependMultiYield02:: volLim1 < 0" << endln;
00146 opserr << "Will reset volLimit to 0.8" << endln;
00147 volLim1 = 0.8;
00148 }
00149 if (r < 0) {
00150 opserr << "FATAL:PressureDependMultiYield02:: rho <= 0" << endln;
00151 exit(-1);
00152 }
00153 if (ei < 0) {
00154 opserr << "FATAL:PressureDependMultiYield02:: e <= 0" << endln;
00155 exit(-1);
00156 }
00157
00158 if (matCount%20 == 0) {
00159 int * temp1 = loadStagex;
00160 int * temp2 = ndmx;
00161 double * temp3 = rhox;
00162 double * temp4 = refShearModulusx;
00163 double * temp5 = refBulkModulusx;
00164 double * temp6 = frictionAnglex;
00165 double * temp7 = peakShearStrainx;
00166 double * temp8 = refPressurex;
00167 double * temp9 = cohesionx;
00168 double * temp10 = pressDependCoeffx;
00169 int * temp11 = numOfSurfacesx;
00170 double * temp12 = residualPressx;
00171 double * temp13 = phaseTransfAnglex;
00172 double * temp14 = contractParam1x;
00173 double * temp14a = contractParam2x;
00174 double * temp14b = contractParam3x;
00175 double * temp15 = dilateParam1x;
00176 double * temp16 = dilateParam2x;
00177 double * temp17 = liquefyParam1x;
00178 double * temp18 = liquefyParam2x;
00179 double * temp19 = dilateParam3x;
00180 double * temp20 = einitx;
00181 double * temp21 = volLimit1x;
00182 double * temp22 = volLimit2x;
00183 double * temp23 = volLimit3x;
00184 double * temp24 = stressRatioPTx;
00185 double * temp25 = Hvx;
00186 double * temp26 = Pvx;
00187
00188 loadStagex = new int[matCount+20];
00189 ndmx = new int[matCount+20];
00190 rhox = new double[matCount+20];
00191 refShearModulusx = new double[matCount+20];
00192 refBulkModulusx = new double[matCount+20];
00193 frictionAnglex = new double[matCount+20];
00194 peakShearStrainx = new double[matCount+20];
00195 refPressurex = new double[matCount+20];
00196 cohesionx = new double[matCount+20];
00197 pressDependCoeffx = new double[matCount+20];
00198 numOfSurfacesx = new int[matCount+20];
00199 residualPressx = new double[matCount+20];
00200 phaseTransfAnglex = new double[matCount+20];
00201 contractParam1x = new double[matCount+20];
00202 contractParam2x = new double[matCount+20];
00203 contractParam3x = new double[matCount+20];
00204 dilateParam1x = new double[matCount+20];
00205 dilateParam2x = new double[matCount+20];
00206 liquefyParam1x = new double[matCount+20];
00207 liquefyParam2x = new double[matCount+20];
00208 dilateParam3x = new double[matCount+20];
00209 einitx = new double[matCount+20];
00210 volLimit1x = new double[matCount+20];
00211 volLimit2x = new double[matCount+20];
00212 volLimit3x = new double[matCount+20];
00213 stressRatioPTx = new double[matCount+20];
00214 Hvx = new double[matCount+20];
00215 Pvx = new double[matCount+20];
00216
00217 for (int i=0; i<matCount; i++) {
00218 loadStagex[i] = temp1[i];
00219 ndmx[i] = temp2[i];
00220 rhox[i] = temp3[i];
00221 refShearModulusx[i] = temp4[i];
00222 refBulkModulusx[i] = temp5[i];
00223 frictionAnglex[i] = temp6[i];
00224 peakShearStrainx[i] = temp7[i];
00225 refPressurex[i] = temp8[i];
00226 cohesionx[i] = temp9[i];
00227 pressDependCoeffx[i] = temp10[i];
00228 numOfSurfacesx[i] = temp11[i];
00229 residualPressx[i] = temp12[i];
00230 phaseTransfAnglex[i] = temp13[i];
00231 contractParam1x[i] = temp14[i];
00232 contractParam2x[i] = temp14a[i];
00233 contractParam3x[i] = temp14b[i];
00234 dilateParam1x[i] = temp15[i];
00235 dilateParam2x[i] = temp16[i];
00236 liquefyParam1x[i] = temp17[i];
00237 liquefyParam2x[i] = temp18[i];
00238 dilateParam3x[i] = temp19[i];
00239 einitx[i] = temp20[i];
00240 volLimit1x[i] = temp21[i];
00241 volLimit2x[i] = temp22[i];
00242 volLimit3x[i] = temp23[i];
00243 stressRatioPTx[i] = temp24[i];
00244 Hvx[i] = temp25[i];
00245 Pvx[i] = temp26[i];
00246 }
00247
00248 if (matCount > 0) {
00249 delete [] temp1; delete [] temp2; delete [] temp3; delete [] temp4;
00250 delete [] temp5; delete [] temp6; delete [] temp7; delete [] temp8;
00251 delete [] temp9; delete [] temp10; delete [] temp11; delete [] temp12;
00252 delete [] temp13; delete [] temp14; delete [] temp14a; delete [] temp14b;
00253 delete [] temp15; delete [] temp16;
00254 delete [] temp17; delete [] temp18; delete [] temp19; delete [] temp20;
00255 delete [] temp21; delete [] temp22; delete [] temp23; delete [] temp24;
00256 delete [] temp25; delete [] temp26;
00257 }
00258 }
00259
00260 ndmx[matCount] = nd;
00261 loadStagex[matCount] = 0;
00262 refShearModulusx[matCount] = refShearModul;
00263 refBulkModulusx[matCount] = refBulkModul;
00264 frictionAnglex[matCount] = frictionAng;
00265 peakShearStrainx[matCount] = peakShearStra;
00266 refPressurex[matCount] = -refPress;
00267 cohesionx[matCount] = cohesi;
00268 pressDependCoeffx[matCount] = pressDependCoe;
00269 numOfSurfacesx[matCount] = numberOfYieldSurf;
00270 rhox[matCount] = r;
00271 phaseTransfAnglex[matCount] = phaseTransformAng;
00272 contractParam1x[matCount] = contractionParam1;
00273 contractParam2x[matCount] = contractionParam2;
00274 contractParam3x[matCount] = contractionParam3;
00275 dilateParam1x[matCount] = dilationParam1;
00276 dilateParam2x[matCount] = dilationParam2;
00277 volLimit1x[matCount] = volLim1;
00278 volLimit2x[matCount] = volLim2;
00279 volLimit3x[matCount] = volLim3;
00280 liquefyParam1x[matCount] = liquefactionParam1;
00281 liquefyParam2x[matCount] = liquefactionParam2;
00282 dilateParam3x[matCount] = dilationParam3;
00283 einitx[matCount] = ei;
00284 Hvx[matCount] = hv;
00285 Pvx[matCount] = pv;
00286
00287 matN = matCount;
00288 matCount ++;
00289 pAtm = atm;
00290
00291 int numOfSurfaces = numOfSurfacesx[matN];
00292 initPress = refPressurex[matN];
00293
00294 e2p = committedActiveSurf = activeSurfaceNum = 0;
00295 onPPZCommitted = onPPZ = -1 ;
00296 PPZSizeCommitted = PPZSize = 0.;
00297 pressureDCommitted = pressureD = modulusFactor = 0.;
00298 cumuDilateStrainOctaCommitted = cumuDilateStrainOcta = 0.;
00299 maxCumuDilateStrainOctaCommitted = maxCumuDilateStrainOcta = 0.;
00300 cumuTranslateStrainOctaCommitted = cumuTranslateStrainOcta = 0.;
00301 prePPZStrainOctaCommitted = prePPZStrainOcta = 0.;
00302 oppoPrePPZStrainOctaCommitted = oppoPrePPZStrainOcta = 0.;
00303 maxPress = 0.;
00304 damage = 0.;
00305
00306 theSurfaces = new MultiYieldSurface[numOfSurfaces+1];
00307 committedSurfaces = new MultiYieldSurface[numOfSurfaces+1];
00308
00309 setUpSurfaces(gredu);
00310 }
00311
00312
00313 PressureDependMultiYield02::PressureDependMultiYield02 ()
00314 : NDMaterial(0,ND_TAG_PressureDependMultiYield02),
00315 currentStress(), trialStress(), currentStrain(),
00316 strainRate(), PPZPivot(), PPZCenter(), PivotStrainRate(6), PivotStrainRateCommitted(6),
00317 PPZPivotCommitted(), PPZCenterCommitted(), theSurfaces(0), committedSurfaces(0)
00318 {
00319
00320 }
00321
00322
00323 PressureDependMultiYield02::PressureDependMultiYield02 (const PressureDependMultiYield02 & a)
00324 : NDMaterial(a.getTag(),ND_TAG_PressureDependMultiYield02),
00325 currentStress(a.currentStress), trialStress(a.trialStress),
00326 currentStrain(a.currentStrain), strainRate(a.strainRate), check(0),
00327 PPZPivot(a.PPZPivot), PPZCenter(a.PPZCenter), updatedTrialStress(a.updatedTrialStress),
00328 PPZPivotCommitted(a.PPZPivotCommitted), PPZCenterCommitted(a.PPZCenterCommitted),
00329 PivotStrainRate(a.PivotStrainRate), PivotStrainRateCommitted(a.PivotStrainRateCommitted)
00330 {
00331 matN = a.matN;
00332
00333 int numOfSurfaces = numOfSurfacesx[matN];
00334
00335 e2p = a.e2p;
00336 strainPTOcta = a.strainPTOcta;
00337 modulusFactor = a.modulusFactor;
00338 activeSurfaceNum = a.activeSurfaceNum;
00339 committedActiveSurf = a.committedActiveSurf;
00340 pressureDCommitted = a.pressureDCommitted;
00341 onPPZCommitted = a.onPPZCommitted;
00342 PPZSizeCommitted = a.PPZSizeCommitted;
00343 cumuDilateStrainOctaCommitted = a.cumuDilateStrainOctaCommitted;
00344 maxCumuDilateStrainOctaCommitted = a.maxCumuDilateStrainOctaCommitted;
00345 cumuTranslateStrainOctaCommitted = a.cumuTranslateStrainOctaCommitted;
00346 prePPZStrainOctaCommitted = a.prePPZStrainOctaCommitted;
00347 oppoPrePPZStrainOctaCommitted = a.oppoPrePPZStrainOctaCommitted;
00348 pressureD = a.pressureD;
00349 onPPZ = a.onPPZ;
00350 PPZSize = a.PPZSize;
00351 cumuDilateStrainOcta = a.cumuDilateStrainOcta;
00352 maxCumuDilateStrainOcta = a.maxCumuDilateStrainOcta;
00353 cumuTranslateStrainOcta = a.cumuTranslateStrainOcta;
00354 prePPZStrainOcta = a.prePPZStrainOcta;
00355 oppoPrePPZStrainOcta = a.oppoPrePPZStrainOcta;
00356 initPress = a.initPress;
00357 maxPress = a.maxPress;
00358 damage = a.damage;
00359
00360 theSurfaces = new MultiYieldSurface[numOfSurfaces+1];
00361 committedSurfaces = new MultiYieldSurface[numOfSurfaces+1];
00362 for(int i=1; i<=numOfSurfaces; i++) {
00363 committedSurfaces[i] = a.committedSurfaces[i];
00364 theSurfaces[i] = a.theSurfaces[i];
00365 }
00366 }
00367
00368
00369 PressureDependMultiYield02::~PressureDependMultiYield02 ()
00370 {
00371 if (theSurfaces != 0) delete [] theSurfaces;
00372 if (committedSurfaces != 0) delete [] committedSurfaces;
00373 }
00374
00375
00376 void PressureDependMultiYield02::elast2Plast(void)
00377 {
00378 int loadStage = loadStagex[matN];
00379 int numOfSurfaces = numOfSurfacesx[matN];
00380
00381 if (loadStage != 1 || e2p == 1) return;
00382 e2p = 1;
00383
00384 if (currentStress.volume() > 0.) {
00385
00386 currentStress.setData(currentStress.deviator(),0);
00387 }
00388
00389
00390 if (currentStress.deviatorLength() == 0.) return;
00391
00392
00393
00394
00395 while (yieldFunc(currentStress, committedSurfaces, ++committedActiveSurf) > 0) {
00396 if (committedActiveSurf == numOfSurfaces) {
00397
00398 deviatorScaling(currentStress, committedSurfaces, numOfSurfaces);
00399 initSurfaceUpdate();
00400 return;
00401 }
00402 }
00403
00404 committedActiveSurf--;
00405 initSurfaceUpdate();
00406 }
00407
00408
00409 int PressureDependMultiYield02::setTrialStrain (const Vector &strain)
00410 {
00411 int ndm = ndmx[matN];
00412
00413 if (ndm==3 && strain.Size()==6)
00414 workV6 = strain;
00415 else if (ndm==2 && strain.Size()==3) {
00416 workV6[0] = strain[0];
00417 workV6[1] = strain[1];
00418 workV6[2] = 0.0;
00419 workV6[3] = strain[2];
00420 workV6[4] = 0.0;
00421 workV6[5] = 0.0;
00422 }
00423 else {
00424 opserr << "Fatal:PressureDependMultiYield02:: Material dimension is: " << ndm << endln;
00425 opserr << "But strain vector size is: " << strain.Size() << endln;
00426 exit(-1);
00427 }
00428
00429
00430 workV6 -= currentStrain.t2Vector(1);
00431 strainRate.setData(workV6, 1);
00432
00433 return 0;
00434 }
00435
00436
00437 int PressureDependMultiYield02::setTrialStrain (const Vector &strain, const Vector &rate)
00438 {
00439 return setTrialStrain (strain);
00440 }
00441
00442
00443 int PressureDependMultiYield02::setTrialStrainIncr (const Vector &strain)
00444 {
00445 int ndm = ndmx[matN];
00446
00447 if (ndm==3 && strain.Size()==6)
00448 workV6 = strain;
00449 else if (ndm==2 && strain.Size()==3) {
00450 workV6[0] = strain[0];
00451 workV6[1] = strain[1];
00452 workV6[2] = 0.0;
00453 workV6[3] = strain[2];
00454 workV6[4] = 0.0;
00455 workV6[5] = 0.0;
00456 }
00457 else {
00458 opserr << "Fatal:PressureDependMultiYield02:: Material dimension is: " << ndm << endln;
00459 opserr << "But strain vector size is: " << strain.Size() << endln;
00460 exit(-1);
00461 }
00462
00463 strainRate.setData(workV6,1);
00464 return 0;
00465 }
00466
00467
00468 int PressureDependMultiYield02::setTrialStrainIncr (const Vector &strain, const Vector &rate)
00469 {
00470 return setTrialStrainIncr(strain);
00471 }
00472
00473
00474 const Matrix & PressureDependMultiYield02::getTangent (void)
00475 {
00476 int loadStage = loadStagex[matN];
00477 double refShearModulus = refShearModulusx[matN];
00478 double refBulkModulus = refBulkModulusx[matN];
00479 double pressDependCoeff = pressDependCoeffx[matN];
00480 double refPressure = refPressurex[matN];
00481 double residualPress = residualPressx[matN];
00482 int ndm = ndmx[matN];
00483
00484 if (loadStage == 1 && e2p == 0) {
00485 initPress = currentStress.volume();
00486 elast2Plast();
00487 }
00488 if (loadStage==2 && initPress==refPressure)
00489 initPress = currentStress.volume();
00490
00491 if (loadStage==0 || loadStage==2) {
00492 double factor;
00493 if (loadStage==0) factor = 1.0;
00494 else {
00495 factor = (initPress-residualPress)/(refPressure-residualPress);
00496 if (factor <= 1.e-10) factor = 1.e-10;
00497 else factor = pow(factor, pressDependCoeff);
00498 factor = (1.e-10>factor) ? 1.e-10 : factor;
00499 }
00500 for (int i=0;i<6;i++)
00501 for (int j=0;j<6;j++) {
00502 theTangent(i,j) = 0.;
00503 if (i==j) theTangent(i,j) += refShearModulus*factor;
00504 if (i<3 && j<3 && i==j) theTangent(i,j) += refShearModulus*factor;
00505 if (i<3 && j<3) theTangent(i,j) += (refBulkModulus - 2.*refShearModulus/3.)*factor;
00506 }
00507 }
00508 else {
00509 double coeff1, coeff2, coeff3, coeff4;
00510 double factor = getModulusFactor(updatedTrialStress);
00511 double shearModulus = factor*refShearModulus;
00512 double bulkModulus = factor*refBulkModulus;
00513
00514
00515 if (Hvx[matN] != 0. && trialStress.volume()<=maxPress
00516 && strainRate.volume()<0. && loadStage == 1) {
00517 double tp = fabs(trialStress.volume() - residualPress);
00518 bulkModulus = (bulkModulus*Hvx[matN]*pow(tp,Pvx[matN]))/(bulkModulus+Hvx[matN]*pow(tp,Pvx[matN]));
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 if (loadStage!=0 && activeSurfaceNum > 0) {
00542 factor = getModulusFactor(trialStress);
00543 shearModulus = factor*refShearModulus;
00544 bulkModulus = factor*refBulkModulus;
00545 getSurfaceNormal(trialStress, workT2V);
00546 workV6 = workT2V.deviator();
00547 double volume = workT2V.volume();
00548 double Ho = 9.*bulkModulus*volume*volume + 2.*shearModulus*(workV6 && workV6);
00549 double plastModul = factor*theSurfaces[activeSurfaceNum].modulus();
00550 coeff1 = 9.*bulkModulus*bulkModulus*volume*volume/(Ho+plastModul);
00551 coeff2 = 4.*shearModulus*shearModulus/(Ho+plastModul);
00552 }
00553
00554 else {
00555 coeff1 = coeff2 = coeff3 = coeff4 = 0.;
00556 workV6.Zero();
00557 }
00558
00559 for (int i=0;i<6;i++)
00560 for (int j=0;j<6;j++) {
00561 theTangent(i,j) = - coeff2*workV6[i]*workV6[j];
00562 if (i==j) theTangent(i,j) += shearModulus;
00563 if (i<3 && j<3 && i==j) theTangent(i,j) += shearModulus;
00564 if (i<3 && j<3) theTangent(i,j) += (bulkModulus - 2.*shearModulus/3. - coeff1);
00565
00566
00567
00568 }
00569 }
00570
00571 if (ndm==3)
00572 return theTangent;
00573 else {
00574 static Matrix workM(3,3);
00575 workM(0,0) = theTangent(0,0);
00576 workM(0,1) = theTangent(0,1);
00577 workM(0,2) = 0.;
00578
00579 workM(1,0) = theTangent(1,0);
00580 workM(1,1) = theTangent(1,1);
00581 workM(1,2) = 0.;
00582
00583 workM(2,0) = 0.;
00584 workM(2,1) = 0.;
00585 workM(2,2) = theTangent(3,3);
00586
00587
00588
00589
00590
00591
00592 return workM;
00593 }
00594 }
00595
00596
00597 const Matrix & PressureDependMultiYield02::getInitialTangent (void)
00598 {
00599 int loadStage = loadStagex[matN];
00600 double refShearModulus = refShearModulusx[matN];
00601 double refBulkModulus = refBulkModulusx[matN];
00602 double pressDependCoeff = pressDependCoeffx[matN];
00603 double refPressure = refPressurex[matN];
00604 double residualPress = residualPressx[matN];
00605 int ndm = ndmx[matN];
00606
00607 if (loadStage == 1 && e2p == 0) {
00608 initPress = currentStress.volume();
00609 elast2Plast();
00610 }
00611 if (loadStage==2 && initPress==refPressure)
00612 initPress = currentStress.volume();
00613 double factor;
00614 if (loadStage==0)
00615 factor = 1.;
00616 else if (loadStage==2) {
00617 factor = (initPress-residualPress)/(refPressure-residualPress);
00618 if (factor <= 1.e-10) factor = 1.e-10;
00619 else factor = pow(factor, pressDependCoeff);
00620 factor = (1.e-10>factor) ? 1.e-10 : factor;
00621 }
00622 else if (loadStage==1)
00623 factor = getModulusFactor(currentStress);
00624
00625 for (int i=0;i<6;i++)
00626 for (int j=0;j<6;j++) {
00627 theTangent(i,j) = 0.;
00628 if (i==j) theTangent(i,j) += refShearModulus*factor;
00629 if (i<3 && j<3 && i==j) theTangent(i,j) += refShearModulus*factor;
00630 if (i<3 && j<3) theTangent(i,j) += (refBulkModulus - 2.*refShearModulus/3.)*factor;
00631 }
00632
00633 if (ndm==3)
00634 return theTangent;
00635 else {
00636 static Matrix workM(3,3);
00637 workM(0,0) = theTangent(0,0);
00638 workM(0,1) = theTangent(0,1);
00639 workM(0,2) = 0.;
00640
00641 workM(1,0) = theTangent(1,0);
00642 workM(1,1) = theTangent(1,1);
00643 workM(1,2) = 0.;
00644
00645 workM(2,0) = 0.;
00646 workM(2,1) = 0.;
00647 workM(2,2) = theTangent(3,3);
00648
00649
00650
00651
00652
00653
00654 return workM;
00655 }
00656 }
00657
00658
00659 const Vector & PressureDependMultiYield02::getStress (void)
00660 {
00661 int loadStage = loadStagex[matN];
00662 int numOfSurfaces = numOfSurfacesx[matN];
00663 int ndm = ndmx[matN];
00664
00665 int i, is;
00666 if (loadStage == 1 && e2p == 0) {
00667 initPress = currentStress.volume();
00668 elast2Plast();
00669 }
00670
00671 if (loadStage!=1) {
00672
00673 getTangent();
00674 workV6 = currentStress.t2Vector();
00675 workV6.addMatrixVector(1.0, theTangent, strainRate.t2Vector(1), 1.0);
00676 trialStress.setData(workV6);
00677 }
00678 else {
00679 for (i=1; i<=numOfSurfaces; i++) theSurfaces[i] = committedSurfaces[i];
00680 activeSurfaceNum = committedActiveSurf;
00681 pressureD = pressureDCommitted;
00682 onPPZ = onPPZCommitted;
00683 PPZSize = PPZSizeCommitted;
00684 cumuDilateStrainOcta = cumuDilateStrainOctaCommitted;
00685 maxCumuDilateStrainOcta = maxCumuDilateStrainOctaCommitted;
00686 cumuTranslateStrainOcta = cumuTranslateStrainOctaCommitted;
00687 prePPZStrainOcta = prePPZStrainOctaCommitted;
00688 oppoPrePPZStrainOcta = oppoPrePPZStrainOctaCommitted;
00689 PPZPivot = PPZPivotCommitted;
00690 PivotStrainRate = PivotStrainRateCommitted;
00691 PPZCenter = PPZCenterCommitted;
00692
00693 subStrainRate = strainRate;
00694 setTrialStress(currentStress);
00695 if (activeSurfaceNum>0 && isLoadReversal(currentStress)) {
00696 updateInnerSurface();
00697 activeSurfaceNum = 0;
00698 }
00699
00700 if (activeSurfaceNum==0 && !isCrossingNextSurface()) {
00701 workV6 = currentStrain.t2Vector();
00702 workV6.addVector(1.0, strainRate.t2Vector(), 1.0);
00703 trialStrain.setData(workV6);
00704 }
00705 else {
00706 int numSubIncre = setSubStrainRate();
00707
00708 for (i=0; i<numSubIncre; i++) {
00709
00710
00711 workV6 = currentStrain.t2Vector();
00712 workV6.addVector(1.0, subStrainRate.t2Vector(), (i+1));
00713 trialStrain.setData(workV6);
00714
00715 if (i==0) {
00716 updatedTrialStress = currentStress;
00717 setTrialStress(currentStress);
00718 is = isLoadReversal(currentStress);
00719 }
00720 else {
00721 updatedTrialStress = trialStress;
00722 workT2V.setData(trialStress.t2Vector());
00723 setTrialStress(trialStress);
00724 is = isLoadReversal(workT2V);
00725 }
00726
00727 if (activeSurfaceNum>0 && is) {
00728 updateInnerSurface();
00729 activeSurfaceNum = 0;
00730 }
00731 if (activeSurfaceNum==0 && !isCrossingNextSurface()) continue;
00732 if (activeSurfaceNum==0) activeSurfaceNum++;
00733 stressCorrection(0);
00734 updateActiveSurface();
00735
00736 double refBulkModulus = refBulkModulusx[matN];
00737
00738 double B = refBulkModulus*modulusFactor;
00739
00740
00741
00742
00743 pressureD += 3.*subStrainRate.volume()
00744 - (trialStress.volume()-updatedTrialStress.volume())/B;
00745 if (pressureD < 0.) pressureD = 0.;
00746
00747 }
00748 }
00749 }
00750
00751 if (ndm==3)
00752 return trialStress.t2Vector();
00753 else {
00754 static Vector workV(3);
00755 workV[0] = trialStress.t2Vector()[0];
00756 workV[1] = trialStress.t2Vector()[1];
00757 workV[2] = trialStress.t2Vector()[3];
00758 return workV;
00759 }
00760 }
00761
00762
00763 const Vector & PressureDependMultiYield02::getStrain (void)
00764 {
00765 return getCommittedStrain();
00766 }
00767
00768
00769 int PressureDependMultiYield02::commitState (void)
00770 {
00771 int loadStage = loadStagex[matN];
00772 int numOfSurfaces = numOfSurfacesx[matN];
00773
00774 currentStress = trialStress;
00775
00776 workV6 = currentStrain.t2Vector();
00777 workV6 += strainRate.t2Vector();
00778 currentStrain.setData(workV6);
00779
00780 workV6.Zero();
00781 strainRate.setData(workV6);
00782
00783 if (loadStage==1) {
00784 committedActiveSurf = activeSurfaceNum;
00785 for (int i=1; i<=numOfSurfaces; i++) committedSurfaces[i] = theSurfaces[i];
00786 pressureDCommitted = pressureD;
00787 onPPZCommitted = onPPZ;
00788 PPZSizeCommitted = PPZSize;
00789 cumuDilateStrainOctaCommitted = cumuDilateStrainOcta;
00790 maxCumuDilateStrainOctaCommitted = maxCumuDilateStrainOcta;
00791 cumuTranslateStrainOctaCommitted = cumuTranslateStrainOcta;
00792 prePPZStrainOctaCommitted = prePPZStrainOcta;
00793 oppoPrePPZStrainOctaCommitted = oppoPrePPZStrainOcta;
00794 PPZPivotCommitted = PPZPivot;
00795 PivotStrainRateCommitted = PivotStrainRate;
00796 PPZCenterCommitted = PPZCenter;
00797 if (currentStress.volume() < maxPress) maxPress = currentStress.volume();
00798 }
00799
00800 return 0;
00801 }
00802
00803
00804 int PressureDependMultiYield02::revertToLastCommit (void)
00805 {
00806 return 0;
00807 }
00808
00809
00810 NDMaterial * PressureDependMultiYield02::getCopy (void)
00811 {
00812 PressureDependMultiYield02 * copy = new PressureDependMultiYield02(*this);
00813 return copy;
00814 }
00815
00816
00817 NDMaterial * PressureDependMultiYield02::getCopy (const char *code)
00818 {
00819 if (strcmp(code,"PressureDependMultiYield02") == 0 || strcmp(code,"PlaneStrain") == 0
00820 || strcmp(code,"ThreeDimensional") == 0) {
00821 PressureDependMultiYield02 * copy = new PressureDependMultiYield02(*this);
00822 return copy;
00823 }
00824
00825 return 0;
00826 }
00827
00828
00829 const char * PressureDependMultiYield02::getType (void) const
00830 {
00831 int ndm = ndmx[matN];
00832
00833 return (ndm == 2) ? "PlaneStrain" : "ThreeDimensional";
00834 }
00835
00836
00837 int PressureDependMultiYield02::getOrder (void) const
00838 {
00839 int ndm = ndmx[matN];
00840
00841 return (ndm == 2) ? 3 : 6;
00842 }
00843
00844
00845 int PressureDependMultiYield02::updateParameter(int responseID, Information &info)
00846 {
00847 if (responseID<10)
00848 loadStagex[matN] = responseID;
00849
00850 else {
00851 if (responseID==10) refShearModulusx[matN]=info.theDouble;
00852 if (responseID==11) refBulkModulusx[matN]=info.theDouble;
00853 }
00854
00855 return 0;
00856 }
00857
00858
00859 int PressureDependMultiYield02::sendSelf(int commitTag, Channel &theChannel)
00860 {
00861 int loadStage = loadStagex[matN];
00862 int ndm = ndmx[matN];
00863 double rho = rhox[matN];
00864 double residualPress = residualPressx[matN];
00865 int numOfSurfaces = numOfSurfacesx[matN];
00866 double refPressure = refPressurex[matN];
00867 double pressDependCoeff =pressDependCoeffx[matN];
00868 double refShearModulus = refShearModulusx[matN];
00869 double refBulkModulus = refBulkModulusx[matN];
00870 double frictionAngle = frictionAnglex[matN];
00871 double cohesion = cohesionx[matN];
00872 double peakShearStrain = peakShearStrainx[matN];
00873 double phaseTransfAngle = phaseTransfAnglex[matN];
00874 double stressRatioPT = stressRatioPTx[matN];
00875 double contractParam1 = contractParam1x[matN];
00876 double contractParam2 = contractParam2x[matN];
00877 double dilateParam1 = dilateParam1x[matN];
00878 double dilateParam2 = dilateParam2x[matN];
00879 double liquefyParam1 = liquefyParam1x[matN];
00880 double liquefyParam2 = liquefyParam2x[matN];
00881 double dilateParam3 = dilateParam3x[matN];
00882 double einit = einitx[matN];
00883 double volLimit1 = volLimit1x[matN];
00884 double volLimit2 = volLimit2x[matN];
00885 double volLimit3 = volLimit3x[matN];
00886
00887 int i, res = 0;
00888
00889 static ID idData(5);
00890 idData(0) = this->getTag();
00891 idData(1) = numOfSurfaces;
00892 idData(2) = loadStage;
00893 idData(3) = ndm;
00894 idData(4) = matN;
00895
00896 res += theChannel.sendID(this->getDbTag(), commitTag, idData);
00897 if (res < 0) {
00898 opserr << "PressureDependMultiYield02::sendSelf -- could not send ID\n";
00899 return res;
00900 }
00901
00902 Vector data(71+numOfSurfaces*8);
00903 data(0) = rho;
00904 data(1) = einit;
00905 data(2) = refShearModulus;
00906 data(3) = refBulkModulus;
00907 data(4) = frictionAngle;
00908 data(5) = peakShearStrain;
00909 data(6) = refPressure;
00910 data(7) = cohesion;
00911 data(8) = pressDependCoeff;
00912 data(9) = phaseTransfAngle;
00913 data(10) = contractParam1;
00914 data(70) = contractParam2;
00915 data(11) = dilateParam1;
00916 data(12) = dilateParam2;
00917 data(13) = volLimit1;
00918 data(14) = volLimit2;
00919 data(15) = volLimit3;
00920 data(16) = pAtm;
00921 data(17) = liquefyParam1;
00922 data(18) = liquefyParam2;
00923 data(19) = dilateParam3;
00924 data(20) = residualPress;
00925 data(21) = stressRatioPT;
00926 data(22) = e2p;
00927 data(23) = committedActiveSurf;
00928 data(24) = strainPTOcta;
00929 data(25) = pressureDCommitted;
00930 data(26) = onPPZCommitted;
00931 data(27) = PPZSizeCommitted;
00932 data(28) = cumuDilateStrainOctaCommitted;
00933 data(29) = maxCumuDilateStrainOctaCommitted;
00934 data(30) = cumuTranslateStrainOctaCommitted;
00935 data(31) = prePPZStrainOctaCommitted;
00936 data(32) = oppoPrePPZStrainOctaCommitted;
00937 data(69) = initPress;
00938
00939 workV6 = currentStress.t2Vector();
00940 for(i = 0; i < 6; i++) data(i+33) = workV6[i];
00941
00942 workV6 = currentStrain.t2Vector();
00943 for(i = 0; i < 6; i++) data(i+39) = workV6[i];
00944
00945 workV6 = PPZPivotCommitted.t2Vector();
00946 for(i = 0; i < 6; i++) data(i+45) = workV6[i];
00947
00948 workV6 = PPZCenterCommitted.t2Vector();
00949 for(i = 0; i < 6; i++) data(i+51) = workV6[i];
00950
00951 for(i = 0; i < numOfSurfaces; i++) {
00952 int k = 58 + i*8;
00953 data(k) = committedSurfaces[i+1].size();
00954 data(k+1) = committedSurfaces[i+1].modulus();
00955 workV6 = committedSurfaces[i+1].center();
00956 data(k+2) = workV6(0);
00957 data(k+3) = workV6(1);
00958 data(k+4) = workV6(2);
00959 data(k+5) = workV6(3);
00960 data(k+6) = workV6(4);
00961 data(k+7) = workV6(5);
00962 }
00963
00964 res += theChannel.sendVector(this->getDbTag(), commitTag, data);
00965 if (res < 0) {
00966 opserr << "PressureDependMultiYield02::sendSelf -- could not send Vector\n";
00967 return res;
00968 }
00969
00970 return res;
00971 }
00972
00973
00974 int PressureDependMultiYield02::recvSelf(int commitTag, Channel &theChannel,
00975 FEM_ObjectBroker &theBroker)
00976 {
00977 int i, res = 0;
00978
00979 static ID idData(5);
00980 res += theChannel.recvID(this->getDbTag(), commitTag, idData);
00981 if (res < 0) {
00982 opserr << "PressureDependMultiYield02::recvelf -- could not recv ID\n";
00983
00984 return res;
00985 }
00986
00987 this->setTag((int)idData(0));
00988 int numOfSurfaces = idData(1);
00989 int loadStage = idData(2);
00990 int ndm = idData(3);
00991 matN = idData(4);
00992
00993 Vector data(71+idData(1)*8);
00994 res += theChannel.recvVector(this->getDbTag(), commitTag, data);
00995 if (res < 0) {
00996 opserr << "PressureDependMultiYield02::recvSelf -- could not recv Vector\n";
00997 return res;
00998 }
00999
01000 double rho = data(0);
01001 double einit = data(1);
01002 double refShearModulus = data(2);
01003 double refBulkModulus = data(3);
01004 double frictionAngle = data(4);
01005 double peakShearStrain = data(5);
01006 double refPressure = data(6);
01007 double cohesion = data(7);
01008 double pressDependCoeff = data(8);
01009 double phaseTransfAngle = data(9);
01010 double contractParam1 = data(10);
01011 double contractParam2 = data(70);
01012 double dilateParam1 = data(11);
01013 double dilateParam2 = data(12);
01014 double volLimit1 = data(13);
01015 double volLimit2 = data(14);
01016 double volLimit3 = data(15);
01017 pAtm = data(16);
01018 double liquefyParam1 = data(17);
01019 double liquefyParam2 = data(18);
01020 double dilateParam3 = data(19);
01021 double residualPress = data(20);
01022 double stressRatioPT = data(21);
01023 e2p = data(22);
01024 committedActiveSurf = data(23);
01025 strainPTOcta = data(24);
01026 pressureDCommitted = data(25);
01027 onPPZCommitted = data(26);
01028 PPZSizeCommitted = data(27);
01029 cumuDilateStrainOctaCommitted = data(28);
01030 maxCumuDilateStrainOctaCommitted = data(29);
01031 cumuTranslateStrainOctaCommitted = data(30);
01032 prePPZStrainOctaCommitted = data(31);
01033 oppoPrePPZStrainOctaCommitted = data(32);
01034 initPress = data(69);
01035
01036 for(i = 0; i < 6; i++) workV6[i] = data(i+33);
01037 currentStress.setData(workV6);
01038
01039 for(i = 0; i < 6; i++) workV6[i] = data(i+39);
01040 currentStrain.setData(workV6);
01041
01042 for(i = 0; i < 6; i++) workV6[i] = data(i+45);
01043 PPZPivotCommitted.setData(workV6);
01044
01045 for(i = 0; i < 6; i++) workV6[i] = data(i+51);
01046 PPZCenterCommitted.setData(workV6);
01047
01048 if (committedSurfaces != 0) {
01049 delete [] committedSurfaces;
01050 delete [] theSurfaces;
01051 }
01052
01053 theSurfaces = new MultiYieldSurface[numOfSurfaces+1];
01054 committedSurfaces = new MultiYieldSurface[numOfSurfaces+1];
01055 for (i=1; i<=numOfSurfaces; i++)
01056 committedSurfaces[i] = MultiYieldSurface();
01057
01058 for(i = 0; i < numOfSurfaces; i++) {
01059 int k = 58 + i*8;
01060 workV6(0) = data(k+2);
01061 workV6(1) = data(k+3);
01062 workV6(2) = data(k+4);
01063 workV6(3) = data(k+5);
01064 workV6(4) = data(k+6);
01065 workV6(5) = data(k+7);
01066 committedSurfaces[i+1].setData(workV6, data(k), data(k+1));
01067 }
01068
01069 loadStagex[matN] = loadStage;
01070 ndmx[matN] = ndm;
01071 rhox[matN] = rho;
01072 residualPressx[matN] = residualPress;
01073 numOfSurfacesx[matN] = numOfSurfaces;
01074 refPressurex[matN] = refPressure;
01075 pressDependCoeffx[matN] =pressDependCoeff;
01076 refShearModulusx[matN] = refShearModulus;
01077 refBulkModulusx[matN] = refBulkModulus;
01078 frictionAnglex[matN] = frictionAngle;
01079 cohesionx[matN] = cohesion;
01080 peakShearStrainx[matN] = peakShearStrain;
01081 phaseTransfAnglex[matN] = phaseTransfAngle;
01082 stressRatioPTx[matN] = stressRatioPT;
01083 contractParam1x[matN] = contractParam1;
01084 contractParam2x[matN] = contractParam2;
01085 dilateParam1x[matN] = dilateParam1;
01086 dilateParam2x[matN] = dilateParam2;
01087 liquefyParam1x[matN] = liquefyParam1;
01088 liquefyParam2x[matN] = liquefyParam2;
01089 dilateParam3x[matN] = dilateParam3;
01090 einitx[matN] = einit;
01091 volLimit1x[matN] = volLimit1;
01092 volLimit2x[matN] = volLimit2;
01093 volLimit3x[matN] = volLimit3;
01094
01095 return res;
01096 }
01097
01098
01099 Response*
01100 PressureDependMultiYield02::setResponse (const char **argv, int argc, Information &matInfo, OPS_Stream &s)
01101 {
01102 if (strcmp(argv[0],"stress") == 0 || strcmp(argv[0],"stresses") == 0)
01103 return new MaterialResponse(this, 1, this->getCommittedStress());
01104
01105 else if (strcmp(argv[0],"strain") == 0 || strcmp(argv[0],"strains") == 0)
01106 return new MaterialResponse(this, 2, this->getCommittedStrain());
01107
01108 else if (strcmp(argv[0],"tangent") == 0)
01109 return new MaterialResponse(this, 3, this->getTangent());
01110
01111 else if (strcmp(argv[0],"backbone") == 0) {
01112 int numOfSurfaces = numOfSurfacesx[matN];
01113 static Matrix curv(numOfSurfaces+1,(argc-1)*2);
01114 for (int i=1; i<argc; i++)
01115 curv(0,(i-1)*2) = atoi(argv[i]);
01116 return new MaterialResponse(this, 4, curv);
01117 }
01118 else
01119 return 0;
01120 }
01121
01122
01123 void PressureDependMultiYield02::getBackbone (Matrix & bb)
01124 {
01125 double residualPress = residualPressx[matN];
01126 double refPressure = refPressurex[matN];
01127 double pressDependCoeff =pressDependCoeffx[matN];
01128 double refShearModulus = refShearModulusx[matN];
01129 int numOfSurfaces = numOfSurfacesx[matN];
01130
01131 double vol, conHeig, scale, factor, shearModulus, stress1,
01132 stress2, strain1, strain2, plastModulus, elast_plast, gre;
01133
01134 for (int k=0; k<bb.noCols()/2; k++) {
01135 vol = bb(0,k*2);
01136 if (vol<=0.) {
01137 opserr <<k<< "\nNDMaterial " <<this->getTag()
01138 <<": invalid confinement for backbone recorder, " << vol << endln;
01139 continue;
01140 }
01141 conHeig = vol + residualPress;
01142 scale = -conHeig / (refPressure-residualPress);
01143 factor = pow(scale, pressDependCoeff);
01144 shearModulus = factor*refShearModulus;
01145
01146 for (int i=1; i<=numOfSurfaces; i++) {
01147 if (i==1) {
01148 stress2 = committedSurfaces[i].size()*conHeig/sqrt(3.0);
01149 strain2 = stress2/shearModulus;
01150 bb(1,k*2) = strain2; bb(1,k*2+1) = shearModulus;
01151 } else {
01152 stress1 = stress2; strain1 = strain2;
01153 plastModulus = factor*committedSurfaces[i-1].modulus();
01154 elast_plast = 2*shearModulus*plastModulus/(2*shearModulus+plastModulus);
01155 stress2 = committedSurfaces[i].size()*conHeig/sqrt(3.0);
01156 strain2 = 2*(stress2-stress1)/elast_plast + strain1;
01157 gre = stress2/strain2;
01158 bb(i,k*2) = strain2; bb(i,k*2+1) = gre;
01159 }
01160 }
01161 }
01162
01163 }
01164
01165
01166 int PressureDependMultiYield02::getResponse (int responseID, Information &matInfo)
01167 {
01168 switch (responseID) {
01169 case -1:
01170 return -1;
01171 case 1:
01172 if (matInfo.theVector != 0)
01173 *(matInfo.theVector) = getCommittedStress();
01174 return 0;
01175 case 2:
01176 if (matInfo.theVector != 0)
01177 *(matInfo.theVector) = getCommittedStrain();
01178 return 0;
01179 case 3:
01180 if (matInfo.theMatrix != 0)
01181 *(matInfo.theMatrix) = getTangent();
01182 return 0;
01183 case 4:
01184 if (matInfo.theMatrix != 0)
01185 getBackbone(*(matInfo.theMatrix));
01186 return 0;
01187 default:
01188 return -1;
01189 }
01190 }
01191
01192
01193 void PressureDependMultiYield02::Print(OPS_Stream &s, int flag )
01194 {
01195 s << "PressureDependMultiYield02" << endln;
01196 }
01197
01198
01199 const Vector & PressureDependMultiYield02::getCommittedStress (void)
01200 {
01201 int ndm = ndmx[matN];
01202 int numOfSurfaces = numOfSurfacesx[matN];
01203 double residualPress = residualPressx[matN];
01204
01205 double scale = currentStress.deviatorRatio(residualPress)/committedSurfaces[numOfSurfaces].size();
01206 if (loadStagex[matN] != 1) scale = 0.;
01207 if (ndm==3) {
01208 static Vector temp7(7);
01209 workV6 = currentStress.t2Vector();
01210 temp7[0] = workV6[0];
01211 temp7[1] = workV6[1];
01212 temp7[2] = workV6[2];
01213 temp7[3] = workV6[3];
01214 temp7[4] = workV6[4];
01215 temp7[5] = workV6[5];
01216 temp7[6] = scale;
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 return temp7;
01227 }
01228
01229 else {
01230 static Vector temp5(5);
01231 workV6 = currentStress.t2Vector();
01232 temp5[0] = workV6[0];
01233 temp5[1] = workV6[1];
01234 temp5[2] = workV6[2];
01235 temp5[3] = workV6[3];
01236 temp5[4] = scale;
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248 return temp5;
01249 }
01250 }
01251
01252
01253 const Vector & PressureDependMultiYield02::getCommittedStrain (void)
01254 {
01255 int ndm = ndmx[matN];
01256
01257 if (ndm==3)
01258 return currentStrain.t2Vector(1);
01259 else {
01260 static Vector workV(3);
01261 workV6 = currentStrain.t2Vector(1);
01262 workV[0] = workV6[0];
01263 workV[1] = workV6[1];
01264 workV[2] = workV6[3];
01265 return workV;
01266 }
01267 }
01268
01269
01270
01271 void PressureDependMultiYield02::setUpSurfaces (double * gredu)
01272 {
01273 double residualPress = residualPressx[matN];
01274 double refPressure = refPressurex[matN];
01275 double pressDependCoeff =pressDependCoeffx[matN];
01276 double refShearModulus = refShearModulusx[matN];
01277 int numOfSurfaces = numOfSurfacesx[matN];
01278 double frictionAngle = frictionAnglex[matN];
01279 double cohesion = cohesionx[matN];
01280 double peakShearStrain = peakShearStrainx[matN];
01281 double phaseTransfAngle = phaseTransfAnglex[matN];
01282 double stressRatioPT = stressRatioPTx[matN];
01283
01284 double refStrain, peakShear, coneHeight;
01285 double stress1, stress2, strain1, strain2, size, elasto_plast_modul, plast_modul;
01286 double ratio1, ratio2;
01287
01288 if (gredu==0) {
01289 double sinPhi = sin(frictionAngle * pi/180.);
01290 double Mnys = 6.*sinPhi/(3.-sinPhi);
01291 double sinPhiPT = sin(phaseTransfAngle * pi/180.);
01292 stressRatioPT = 6.*sinPhiPT/(3.-sinPhiPT);
01293
01294 residualPress = 2 * cohesion / Mnys;
01295
01296 if (residualPress < 0.01) residualPress = 0.01;
01297 coneHeight = - (refPressure - residualPress);
01298 peakShear = sqrt(2.) * coneHeight * Mnys / 3.;
01299 refStrain = (peakShearStrain * peakShear)
01300 / (refShearModulus * peakShearStrain - peakShear);
01301
01302 double stressInc = peakShear / numOfSurfaces;
01303
01304 for (int ii=1; ii<=numOfSurfaces; ii++){
01305 stress1 = ii * stressInc;
01306 stress2 = stress1 + stressInc;
01307 ratio1 = 3. * stress1 / sqrt(2.) / coneHeight;
01308 ratio2 = 3. * stress2 / sqrt(2.) / coneHeight;
01309 strain1 = stress1 * refStrain / (refShearModulus * refStrain - stress1);
01310 strain2 = stress2 * refStrain / (refShearModulus * refStrain - stress2);
01311
01312 if (ratio1 <= stressRatioPT && ratio2 >= stressRatioPT) {
01313 double ratio = (ratio2 - stressRatioPT)/(ratio2 - ratio1);
01314 strainPTOcta = strain2 - ratio * (strain2 - strain1);
01315 }
01316
01317 size = ratio1;
01318 elasto_plast_modul = 2.*(stress2 - stress1)/(strain2 - strain1);
01319 if ( (2.*refShearModulus - elasto_plast_modul) <= 0)
01320 plast_modul = UP_LIMIT;
01321 else
01322 plast_modul = (2.*refShearModulus * elasto_plast_modul)/
01323 (2.*refShearModulus - elasto_plast_modul);
01324 if (plast_modul < 0) plast_modul = 0;
01325 if (plast_modul > UP_LIMIT) plast_modul = UP_LIMIT;
01326 if (ii==numOfSurfaces) plast_modul = 0;
01327 workV6.Zero();
01328
01329 committedSurfaces[ii] = MultiYieldSurface(workV6,size,plast_modul);
01330 }
01331 }
01332 else {
01333 int ii = 2*(numOfSurfaces-1);
01334 double tmax = refShearModulus*gredu[ii]*gredu[ii+1];
01335 double Mnys = -(sqrt(3.) * tmax - 2.* cohesion) / refPressure;
01336 residualPress = 2 * cohesion / Mnys;
01337 if (residualPress < 0.01) residualPress = 0.01;
01338 coneHeight = - (refPressure - residualPress);
01339
01340 double sinPhi = 3*Mnys /(6+Mnys);
01341 if (sinPhi<0. || sinPhi>1.) {
01342 opserr <<"\nNDMaterial " <<this->getTag()<<": Invalid friction angle, please modify ref. pressure or G/Gmax curve."<<endln;
01343 exit(-1);
01344 }
01345
01346 frictionAngle = asin(sinPhi)*180/pi;
01347 opserr << "\nNDMaterial " <<this->getTag()<<": Friction angle is "<<frictionAngle<<"\n"<<endln;
01348 if (phaseTransfAngle > frictionAngle) {
01349 opserr << "\nNDMaterial " <<this->getTag()<<": phase Transformation Angle > friction Angle,"
01350 << "will set phase Transformation Angle = friction Angle.\n" <<endln;
01351 phaseTransfAngle = frictionAngle;
01352 }
01353 double sinPhiPT = sin(phaseTransfAngle * pi/180.);
01354 stressRatioPT = 6.*sinPhiPT/(3.-sinPhiPT);
01355
01356 for (int i=1; i<numOfSurfaces; i++) {
01357 int ii = 2*(i-1);
01358 strain1 = gredu[ii];
01359 stress1 = refShearModulus*gredu[ii+1]*strain1;
01360 strain2 = gredu[ii+2];
01361 stress2 = refShearModulus*gredu[ii+3]*strain2;
01362
01363 ratio1 = sqrt(3.) * stress1 / coneHeight;
01364 ratio2 = sqrt(3.) * stress2 / coneHeight;
01365 if (ratio1 <= stressRatioPT && ratio2 >= stressRatioPT) {
01366 double ratio = (ratio2 - stressRatioPT)/(ratio2 - ratio1);
01367
01368 strainPTOcta = sqrt(6.)/3 * (strain2 - ratio * (strain2 - strain1));
01369 }
01370
01371 size = ratio1;
01372 elasto_plast_modul = 2.*(stress2 - stress1)/(strain2 - strain1);
01373
01374 if ( (2.*refShearModulus - elasto_plast_modul) <= 0)
01375 plast_modul = UP_LIMIT;
01376 else
01377 plast_modul = (2.*refShearModulus * elasto_plast_modul)/
01378 (2.*refShearModulus - elasto_plast_modul);
01379 if (plast_modul <= 0) {
01380 opserr << "\nNDMaterial " <<this->getTag()<<": Surface " << i
01381 << " has plastic modulus < 0.\n Please modify G/Gmax curve.\n"<<endln;
01382 exit(-1);
01383 }
01384 if (plast_modul > UP_LIMIT) plast_modul = UP_LIMIT;
01385
01386 workV6.Zero();
01387
01388 committedSurfaces[i] = MultiYieldSurface(workV6,size,plast_modul);
01389
01390 if (i==(numOfSurfaces-1)) {
01391 plast_modul = 0;
01392 size = ratio2;
01393
01394 committedSurfaces[i+1] = MultiYieldSurface(workV6,size,plast_modul);
01395 }
01396 }
01397 }
01398
01399 residualPressx[matN] = residualPress;
01400 frictionAnglex[matN] = frictionAngle;
01401 cohesionx[matN] = cohesion;
01402 phaseTransfAnglex[matN] = phaseTransfAngle;
01403 stressRatioPTx[matN] = stressRatioPT;
01404 }
01405
01406
01407 double PressureDependMultiYield02::yieldFunc(const T2Vector & stress,
01408 const MultiYieldSurface * surfaces,
01409 int surfaceNum)
01410 {
01411 double residualPress = residualPressx[matN];
01412
01413 double coneHeight = stress.volume() - residualPress;
01414
01415 workV6 = stress.deviator();
01416 workV6.addVector(1.0, surfaces[surfaceNum].center(), -coneHeight);
01417
01418 double sz = surfaces[surfaceNum].size()*coneHeight;
01419
01420 return 3./2.*(workV6 && workV6) - sz * sz;
01421 }
01422
01423
01424 void PressureDependMultiYield02::deviatorScaling(T2Vector & stress,
01425 const MultiYieldSurface * surfaces,
01426 int surfaceNum)
01427 {
01428 double residualPress = residualPressx[matN];
01429 int numOfSurfaces = numOfSurfacesx[matN];
01430
01431 double diff = yieldFunc(stress, surfaces, surfaceNum);
01432 double coneHeight = stress.volume() - residualPress;
01433
01434 if ( surfaceNum < numOfSurfaces && diff < 0. ) {
01435 double sz = -surfaces[surfaceNum].size()*coneHeight;
01436 double deviaSz = sqrt(sz*sz + diff);
01437 static Vector devia(6);
01438 devia = stress.deviator();
01439 workV6 = devia;
01440 workV6.addVector(1.0, surfaces[surfaceNum].center(), -coneHeight);
01441 double coeff = (sz-deviaSz) / deviaSz;
01442 if (coeff < 1.e-13) coeff = 1.e-13;
01443
01444 devia.addVector(1.0, workV6, coeff);
01445 stress.setData(devia, stress.volume());
01446 deviatorScaling(stress, surfaces, surfaceNum);
01447 }
01448
01449 if (surfaceNum==numOfSurfaces && fabs(diff) > LOW_LIMIT) {
01450 double sz = -surfaces[surfaceNum].size()*coneHeight;
01451
01452 workV6 = stress.deviator();
01453 workV6 *= sz/sqrt(diff+sz*sz);
01454 stress.setData(workV6, stress.volume());
01455 }
01456 }
01457
01458
01459 void PressureDependMultiYield02::initSurfaceUpdate(void)
01460 {
01461 double residualPress = residualPressx[matN];
01462 int numOfSurfaces = numOfSurfacesx[matN];
01463
01464 if (committedActiveSurf == 0) return;
01465
01466 double coneHeight = - (currentStress.volume() - residualPress);
01467 static Vector devia(6);
01468 devia = currentStress.deviator();
01469 double Ms = sqrt(3./2.*(devia && devia));
01470
01471 if (committedActiveSurf < numOfSurfaces) {
01472
01473 workV6.addVector(0.0, devia, (1. - committedSurfaces[committedActiveSurf].size()*coneHeight / Ms));
01474
01475
01476 workV6 /= -coneHeight;
01477 committedSurfaces[committedActiveSurf].setCenter(workV6);
01478 }
01479
01480 for (int i=1; i<committedActiveSurf; i++) {
01481
01482 workV6.addVector(0.0, devia, (1. - committedSurfaces[i].size()*coneHeight / Ms));
01483
01484 workV6 /= -coneHeight;
01485 committedSurfaces[i].setCenter(workV6);
01486 theSurfaces[i] = committedSurfaces[i];
01487 }
01488 activeSurfaceNum = committedActiveSurf;
01489 }
01490
01491
01492 void PressureDependMultiYield02::initStrainUpdate(void)
01493 {
01494 double residualPress = residualPressx[matN];
01495 double refPressure = refPressurex[matN];
01496 double pressDependCoeff =pressDependCoeffx[matN];
01497 double refShearModulus = refShearModulusx[matN];
01498 double refBulkModulus = refBulkModulusx[matN];
01499 double stressRatioPT = stressRatioPTx[matN];
01500
01501
01502 double stressRatio = currentStress.deviatorRatio(residualPress);
01503 double ratio = (-currentStress.volume()+residualPress)/(-refPressure+residualPress);
01504 ratio = pow(ratio, 1.-pressDependCoeff);
01505 modulusFactor = getModulusFactor(currentStress);
01506 double shearCoeff = 1./(2.*refShearModulus*modulusFactor);
01507 double bulkCoeff = 1./(3.*refBulkModulus*modulusFactor);
01508
01509
01510
01511
01512
01513 workV6.addVector(0.0, currentStress.deviator(), shearCoeff);
01514 currentStrain.setData(workV6, currentStress.volume()*bulkCoeff);
01515
01516 double octalStrain = currentStrain.octahedralShear(1);
01517 if (octalStrain <= LOW_LIMIT) octalStrain = LOW_LIMIT;
01518
01519
01520 double scale, PPZLimit;
01521 if (stressRatio >= stressRatioPT) {
01522 onPPZCommitted = 2;
01523 prePPZStrainOctaCommitted = strainPTOcta * ratio;
01524 PPZLimit = getPPZLimits(1,currentStress);
01525 scale = sqrt(prePPZStrainOctaCommitted+PPZLimit)/octalStrain;
01526 }
01527 else {
01528 onPPZCommitted = -1;
01529 prePPZStrainOctaCommitted = octalStrain;
01530 if (prePPZStrainOctaCommitted > strainPTOcta * ratio)
01531 prePPZStrainOctaCommitted=strainPTOcta*ratio;
01532 scale = sqrt(prePPZStrainOctaCommitted)/octalStrain;
01533 }
01534
01535 workV6.addVector(0.0, currentStrain.deviator(), scale);
01536 currentStrain.setData(workV6, currentStrain.volume());
01537 PPZPivotCommitted = currentStrain;
01538 }
01539
01540
01541 double PressureDependMultiYield02::getModulusFactor(T2Vector & stress)
01542 {
01543 double residualPress = residualPressx[matN];
01544 double refPressure = refPressurex[matN];
01545 double pressDependCoeff =pressDependCoeffx[matN];
01546
01547 double conHeig = stress.volume() - residualPress;
01548 double scale = conHeig / (refPressure-residualPress);
01549 scale = pow(scale, pressDependCoeff);
01550
01551 return (1.e-10>scale) ? 1.e-10 : scale;
01552 }
01553
01554
01555 void PressureDependMultiYield02::setTrialStress(T2Vector & stress)
01556 {
01557 double refShearModulus = refShearModulusx[matN];
01558 double refBulkModulus = refBulkModulusx[matN];
01559
01560 modulusFactor = getModulusFactor(stress);
01561
01562
01563 workV6 = stress.deviator();
01564 workV6.addVector(1.0, subStrainRate.deviator(), 2*refShearModulus*modulusFactor);
01565
01566 double B = refBulkModulus*modulusFactor;
01567
01568 if (Hvx[matN] != 0. && trialStress.volume()<=maxPress
01569 && subStrainRate.volume()<0. && loadStagex[matN] == 1) {
01570 double tp = fabs(trialStress.volume() - residualPressx[matN]);
01571 B = (B*Hvx[matN]*pow(tp,Pvx[matN]))/(B+Hvx[matN]*pow(tp,Pvx[matN]));
01572 }
01573
01574 double volume = stress.volume() + subStrainRate.volume()*3.*B;
01575
01576 if (volume > 0.) volume = 0.;
01577 trialStress.setData(workV6, volume);
01578 }
01579
01580
01581 int PressureDependMultiYield02::setSubStrainRate(void)
01582 {
01583 double residualPress = residualPressx[matN];
01584 double refShearModulus = refShearModulusx[matN];
01585 int numOfSurfaces = numOfSurfacesx[matN];
01586
01587
01588 if (strainRate.isZero()) return 0;
01589
01590 double elast_plast_modulus;
01591 double conHeig = -(currentStress.volume() - residualPress);
01592 double factor = getModulusFactor(currentStress);
01593 if (activeSurfaceNum==0)
01594 elast_plast_modulus = 2*refShearModulus*factor;
01595 else {
01596 double plast_modulus = theSurfaces[activeSurfaceNum].modulus()*factor;
01597 elast_plast_modulus = 2*refShearModulus*factor*plast_modulus
01598 / (2*refShearModulus*factor+plast_modulus);
01599 }
01600
01601 workV6.addVector(0.0, strainRate.deviator(), elast_plast_modulus);
01602 workT2V.setData(workV6,0);
01603
01604 double singleCross = theSurfaces[numOfSurfaces].size()*conHeig / numOfSurfaces;
01605 double totalCross = 3.*workT2V.octahedralShear() / sqrt(2.);
01606 int numOfSub = totalCross/singleCross + 1;
01607 if (numOfSub > numOfSurfaces) numOfSub = numOfSurfaces;
01608
01609 int numOfSub1 = strainRate.octahedralShear(1) / 1.0e-5;
01610 int numOfSub2 = strainRate.volume() / 1.e-5;
01611 if (numOfSub1 > numOfSub) numOfSub = numOfSub1;
01612 if (numOfSub2 > numOfSub) numOfSub = numOfSub2;
01613
01614 workV6.addVector(0.0, strainRate.t2Vector(), 1.0/numOfSub);
01615
01616 subStrainRate.setData(workV6);
01617
01618 return numOfSub;
01619 }
01620
01621
01622 void
01623 PressureDependMultiYield02::getContactStress(T2Vector &contactStress)
01624 {
01625 double residualPress = residualPressx[matN];
01626
01627 double conHeig = trialStress.volume() - residualPress;
01628 static Vector center(6);
01629 center = theSurfaces[activeSurfaceNum].center();
01630
01631 workV6 = trialStress.deviator();
01632 workV6.addVector(1.0, center, -conHeig);
01633 double Ms = sqrt(3./2.*(workV6 && workV6));
01634
01635 workV6.addVector(theSurfaces[activeSurfaceNum].size()*(-conHeig) / Ms, center, conHeig);
01636
01637 contactStress.setData(workV6,trialStress.volume());
01638 }
01639
01640
01641 int PressureDependMultiYield02::isLoadReversal(const T2Vector & stress)
01642 {
01643 if(activeSurfaceNum == 0) return 0;
01644
01645 getSurfaceNormal(stress, workT2V);
01646
01647
01648
01649 workV6 = trialStress.t2Vector();
01650 workV6 -= currentStress.t2Vector();
01651
01652 if ((workV6 && workT2V.t2Vector()) < 0) return 1;
01653
01654 return 0;
01655 }
01656
01657
01658 void
01659 PressureDependMultiYield02::getSurfaceNormal(const T2Vector & stress, T2Vector &normal)
01660 {
01661 double residualPress = residualPressx[matN];
01662
01663 double conHeig = stress.volume() - residualPress;
01664 workV6 = stress.deviator();
01665 static Vector center(6);
01666 center = theSurfaces[activeSurfaceNum].center();
01667 double sz = theSurfaces[activeSurfaceNum].size();
01668 double volume = conHeig*((center && center) - 2./3.*sz*sz) - (workV6 && center);
01669
01670 workV6.addVector(1.0, center, -conHeig);
01671 workV6 *= 3.0;
01672 workT2V.setData(workV6, volume);
01673
01674 normal.setData(workT2V.unitT2Vector());
01675 }
01676
01677
01678 double PressureDependMultiYield02::getPlasticPotential(const T2Vector & contactStress,
01679 const T2Vector & surfaceNormal)
01680 {
01681 double residualPress = residualPressx[matN];
01682 double stressRatioPT = stressRatioPTx[matN];
01683 double contractParam1 = contractParam1x[matN];
01684 double contractParam2 = contractParam2x[matN];
01685 double contractParam3 = contractParam3x[matN];
01686 double dilateParam1 = dilateParam1x[matN];
01687 double dilateParam2 = dilateParam2x[matN];
01688
01689 double plasticPotential, contractRule, shearLoading, angle;
01690
01691 double contactRatio = contactStress.deviatorRatio(residualPress);
01692 double factorPT = contactRatio/stressRatioPT;
01693
01694 double currentRatio = updatedTrialStress.deviatorRatio(residualPress);
01695 double trialRatio = trialStress.deviatorRatio(residualPress);
01696 shearLoading = updatedTrialStress.deviator() && trialStress.deviator();
01697
01698
01699 if (factorPT >= 1. && trialRatio >= currentRatio && shearLoading >= 0.) {
01700 updatePPZ(contactStress);
01701 if (onPPZ==1)
01702 plasticPotential = 0.;
01703 else if (onPPZ==2) {
01704 factorPT -= 1.0;
01705 double dilateParam3 = dilateParam3x[matN];
01706 double ppp=pow((fabs(contactStress.volume())+fabs(residualPress))/pAtm, -dilateParam3);
01707 plasticPotential = ppp*factorPT*(factorPT)*(dilateParam1+pow(cumuDilateStrainOcta,dilateParam2));
01708 if (plasticPotential < 0.) plasticPotential = -plasticPotential;
01709 if (plasticPotential>5.0e4) plasticPotential = 5.0e4;
01710 }
01711 else {
01712 opserr << "FATAL: Wrong onPPZ value: " << onPPZ << endln;
01713 exit(-1);
01714 }
01715 } else {
01716 if (currentRatio==0.) angle = 1.0;
01717 else {
01718 workV6 = trialStress.deviator();
01719 workV6 /= (fabs(trialStress.volume())+fabs(residualPress));
01720 workV6 -= updatedTrialStress.deviator()/(fabs(updatedTrialStress.volume())+fabs(residualPress));
01721
01722
01723
01724 workT2V = T2Vector(workV6);
01725 if (workT2V.deviatorLength() == 0.) angle = 1.0;
01726
01727 else angle = (updatedTrialStress.deviator() && workV6)/workT2V.deviatorLength()/updatedTrialStress.deviatorLength();
01728 }
01729 factorPT = factorPT*angle - 1.0;
01730
01731 contractRule = pow((fabs(contactStress.volume())+fabs(residualPress))/pAtm, contractParam3);
01732 if (contractRule < 0.1) contractRule = 0.1;
01733
01734
01735
01736
01737
01738 plasticPotential = -(factorPT)*(factorPT)*(contractParam1+maxCumuDilateStrainOcta*contractParam2)*contractRule;
01739
01740 if (plasticPotential > 0.) plasticPotential = -plasticPotential;
01741
01742 if (onPPZ > 0) onPPZ = 0;
01743 if (onPPZ != -1) PPZTranslation(contactStress);
01744 }
01745
01746 if (isCriticalState(contactStress)) plasticPotential = 0;
01747 return plasticPotential;
01748 }
01749
01750
01751 int PressureDependMultiYield02::isCriticalState(const T2Vector & stress)
01752 {
01753 double einit = einitx[matN];
01754 double volLimit1 = volLimit1x[matN];
01755 double volLimit2 = volLimit2x[matN];
01756 double volLimit3 = volLimit3x[matN];
01757
01758 double vol = trialStrain.volume()*3.0;
01759 double etria = einit + vol + vol*einit;
01760 vol = currentStrain.volume()*3.0;
01761 double ecurr = einit + vol + vol*einit;
01762
01763 double ecr1, ecr2;
01764 if (volLimit3 != 0.) {
01765 ecr1 = volLimit1 - volLimit2*pow(abs(-stress.volume()/pAtm), volLimit3);
01766 ecr2 = volLimit1 - volLimit2*pow(abs(-updatedTrialStress.volume()/pAtm), volLimit3);
01767 } else {
01768 ecr1 = volLimit1 - volLimit2*log(abs(-stress.volume()/pAtm));
01769 ecr2 = volLimit1 - volLimit2*log(abs(-updatedTrialStress.volume()/pAtm));
01770 }
01771
01772 if (ecurr < ecr2 && etria < ecr1) return 0;
01773 if (ecurr > ecr2 && etria > ecr1) return 0;
01774 return 1;
01775 }
01776
01777
01778 void PressureDependMultiYield02::updatePPZ(const T2Vector & contactStress)
01779 {
01780 double liquefyParam1 = liquefyParam1x[matN];
01781 double residualPress = residualPressx[matN];
01782 double refPressure = refPressurex[matN];
01783 double pressDependCoeff =pressDependCoeffx[matN];
01784 double liquefyParam2 = liquefyParam2x[matN];
01785
01786
01787
01788 double temp = strainRate.deviator() && PivotStrainRateCommitted;
01789 check = strainRate.deviator()[3];
01790
01791 if (onPPZ < 1) {
01792 damage = 0.0;
01793 if ((maxPress-currentStress.volume())/(maxPress-residualPress) > 0.)
01794 damage = pow((maxPress-currentStress.volume())/(maxPress-residualPress),0.25);
01795 }
01796
01797
01798 if (liquefyParam1==0. || (onPPZ < 1 && damage < 0.)) {
01799 if (onPPZ==2) {
01800 PPZPivot = trialStrain;
01801
01802 cumuDilateStrainOcta += subStrainRate.octahedralShear(1);
01803 }
01804 else if (onPPZ != 2) {
01805 onPPZ = 2;
01806 PPZPivot = trialStrain;
01807 PivotStrainRate = strainRate.deviator();
01808 if (temp < 0.) cumuDilateStrainOcta = 0.;
01809
01810 }
01811 return;
01812 }
01813
01814
01815 if (onPPZ==2) {
01816 PPZPivot = trialStrain;
01817
01818 cumuDilateStrainOcta += subStrainRate.octahedralShear(1);
01819
01820 double zzz = 0.;
01821 if (damage > zzz) zzz = damage;
01822 maxCumuDilateStrainOcta += zzz*liquefyParam1*subStrainRate.octahedralShear(1);
01823 return;
01824 }
01825
01826 if (onPPZ==-1 || onPPZ==0) {
01827
01828
01829
01830
01831
01832 if (temp < 0.) {
01833 double volume = -contactStress.volume();
01834 oppoPrePPZStrainOcta = prePPZStrainOcta;
01835 double ratio = (volume+residualPress)/(-refPressure+residualPress);
01836 ratio = pow(ratio, 1.-pressDependCoeff);
01837 prePPZStrainOcta = ratio * strainPTOcta;
01838 if (oppoPrePPZStrainOcta == 0.) oppoPrePPZStrainOcta = prePPZStrainOcta;
01839 }
01840 }
01841
01842
01843
01844
01845 PPZSize = (cumuTranslateStrainOcta+maxCumuDilateStrainOcta)/2.;
01846
01847
01848
01849 if (onPPZ==0 || (onPPZ==1 && temp < 0.0)) {
01850
01851
01852
01853
01854 workV6 = PPZPivot.t2Vector();
01855 workV6.addVector(1.0, PPZCenter.t2Vector(), -1.);
01856 workT2V.setData(workV6);
01857
01858 double coeff;
01859 if (workT2V.octahedralShear(1)==0.) coeff = 0.;
01860 else coeff = (PPZSize-cumuTranslateStrainOcta)/workT2V.octahedralShear(1);
01861
01862 workV6 = PPZPivot.t2Vector();
01863 workV6.addVector(1.0, workT2V.t2Vector(), -coeff);
01864 PPZCenter.setData(workV6);
01865 }
01866
01867
01868 workV6 = trialStrain.t2Vector();
01869 workV6.addVector(1.0, PPZCenter.t2Vector(), -1.);
01870 workT2V.setData(workV6);
01871
01872
01873
01874 if (workT2V.octahedralShear(1) > PPZSize) {
01875
01876
01877
01878
01879
01880 cumuDilateStrainOcta = 0.;
01881
01882
01883 onPPZ = 2;
01884 PPZPivot = trialStrain;
01885 PivotStrainRate = strainRate.deviator();
01886 cumuTranslateStrainOcta = 0.;
01887 }
01888 else {
01889 if (onPPZ == 0 || onPPZ == 1) PPZTranslation(contactStress);
01890
01891 if (onPPZ == -1 || onPPZ == 0) onPPZ = 1;
01892 }
01893 }
01894
01895
01896 void PressureDependMultiYield02::PPZTranslation(const T2Vector & contactStress)
01897 {
01898 double liquefyParam1 = liquefyParam1x[matN];
01899 double liquefyParam2 = liquefyParam2x[matN];
01900 double residualPress = residualPressx[matN];
01901
01902
01903
01904
01905 if (liquefyParam1==0.) return;
01906
01907
01908
01909
01910 damage = 0.0;
01911 if ((maxPress-currentStress.volume())/(maxPress-residualPress) > 0.)
01912 damage = pow((maxPress-currentStress.volume())/(maxPress-residualPress),0.25);
01913
01914 double zzz = 0.;
01915 if (damage > zzz) zzz = damage;
01916
01917 double temp = strainRate.deviator() && PivotStrainRateCommitted;
01918
01919 if (temp < 0.0) {
01920
01921
01922 workV6 = trialStrain.deviator();
01923 workV6 -= PPZPivot.deviator();
01924 workT2V.setData(workV6);
01925
01926 temp = workT2V.octahedralShear(1);
01927 if (cumuTranslateStrainOcta < zzz*liquefyParam2*temp)
01928 cumuTranslateStrainOcta = zzz*liquefyParam2*temp;
01929
01930
01931
01932
01933
01934
01935 }
01936 }
01937
01938
01939 double PressureDependMultiYield02::getPPZLimits(int which, const T2Vector & contactStress)
01940 {
01941 double liquefyParam1 = liquefyParam1x[matN];
01942 double liquefyParam2 = liquefyParam2x[matN];
01943 double dilateParam3 = dilateParam3x[matN];
01944
01945 double PPZLimit, temp;
01946 double volume = -contactStress.volume();
01947
01948 if (volume >= liquefyParam1) PPZLimit = 0.;
01949 else {
01950 temp = volume*pi/liquefyParam1/2.;
01951
01952 PPZLimit = liquefyParam2 * pow(cos(temp), 3.);
01953
01954 PPZLimit = 0.0;
01955 }
01956
01957 if (which==1)
01958 return PPZLimit;
01959 else if (which==2)
01960 return dilateParam3 * PPZLimit;
01961 else {
01962 opserr << "FATAL:PressureDependMultiYield02::getPPZLimits: unknown argument value" << endln;
01963 exit(-1);
01964 return 0.0;
01965 }
01966 }
01967
01968
01969 double PressureDependMultiYield02::getLoadingFunc(const T2Vector & contactStress,
01970 const T2Vector & surfaceNormal,
01971 double * plasticPotential,
01972 int crossedSurface)
01973 {
01974 int numOfSurfaces = numOfSurfacesx[matN];
01975 double refShearModulus = refShearModulusx[matN];
01976 double refBulkModulus = refBulkModulusx[matN];
01977
01978 double loadingFunc, limit;
01979 double modul = theSurfaces[activeSurfaceNum].modulus();
01980 double temp1 = 2. * refShearModulus * modulusFactor
01981 * (surfaceNormal.deviator() && surfaceNormal.deviator()) ;
01982 double temp2 = 9. * refBulkModulus * modulusFactor
01983 * surfaceNormal.volume() * (*plasticPotential) ;
01984
01985
01986 double temp = temp1 + temp2 + modul * modulusFactor;
01987 if (activeSurfaceNum == numOfSurfaces)
01988 limit = theSurfaces[activeSurfaceNum-1].modulus() * modulusFactor /2.;
01989 else limit = modul * modulusFactor /2.;
01990 if (temp < limit) {
01991 (*plasticPotential) = (temp2 + limit - temp)/(9. * refBulkModulus * modulusFactor
01992 * surfaceNormal.volume());
01993 temp = limit;
01994 }
01995
01996
01997 workV6 = trialStress.deviator();
01998 workV6 -= contactStress.deviator();
01999 loadingFunc = (surfaceNormal.t2Vector() && workV6) /temp;
02000
02001 if (loadingFunc < 0.) loadingFunc = 0;
02002
02003
02004 if(crossedSurface) {
02005 temp = (theSurfaces[activeSurfaceNum-1].modulus() - modul)
02006 /theSurfaces[activeSurfaceNum-1].modulus();
02007 loadingFunc *= temp;
02008 }
02009
02010 return loadingFunc;
02011 }
02012
02013
02014 int PressureDependMultiYield02::stressCorrection(int crossedSurface)
02015 {
02016 double refShearModulus = refShearModulusx[matN];
02017 double refBulkModulus = refBulkModulusx[matN];
02018
02019 static T2Vector contactStress;
02020 getContactStress(contactStress);
02021 static T2Vector surfNormal;
02022 getSurfaceNormal(contactStress, surfNormal);
02023 double plasticPotential = getPlasticPotential(contactStress,surfNormal);
02024 double tVolume = trialStress.volume();
02025 double loadingFunc = getLoadingFunc(contactStress, surfNormal,
02026 &plasticPotential, crossedSurface);
02027 double volume = tVolume - plasticPotential*3*refBulkModulus*modulusFactor*loadingFunc;
02028
02029
02030
02031 workV6 = trialStress.deviator();
02032
02033 if (volume > 0. && volume != tVolume) {
02034 double coeff = tVolume / (tVolume - volume);
02035 coeff *= -2*refShearModulus*modulusFactor*loadingFunc;
02036 workV6.addVector(1.0, surfNormal.deviator(), coeff);
02037 volume = 0.;
02038 } else if (volume > 0.) {
02039 volume = 0.;
02040 } else {
02041 double coeff = -2*refShearModulus*modulusFactor*loadingFunc;
02042 workV6.addVector(1.0, surfNormal.deviator(), coeff);
02043 }
02044
02045
02046
02047
02048
02049 trialStress.setData(workV6, volume);
02050 deviatorScaling(trialStress, theSurfaces, activeSurfaceNum);
02051
02052 if (isCrossingNextSurface()) {
02053 activeSurfaceNum++;
02054 return stressCorrection(1);
02055 }
02056
02057 return 0;
02058 }
02059
02060
02061 void PressureDependMultiYield02::updateActiveSurface(void)
02062 {
02063 double residualPress = residualPressx[matN];
02064 int numOfSurfaces = numOfSurfacesx[matN];
02065
02066 if (activeSurfaceNum == numOfSurfaces) return;
02067
02068 double A, B, C, X;
02069 static Vector t1(6);
02070 static Vector t2(6);
02071 static Vector center(6);
02072 static Vector outcenter(6);
02073 double conHeig = trialStress.volume() - residualPress;
02074 center = theSurfaces[activeSurfaceNum].center();
02075 double size = theSurfaces[activeSurfaceNum].size();
02076 outcenter = theSurfaces[activeSurfaceNum+1].center();
02077 double outsize = theSurfaces[activeSurfaceNum+1].size();
02078
02079
02080
02081 t1 = trialStress.deviator();
02082 t1.addVector(1.0, center, -conHeig);
02083 t2 = center;
02084 t2 -= outcenter;
02085 t2 *=conHeig;
02086
02087 A = t1 && t1;
02088 B = 2. * (t1 && t2);
02089 C = (t2 && t2) - 2./3.* outsize * outsize * conHeig * conHeig;
02090 X = secondOrderEqn(A,B,C,0);
02091 if ( fabs(X-1.) < LOW_LIMIT ) X = 1.;
02092 if (X < 1.) return;
02093
02094 if (X < 1.){
02095
02096 t2 = trialStress.deviator();
02097 t2.addVector(1.0, outcenter, -conHeig);
02098
02099 double xx1 = (t2 && t2) - 2./3.* outsize * outsize * conHeig * conHeig;
02100 double xx2 = (t1 && t1) - 2./3.* size * size * conHeig * conHeig;
02101 opserr << "FATAL:PressureDependMultiYield02::updateActiveSurface(): error in Direction of surface motion." << endln;
02102 opserr << "X-1= " << X-1 <<" A= "<<A<<" B= "<<B<<" C= "<<C <<" M= "<<activeSurfaceNum<<" low_limit="<<LOW_LIMIT<< endln;
02103 opserr << "diff1= "<<xx1 <<" diff2= "<<xx2 <<" p= "<<conHeig<<" size= "<<size<<" outs= "<<outsize<<endln;
02104 exit(-1);
02105 }
02106
02107
02108
02109
02110 workV6.addVector(0.0, t1, X);
02111 workV6.addVector(1.0, center, conHeig);
02112 workV6 *= (1.0 - size / outsize);
02113 t2 = center;
02114 t2.addVector(1.0, outcenter, -size/outsize);
02115 t2 *= conHeig;
02116 workV6 -= t2;
02117
02118 workT2V.setData(workV6);
02119 if (workT2V.deviatorLength() < LOW_LIMIT) return;
02120
02121 workV6 = workT2V.deviator();
02122 A = conHeig * conHeig * (workV6 && workV6);
02123 B = 2 * conHeig * (t1 && workV6);
02124 if (fabs(B) < LOW_LIMIT) B = 0.;
02125 C = (t1 && t1) - 2./3.* size * size * conHeig * conHeig;
02126 if ( fabs(C) < LOW_LIMIT || fabs(C)/(t1 && t1) < LOW_LIMIT ) return;
02127 if (B > 0. || C < 0.) {
02128 opserr << "FATAL:PressureDependMultiYield02::updateActiveSurface(): error in surface motion.\n"
02129 << "A= " <<A <<" B= " <<B <<" C= "<<C <<" (t1&&t1)= "<<(t1&&t1) <<endln;
02130 exit(-1);
02131 }
02132 X = secondOrderEqn(A,B,C,1);
02133
02134 center.addVector(1.0, workV6, -X);
02135 theSurfaces[activeSurfaceNum].setCenter(center);
02136 }
02137
02138
02139 void PressureDependMultiYield02::updateInnerSurface(void)
02140 {
02141 double residualPress = residualPressx[matN];
02142
02143 if (activeSurfaceNum <= 1) return;
02144 static Vector devia(6);
02145 static Vector center(6);
02146
02147 double conHeig = currentStress.volume() - residualPress;
02148 devia = currentStress.deviator();
02149 center = theSurfaces[activeSurfaceNum].center();
02150 double size = theSurfaces[activeSurfaceNum].size();
02151
02152 for (int i=1; i<activeSurfaceNum; i++) {
02153 workV6.addVector(0.0, center, conHeig);
02154 workV6 -= devia;
02155 workV6 *= theSurfaces[i].size()/size;
02156 workV6 += devia;
02157
02158
02159
02160 workV6 /= conHeig;
02161 theSurfaces[i].setCenter(workV6);
02162 }
02163 }
02164
02165
02166 int PressureDependMultiYield02:: isCrossingNextSurface(void)
02167 {
02168 int numOfSurfaces = numOfSurfacesx[matN];
02169
02170 if (activeSurfaceNum == numOfSurfaces) return 0;
02171
02172 if(yieldFunc(trialStress, theSurfaces, activeSurfaceNum+1) > 0) return 1;
02173
02174 return 0;
02175 }