PressureIndependMultiYield.cpp

Go to the documentation of this file.
00001 // $Revision: 1.31 $
00002 // $Date: 2006/08/04 18:29:48 $
00003 // $Source: /usr/local/cvs/OpenSees/SRC/material/nD/soil/PressureIndependMultiYield.cpp,v $
00004                                                                         
00005 // Written: ZHY
00006 // Created: August 2000
00007 
00008 //
00009 // PressureIndependMultiYield.cpp
00010 // -------------------
00011 //
00012 #include <math.h>
00013 #include <stdlib.h>
00014 #include <PressureIndependMultiYield.h>
00015 #include <Information.h>
00016 #include <ID.h>
00017 #include <MaterialResponse.h>
00018 
00019 Matrix PressureIndependMultiYield::theTangent(6,6);
00020 T2Vector PressureIndependMultiYield::subStrainRate;
00021 int PressureIndependMultiYield::matCount=0;
00022 int* PressureIndependMultiYield::loadStagex=0;  //=0 if elastic; =1 if plastic
00023 int* PressureIndependMultiYield::ndmx=0;  //num of dimensions (2 or 3)
00024 double* PressureIndependMultiYield::rhox=0;
00025 double* PressureIndependMultiYield::frictionAnglex=0;
00026 double* PressureIndependMultiYield::peakShearStrainx=0;
00027 double* PressureIndependMultiYield::refPressurex=0;
00028 double* PressureIndependMultiYield::cohesionx=0;
00029 double* PressureIndependMultiYield::pressDependCoeffx=0;
00030 int*    PressureIndependMultiYield::numOfSurfacesx=0;
00031 double* PressureIndependMultiYield::residualPressx=0;
00032 
00033 PressureIndependMultiYield::PressureIndependMultiYield (int tag, int nd, 
00034                                                         double r, double refShearModul,
00035                                                         double refBulkModul, 
00036                                                         double cohesi, double peakShearStra, 
00037                                                         double frictionAng, double refPress, double pressDependCoe,
00038                                                         int numberOfYieldSurf, double * gredu)
00039  : NDMaterial(tag,ND_TAG_PressureIndependMultiYield), currentStress(),
00040    trialStress(), currentStrain(), strainRate()
00041 {
00042   if (nd !=2 && nd !=3) {
00043     opserr << "FATAL:PressureIndependMultiYield:: dimension error" << endln;
00044     opserr << "Dimension has to be 2 or 3, you give nd= " << nd << endln;
00045     exit(-1);
00046   }
00047   if (refShearModul <= 0) {
00048     opserr << "FATAL:PressureIndependMultiYield::PressureIndependMultiYield: refShearModulus <= 0" << endln;
00049     exit(-1);
00050   }
00051   if (refBulkModul <= 0) {
00052     opserr << "FATAL:PressureIndependMultiYield::PressureIndependMultiYield: refBulkModulus <= 0" << endln;
00053     exit(-1);
00054   }
00055   if (frictionAng < 0.) {
00056     opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: frictionAngle < 0" << endln;
00057     opserr << "Will reset frictionAngle to zero." << endln;
00058     frictionAng = 0.;
00059   }
00060   if (frictionAng == 0. && cohesi <= 0. ) {
00061     opserr << "FATAL:PressureIndependMultiYield::PressureIndependMultiYield: frictionAngle && cohesion <= 0." << endln;
00062     exit(-1);
00063   }
00064   if (cohesi <= 0) {
00065     opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: cohesion <= 0" << endln;
00066     opserr << "Will reset cohesion to zero." << endln;
00067     cohesi = 0.;
00068   }
00069   if (peakShearStra <= 0) {
00070     opserr << "FATAL:PressureIndependMultiYield::PressureIndependMultiYield: peakShearStra <= 0" << endln;
00071     exit(-1);
00072   }
00073   if (refPress <= 0) {
00074     opserr << "FATAL:PressureIndependMultiYield::PressureIndependMultiYield: refPress <= 0" << endln;
00075     exit(-1);
00076   }
00077   if (pressDependCoe < 0) {
00078     opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: pressDependCoe < 0" << endln;
00079     opserr << "Will reset pressDependCoe to zero." << endln;
00080     pressDependCoe = 0.;
00081   }
00082   if (pressDependCoe > 0 && frictionAng == 0) {
00083     opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: pressDependCoe > 0 while frictionAngle = 0" << endln;
00084     opserr << "Will reset pressDependCoe to zero." << endln;
00085     pressDependCoe = 0.;
00086   }
00087   if (numberOfYieldSurf <= 0) {
00088     opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: numberOfSurfaces <= 0" << endln;
00089     opserr << "Will use 10 yield surfaces." << endln;
00090     numberOfYieldSurf = 10;
00091   }
00092   if (numberOfYieldSurf > 100) {
00093     opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: numberOfSurfaces > 100" << endln;
00094     opserr << "Will use 100 yield surfaces." << endln;
00095     numberOfYieldSurf = 100;
00096   }
00097   if (r < 0) {
00098     opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: mass density < 0" << endln;
00099     opserr << "Will use rho = 0." << endln;
00100     r = 0.;
00101   }
00102 
00103   if (matCount%20 == 0) {
00104      int * temp1 = loadStagex;
00105          int * temp2 = ndmx;
00106          double * temp3 = rhox;
00107      double * temp6 = frictionAnglex;
00108      double * temp7 = peakShearStrainx;
00109      double * temp8 = refPressurex;
00110      double * temp9 = cohesionx;
00111      double * temp10 = pressDependCoeffx;
00112          int * temp11 = numOfSurfacesx;
00113      double * temp12 = residualPressx;
00114      loadStagex = new int[matCount+20];
00115      ndmx = new int[matCount+20];
00116      rhox = new double[matCount+20];
00117      frictionAnglex = new double[matCount+20];
00118      peakShearStrainx = new double[matCount+20];
00119      refPressurex = new double[matCount+20];
00120          cohesionx = new double[matCount+20];
00121      pressDependCoeffx = new double[matCount+20];
00122      numOfSurfacesx = new int[matCount+20];
00123      residualPressx = new double[matCount+20];
00124 
00125          for (int i=0; i<matCount; i++) {
00126          loadStagex[i] = temp1[i];
00127                  ndmx[i] = temp2[i];
00128          rhox[i] = temp3[i];
00129          frictionAnglex[i] = temp6[i];
00130          peakShearStrainx[i] = temp7[i];
00131          refPressurex[i] = temp8[i];
00132          cohesionx[i] = temp9[i];
00133          pressDependCoeffx[i] = temp10[i];
00134          numOfSurfacesx[i] = temp11[i];
00135          residualPressx[i] = temp12[i];
00136      }
00137 
00138          if (matCount > 0) {
00139              delete [] temp1; delete [] temp2; delete [] temp3;
00140              delete [] temp6; delete [] temp7; delete [] temp8; 
00141              delete [] temp9; delete [] temp10; delete [] temp11; 
00142                  delete [] temp12;
00143      }
00144   }
00145 
00146   ndmx[matCount] = nd;
00147   loadStagex[matCount] = 0;   //default
00148   refShearModulus = refShearModul;
00149   refBulkModulus = refBulkModul;
00150   frictionAnglex[matCount] = frictionAng;
00151   peakShearStrainx[matCount] = peakShearStra;
00152   refPressurex[matCount] = -refPress;  //compression is negative
00153   cohesionx[matCount] = cohesi;
00154   pressDependCoeffx[matCount] = pressDependCoe;
00155   numOfSurfacesx[matCount] = numberOfYieldSurf;
00156   rhox[matCount] = r;
00157 
00158   e2p = 0;
00159   matN = matCount;
00160   matCount ++;
00161 
00162         theSurfaces = new MultiYieldSurface[numberOfYieldSurf+1]; //first surface not used
00163   committedSurfaces = new MultiYieldSurface[numberOfYieldSurf+1]; 
00164         activeSurfaceNum = committedActiveSurf = 0; 
00165 
00166   setUpSurfaces(gredu);  // residualPress is calculated inside.
00167 }
00168    
00169 
00170 PressureIndependMultiYield::PressureIndependMultiYield () 
00171  : NDMaterial(0,ND_TAG_PressureIndependMultiYield), 
00172    currentStress(), trialStress(), currentStrain(), 
00173   strainRate(), theSurfaces(0), committedSurfaces(0)
00174 {
00175   //does nothing
00176 }
00177 
00178 
00179 PressureIndependMultiYield::PressureIndependMultiYield (const PressureIndependMultiYield & a)
00180  : NDMaterial(a.getTag(),ND_TAG_PressureIndependMultiYield), 
00181    currentStress(a.currentStress), trialStress(a.trialStress), 
00182   currentStrain(a.currentStrain), strainRate(a.strainRate)
00183 {
00184   matN = a.matN;
00185   e2p = a.e2p;
00186   refShearModulus = a.refShearModulus;
00187   refBulkModulus = a.refBulkModulus;
00188 
00189   int numOfSurfaces = numOfSurfacesx[matN];
00190 
00191   committedActiveSurf = a.committedActiveSurf;
00192   activeSurfaceNum = a.activeSurfaceNum; 
00193 
00194   theSurfaces = new MultiYieldSurface[numOfSurfaces+1];  //first surface not used
00195   committedSurfaces = new MultiYieldSurface[numOfSurfaces+1];  
00196   for(int i=1; i<=numOfSurfaces; i++) {
00197     committedSurfaces[i] = a.committedSurfaces[i];  
00198     theSurfaces[i] = a.theSurfaces[i];  
00199   }
00200 }
00201 
00202 
00203 PressureIndependMultiYield::~PressureIndependMultiYield ()
00204 {
00205   if (theSurfaces != 0) delete [] theSurfaces;
00206   if (committedSurfaces != 0) delete [] committedSurfaces;
00207 }
00208 
00209 
00210 void PressureIndependMultiYield::elast2Plast(void)
00211 {
00212   int loadStage = loadStagex[matN];
00213   double frictionAngle = frictionAnglex[matN];
00214   int numOfSurfaces = numOfSurfacesx[matN];
00215 
00216   if (loadStage != 1 || e2p == 1) return;
00217   e2p = 1;
00218 
00219   if (currentStress.volume() > 0. && frictionAngle > 0.) {
00220     //opserr << "WARNING:PressureIndependMultiYield::elast2Plast(): material in tension." << endln;
00221     currentStress.setData(currentStress.deviator(),0);
00222   }
00223 
00224   paramScaling();  // scale surface parameters corresponding to initial confinement
00225 
00226   // Active surface is 0, return
00227   if (currentStress.deviatorLength() == 0.) return;
00228 
00229   // Find active surface
00230   while (yieldFunc(currentStress, committedSurfaces, ++committedActiveSurf) > 0) {
00231     if (committedActiveSurf == numOfSurfaces) {
00232       //opserr <<"WARNING:PressureIndependMultiYield::elast2Plast(): stress out of failure surface"<<endln;
00233       deviatorScaling(currentStress, committedSurfaces, numOfSurfaces);
00234       initSurfaceUpdate();
00235       return;
00236     }
00237   } 
00238   committedActiveSurf--;
00239   initSurfaceUpdate();
00240 }
00241 
00242 
00243 int PressureIndependMultiYield::setTrialStrain (const Vector &strain)
00244 {
00245   int ndm = ndmx[matN];
00246 
00247   static Vector temp(6);
00248   if (ndm==3 && strain.Size()==6) 
00249     temp = strain;
00250   else if (ndm==2 && strain.Size()==3) {
00251     temp[0] = strain[0];
00252     temp[1] = strain[1];
00253     temp[2] = 0.0;
00254     temp[3] = strain[2];
00255     temp[4] = 0.0;
00256     temp[5] = 0.0;
00257   }
00258   else {
00259     opserr << "Fatal:D2PressDepMYS:: Material dimension is: " << ndm << endln;
00260     opserr << "But strain vector size is: " << strain.Size() << endln;
00261     exit(-1);
00262   }
00263         
00264   //strainRate.setData(temp-currentStrain.t2Vector(1),1);
00265   temp -= currentStrain.t2Vector(1);
00266   strainRate.setData(temp, 1);
00267         
00268   return 0;
00269 }
00270 
00271 
00272 int PressureIndependMultiYield::setTrialStrain (const Vector &strain, const Vector &rate)
00273 {
00274   return setTrialStrain (strain);
00275 }
00276 
00277 
00278 int PressureIndependMultiYield::setTrialStrainIncr (const Vector &strain)
00279 {
00280   int ndm = ndmx[matN];
00281 
00282   static Vector temp(6);
00283   if (ndm==3 && strain.Size()==6) 
00284     temp = strain;
00285   else if (ndm==2 && strain.Size()==3) {
00286     temp[0] = strain[0];
00287     temp[1] = strain[1];
00288     temp[3] = strain[2];
00289   }
00290   else {
00291     opserr << "Fatal:D2PressDepMYS:: Material dimension is: " << ndm << endln;
00292     opserr << "But strain vector size is: " << strain.Size() << endln;
00293     exit(-1);
00294   }
00295   
00296   strainRate.setData(temp,1);
00297   return 0;
00298 }
00299 
00300 
00301 int PressureIndependMultiYield::setTrialStrainIncr (const Vector &strain, const Vector &rate)
00302 {
00303   return setTrialStrainIncr(strain);
00304 }
00305 
00306 
00307 const Matrix & PressureIndependMultiYield::getTangent (void)
00308 {
00309   int loadStage = loadStagex[matN];
00310   int ndm = ndmx[matN];
00311 
00312   if (loadStage == 1 && e2p == 0) elast2Plast();
00313 
00314   if (loadStage!=1) {  //linear elastic
00315     for (int i=0;i<6;i++) 
00316       for (int j=0;j<6;j++) {
00317         theTangent(i,j) = 0.;
00318         if (i==j) theTangent(i,j) += refShearModulus;
00319         if (i<3 && j<3 && i==j) theTangent(i,j) += refShearModulus;
00320         if (i<3 && j<3) theTangent(i,j) += (refBulkModulus - 2.*refShearModulus/3.);
00321       }
00322 
00323   }
00324   else {
00325     double coeff;
00326     static Vector devia(6);
00327     
00328     /*if (committedActiveSurf > 0) {
00329       //devia = currentStress.deviator()-committedSurfaces[committedActiveSurf].center();
00330       devia = currentStress.deviator();
00331       devia -= committedSurfaces[committedActiveSurf].center();
00332         
00333       double size = committedSurfaces[committedActiveSurf].size();
00334       double plastModul = committedSurfaces[committedActiveSurf].modulus();
00335       coeff = 6.*refShearModulus*refShearModulus/(2.*refShearModulus+plastModul)/size/size;
00336     }*/
00337     if (activeSurfaceNum > 0) {
00338       //devia = currentStress.deviator()-committedSurfaces[committedActiveSurf].center();
00339       devia = trialStress.deviator();
00340       devia -= theSurfaces[activeSurfaceNum].center();
00341         
00342       double size = theSurfaces[activeSurfaceNum].size();
00343       double plastModul = theSurfaces[activeSurfaceNum].modulus();
00344       coeff = 6.*refShearModulus*refShearModulus/(2.*refShearModulus+plastModul)/size/size;
00345     }
00346 
00347     else coeff = 0.;
00348     
00349     for (int i=0;i<6;i++) 
00350       for (int j=0;j<6;j++) {
00351         theTangent(i,j) = - coeff*devia[i]*devia[j];
00352         if (i==j) theTangent(i,j) += refShearModulus;
00353         if (i<3 && j<3 && i==j) theTangent(i,j) += refShearModulus;
00354         if (i<3 && j<3) theTangent(i,j) += (refBulkModulus - 2.*refShearModulus/3.);
00355       }
00356   }
00357 
00358   if (ndm==3) 
00359     return theTangent;
00360   else {
00361     static Matrix workM(3,3);
00362     workM(0,0) = theTangent(0,0);
00363     workM(0,1) = theTangent(0,1);
00364     workM(0,2) = theTangent(0,3);
00365     workM(1,0) = theTangent(1,0);
00366     workM(1,1) = theTangent(1,1);
00367     workM(1,2) = theTangent(1,3);
00368     workM(2,0) = theTangent(3,0);
00369     workM(2,1) = theTangent(3,1);
00370     workM(2,2) = theTangent(3,3);
00371     return workM;
00372   }
00373 }
00374 
00375 
00376 const Matrix & PressureIndependMultiYield::getInitialTangent (void)
00377 {
00378   int ndm = ndmx[matN];
00379 
00380   for (int i=0;i<6;i++) 
00381     for (int j=0;j<6;j++) {
00382       theTangent(i,j) = 0.;
00383       if (i==j) theTangent(i,j) += refShearModulus;
00384       if (i<3 && j<3 && i==j) theTangent(i,j) += refShearModulus;
00385       if (i<3 && j<3) theTangent(i,j) += (refBulkModulus - 2.*refShearModulus/3.);
00386     }
00387 
00388   if (ndm==3) 
00389     return theTangent;
00390   else {
00391     static Matrix workM(3,3);
00392     workM(0,0) = theTangent(0,0);
00393     workM(0,1) = theTangent(0,1);
00394     workM(0,2) = theTangent(0,3);
00395     workM(1,0) = theTangent(1,0);
00396     workM(1,1) = theTangent(1,1);
00397     workM(1,2) = theTangent(1,3);
00398     workM(2,0) = theTangent(3,0);
00399     workM(2,1) = theTangent(3,1);
00400     workM(2,2) = theTangent(3,3);
00401     return workM;
00402   }
00403 }
00404 
00405 
00406 const Vector & PressureIndependMultiYield::getStress (void)
00407 {
00408   int loadStage = loadStagex[matN];
00409   int numOfSurfaces = numOfSurfacesx[matN];
00410   int ndm = ndmx[matN];
00411 
00412   int i;
00413   if (loadStage == 1 && e2p == 0) elast2Plast();
00414 
00415   if (loadStage!=1) {  //linear elastic
00416     //trialStrain.setData(currentStrain.t2Vector() + strainRate.t2Vector());
00417     getTangent();
00418     static Vector a(6);
00419     a = currentStress.t2Vector();
00420         a.addMatrixVector(1.0, theTangent, strainRate.t2Vector(1), 1.0);
00421     trialStress.setData(a);
00422   }
00423 
00424   else {
00425     for (i=1; i<=numOfSurfaces; i++) theSurfaces[i] = committedSurfaces[i];
00426     activeSurfaceNum = committedActiveSurf;
00427     subStrainRate = strainRate;
00428     setTrialStress(currentStress);
00429     if (isLoadReversal()) {
00430       updateInnerSurface();
00431       activeSurfaceNum = 0;
00432     }
00433     int numSubIncre = setSubStrainRate();
00434     
00435     for (i=0; i<numSubIncre; i++) {
00436       if (i==0)  
00437         setTrialStress(currentStress);
00438       else 
00439         setTrialStress(trialStress);
00440       if (activeSurfaceNum==0 && !isCrossingNextSurface()) continue;
00441       if (activeSurfaceNum==0) activeSurfaceNum++;
00442       stressCorrection(0);
00443       updateActiveSurface();
00444     }
00445     //volume stress change
00446     double volum = refBulkModulus*(strainRate.volume()*3.);
00447     volum += currentStress.volume();
00448      //if (volum > 0) volum = 0.;
00449     trialStress.setData(trialStress.deviator(),volum);
00450   }
00451 
00452   if (ndm==3)
00453     return trialStress.t2Vector();
00454   else {
00455     static Vector workV(3);
00456     workV[0] = trialStress.t2Vector()[0];
00457     workV[1] = trialStress.t2Vector()[1];
00458     workV[2] = trialStress.t2Vector()[3];
00459     return workV;
00460   }
00461 }
00462 
00463 
00464 const Vector & PressureIndependMultiYield::getStrain (void)
00465 {
00466   return getCommittedStrain();
00467 }
00468 
00469 
00470 int PressureIndependMultiYield::commitState (void)
00471 {
00472   int loadStage = loadStagex[matN];
00473   int numOfSurfaces = numOfSurfacesx[matN];
00474 
00475   currentStress = trialStress;
00476   
00477   //currentStrain = T2Vector(currentStrain.t2Vector() + strainRate.t2Vector());
00478   static Vector temp(6);
00479   temp = currentStrain.t2Vector();
00480   temp += strainRate.t2Vector();
00481   currentStrain.setData(temp);
00482   temp.Zero();
00483   strainRate.setData(temp);
00484   
00485   if (loadStage==1) {
00486     committedActiveSurf = activeSurfaceNum;
00487     for (int i=1; i<=numOfSurfaces; i++) committedSurfaces[i] = theSurfaces[i];
00488   }
00489 
00490   return 0;
00491 }
00492  
00493 
00494 int PressureIndependMultiYield::revertToLastCommit (void)
00495 {
00496   return 0;
00497 }
00498 
00499 
00500 NDMaterial * PressureIndependMultiYield::getCopy (void)
00501 {
00502   PressureIndependMultiYield * copy = new PressureIndependMultiYield(*this);
00503   return copy;
00504 }
00505 
00506 
00507 NDMaterial * PressureIndependMultiYield::getCopy (const char *code)
00508 {
00509   if (strcmp(code,"PressureIndependMultiYield") == 0 || strcmp(code,"PlaneStrain") == 0
00510       || strcmp(code,"ThreeDimensional") == 0) {
00511     PressureIndependMultiYield * copy = new PressureIndependMultiYield(*this);
00512     return copy;
00513   }
00514 
00515   return 0;
00516 }
00517 
00518 
00519 const char * PressureIndependMultiYield::getType (void) const
00520 {
00521   int ndm = ndmx[matN];
00522 
00523   return (ndm == 2) ? "PlaneStrain" : "ThreeDimensional";
00524 }
00525 
00526 
00527 int PressureIndependMultiYield::getOrder (void) const
00528 {
00529   int ndm = ndmx[matN];
00530 
00531   return (ndm == 2) ? 3 : 6;
00532 }
00533 
00534 
00535 int PressureIndependMultiYield::updateParameter(int responseID, Information &info)
00536 {
00537         if (responseID<10)
00538                 loadStagex[matN] = responseID;
00539 
00540   return 0;
00541 }
00542 
00543 
00544 int PressureIndependMultiYield::sendSelf(int commitTag, Channel &theChannel)
00545 {
00546   int loadStage = loadStagex[matN];
00547   int ndm = ndmx[matN];
00548   int numOfSurfaces = numOfSurfacesx[matN];
00549   double rho = rhox[matN];
00550   double frictionAngle = frictionAnglex[matN];
00551   double peakShearStrain = peakShearStrainx[matN];
00552   double refPressure = refPressurex[matN];
00553   double cohesion = cohesionx[matN];
00554   double pressDependCoeff = pressDependCoeffx[matN];
00555   double residualPress = residualPressx[matN];
00556 
00557   int i, res = 0;
00558 
00559   static ID idData(5);
00560   idData(0) = this->getTag();
00561   idData(1) = numOfSurfaces;
00562   idData(2) = loadStage;
00563   idData(3) = ndm;
00564   idData(4) = matN;
00565 
00566   res += theChannel.sendID(this->getDbTag(), commitTag, idData);
00567   if (res < 0) {
00568     opserr << "PressureDependMultiYield::sendSelf -- could not send ID\n";
00569     return res;
00570   }
00571 
00572   Vector data(23+numOfSurfaces*8);
00573   static Vector temp(6);
00574   data(0) = rho;
00575   data(1) = refShearModulus;
00576   data(2) = refBulkModulus;
00577   data(3) = frictionAngle;
00578   data(4) = peakShearStrain;
00579   data(5) = refPressure;
00580   data(6) = cohesion;
00581   data(7) = pressDependCoeff;
00582   data(8) = residualPress;
00583   data(9) = e2p;
00584   data(10) = committedActiveSurf;
00585         
00586   temp = currentStress.t2Vector();
00587   for(i = 0; i < 6; i++) data(i+11) = temp[i];
00588   
00589   temp = currentStrain.t2Vector();
00590   for(i = 0; i < 6; i++) data(i+17) = temp[i];
00591   
00592   for(i = 0; i < numOfSurfaces; i++) {
00593     int k = 23 + i*8;
00594     data(k) = committedSurfaces[i+1].size();
00595     data(k+1) = committedSurfaces[i+1].modulus();
00596     temp = committedSurfaces[i+1].center();
00597     data(k+2) = temp(0);
00598     data(k+3) = temp(1);
00599     data(k+4) = temp(2);
00600     data(k+5) = temp(3);
00601     data(k+6) = temp(4);
00602     data(k+7) = temp(5);
00603   }
00604 
00605   res += theChannel.sendVector(this->getDbTag(), commitTag, data);
00606   if (res < 0) {
00607     opserr << "PressureDependMultiYield::sendSelf -- could not send Vector\n";
00608     return res;
00609   }
00610   
00611   return res;
00612 }
00613 
00614 
00615 int PressureIndependMultiYield::recvSelf(int commitTag, Channel &theChannel, 
00616                                          FEM_ObjectBroker &theBroker)    
00617 {
00618   int i, res = 0;
00619 
00620   static ID idData(5);
00621 
00622   res += theChannel.recvID(this->getDbTag(), commitTag, idData);
00623   if (res < 0) {
00624     opserr << "PressureDependMultiYield::recvSelf -- could not recv ID\n";
00625     return res;
00626   }
00627 
00628   this->setTag((int)idData(0));
00629   int numOfSurfaces = idData(1);
00630   int loadStage = idData(2);
00631   int ndm = idData(3);
00632   matN = idData(4);
00633 
00634   Vector data(23+idData(1)*8);
00635   static Vector temp(6);
00636   
00637   res += theChannel.recvVector(this->getDbTag(), commitTag, data);
00638   if (res < 0) {
00639     opserr << "PressureDependMultiYield::recvSelf -- could not recv Vector\n";
00640     return res;
00641   }
00642     
00643   double rho = data(0);
00644   double refShearModulus = data(1);
00645   double refBulkModulus = data(2);
00646   double frictionAngle = data(3);
00647   double peakShearStrain = data(4);
00648   double refPressure = data(5);
00649   double cohesion = data(6);
00650   double pressDependCoeff = data(7);
00651   double residualPress = data(8);
00652   e2p = data(9);
00653   committedActiveSurf = data(10);
00654   
00655   for(i = 0; i < 6; i++) temp[i] = data(i+11);
00656   currentStress.setData(temp);
00657   
00658   for(i = 0; i < 6; i++) temp[i] = data(i+17);
00659   currentStrain.setData(temp);
00660 
00661   if (committedSurfaces != 0) {
00662     delete [] committedSurfaces;
00663     delete [] theSurfaces;
00664   }
00665 
00666   theSurfaces = new MultiYieldSurface[numOfSurfaces+1]; //first surface not used
00667   committedSurfaces = new MultiYieldSurface[numOfSurfaces+1]; 
00668   for (i=1; i<=numOfSurfaces; i++) {
00669     committedSurfaces[i] = MultiYieldSurface();
00670   }
00671   
00672   for(i = 0; i < numOfSurfaces; i++) {
00673     int k = 23 + i*8;
00674     temp(0) = data(k+2);
00675     temp(1) = data(k+3);
00676     temp(2) = data(k+4);
00677     temp(3) = data(k+5);
00678     temp(4) = data(k+6);
00679     temp(5) = data(k+7);
00680     committedSurfaces[i+1].setData(temp, data(k), data(k+1));
00681   }
00682   
00683   loadStagex[matN] = loadStage;
00684   ndmx[matN] = ndm;
00685   numOfSurfacesx[matN] = numOfSurfaces;
00686   rhox[matN] = rho;
00687   frictionAnglex[matN] = frictionAngle;
00688   peakShearStrainx[matN] = peakShearStrain;
00689   refPressurex[matN] = refPressure;
00690   cohesionx[matN] = cohesion;
00691   pressDependCoeffx[matN] = pressDependCoeff;
00692   residualPressx[matN] = residualPress;
00693 
00694   return res;
00695 }
00696 
00697 
00698 Response*
00699 PressureIndependMultiYield::setResponse (const char **argv, int argc, Information &matInfo, OPS_Stream &output)
00700 {
00701   if (strcmp(argv[0],"stress") == 0 || strcmp(argv[0],"stresses") == 0)
00702     return new MaterialResponse(this, 1, this->getCommittedStress());
00703   
00704   else if (strcmp(argv[0],"strain") == 0 || strcmp(argv[0],"strains") == 0)
00705     return new MaterialResponse(this, 2, this->getCommittedStrain());
00706   
00707   else if (strcmp(argv[0],"tangent") == 0)
00708     return new MaterialResponse(this, 3, this->getTangent());
00709   
00710   else if (strcmp(argv[0],"backbone") == 0) {
00711     int numOfSurfaces = numOfSurfacesx[matN];
00712     static Matrix curv(numOfSurfaces+1,(argc-1)*2);
00713     for (int i=1; i<argc; i++)
00714       curv(0,(i-1)*2) = atoi(argv[i]);
00715     return new MaterialResponse(this, 4, curv);
00716   }
00717   else
00718     return 0;
00719 }
00720 
00721 
00722 int PressureIndependMultiYield::getResponse (int responseID, Information &matInfo)
00723 {
00724   switch (responseID) {
00725   case -1:
00726     return -1;
00727   case 1:
00728     if (matInfo.theVector != 0)
00729       *(matInfo.theVector) = getCommittedStress();
00730     return 0;
00731   case 2:
00732     if (matInfo.theVector != 0)
00733       *(matInfo.theVector) = getCommittedStrain();
00734     return 0;
00735   case 3:
00736     if (matInfo.theMatrix != 0)
00737       *(matInfo.theMatrix) = getTangent();
00738     return 0;
00739   case 4:
00740     if (matInfo.theMatrix != 0) 
00741       getBackbone(*(matInfo.theMatrix));
00742     return 0;
00743   default:
00744     return -1;
00745   }
00746 }
00747 
00748 
00749 void PressureIndependMultiYield::getBackbone (Matrix & bb)
00750 {
00751   double residualPress = residualPressx[matN];
00752   double refPressure = refPressurex[matN];
00753   double pressDependCoeff =pressDependCoeffx[matN];
00754   int numOfSurfaces = numOfSurfacesx[matN];
00755 
00756   double vol, conHeig, scale, factor, shearModulus, stress1, 
00757                      stress2, strain1, strain2, plastModulus, elast_plast, gre;
00758 
00759         for (int k=0; k<bb.noCols()/2; k++) {
00760                 vol = bb(0,k*2);
00761                 if (vol<=0.) {
00762                         opserr <<k<< "\nNDMaterial " <<this->getTag()
00763                           <<": invalid confinement for backbone recorder, " << vol << endln;
00764                         continue;
00765                 }
00766                 conHeig = vol + residualPress;
00767                 scale = -conHeig / (refPressure-residualPress);
00768                 factor = pow(scale, pressDependCoeff); 
00769                 shearModulus = factor*refShearModulus;
00770                 for (int i=1; i<=numOfSurfaces; i++) {
00771                         if (i==1) {
00772                                 stress2 = committedSurfaces[i].size()*factor/sqrt(3.0);
00773                                 strain2 = stress2/shearModulus;
00774                                 bb(1,k*2) = strain2; bb(1,k*2+1) = shearModulus;
00775                         } else {
00776                                 stress1 = stress2; strain1 = strain2;
00777                                 plastModulus = factor*committedSurfaces[i-1].modulus();
00778                                 elast_plast = 2*shearModulus*plastModulus/(2*shearModulus+plastModulus);
00779                                 stress2 = factor*committedSurfaces[i].size()/sqrt(3.0);
00780                           strain2 = 2*(stress2-stress1)/elast_plast + strain1;
00781                                 gre = stress2/strain2;
00782                 bb(i,k*2) = strain2; bb(i,k*2+1) = gre;
00783                         }
00784                 }
00785         }
00786 
00787 }
00788 
00789 void PressureIndependMultiYield::Print(OPS_Stream &s, int flag )
00790 {
00791   s << "PressureIndependMultiYield" << endln;
00792 }
00793 
00794 
00795 const Vector & PressureIndependMultiYield::getCommittedStress (void)
00796 {
00797         int ndm = ndmx[matN];
00798         int numOfSurfaces = numOfSurfacesx[matN];
00799 
00800         double scale = sqrt(3./2.)*currentStress.deviatorLength()/committedSurfaces[numOfSurfaces].size();
00801         if (loadStagex[matN] != 1) scale = 0.;
00802         if (ndm==3) {
00803                 static Vector temp7(7), temp6(6);
00804                 temp6 = currentStress.t2Vector();
00805     temp7[0] = temp6[0];
00806     temp7[1] = temp6[1];
00807     temp7[2] = temp6[2];
00808     temp7[3] = temp6[3];
00809     temp7[4] = temp6[4];
00810     temp7[5] = temp6[5];
00811     temp7[6] = scale;
00812         return temp7;
00813         }
00814   else {
00815     static Vector temp5(5), temp6(6);
00816                 temp6 = currentStress.t2Vector();
00817     temp5[0] = temp6[0];
00818     temp5[1] = temp6[1];
00819     temp5[2] = temp6[2];
00820     temp5[3] = temp6[3];
00821     temp5[4] = scale;
00822     return temp5;
00823   }
00824 }
00825 
00826 
00827 const Vector & PressureIndependMultiYield::getCommittedStrain (void)
00828 {       
00829         int ndm = ndmx[matN];
00830 
00831   if (ndm==3)
00832     return currentStrain.t2Vector(1);
00833   else {
00834     static Vector workV(3), temp6(6);
00835                 temp6 = currentStrain.t2Vector(1);
00836     workV[0] = temp6[0];
00837     workV[1] = temp6[1];
00838     workV[2] = temp6[3];
00839     return workV;
00840   }
00841 }
00842 
00843 
00844 // NOTE: surfaces[0] is not used 
00845 void PressureIndependMultiYield::setUpSurfaces (double * gredu)
00846 { 
00847     double residualPress = residualPressx[matN];
00848     double refPressure = refPressurex[matN];
00849     double pressDependCoeff =pressDependCoeffx[matN];
00850     int numOfSurfaces = numOfSurfacesx[matN];
00851     double frictionAngle = frictionAnglex[matN];
00852         double cohesion = cohesionx[matN];
00853     double peakShearStrain = peakShearStrainx[matN];
00854 
00855         double  stress1, stress2, strain1, strain2, size, elasto_plast_modul, plast_modul;
00856         double pi = 3.14159265358979;
00857         double refStrain, peakShear, coneHeight;
00858 
00859         if (gredu == 0) {  //automatic generation of surfaces
00860           if (frictionAngle > 0) {
00861             double sinPhi = sin(frictionAngle * pi/180.);
00862             double Mnys = 6.*sinPhi/(3.-sinPhi);
00863             residualPress = 3.* cohesion / (sqrt(2.) * Mnys);
00864                   coneHeight = - (refPressure - residualPress);
00865                   peakShear = sqrt(2.) * coneHeight * Mnys / 3.; 
00866                   refStrain = (peakShearStrain * peakShear) 
00867                                     / (refShearModulus * peakShearStrain - peakShear);
00868                 }
00869 
00870           else if (frictionAngle == 0.) { // cohesion = peakShearStrength
00871                   peakShear = 2*sqrt(2.)*cohesion/3;
00872                   refStrain = (peakShearStrain * peakShear) 
00873                                     / (refShearModulus * peakShearStrain - peakShear);
00874                   residualPress = 0.;
00875                 }
00876         
00877           double stressInc = peakShear / numOfSurfaces;
00878 
00879           for (int ii=1; ii<=numOfSurfaces; ii++){
00880         stress1 = ii * stressInc; 
00881                                 stress2 = stress1 + stressInc;
00882         strain1 = stress1 * refStrain / (refShearModulus * refStrain - stress1);
00883         strain2 = stress2 * refStrain / (refShearModulus * refStrain - stress2);
00884         if (frictionAngle > 0.) size = 3. * stress1 / sqrt(2.) / coneHeight;
00885         else if (frictionAngle == 0.) size = 3. * stress1 / sqrt(2.);
00886  
00887         elasto_plast_modul = 2.*(stress2 - stress1)/(strain2 - strain1);
00888 
00889         if ( (2.*refShearModulus - elasto_plast_modul) <= 0) 
00890                                         plast_modul = UP_LIMIT;
00891         else 
00892                                         plast_modul = (2.*refShearModulus * elasto_plast_modul)/
00893                         (2.*refShearModulus - elasto_plast_modul);
00894         if (plast_modul < 0) plast_modul = 0;
00895         if (plast_modul > UP_LIMIT) plast_modul = UP_LIMIT;
00896         if (ii==numOfSurfaces) plast_modul = 0;
00897 
00898                     static Vector temp(6);
00899         committedSurfaces[ii] = MultiYieldSurface(temp,size,plast_modul);
00900                 }  // ii
00901         } 
00902         else {  //user defined surfaces
00903                 if (frictionAngle > 0) {   // ignore user defined frictionAngle 
00904                   int ii = 2*(numOfSurfaces-1);
00905                         double tmax = refShearModulus*gredu[ii]*gredu[ii+1];
00906                         double Mnys = -(sqrt(3.) * tmax - 2. * cohesion) / refPressure;
00907                         if (Mnys <= 0) {   // also ignore user defined cohesion
00908          cohesion = sqrt(3.)/2 * tmax;
00909          frictionAngle = 0.;  
00910                      coneHeight = 1.;
00911                      residualPress = 0.;
00912       } else {
00913          double sinPhi = 3*Mnys /(6+Mnys);
00914                if (sinPhi<0. || sinPhi>1.) {
00915                                          opserr <<"\nNDMaterial " <<this->getTag()<<": Invalid friction angle, please modify ref. pressure or G/Gmax curve."<<endln;
00916            exit(-1);
00917                                  } 
00918           residualPress = 2. * cohesion / Mnys;
00919         if (residualPress < 0.01) residualPress = 0.01; 
00920         coneHeight = - (refPressure - residualPress);
00921         frictionAngle = asin(sinPhi)*180/pi;
00922                         }
00923     }  else if (frictionAngle == 0.) {   // ignore user defined cohesion
00924                                 int ii = 2*(numOfSurfaces-1);
00925                                 double tmax = refShearModulus*gredu[ii]*gredu[ii+1];
00926         cohesion = sqrt(3.)/2 * tmax;
00927                                 coneHeight = 1.;
00928                                 residualPress = 0.;
00929                 }
00930 
00931                 opserr << "\nNDMaterial " <<this->getTag()<<": Friction angle = "<<frictionAngle
00932                                                            <<", Cohesion = "<<cohesion<<"\n"<<endln;
00933 
00934     if (frictionAngle == 0.) pressDependCoeff = 0.; // ignore user defined pressDependCoeff
00935 
00936                 for (int i=1; i<numOfSurfaces; i++) {
00937                         int ii = 2*(i-1);
00938                         strain1 = gredu[ii]; 
00939       stress1 = refShearModulus*gredu[ii+1]*strain1; 
00940                         strain2 = gredu[ii+2]; 
00941       stress2 = refShearModulus*gredu[ii+3]*strain2; 
00942 
00943       size = sqrt(3.) * stress1 / coneHeight;
00944       elasto_plast_modul = 2.*(stress2 - stress1)/(strain2 - strain1);
00945                         if ( (2.*refShearModulus - elasto_plast_modul) <= 0) 
00946                                         plast_modul = UP_LIMIT;
00947       else 
00948                                         plast_modul = (2.*refShearModulus * elasto_plast_modul)/
00949                         (2.*refShearModulus - elasto_plast_modul);
00950       if (plast_modul <= 0) {
00951                                 opserr << "\nNDMaterial " <<this->getTag()<<": Surface " << i 
00952                                            << " has plastic modulus < 0.\n Please modify G/Gmax curve.\n"<<endln;
00953         exit(-1);
00954       }
00955       if (plast_modul > UP_LIMIT) plast_modul = UP_LIMIT;
00956 
00957                   static Vector temp(6);
00958       committedSurfaces[i] = MultiYieldSurface(temp,size,plast_modul);
00959 
00960                         if (i==(numOfSurfaces-1)) {
00961                                 plast_modul = 0;
00962                                 size = sqrt(3.) * stress2 / coneHeight;
00963         committedSurfaces[i+1] = MultiYieldSurface(temp,size,plast_modul);
00964                         }
00965                 }
00966   }  
00967 
00968   residualPressx[matN] = residualPress;
00969   frictionAnglex[matN] = frictionAngle;
00970   cohesionx[matN] = cohesion;
00971 }
00972 
00973 
00974 double PressureIndependMultiYield::yieldFunc(const T2Vector & stress, 
00975                                                                                          const MultiYieldSurface * surfaces, int surfaceNum)
00976 {
00977         static Vector temp(6);
00978         //temp = stress.deviator() - surfaces[surfaceNum].center();
00979         temp = stress.deviator();
00980         temp -= surfaces[surfaceNum].center();
00981 
00982         double sz = surfaces[surfaceNum].size();
00983         return 3./2.*(temp && temp) - sz * sz;
00984 }
00985 
00986 
00987 void PressureIndependMultiYield::deviatorScaling(T2Vector & stress, const MultiYieldSurface * surfaces, 
00988                                                                                                                                                         int surfaceNum, int count)
00989 {
00990         count++;
00991         int numOfSurfaces = numOfSurfacesx[matN];
00992     
00993         double diff = yieldFunc(stress, surfaces, surfaceNum);
00994 
00995         if ( surfaceNum < numOfSurfaces && diff < 0. ) {
00996                 double sz = surfaces[surfaceNum].size();
00997                 double deviaSz = sqrt(sz*sz + diff);
00998                 static Vector devia(6);
00999                 devia = stress.deviator(); 
01000                 static Vector temp(6);
01001                 temp = devia - surfaces[surfaceNum].center();
01002                 double coeff = (sz-deviaSz) / deviaSz;
01003                 if (coeff < 1.e-13) coeff = 1.e-13;
01004                 devia.addVector(1.0, temp, coeff);
01005                 stress.setData(devia, stress.volume());
01006                 deviatorScaling(stress, surfaces, surfaceNum, count);  // recursive call
01007         }
01008 
01009         if (surfaceNum==numOfSurfaces && fabs(diff) > LOW_LIMIT) {
01010                 double sz = surfaces[surfaceNum].size();
01011                 static Vector newDevia(6);
01012                 newDevia.addVector(0.0, stress.deviator(), sz/sqrt(diff+sz*sz));
01013                 stress.setData(newDevia, stress.volume());
01014         }
01015 }
01016 
01017 
01018 void PressureIndependMultiYield::initSurfaceUpdate()
01019 {
01020         if (committedActiveSurf == 0) return; 
01021 
01022         int numOfSurfaces = numOfSurfacesx[matN];
01023 
01024         static Vector devia(6);
01025         devia = currentStress.deviator();
01026         double Ms = sqrt(3./2.*(devia && devia));
01027         static Vector newCenter(6);
01028 
01029         if (committedActiveSurf < numOfSurfaces) { // failure surface can't move
01030                 //newCenter = devia * (1. - committedSurfaces[activeSurfaceNum].size() / Ms); 
01031                 newCenter.addVector(0.0, devia, 1.0-committedSurfaces[committedActiveSurf].size()/Ms);
01032                 committedSurfaces[committedActiveSurf].setCenter(newCenter);
01033         }
01034 
01035         for (int i=1; i<committedActiveSurf; i++) {
01036           newCenter = devia * (1. - committedSurfaces[i].size() / Ms);
01037           committedSurfaces[i].setCenter(newCenter); 
01038         }
01039 }
01040 
01041 
01042 void PressureIndependMultiYield::paramScaling(void)
01043 {
01044         int numOfSurfaces = numOfSurfacesx[matN];
01045         double frictionAngle = frictionAnglex[matN];
01046     double residualPress = residualPressx[matN];
01047     double refPressure = refPressurex[matN];
01048     double pressDependCoeff =pressDependCoeffx[matN];
01049 
01050         if (frictionAngle == 0.) return;
01051 
01052         double conHeig = - (currentStress.volume() - residualPress);
01053         double scale = -conHeig / (refPressure-residualPress);
01054            
01055         scale = pow(scale, pressDependCoeff); 
01056         refShearModulus *= scale;
01057         refBulkModulus *= scale;
01058 
01059         double plastModul, size;
01060         static Vector temp(6);
01061         for (int i=1; i<=numOfSurfaces; i++) {
01062           plastModul = committedSurfaces[i].modulus() * scale;
01063           size = committedSurfaces[i].size() * conHeig;
01064           committedSurfaces[i] =  MultiYieldSurface(temp,size,plastModul);
01065         }
01066 
01067 }
01068 
01069 
01070 void PressureIndependMultiYield::setTrialStress(T2Vector & stress)
01071 {
01072   static Vector devia(6);
01073   //devia = stress.deviator() + subStrainRate.deviator()*2.*refShearModulus;
01074   devia = stress.deviator();
01075   devia.addVector(1.0, subStrainRate.deviator(), 2.*refShearModulus);
01076   
01077   trialStress.setData(devia, stress.volume());
01078 }
01079 
01080 
01081 int PressureIndependMultiYield::setSubStrainRate(void)
01082 {
01083     int numOfSurfaces = numOfSurfacesx[matN];
01084 
01085         //if (activeSurfaceNum==numOfSurfaces) return 1;
01086 
01087         //if (strainRate==T2Vector()) return 0;
01088         if (strainRate.isZero()) return 0;
01089 
01090         double elast_plast_modulus;
01091         if (activeSurfaceNum==0) 
01092           elast_plast_modulus = 2*refShearModulus;
01093         else {
01094           double plast_modulus = theSurfaces[activeSurfaceNum].modulus();
01095           elast_plast_modulus = 2*refShearModulus*plast_modulus 
01096             / (2*refShearModulus+plast_modulus);
01097         }
01098         static Vector incre(6);
01099         //incre = strainRate.deviator()*elast_plast_modulus;
01100         incre.addVector(0.0, strainRate.deviator(),elast_plast_modulus);
01101 
01102         static T2Vector increStress;
01103         increStress.setData(incre, 0);
01104         double singleCross = theSurfaces[numOfSurfaces].size() / numOfSurfaces;
01105         double totalCross = 3.*increStress.octahedralShear() / sqrt(2.);
01106         int numOfSub = totalCross/singleCross + 1;
01107         if (numOfSub > numOfSurfaces) numOfSub = numOfSurfaces;
01108         //incre = strainRate.t2Vector() / numOfSub;
01109         incre = strainRate.t2Vector();
01110         incre /= numOfSub;
01111         subStrainRate.setData(incre);
01112 
01113         return numOfSub;
01114 }
01115 
01116 
01117 void
01118 PressureIndependMultiYield::getContactStress(T2Vector &contactStress)
01119 {
01120         static Vector center(6);
01121         center = theSurfaces[activeSurfaceNum].center(); 
01122         static Vector devia(6);
01123         //devia = trialStress.deviator() - center;
01124         devia = trialStress.deviator();
01125         devia -= center;
01126 
01127         double Ms = sqrt(3./2.*(devia && devia));
01128         //devia = devia * theSurfaces[activeSurfaceNum].size() / Ms + center;
01129         devia *= theSurfaces[activeSurfaceNum].size() / Ms;
01130         devia += center;
01131 
01132         contactStress.setData(devia,trialStress.volume()); 
01133 }
01134 
01135 
01136 int PressureIndependMultiYield::isLoadReversal(void)
01137 {
01138   if(activeSurfaceNum == 0) return 0;
01139 
01140   static Vector surfaceNormal(6);
01141   getSurfaceNormal(currentStress, surfaceNormal);
01142  
01143   //(((trialStress.deviator() - currentStress.deviator()) && surfaceNormal) < 0) 
01144   // return 1;
01145   static Vector a(6);
01146   a = trialStress.deviator();
01147   a-= currentStress.deviator();
01148   if((a && surfaceNormal) < 0) 
01149     return 1;
01150 
01151   return 0;   
01152 }
01153 
01154 
01155 void
01156 PressureIndependMultiYield::getSurfaceNormal(const T2Vector & stress, Vector &surfaceNormal)
01157 {
01158   //Q = stress.deviator() - theSurfaces[activeSurfaceNum].center();
01159   // return Q / sqrt(Q && Q);
01160 
01161   surfaceNormal = stress.deviator();
01162   surfaceNormal -= theSurfaces[activeSurfaceNum].center();
01163   surfaceNormal /= sqrt(surfaceNormal && surfaceNormal);
01164 }
01165 
01166 
01167 double PressureIndependMultiYield::getLoadingFunc(const T2Vector & contactStress, 
01168                                                                          const Vector & surfaceNormal, int crossedSurface)
01169 {
01170   double loadingFunc;
01171   double temp1 = 2. * refShearModulus ;
01172   double temp2 = theSurfaces[activeSurfaceNum].modulus();
01173 
01174   //for crossing first surface
01175   double temp = temp1 + temp2;
01176   //loadingFunc = (surfaceNormal && (trialStress.deviator()-contactStress.deviator()))/temp;
01177   static Vector tmp(6);
01178   tmp =trialStress.deviator();
01179   tmp -= contactStress.deviator();
01180   loadingFunc = (surfaceNormal && tmp)/temp;
01181    //for crossing more than one surface
01182   if(crossedSurface) {
01183     double temp3 = theSurfaces[activeSurfaceNum-1].modulus();
01184     loadingFunc *= (temp3 - temp2)/temp3;
01185   }
01186 
01187   return loadingFunc;
01188 }
01189 
01190 
01191 void PressureIndependMultiYield::stressCorrection(int crossedSurface)
01192 {
01193         static T2Vector contactStress;
01194         this->getContactStress(contactStress);
01195         static Vector surfaceNormal(6);
01196         this->getSurfaceNormal(contactStress, surfaceNormal);
01197         double loadingFunc = getLoadingFunc(contactStress, surfaceNormal, crossedSurface);
01198         static Vector devia(6);
01199 
01200         //devia = trialStress.deviator() - surfaceNormal * 2 * refShearModulus * loadingFunc;
01201         devia.addVector(0.0, surfaceNormal, -2*refShearModulus*loadingFunc);
01202         devia += trialStress.deviator();
01203 
01204         trialStress.setData(devia, trialStress.volume());
01205         deviatorScaling(trialStress, theSurfaces, activeSurfaceNum);
01206 
01207         if (isCrossingNextSurface()) {
01208                 activeSurfaceNum++;
01209                 stressCorrection(1);  //recursive call
01210         }
01211 }
01212 
01213 
01214 void PressureIndependMultiYield::updateActiveSurface(void)
01215 {
01216   int numOfSurfaces = numOfSurfacesx[matN];
01217 
01218   if (activeSurfaceNum == numOfSurfaces) return;
01219 
01220         double A, B, C, X;
01221         static T2Vector direction;
01222         static Vector t1(6);
01223         static Vector t2(6);
01224         static Vector temp(6);
01225         static Vector center(6);
01226         center = theSurfaces[activeSurfaceNum].center();
01227         double size = theSurfaces[activeSurfaceNum].size();
01228         static Vector outcenter(6);
01229         outcenter= theSurfaces[activeSurfaceNum+1].center();
01230         double outsize = theSurfaces[activeSurfaceNum+1].size();
01231 
01232 
01233         //t1 = trialStress.deviator() - center;
01234         //t2 = center - outcenter;
01235         t1 = trialStress.deviator();
01236         t1 -= center;
01237         t2 = center;
01238         t2 -= outcenter;
01239 
01240         A = t1 && t1;
01241         B = 2. * (t1 && t2);
01242         C = (t2 && t2) - 2./3.* outsize * outsize;
01243         X = secondOrderEqn(A,B,C,0);
01244         if ( fabs(X-1.) < LOW_LIMIT ) X = 1.;
01245         if (X < 1.){
01246           opserr << "FATAL:PressureIndependMultiYield::updateActiveSurface(): error in Direction of surface motion." 
01247                << endln; 
01248           exit(-1);
01249         }
01250 
01251         //temp = (t1 * X + center) * (1. - size / outsize) - (center - outcenter * size / outsize);
01252         temp = center;
01253         temp.addVector(1.0, t1, X);
01254         temp *= (1.0 - size/outsize);
01255         t2 = center;
01256         t2.addVector(1.0, outcenter, -size/outsize);
01257         temp -= t2;
01258 
01259         direction.setData(temp);
01260 
01261         if (direction.deviatorLength() < LOW_LIMIT) return;
01262 
01263         temp = direction.deviator();  
01264         A = temp && temp;
01265         B = - 2 * (t1 && temp);
01266         if (fabs(B) < LOW_LIMIT) B = 0.; 
01267         C = (t1 && t1) - 2./3.* size * size;
01268         if ( fabs(C) < LOW_LIMIT || fabs(C)/(t1 && t1) < LOW_LIMIT ) return;
01269 
01270         if (B > 0. || C < 0.) {
01271           opserr << "FATAL:PressureIndependMultiYield::updateActiveSurface(): error in surface motion.\n" 
01272                << "A= " <<A <<" B= " <<B <<" C= "<<C <<" (t1&&t1)= "<<(t1&&t1) <<endln; 
01273           exit(-1);
01274         }
01275         X = secondOrderEqn(A,B,C,1);  
01276 
01277         //center += temp * X;
01278         center.addVector(1.0, temp, X);
01279         theSurfaces[activeSurfaceNum].setCenter(center);
01280 }      
01281 
01282 
01283 void PressureIndependMultiYield::updateInnerSurface(void)
01284 {
01285         if (activeSurfaceNum <= 1) return;
01286 
01287         static Vector devia(6);
01288         devia = currentStress.deviator();
01289         static Vector center(6);
01290         center = theSurfaces[activeSurfaceNum].center();
01291         double size = theSurfaces[activeSurfaceNum].size();
01292         static Vector newcenter(6);
01293 
01294         for (int i=1; i<activeSurfaceNum; i++) {
01295                 //newcenter = devia - (devia - center) * theSurfaces[i].size() / size;
01296                 newcenter = center; 
01297                 newcenter -= devia;
01298                 newcenter *= theSurfaces[i].size()/size;
01299                 newcenter += devia;
01300 
01301                 theSurfaces[i].setCenter(newcenter);
01302         }
01303 }
01304 
01305 
01306 int PressureIndependMultiYield:: isCrossingNextSurface(void)
01307 {
01308   int numOfSurfaces = numOfSurfacesx[matN];
01309   if (activeSurfaceNum == numOfSurfaces) return 0;  
01310 
01311   if(yieldFunc(trialStress, theSurfaces, activeSurfaceNum+1) > 0) return 1;
01312   
01313   return 0;
01314 }
01315  

Generated on Mon Oct 23 15:05:16 2006 for OpenSees by doxygen 1.5.0