PageRenderTime 100ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/SRC/material/nD/soil/PressureIndependMultiYield.cpp

https://bitbucket.org/lge/opensees
C++ | 1407 lines | 1117 code | 235 blank | 55 comment | 282 complexity | bcb0aaffd4dcf06d35ac4c16d5081d28 MD5 | raw file
  1. // $Revision: 1.41 $
  2. // $Date: 2009-10-07 20:14:00 $
  3. // $Source: /usr/local/cvs/OpenSees/SRC/material/nD/soil/PressureIndependMultiYield.cpp,v $
  4. // Written: ZHY
  5. // Created: August 2000
  6. // Last Modified: September 2009
  7. //
  8. // PressureIndependMultiYield.cpp
  9. // -------------------
  10. //
  11. #include <math.h>
  12. #include <stdlib.h>
  13. #include <PressureIndependMultiYield.h>
  14. #include <Information.h>
  15. #include <ID.h>
  16. #include <MaterialResponse.h>
  17. #include <Parameter.h>
  18. #include <string.h>
  19. Matrix PressureIndependMultiYield::theTangent(6,6);
  20. T2Vector PressureIndependMultiYield::subStrainRate;
  21. int PressureIndependMultiYield::matCount=0;
  22. int* PressureIndependMultiYield::loadStagex=0; //=0 if elastic; =1 if plastic
  23. int* PressureIndependMultiYield::ndmx=0; //num of dimensions (2 or 3)
  24. double* PressureIndependMultiYield::rhox=0;
  25. double* PressureIndependMultiYield::frictionAnglex=0;
  26. double* PressureIndependMultiYield::peakShearStrainx=0;
  27. double* PressureIndependMultiYield::refPressurex=0;
  28. double* PressureIndependMultiYield::cohesionx=0;
  29. double* PressureIndependMultiYield::pressDependCoeffx=0;
  30. int* PressureIndependMultiYield::numOfSurfacesx=0;
  31. double* PressureIndependMultiYield::residualPressx=0;
  32. PressureIndependMultiYield::PressureIndependMultiYield (int tag, int nd,
  33. double r, double refShearModul,
  34. double refBulkModul,
  35. double cohesi, double peakShearStra,
  36. double frictionAng, double refPress, double pressDependCoe,
  37. int numberOfYieldSurf, double * gredu)
  38. : NDMaterial(tag,ND_TAG_PressureIndependMultiYield), currentStress(),
  39. trialStress(), currentStrain(), strainRate()
  40. {
  41. if (nd !=2 && nd !=3) {
  42. opserr << "FATAL:PressureIndependMultiYield:: dimension error" << endln;
  43. opserr << "Dimension has to be 2 or 3, you give nd= " << nd << endln;
  44. exit(-1);
  45. }
  46. if (refShearModul <= 0) {
  47. opserr << "FATAL:PressureIndependMultiYield::PressureIndependMultiYield: refShearModulus <= 0" << endln;
  48. exit(-1);
  49. }
  50. if (refBulkModul <= 0) {
  51. opserr << "FATAL:PressureIndependMultiYield::PressureIndependMultiYield: refBulkModulus <= 0" << endln;
  52. exit(-1);
  53. }
  54. if (frictionAng < 0.) {
  55. opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: frictionAngle < 0" << endln;
  56. opserr << "Will reset frictionAngle to zero." << endln;
  57. frictionAng = 0.;
  58. }
  59. if (frictionAng == 0. && cohesi <= 0. ) {
  60. opserr << "FATAL:PressureIndependMultiYield::PressureIndependMultiYield: frictionAngle && cohesion <= 0." << endln;
  61. exit(-1);
  62. }
  63. if (cohesi <= 0) {
  64. opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: cohesion <= 0" << endln;
  65. opserr << "Will reset cohesion to zero." << endln;
  66. cohesi = 0.;
  67. }
  68. if (peakShearStra <= 0) {
  69. opserr << "FATAL:PressureIndependMultiYield::PressureIndependMultiYield: peakShearStra <= 0" << endln;
  70. exit(-1);
  71. }
  72. if (refPress <= 0) {
  73. opserr << "FATAL:PressureIndependMultiYield::PressureIndependMultiYield: refPress <= 0" << endln;
  74. exit(-1);
  75. }
  76. if (pressDependCoe < 0) {
  77. opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: pressDependCoe < 0" << endln;
  78. opserr << "Will reset pressDependCoe to zero." << endln;
  79. pressDependCoe = 0.;
  80. }
  81. if (pressDependCoe > 0 && frictionAng == 0) {
  82. opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: pressDependCoe > 0 while frictionAngle = 0" << endln;
  83. opserr << "Will reset pressDependCoe to zero." << endln;
  84. pressDependCoe = 0.;
  85. }
  86. if (numberOfYieldSurf <= 0) {
  87. opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: numberOfSurfaces <= 0" << endln;
  88. opserr << "Will use 10 yield surfaces." << endln;
  89. numberOfYieldSurf = 10;
  90. }
  91. if (numberOfYieldSurf > 100) {
  92. opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: numberOfSurfaces > 100" << endln;
  93. opserr << "Will use 100 yield surfaces." << endln;
  94. numberOfYieldSurf = 100;
  95. }
  96. if (r < 0) {
  97. opserr << "WARNING:PressureIndependMultiYield::PressureIndependMultiYield: mass density < 0" << endln;
  98. opserr << "Will use rho = 0." << endln;
  99. r = 0.;
  100. }
  101. if (matCount%20 == 0) {
  102. int * temp1 = loadStagex;
  103. int * temp2 = ndmx;
  104. double * temp3 = rhox;
  105. double * temp6 = frictionAnglex;
  106. double * temp7 = peakShearStrainx;
  107. double * temp8 = refPressurex;
  108. double * temp9 = cohesionx;
  109. double * temp10 = pressDependCoeffx;
  110. int * temp11 = numOfSurfacesx;
  111. double * temp12 = residualPressx;
  112. loadStagex = new int[matCount+20];
  113. ndmx = new int[matCount+20];
  114. rhox = new double[matCount+20];
  115. frictionAnglex = new double[matCount+20];
  116. peakShearStrainx = new double[matCount+20];
  117. refPressurex = new double[matCount+20];
  118. cohesionx = new double[matCount+20];
  119. pressDependCoeffx = new double[matCount+20];
  120. numOfSurfacesx = new int[matCount+20];
  121. residualPressx = new double[matCount+20];
  122. for (int i=0; i<matCount; i++) {
  123. loadStagex[i] = temp1[i];
  124. ndmx[i] = temp2[i];
  125. rhox[i] = temp3[i];
  126. frictionAnglex[i] = temp6[i];
  127. peakShearStrainx[i] = temp7[i];
  128. refPressurex[i] = temp8[i];
  129. cohesionx[i] = temp9[i];
  130. pressDependCoeffx[i] = temp10[i];
  131. numOfSurfacesx[i] = temp11[i];
  132. residualPressx[i] = temp12[i];
  133. }
  134. if (matCount > 0) {
  135. delete [] temp1; delete [] temp2; delete [] temp3;
  136. delete [] temp6; delete [] temp7; delete [] temp8;
  137. delete [] temp9; delete [] temp10; delete [] temp11;
  138. delete [] temp12;
  139. }
  140. }
  141. ndmx[matCount] = nd;
  142. loadStagex[matCount] = 0; //default
  143. refShearModulus = refShearModul;
  144. refBulkModulus = refBulkModul;
  145. frictionAnglex[matCount] = frictionAng;
  146. peakShearStrainx[matCount] = peakShearStra;
  147. refPressurex[matCount] = -refPress; //compression is negative
  148. cohesionx[matCount] = cohesi;
  149. pressDependCoeffx[matCount] = pressDependCoe;
  150. numOfSurfacesx[matCount] = numberOfYieldSurf;
  151. rhox[matCount] = r;
  152. e2p = 0;
  153. matN = matCount;
  154. matCount ++;
  155. theSurfaces = new MultiYieldSurface[numberOfYieldSurf+1]; //first surface not used
  156. committedSurfaces = new MultiYieldSurface[numberOfYieldSurf+1];
  157. activeSurfaceNum = committedActiveSurf = 0;
  158. setUpSurfaces(gredu); // residualPress is calculated inside.
  159. }
  160. PressureIndependMultiYield::PressureIndependMultiYield ()
  161. : NDMaterial(0,ND_TAG_PressureIndependMultiYield),
  162. currentStress(), trialStress(), currentStrain(),
  163. strainRate(), theSurfaces(0), committedSurfaces(0)
  164. {
  165. //does nothing
  166. }
  167. PressureIndependMultiYield::PressureIndependMultiYield (const PressureIndependMultiYield & a)
  168. : NDMaterial(a.getTag(),ND_TAG_PressureIndependMultiYield),
  169. currentStress(a.currentStress), trialStress(a.trialStress),
  170. currentStrain(a.currentStrain), strainRate(a.strainRate)
  171. {
  172. matN = a.matN;
  173. e2p = a.e2p;
  174. refShearModulus = a.refShearModulus;
  175. refBulkModulus = a.refBulkModulus;
  176. int numOfSurfaces = numOfSurfacesx[matN];
  177. committedActiveSurf = a.committedActiveSurf;
  178. activeSurfaceNum = a.activeSurfaceNum;
  179. theSurfaces = new MultiYieldSurface[numOfSurfaces+1]; //first surface not used
  180. committedSurfaces = new MultiYieldSurface[numOfSurfaces+1];
  181. for(int i=1; i<=numOfSurfaces; i++) {
  182. committedSurfaces[i] = a.committedSurfaces[i];
  183. theSurfaces[i] = a.theSurfaces[i];
  184. }
  185. }
  186. PressureIndependMultiYield::~PressureIndependMultiYield ()
  187. {
  188. if (theSurfaces != 0) delete [] theSurfaces;
  189. if (committedSurfaces != 0) delete [] committedSurfaces;
  190. }
  191. void PressureIndependMultiYield::elast2Plast(void)
  192. {
  193. int loadStage = loadStagex[matN];
  194. double frictionAngle = frictionAnglex[matN];
  195. int numOfSurfaces = numOfSurfacesx[matN];
  196. if (loadStage != 1 || e2p == 1) return;
  197. e2p = 1;
  198. if (currentStress.volume() > 0. && frictionAngle > 0.) {
  199. //opserr << "WARNING:PressureIndependMultiYield::elast2Plast(): material in tension." << endln;
  200. currentStress.setData(currentStress.deviator(),0);
  201. }
  202. paramScaling(); // scale surface parameters corresponding to initial confinement
  203. // Active surface is 0, return
  204. if (currentStress.deviatorLength() == 0.) return;
  205. // Find active surface
  206. while (yieldFunc(currentStress, committedSurfaces, ++committedActiveSurf) > 0) {
  207. if (committedActiveSurf == numOfSurfaces) {
  208. //opserr <<"WARNING:PressureIndependMultiYield::elast2Plast(): stress out of failure surface"<<endln;
  209. deviatorScaling(currentStress, committedSurfaces, numOfSurfaces);
  210. initSurfaceUpdate();
  211. return;
  212. }
  213. }
  214. committedActiveSurf--;
  215. initSurfaceUpdate();
  216. }
  217. int PressureIndependMultiYield::setTrialStrain (const Vector &strain)
  218. {
  219. int ndm = ndmx[matN];
  220. if (ndmx[matN] == 0) ndm = 2;
  221. static Vector temp(6);
  222. if (ndm==3 && strain.Size()==6)
  223. temp = strain;
  224. else if (ndm==2 && strain.Size()==3) {
  225. temp[0] = strain[0];
  226. temp[1] = strain[1];
  227. temp[2] = 0.0;
  228. temp[3] = strain[2];
  229. temp[4] = 0.0;
  230. temp[5] = 0.0;
  231. }
  232. else {
  233. opserr << "Fatal:D2PressDepMYS:: Material dimension is: " << ndm << endln;
  234. opserr << "But strain vector size is: " << strain.Size() << endln;
  235. exit(-1);
  236. }
  237. //strainRate.setData(temp-currentStrain.t2Vector(1),1);
  238. temp -= currentStrain.t2Vector(1);
  239. strainRate.setData(temp, 1);
  240. return 0;
  241. }
  242. int PressureIndependMultiYield::setTrialStrain (const Vector &strain, const Vector &rate)
  243. {
  244. return setTrialStrain (strain);
  245. }
  246. int PressureIndependMultiYield::setTrialStrainIncr (const Vector &strain)
  247. {
  248. int ndm = ndmx[matN];
  249. if (ndmx[matN] == 0) ndm = 2;
  250. static Vector temp(6);
  251. if (ndm==3 && strain.Size()==6)
  252. temp = strain;
  253. else if (ndm==2 && strain.Size()==3) {
  254. temp[0] = strain[0];
  255. temp[1] = strain[1];
  256. temp[3] = strain[2];
  257. }
  258. else {
  259. opserr << "Fatal:D2PressDepMYS:: Material dimension is: " << ndm << endln;
  260. opserr << "But strain vector size is: " << strain.Size() << endln;
  261. exit(-1);
  262. }
  263. strainRate.setData(temp,1);
  264. return 0;
  265. }
  266. int PressureIndependMultiYield::setTrialStrainIncr (const Vector &strain, const Vector &rate)
  267. {
  268. return setTrialStrainIncr(strain);
  269. }
  270. const Matrix & PressureIndependMultiYield::getTangent (void)
  271. {
  272. int loadStage = loadStagex[matN];
  273. int ndm = ndmx[matN];
  274. if (ndmx[matN] == 0) ndm = 3;
  275. if (loadStage == 1 && e2p == 0) elast2Plast();
  276. if (loadStage!=1) { //linear elastic
  277. for (int i=0;i<6;i++)
  278. for (int j=0;j<6;j++) {
  279. theTangent(i,j) = 0.;
  280. if (i==j) theTangent(i,j) += refShearModulus;
  281. if (i<3 && j<3 && i==j) theTangent(i,j) += refShearModulus;
  282. if (i<3 && j<3) theTangent(i,j) += (refBulkModulus - 2.*refShearModulus/3.);
  283. }
  284. }
  285. else {
  286. double coeff;
  287. static Vector devia(6);
  288. /*if (committedActiveSurf > 0) {
  289. //devia = currentStress.deviator()-committedSurfaces[committedActiveSurf].center();
  290. devia = currentStress.deviator();
  291. devia -= committedSurfaces[committedActiveSurf].center();
  292. double size = committedSurfaces[committedActiveSurf].size();
  293. double plastModul = committedSurfaces[committedActiveSurf].modulus();
  294. coeff = 6.*refShearModulus*refShearModulus/(2.*refShearModulus+plastModul)/size/size;
  295. }*/
  296. if (activeSurfaceNum > 0) {
  297. //devia = currentStress.deviator()-committedSurfaces[committedActiveSurf].center();
  298. devia = trialStress.deviator();
  299. devia -= theSurfaces[activeSurfaceNum].center();
  300. double size = theSurfaces[activeSurfaceNum].size();
  301. double plastModul = theSurfaces[activeSurfaceNum].modulus();
  302. coeff = 6.*refShearModulus*refShearModulus/(2.*refShearModulus+plastModul)/size/size;
  303. }
  304. else coeff = 0.;
  305. for (int i=0;i<6;i++)
  306. for (int j=0;j<6;j++) {
  307. theTangent(i,j) = - coeff*devia[i]*devia[j];
  308. if (i==j) theTangent(i,j) += refShearModulus;
  309. if (i<3 && j<3 && i==j) theTangent(i,j) += refShearModulus;
  310. if (i<3 && j<3) theTangent(i,j) += (refBulkModulus - 2.*refShearModulus/3.);
  311. }
  312. }
  313. if (ndm==3)
  314. return theTangent;
  315. else {
  316. static Matrix workM(3,3);
  317. workM(0,0) = theTangent(0,0);
  318. workM(0,1) = theTangent(0,1);
  319. workM(0,2) = theTangent(0,3);
  320. workM(1,0) = theTangent(1,0);
  321. workM(1,1) = theTangent(1,1);
  322. workM(1,2) = theTangent(1,3);
  323. workM(2,0) = theTangent(3,0);
  324. workM(2,1) = theTangent(3,1);
  325. workM(2,2) = theTangent(3,3);
  326. return workM;
  327. }
  328. }
  329. const Matrix & PressureIndependMultiYield::getInitialTangent (void)
  330. {
  331. int ndm = ndmx[matN];
  332. if (ndmx[matN] == 0) ndm = 3;
  333. for (int i=0;i<6;i++)
  334. for (int j=0;j<6;j++) {
  335. theTangent(i,j) = 0.;
  336. if (i==j) theTangent(i,j) += refShearModulus;
  337. if (i<3 && j<3 && i==j) theTangent(i,j) += refShearModulus;
  338. if (i<3 && j<3) theTangent(i,j) += (refBulkModulus - 2.*refShearModulus/3.);
  339. }
  340. if (ndm==3)
  341. return theTangent;
  342. else {
  343. static Matrix workM(3,3);
  344. workM(0,0) = theTangent(0,0);
  345. workM(0,1) = theTangent(0,1);
  346. workM(0,2) = theTangent(0,3);
  347. workM(1,0) = theTangent(1,0);
  348. workM(1,1) = theTangent(1,1);
  349. workM(1,2) = theTangent(1,3);
  350. workM(2,0) = theTangent(3,0);
  351. workM(2,1) = theTangent(3,1);
  352. workM(2,2) = theTangent(3,3);
  353. return workM;
  354. }
  355. }
  356. const Vector & PressureIndependMultiYield::getStress (void)
  357. {
  358. int loadStage = loadStagex[matN];
  359. int numOfSurfaces = numOfSurfacesx[matN];
  360. int ndm = ndmx[matN];
  361. if (ndmx[matN] == 0) ndm = 3;
  362. int i;
  363. if (loadStage == 1 && e2p == 0) elast2Plast();
  364. if (loadStage!=1) { //linear elastic
  365. //trialStrain.setData(currentStrain.t2Vector() + strainRate.t2Vector());
  366. getTangent();
  367. static Vector a(6);
  368. a = currentStress.t2Vector();
  369. a.addMatrixVector(1.0, theTangent, strainRate.t2Vector(1), 1.0);
  370. trialStress.setData(a);
  371. }
  372. else {
  373. for (i=1; i<=numOfSurfaces; i++) theSurfaces[i] = committedSurfaces[i];
  374. activeSurfaceNum = committedActiveSurf;
  375. subStrainRate = strainRate;
  376. setTrialStress(currentStress);
  377. if (isLoadReversal()) {
  378. updateInnerSurface();
  379. activeSurfaceNum = 0;
  380. }
  381. int numSubIncre = setSubStrainRate();
  382. for (i=0; i<numSubIncre; i++) {
  383. if (i==0)
  384. setTrialStress(currentStress);
  385. else
  386. setTrialStress(trialStress);
  387. if (activeSurfaceNum==0 && !isCrossingNextSurface()) continue;
  388. if (activeSurfaceNum==0) activeSurfaceNum++;
  389. stressCorrection(0);
  390. updateActiveSurface();
  391. }
  392. //volume stress change
  393. double volum = refBulkModulus*(strainRate.volume()*3.);
  394. volum += currentStress.volume();
  395. //if (volum > 0) volum = 0.;
  396. trialStress.setData(trialStress.deviator(),volum);
  397. }
  398. if (ndm==3)
  399. return trialStress.t2Vector();
  400. else {
  401. static Vector workV(3);
  402. workV[0] = trialStress.t2Vector()[0];
  403. workV[1] = trialStress.t2Vector()[1];
  404. workV[2] = trialStress.t2Vector()[3];
  405. return workV;
  406. }
  407. }
  408. const Vector & PressureIndependMultiYield::getStrain (void)
  409. {
  410. return getCommittedStrain();
  411. }
  412. int PressureIndependMultiYield::commitState (void)
  413. {
  414. int loadStage = loadStagex[matN];
  415. int numOfSurfaces = numOfSurfacesx[matN];
  416. currentStress = trialStress;
  417. //currentStrain = T2Vector(currentStrain.t2Vector() + strainRate.t2Vector());
  418. static Vector temp(6);
  419. temp = currentStrain.t2Vector();
  420. temp += strainRate.t2Vector();
  421. currentStrain.setData(temp);
  422. temp.Zero();
  423. strainRate.setData(temp);
  424. if (loadStage==1) {
  425. committedActiveSurf = activeSurfaceNum;
  426. for (int i=1; i<=numOfSurfaces; i++) committedSurfaces[i] = theSurfaces[i];
  427. }
  428. return 0;
  429. }
  430. int PressureIndependMultiYield::revertToLastCommit (void)
  431. {
  432. return 0;
  433. }
  434. NDMaterial * PressureIndependMultiYield::getCopy (void)
  435. {
  436. PressureIndependMultiYield * copy = new PressureIndependMultiYield(*this);
  437. return copy;
  438. }
  439. NDMaterial * PressureIndependMultiYield::getCopy (const char *code)
  440. {
  441. if (strcmp(code,"PressureIndependMultiYield") == 0 || strcmp(code,"PlaneStrain") == 0
  442. || strcmp(code,"ThreeDimensional") == 0) {
  443. PressureIndependMultiYield * copy = new PressureIndependMultiYield(*this);
  444. return copy;
  445. }
  446. return 0;
  447. }
  448. const char * PressureIndependMultiYield::getType (void) const
  449. {
  450. int ndm = ndmx[matN];
  451. if (ndmx[matN] == 0) ndm = 2;
  452. return (ndm == 2) ? "PlaneStrain" : "ThreeDimensional";
  453. }
  454. int PressureIndependMultiYield::getOrder (void) const
  455. {
  456. int ndm = ndmx[matN];
  457. if (ndmx[matN] == 0) ndm = 2;
  458. return (ndm == 2) ? 3 : 6;
  459. }
  460. int PressureIndependMultiYield::setParameter(const char **argv, int argc, Parameter &param)
  461. {
  462. if (argc < 2)
  463. return -1;
  464. int theMaterialTag;
  465. theMaterialTag = atoi(argv[1]);
  466. // check for material tag
  467. if (theMaterialTag == this->getTag()) {
  468. if (strcmp(argv[0],"updateMaterialStage") == 0) {
  469. return param.addObject(1, this);
  470. }
  471. else if (strcmp(argv[0],"shearModulus") == 0)
  472. return param.addObject(10, this);
  473. else if (strcmp(argv[0],"bulkModulus") == 0)
  474. return param.addObject(11, this);
  475. }
  476. return -1;
  477. }
  478. int PressureIndependMultiYield::updateParameter(int responseID, Information &info)
  479. {
  480. if (responseID == 1)
  481. loadStagex[matN] = info.theInt;
  482. else if (responseID==10)
  483. refShearModulus = info.theDouble;
  484. else if (responseID==11)
  485. refBulkModulus = info.theDouble;
  486. // used by BBarFourNodeQuadUP element
  487. else if (responseID==20 && ndmx[matN] == 2)
  488. ndmx[matN] = 0;
  489. return 0;
  490. }
  491. int PressureIndependMultiYield::sendSelf(int commitTag, Channel &theChannel)
  492. {
  493. int loadStage = loadStagex[matN];
  494. int ndm = ndmx[matN];
  495. int numOfSurfaces = numOfSurfacesx[matN];
  496. double rho = rhox[matN];
  497. double frictionAngle = frictionAnglex[matN];
  498. double peakShearStrain = peakShearStrainx[matN];
  499. double refPressure = refPressurex[matN];
  500. double cohesion = cohesionx[matN];
  501. double pressDependCoeff = pressDependCoeffx[matN];
  502. double residualPress = residualPressx[matN];
  503. int i, res = 0;
  504. static ID idData(5);
  505. idData(0) = this->getTag();
  506. idData(1) = numOfSurfaces;
  507. idData(2) = loadStage;
  508. idData(3) = ndm;
  509. idData(4) = matN;
  510. res += theChannel.sendID(this->getDbTag(), commitTag, idData);
  511. if (res < 0) {
  512. opserr << "PressureIndependMultiYield::sendSelf -- could not send ID\n";
  513. return res;
  514. }
  515. Vector data(24+numOfSurfaces*8);
  516. static Vector temp(6);
  517. data(0) = rho;
  518. data(1) = refShearModulus;
  519. data(2) = refBulkModulus;
  520. data(3) = frictionAngle;
  521. data(4) = peakShearStrain;
  522. data(5) = refPressure;
  523. data(6) = cohesion;
  524. data(7) = pressDependCoeff;
  525. data(8) = residualPress;
  526. data(9) = e2p;
  527. data(10) = committedActiveSurf;
  528. data(11) = activeSurfaceNum;
  529. temp = currentStress.t2Vector();
  530. for(i = 0; i < 6; i++) data(i+12) = temp[i];
  531. temp = currentStrain.t2Vector();
  532. for(i = 0; i < 6; i++) data(i+18) = temp[i];
  533. for(i = 0; i < numOfSurfaces; i++) {
  534. int k = 24 + i*8;
  535. data(k) = committedSurfaces[i+1].size();
  536. data(k+1) = committedSurfaces[i+1].modulus();
  537. temp = committedSurfaces[i+1].center();
  538. data(k+2) = temp(0);
  539. data(k+3) = temp(1);
  540. data(k+4) = temp(2);
  541. data(k+5) = temp(3);
  542. data(k+6) = temp(4);
  543. data(k+7) = temp(5);
  544. }
  545. res += theChannel.sendVector(this->getDbTag(), commitTag, data);
  546. if (res < 0) {
  547. opserr << "PressureIndependMultiYield::sendSelf -- could not send Vector\n";
  548. return res;
  549. }
  550. return res;
  551. }
  552. int PressureIndependMultiYield::recvSelf(int commitTag, Channel &theChannel,
  553. FEM_ObjectBroker &theBroker)
  554. {
  555. int i, res = 0;
  556. static ID idData(5);
  557. res += theChannel.recvID(this->getDbTag(), commitTag, idData);
  558. if (res < 0) {
  559. opserr << "PressureIndependMultiYield::recvSelf -- could not recv ID\n";
  560. return res;
  561. }
  562. this->setTag((int)idData(0));
  563. int numOfSurfaces = idData(1);
  564. int loadStage = idData(2);
  565. int ndm = idData(3);
  566. matN = idData(4);
  567. Vector data(24+idData(1)*8);
  568. static Vector temp(6);
  569. res += theChannel.recvVector(this->getDbTag(), commitTag, data);
  570. if (res < 0) {
  571. opserr << "PressureIndependMultiYield::recvSelf -- could not recv Vector\n";
  572. return res;
  573. }
  574. double rho = data(0);
  575. refShearModulus = data(1);
  576. refBulkModulus = data(2);
  577. double frictionAngle = data(3);
  578. double peakShearStrain = data(4);
  579. double refPressure = data(5);
  580. double cohesion = data(6);
  581. double pressDependCoeff = data(7);
  582. double residualPress = data(8);
  583. e2p = data(9);
  584. committedActiveSurf = data(10);
  585. activeSurfaceNum = data(11);
  586. for(i = 0; i < 6; i++) temp[i] = data(i+12);
  587. currentStress.setData(temp);
  588. for(i = 0; i < 6; i++) temp[i] = data(i+18);
  589. currentStrain.setData(temp);
  590. if (committedSurfaces != 0) {
  591. delete [] committedSurfaces;
  592. delete [] theSurfaces;
  593. }
  594. theSurfaces = new MultiYieldSurface[numOfSurfaces+1]; //first surface not used
  595. committedSurfaces = new MultiYieldSurface[numOfSurfaces+1];
  596. for(i = 0; i < numOfSurfaces; i++) {
  597. int k = 24 + i*8;
  598. temp(0) = data(k+2);
  599. temp(1) = data(k+3);
  600. temp(2) = data(k+4);
  601. temp(3) = data(k+5);
  602. temp(4) = data(k+6);
  603. temp(5) = data(k+7);
  604. committedSurfaces[i+1].setData(temp, data(k), data(k+1));
  605. }
  606. int *temp1, *temp2, *temp11;
  607. double *temp3, *temp6, *temp7, *temp8, *temp9, *temp10, *temp12;
  608. if (matN >= matCount*20) { // allocate memory if not enough
  609. temp1 = loadStagex;
  610. temp2 = ndmx;
  611. temp3 = rhox;
  612. temp6 = frictionAnglex;
  613. temp7 = peakShearStrainx;
  614. temp8 = refPressurex;
  615. temp9 = cohesionx;
  616. temp10 = pressDependCoeffx;
  617. temp11 = numOfSurfacesx;
  618. temp12 = residualPressx;
  619. loadStagex = new int[(matCount+1)*20];
  620. ndmx = new int[(matCount+1)*20];
  621. rhox = new double[(matCount+1)*20];
  622. frictionAnglex = new double[(matCount+1)*20];
  623. peakShearStrainx = new double[(matCount+1)*20];
  624. refPressurex = new double[(matCount+1)*20];
  625. cohesionx = new double[(matCount+1)*20];
  626. pressDependCoeffx = new double[(matCount+1)*20];
  627. numOfSurfacesx = new int[(matCount+1)*20];
  628. residualPressx = new double[(matCount+1)*20];
  629. for (int i=0; i<matCount*20; i++) {
  630. loadStagex[i] = temp1[i];
  631. ndmx[i] = temp2[i];
  632. rhox[i] = temp3[i];
  633. frictionAnglex[i] = temp6[i];
  634. peakShearStrainx[i] = temp7[i];
  635. refPressurex[i] = temp8[i];
  636. cohesionx[i] = temp9[i];
  637. pressDependCoeffx[i] = temp10[i];
  638. numOfSurfacesx[i] = temp11[i];
  639. residualPressx[i] = temp12[i];
  640. }
  641. if( matCount > 0 ) {
  642. delete [] temp1; delete [] temp2; delete [] temp3;
  643. delete [] temp6; delete [] temp7; delete [] temp8;
  644. delete [] temp9; delete [] temp10; delete [] temp11;
  645. delete [] temp12;
  646. }
  647. matCount += 1;
  648. }
  649. loadStagex[matN] = loadStage;
  650. ndmx[matN] = ndm;
  651. numOfSurfacesx[matN] = numOfSurfaces;
  652. rhox[matN] = rho;
  653. frictionAnglex[matN] = frictionAngle;
  654. peakShearStrainx[matN] = peakShearStrain;
  655. refPressurex[matN] = refPressure;
  656. cohesionx[matN] = cohesion;
  657. pressDependCoeffx[matN] = pressDependCoeff;
  658. residualPressx[matN] = residualPress;
  659. return res;
  660. }
  661. Response*
  662. PressureIndependMultiYield::setResponse (const char **argv, int argc, OPS_Stream &output)
  663. {
  664. if (strcmp(argv[0],"stress") == 0 || strcmp(argv[0],"stresses") == 0)
  665. return new MaterialResponse(this, 1, this->getCommittedStress());
  666. else if (strcmp(argv[0],"strain") == 0 || strcmp(argv[0],"strains") == 0)
  667. return new MaterialResponse(this, 2, this->getCommittedStrain());
  668. else if (strcmp(argv[0],"tangent") == 0)
  669. return new MaterialResponse(this, 3, this->getTangent());
  670. else if (strcmp(argv[0],"backbone") == 0) {
  671. int numOfSurfaces = numOfSurfacesx[matN];
  672. static Matrix curv(numOfSurfaces+1,(argc-1)*2);
  673. for (int i=1; i<argc; i++)
  674. curv(0,(i-1)*2) = atoi(argv[i]);
  675. return new MaterialResponse(this, 4, curv);
  676. }
  677. else
  678. return 0;
  679. }
  680. int PressureIndependMultiYield::getResponse (int responseID, Information &matInfo)
  681. {
  682. switch (responseID) {
  683. case -1:
  684. return -1;
  685. case 1:
  686. if (matInfo.theVector != 0)
  687. *(matInfo.theVector) = getCommittedStress();
  688. return 0;
  689. case 2:
  690. if (matInfo.theVector != 0)
  691. *(matInfo.theVector) = getCommittedStrain();
  692. return 0;
  693. case 3:
  694. if (matInfo.theMatrix != 0)
  695. *(matInfo.theMatrix) = getTangent();
  696. return 0;
  697. case 4:
  698. if (matInfo.theMatrix != 0)
  699. getBackbone(*(matInfo.theMatrix));
  700. return 0;
  701. default:
  702. return -1;
  703. }
  704. }
  705. void PressureIndependMultiYield::getBackbone (Matrix & bb)
  706. {
  707. double residualPress = residualPressx[matN];
  708. double refPressure = refPressurex[matN];
  709. double pressDependCoeff =pressDependCoeffx[matN];
  710. int numOfSurfaces = numOfSurfacesx[matN];
  711. double vol, conHeig, scale, factor, shearModulus, stress1,
  712. stress2, strain1, strain2, plastModulus, elast_plast, gre;
  713. for (int k=0; k<bb.noCols()/2; k++) {
  714. vol = bb(0,k*2);
  715. if (vol<=0.) {
  716. opserr <<k<< "\nNDMaterial " <<this->getTag()
  717. <<": invalid confinement for backbone recorder, " << vol << endln;
  718. continue;
  719. }
  720. conHeig = vol + residualPress;
  721. scale = -conHeig / (refPressure-residualPress);
  722. factor = pow(scale, pressDependCoeff);
  723. shearModulus = factor*refShearModulus;
  724. for (int i=1; i<=numOfSurfaces; i++) {
  725. if (i==1) {
  726. stress2 = committedSurfaces[i].size()*factor/sqrt(3.0);
  727. strain2 = stress2/shearModulus;
  728. bb(1,k*2) = strain2; bb(1,k*2+1) = shearModulus;
  729. } else {
  730. stress1 = stress2; strain1 = strain2;
  731. plastModulus = factor*committedSurfaces[i-1].modulus();
  732. elast_plast = 2*shearModulus*plastModulus/(2*shearModulus+plastModulus);
  733. stress2 = factor*committedSurfaces[i].size()/sqrt(3.0);
  734. strain2 = 2*(stress2-stress1)/elast_plast + strain1;
  735. gre = stress2/strain2;
  736. bb(i,k*2) = strain2; bb(i,k*2+1) = gre;
  737. }
  738. }
  739. }
  740. }
  741. void PressureIndependMultiYield::Print(OPS_Stream &s, int flag )
  742. {
  743. s << "PressureIndependMultiYield - loadStage: " << loadStagex[matN] << endln;
  744. }
  745. const Vector & PressureIndependMultiYield::getCommittedStress (void)
  746. {
  747. int ndm = ndmx[matN];
  748. if (ndmx[matN] == 0) ndm = 2;
  749. int numOfSurfaces = numOfSurfacesx[matN];
  750. double scale = sqrt(3./2.)*currentStress.deviatorLength()/committedSurfaces[numOfSurfaces].size();
  751. if (loadStagex[matN] != 1) scale = 0.;
  752. if (ndm==3) {
  753. static Vector temp7(7), temp6(6);
  754. temp6 = currentStress.t2Vector();
  755. temp7[0] = temp6[0];
  756. temp7[1] = temp6[1];
  757. temp7[2] = temp6[2];
  758. temp7[3] = temp6[3];
  759. temp7[4] = temp6[4];
  760. temp7[5] = temp6[5];
  761. temp7[6] = scale;
  762. return temp7;
  763. }
  764. else {
  765. static Vector temp5(5), temp6(6);
  766. temp6 = currentStress.t2Vector();
  767. temp5[0] = temp6[0];
  768. temp5[1] = temp6[1];
  769. temp5[2] = temp6[2];
  770. temp5[3] = temp6[3];
  771. temp5[4] = scale;
  772. return temp5;
  773. }
  774. }
  775. const Vector & PressureIndependMultiYield::getCommittedStrain (void)
  776. {
  777. int ndm = ndmx[matN];
  778. if (ndmx[matN] == 0) ndm = 2;
  779. if (ndm==3)
  780. return currentStrain.t2Vector(1);
  781. else {
  782. static Vector workV(3), temp6(6);
  783. temp6 = currentStrain.t2Vector(1);
  784. workV[0] = temp6[0];
  785. workV[1] = temp6[1];
  786. workV[2] = temp6[3];
  787. return workV;
  788. }
  789. }
  790. // NOTE: surfaces[0] is not used
  791. void PressureIndependMultiYield::setUpSurfaces (double * gredu)
  792. {
  793. double residualPress = residualPressx[matN];
  794. double refPressure = refPressurex[matN];
  795. double pressDependCoeff =pressDependCoeffx[matN];
  796. int numOfSurfaces = numOfSurfacesx[matN];
  797. double frictionAngle = frictionAnglex[matN];
  798. double cohesion = cohesionx[matN];
  799. double peakShearStrain = peakShearStrainx[matN];
  800. double stress1, stress2, strain1, strain2, size, elasto_plast_modul, plast_modul;
  801. double pi = 3.14159265358979;
  802. double refStrain, peakShear, coneHeight;
  803. if (gredu == 0) { //automatic generation of surfaces
  804. if (frictionAngle > 0) {
  805. double sinPhi = sin(frictionAngle * pi/180.);
  806. double Mnys = 6.*sinPhi/(3.-sinPhi);
  807. residualPress = 3.* cohesion / (sqrt(2.) * Mnys);
  808. coneHeight = - (refPressure - residualPress);
  809. peakShear = sqrt(2.) * coneHeight * Mnys / 3.;
  810. refStrain = (peakShearStrain * peakShear)
  811. / (refShearModulus * peakShearStrain - peakShear);
  812. }
  813. else if (frictionAngle == 0.) { // cohesion = peakShearStrength
  814. peakShear = 2*sqrt(2.)*cohesion/3;
  815. refStrain = (peakShearStrain * peakShear)
  816. / (refShearModulus * peakShearStrain - peakShear);
  817. residualPress = 0.;
  818. }
  819. double stressInc = peakShear / numOfSurfaces;
  820. for (int ii=1; ii<=numOfSurfaces; ii++){
  821. stress1 = ii * stressInc;
  822. stress2 = stress1 + stressInc;
  823. strain1 = stress1 * refStrain / (refShearModulus * refStrain - stress1);
  824. strain2 = stress2 * refStrain / (refShearModulus * refStrain - stress2);
  825. if (frictionAngle > 0.) size = 3. * stress1 / sqrt(2.) / coneHeight;
  826. else if (frictionAngle == 0.) size = 3. * stress1 / sqrt(2.);
  827. elasto_plast_modul = 2.*(stress2 - stress1)/(strain2 - strain1);
  828. if ( (2.*refShearModulus - elasto_plast_modul) <= 0)
  829. plast_modul = UP_LIMIT;
  830. else
  831. plast_modul = (2.*refShearModulus * elasto_plast_modul)/
  832. (2.*refShearModulus - elasto_plast_modul);
  833. if (plast_modul < 0) plast_modul = 0;
  834. if (plast_modul > UP_LIMIT) plast_modul = UP_LIMIT;
  835. if (ii==numOfSurfaces) plast_modul = 0;
  836. static Vector temp(6);
  837. committedSurfaces[ii] = MultiYieldSurface(temp,size,plast_modul);
  838. } // ii
  839. }
  840. else { //user defined surfaces
  841. if (frictionAngle > 0) { // ignore user defined frictionAngle
  842. int ii = 2*(numOfSurfaces-1);
  843. double tmax = refShearModulus*gredu[ii]*gredu[ii+1];
  844. double Mnys = -(sqrt(3.) * tmax - 2. * cohesion) / refPressure;
  845. if (Mnys <= 0) { // also ignore user defined cohesion
  846. cohesion = sqrt(3.)/2 * tmax;
  847. frictionAngle = 0.;
  848. coneHeight = 1.;
  849. residualPress = 0.;
  850. } else {
  851. double sinPhi = 3*Mnys /(6+Mnys);
  852. if (sinPhi<0. || sinPhi>1.) {
  853. opserr <<"\nNDMaterial " <<this->getTag()<<": Invalid friction angle, please modify ref. pressure or G/Gmax curve."<<endln;
  854. exit(-1);
  855. }
  856. residualPress = 2. * cohesion / Mnys;
  857. if (residualPress < 0.01*refPressure) residualPress = 0.01*refPressure;
  858. coneHeight = - (refPressure - residualPress);
  859. frictionAngle = asin(sinPhi)*180/pi;
  860. }
  861. } else if (frictionAngle == 0.) { // ignore user defined cohesion
  862. int ii = 2*(numOfSurfaces-1);
  863. double tmax = refShearModulus*gredu[ii]*gredu[ii+1];
  864. cohesion = sqrt(3.)/2 * tmax;
  865. coneHeight = 1.;
  866. residualPress = 0.;
  867. }
  868. opserr << "\nNDMaterial " <<this->getTag()<<": Friction angle = "<<frictionAngle
  869. <<", Cohesion = "<<cohesion<<"\n"<<endln;
  870. if (frictionAngle == 0.) pressDependCoeff = 0.; // ignore user defined pressDependCoeff
  871. for (int i=1; i<numOfSurfaces; i++) {
  872. int ii = 2*(i-1);
  873. strain1 = gredu[ii];
  874. stress1 = refShearModulus*gredu[ii+1]*strain1;
  875. strain2 = gredu[ii+2];
  876. stress2 = refShearModulus*gredu[ii+3]*strain2;
  877. size = sqrt(3.) * stress1 / coneHeight;
  878. elasto_plast_modul = 2.*(stress2 - stress1)/(strain2 - strain1);
  879. if ( (2.*refShearModulus - elasto_plast_modul) <= 0)
  880. plast_modul = UP_LIMIT;
  881. else
  882. plast_modul = (2.*refShearModulus * elasto_plast_modul)/
  883. (2.*refShearModulus - elasto_plast_modul);
  884. if (plast_modul <= 0) {
  885. opserr << "\nNDMaterial " <<this->getTag()<<": Surface " << i
  886. << " has plastic modulus < 0.\n Please modify G/Gmax curve.\n"<<endln;
  887. exit(-1);
  888. }
  889. if (plast_modul > UP_LIMIT) plast_modul = UP_LIMIT;
  890. static Vector temp(6);
  891. committedSurfaces[i] = MultiYieldSurface(temp,size,plast_modul);
  892. if (i==(numOfSurfaces-1)) {
  893. plast_modul = 0;
  894. size = sqrt(3.) * stress2 / coneHeight;
  895. committedSurfaces[i+1] = MultiYieldSurface(temp,size,plast_modul);
  896. }
  897. }
  898. }
  899. residualPressx[matN] = residualPress;
  900. frictionAnglex[matN] = frictionAngle;
  901. cohesionx[matN] = cohesion;
  902. }
  903. double PressureIndependMultiYield::yieldFunc(const T2Vector & stress,
  904. const MultiYieldSurface * surfaces, int surfaceNum)
  905. {
  906. static Vector temp(6);
  907. //temp = stress.deviator() - surfaces[surfaceNum].center();
  908. temp = stress.deviator();
  909. temp -= surfaces[surfaceNum].center();
  910. double sz = surfaces[surfaceNum].size();
  911. return 3./2.*(temp && temp) - sz * sz;
  912. }
  913. void PressureIndependMultiYield::deviatorScaling(T2Vector & stress, const MultiYieldSurface * surfaces,
  914. int surfaceNum, int count)
  915. {
  916. count++;
  917. int numOfSurfaces = numOfSurfacesx[matN];
  918. double diff = yieldFunc(stress, surfaces, surfaceNum);
  919. if ( surfaceNum < numOfSurfaces && diff < 0. ) {
  920. double sz = surfaces[surfaceNum].size();
  921. double deviaSz = sqrt(sz*sz + diff);
  922. static Vector devia(6);
  923. devia = stress.deviator();
  924. static Vector temp(6);
  925. temp = devia - surfaces[surfaceNum].center();
  926. double coeff = (sz-deviaSz) / deviaSz;
  927. if (coeff < 1.e-13) coeff = 1.e-13;
  928. devia.addVector(1.0, temp, coeff);
  929. stress.setData(devia, stress.volume());
  930. deviatorScaling(stress, surfaces, surfaceNum, count); // recursive call
  931. }
  932. if (surfaceNum==numOfSurfaces && fabs(diff) > LOW_LIMIT) {
  933. double sz = surfaces[surfaceNum].size();
  934. static Vector newDevia(6);
  935. newDevia.addVector(0.0, stress.deviator(), sz/sqrt(diff+sz*sz));
  936. stress.setData(newDevia, stress.volume());
  937. }
  938. }
  939. void PressureIndependMultiYield::initSurfaceUpdate()
  940. {
  941. if (committedActiveSurf == 0) return;
  942. int numOfSurfaces = numOfSurfacesx[matN];
  943. static Vector devia(6);
  944. devia = currentStress.deviator();
  945. double Ms = sqrt(3./2.*(devia && devia));
  946. static Vector newCenter(6);
  947. if (committedActiveSurf < numOfSurfaces) { // failure surface can't move
  948. //newCenter = devia * (1. - committedSurfaces[activeSurfaceNum].size() / Ms);
  949. newCenter.addVector(0.0, devia, 1.0-committedSurfaces[committedActiveSurf].size()/Ms);
  950. committedSurfaces[committedActiveSurf].setCenter(newCenter);
  951. }
  952. for (int i=1; i<committedActiveSurf; i++) {
  953. newCenter = devia * (1. - committedSurfaces[i].size() / Ms);
  954. committedSurfaces[i].setCenter(newCenter);
  955. }
  956. }
  957. void PressureIndependMultiYield::paramScaling(void)
  958. {
  959. int numOfSurfaces = numOfSurfacesx[matN];
  960. double frictionAngle = frictionAnglex[matN];
  961. double residualPress = residualPressx[matN];
  962. double refPressure = refPressurex[matN];
  963. double pressDependCoeff =pressDependCoeffx[matN];
  964. if (frictionAngle == 0.) return;
  965. double conHeig = - (currentStress.volume() - residualPress);
  966. double scale = -conHeig / (refPressure-residualPress);
  967. scale = pow(scale, pressDependCoeff);
  968. refShearModulus *= scale;
  969. refBulkModulus *= scale;
  970. double plastModul, size;
  971. static Vector temp(6);
  972. for (int i=1; i<=numOfSurfaces; i++) {
  973. plastModul = committedSurfaces[i].modulus() * scale;
  974. size = committedSurfaces[i].size() * conHeig;
  975. committedSurfaces[i] = MultiYieldSurface(temp,size,plastModul);
  976. }
  977. }
  978. void PressureIndependMultiYield::setTrialStress(T2Vector & stress)
  979. {
  980. static Vector devia(6);
  981. //devia = stress.deviator() + subStrainRate.deviator()*2.*refShearModulus;
  982. devia = stress.deviator();
  983. devia.addVector(1.0, subStrainRate.deviator(), 2.*refShearModulus);
  984. trialStress.setData(devia, stress.volume());
  985. }
  986. int PressureIndependMultiYield::setSubStrainRate(void)
  987. {
  988. int numOfSurfaces = numOfSurfacesx[matN];
  989. //if (activeSurfaceNum==numOfSurfaces) return 1;
  990. //if (strainRate==T2Vector()) return 0;
  991. if (strainRate.isZero()) return 0;
  992. double elast_plast_modulus;
  993. if (activeSurfaceNum==0)
  994. elast_plast_modulus = 2*refShearModulus;
  995. else {
  996. double plast_modulus = theSurfaces[activeSurfaceNum].modulus();
  997. elast_plast_modulus = 2*refShearModulus*plast_modulus
  998. / (2*refShearModulus+plast_modulus);
  999. }
  1000. static Vector incre(6);
  1001. //incre = strainRate.deviator()*elast_plast_modulus;
  1002. incre.addVector(0.0, strainRate.deviator(),elast_plast_modulus);
  1003. static T2Vector increStress;
  1004. increStress.setData(incre, 0);
  1005. double singleCross = theSurfaces[numOfSurfaces].size() / numOfSurfaces;
  1006. double totalCross = 3.*increStress.octahedralShear() / sqrt(2.);
  1007. int numOfSub = totalCross/singleCross + 1;
  1008. if (numOfSub > numOfSurfaces) numOfSub = numOfSurfaces;
  1009. //incre = strainRate.t2Vector() / numOfSub;
  1010. incre = strainRate.t2Vector();
  1011. incre /= numOfSub;
  1012. subStrainRate.setData(incre);
  1013. return numOfSub;
  1014. }
  1015. void
  1016. PressureIndependMultiYield::getContactStress(T2Vector &contactStress)
  1017. {
  1018. static Vector center(6);
  1019. center = theSurfaces[activeSurfaceNum].center();
  1020. static Vector devia(6);
  1021. //devia = trialStress.deviator() - center;
  1022. devia = trialStress.deviator();
  1023. devia -= center;
  1024. double Ms = sqrt(3./2.*(devia && devia));
  1025. //devia = devia * theSurfaces[activeSurfaceNum].size() / Ms + center;
  1026. devia *= theSurfaces[activeSurfaceNum].size() / Ms;
  1027. devia += center;
  1028. contactStress.setData(devia,trialStress.volume());
  1029. }
  1030. int PressureIndependMultiYield::isLoadReversal(void)
  1031. {
  1032. if(activeSurfaceNum == 0) return 0;
  1033. static Vector surfaceNormal(6);
  1034. getSurfaceNormal(currentStress, surfaceNormal);
  1035. //(((trialStress.deviator() - currentStress.deviator()) && surfaceNormal) < 0)
  1036. // return 1;
  1037. static Vector a(6);
  1038. a = trialStress.deviator();
  1039. a-= currentStress.deviator();
  1040. if((a && surfaceNormal) < 0)
  1041. return 1;
  1042. return 0;
  1043. }
  1044. void
  1045. PressureIndependMultiYield::getSurfaceNormal(const T2Vector & stress, Vector &surfaceNormal)
  1046. {
  1047. //Q = stress.deviator() - theSurfaces[activeSurfaceNum].center();
  1048. // return Q / sqrt(Q && Q);
  1049. surfaceNormal = stress.deviator();
  1050. surfaceNormal -= theSurfaces[activeSurfaceNum].center();
  1051. surfaceNormal /= sqrt(surfaceNormal && surfaceNormal);
  1052. }
  1053. double PressureIndependMultiYield::getLoadingFunc(const T2Vector & contactStress,
  1054. const Vector & surfaceNormal, int crossedSurface)
  1055. {
  1056. double loadingFunc;
  1057. double temp1 = 2. * refShearModulus ;
  1058. double temp2 = theSurfaces[activeSurfaceNum].modulus();
  1059. //for crossing first surface
  1060. double temp = temp1 + temp2;
  1061. //loadingFunc = (surfaceNormal && (trialStress.deviator()-contactStress.deviator()))/temp;
  1062. static Vector tmp(6);
  1063. tmp =trialStress.deviator();
  1064. tmp -= contactStress.deviator();
  1065. loadingFunc = (surfaceNormal && tmp)/temp;
  1066. //for crossing more than one surface
  1067. if(crossedSurface) {
  1068. double temp3 = theSurfaces[activeSurfaceNum-1].modulus();
  1069. loadingFunc *= (temp3 - temp2)/temp3;
  1070. }
  1071. return loadingFunc;
  1072. }
  1073. void PressureIndependMultiYield::stressCorrection(int crossedSurface)
  1074. {
  1075. static T2Vector contactStress;
  1076. this->getContactStress(contactStress);
  1077. static Vector surfaceNormal(6);
  1078. this->getSurfaceNormal(contactStress, surfaceNormal);
  1079. double loadingFunc = getLoadingFunc(contactStress, surfaceNormal, crossedSurface);
  1080. static Vector devia(6);
  1081. //devia = trialStress.deviator() - surfaceNormal * 2 * refShearModulus * loadingFunc;
  1082. devia.addVector(0.0, surfaceNormal, -2*refShearModulus*loadingFunc);
  1083. devia += trialStress.deviator();
  1084. trialStress.setData(devia, trialStress.volume());
  1085. deviatorScaling(trialStress, theSurfaces, activeSurfaceNum);
  1086. if (isCrossingNextSurface()) {
  1087. activeSurfaceNum++;
  1088. stressCorrection(1); //recursive call
  1089. }
  1090. }
  1091. void PressureIndependMultiYield::updateActiveSurface(void)
  1092. {
  1093. int numOfSurfaces = numOfSurfacesx[matN];
  1094. if (activeSurfaceNum == numOfSurfaces) return;
  1095. double A, B, C, X;
  1096. static T2Vector direction;
  1097. static Vector t1(6);
  1098. static Vector t2(6);
  1099. static Vector temp(6);
  1100. static Vector center(6);
  1101. center = theSurfaces[activeSurfaceNum].center();
  1102. double size = theSurfaces[activeSurfaceNum].size();
  1103. static Vector outcenter(6);
  1104. outcenter= theSurfaces[activeSurfaceNum+1].center();
  1105. double outsize = theSurfaces[activeSurfaceNum+1].size();
  1106. //t1 = trialStress.deviator() - center;
  1107. //t2 = center - outcenter;
  1108. t1 = trialStress.deviator();
  1109. t1 -= center;
  1110. t2 = center;
  1111. t2 -= outcenter;
  1112. A = t1 && t1;
  1113. B = 2. * (t1 && t2);
  1114. C = (t2 && t2) - 2./3.* outsize * outsize;
  1115. X = secondOrderEqn(A,B,C,0);
  1116. if ( fabs(X-1.) < LOW_LIMIT ) X = 1.;
  1117. if (X < 1.){
  1118. opserr << "FATAL:PressureIndependMultiYield::updateActiveSurface(): error in Direction of surface motion."
  1119. << endln;
  1120. exit(-1);
  1121. }
  1122. //temp = (t1 * X + center) * (1. - size / outsize) - (center - outcenter * size / outsize);
  1123. temp = center;
  1124. temp.addVector(1.0, t1, X);
  1125. temp *= (1.0 - size/outsize);
  1126. t2 = center;
  1127. t2.addVector(1.0, outcenter, -size/outsize);
  1128. temp -= t2;
  1129. direction.setData(temp);
  1130. if (direction.deviatorLength() < LOW_LIMIT) return;
  1131. temp = direction.deviator();
  1132. A = temp && temp;
  1133. B = - 2 * (t1 && temp);
  1134. if (fabs(B) < LOW_LIMIT) B = 0.;
  1135. C = (t1 && t1) - 2./3.* size * size;
  1136. if ( fabs(C) < LOW_LIMIT || fabs(C)/(t1 && t1) < LOW_LIMIT ) return;
  1137. if (B > 0. || C < 0.) {
  1138. opserr << "FATAL:PressureIndependMultiYield::updateActiveSurface(): error in surface motion.\n"
  1139. << "A= " <<A <<" B= " <<B <<" C= "<<C <<" (t1&&t1)= "<<(t1&&t1) <<endln;
  1140. exit(-1);
  1141. }
  1142. X = secondOrderEqn(A,B,C,1);
  1143. //center += temp * X;
  1144. center.addVector(1.0, temp, X);
  1145. theSurfaces[activeSurfaceNum].setCenter(center);
  1146. }
  1147. void PressureIndependMultiYield::updateInnerSurface(void)
  1148. {
  1149. if (activeSurfaceNum <= 1) return;
  1150. static Vector devia(6);
  1151. devia = currentStress.deviator();
  1152. static Vector center(6);
  1153. center = theSurfaces[activeSurfaceNum].center();
  1154. double size = theSurfaces[activeSurfaceNum].size();
  1155. static Vector newcenter(6);
  1156. for (int i=1; i<activeSurfaceNum; i++) {
  1157. //newcenter = devia - (devia - center) * theSurfaces[i].size() / size;
  1158. newcenter = center;
  1159. newcenter -= devia;
  1160. newcenter *= theSurfaces[i].size()/size;
  1161. newcenter += devia;
  1162. theSurfaces[i].setCenter(newcenter);
  1163. }
  1164. }
  1165. int PressureIndependMultiYield:: isCrossingNextSurface(void)
  1166. {
  1167. int numOfSurfaces = numOfSurfacesx[matN];
  1168. if (activeSurfaceNum == numOfSurfaces) return 0;
  1169. if(yieldFunc(trialStress, theSurfaces, activeSurfaceNum+1) > 0) return 1;
  1170. return 0;
  1171. }