OOFEM 3.0
Loading...
Searching...
No Matches
druckerPragerPlasticitySM.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
36
37#include "floatarray.h"
38#include "floatmatrix.h"
40#include "gausspoint.h"
41#include "intarray.h"
44#include "datastream.h"
45#include "contextioerr.h"
46#include "mathfem.h"
47#include "classfactory.h"
48
49namespace oofem {
51
52DruckerPragerPlasticitySMStatus :: DruckerPragerPlasticitySMStatus(GaussPoint *gp) :
54{
55 stressVector.resize(6);
56 strainVector.resize(6);
59}
60
61void
62DruckerPragerPlasticitySMStatus :: initTempStatus()
63{
64 // Call the function of the parent class to initialize the variables defined there.
65 StructuralMaterialStatus :: initTempStatus();
66
71}
72
73void
74DruckerPragerPlasticitySMStatus :: updateYourself(TimeStep *tStep)
75{
76 // Call corresponding function of the parent class to update variables defined there.
77 StructuralMaterialStatus :: updateYourself(tStep);
78
79 // update variables defined in DruckerPragerPlasticitySMStatus
84}
85
86void
87DruckerPragerPlasticitySMStatus :: printOutputAt(FILE *file, TimeStep *tStep) const
88{
89 // Call corresponding function of the parent class to print variables defined there.
90 StructuralMaterialStatus :: printOutputAt(file, tStep);
91
92 fprintf(file, "\tstatus { ");
93
94 // print status flag
95 switch ( state_flag ) {
96 case DruckerPragerPlasticitySMStatus :: DP_Elastic:
97 fprintf(file, " Elastic, ");
98 break;
99 case DruckerPragerPlasticitySMStatus :: DP_Yielding:
100 fprintf(file, " Yielding, ");
101 break;
102 case DruckerPragerPlasticitySMStatus :: DP_Vertex:
103 fprintf(file, " Vertex_return, ");
104 break;
105 case DruckerPragerPlasticitySMStatus :: DP_Unloading:
106 fprintf(file, " Unloading, ");
107 break;
108 }
109
110 // print plastic strain vector
111 auto plasticStrainVector = givePlasticStrainVector();
112
113 fprintf(file, "plasticStrains ");
114 for ( auto &val : plasticStrainVector ) {
115 fprintf( file, " %.4e", val );
116 }
117
118 fprintf(file, "}\n");
119
120 fprintf(file, "\t\thardening_parameter ");
121 // print hardening parameter
122 fprintf(file, " %.4e\n", kappa);
123}
124
125void
126DruckerPragerPlasticitySMStatus :: saveContext(DataStream &stream, ContextMode mode)
127{
128 StructuralMaterialStatus :: saveContext(stream, mode);
129
131 if ( ( iores = plasticStrainDeviator.storeYourself(stream) ) != CIO_OK ) {
132 THROW_CIOERR(iores);
133 }
134
135 if ( !stream.write(volumetricPlasticStrain) ) {
137 }
138
139 if ( !stream.write(kappa) ) {
141 }
142
143 if ( !stream.write(temp_state_flag) ) {
145 }
146}
147
148
149void
150DruckerPragerPlasticitySMStatus :: restoreContext(DataStream &stream, ContextMode mode)
151{
152 StructuralMaterialStatus :: restoreContext(stream, mode);
153
155 if ( ( iores = plasticStrainDeviator.restoreYourself(stream) ) != CIO_OK ) {
156 THROW_CIOERR(iores);
157 }
158
159 if ( !stream.read(volumetricPlasticStrain) ) {
161 }
162
163 if ( !stream.read(kappa) ) {
165 }
166
167 if ( !stream.read(temp_state_flag) ) {
169 }
170}
171
172// *************************************************************
173// *** CLASS DRUCKER-PRAGER PLASTICITY STRUCTURAL MATERIAL ***
174// *************************************************************
175
176
177DruckerPragerPlasticitySM :: DruckerPragerPlasticitySM(int n, Domain *d) :
178 StructuralMaterial(n, d),
179 LEMaterial(n, d)
180{}
181
182
183void
184DruckerPragerPlasticitySM :: initializeFrom(InputRecord &ir)
185{
186 // call the corresponding service of structural material
187 StructuralMaterial :: initializeFrom(ir);
188 // call the corresponding service for the linear elastic material
189 LEMaterial.initializeFrom(ir);
190
191 // initialize elastic constants
192 //eM = LEMaterial.give(Ex,gp);
193 //nu = LEMaterial.give(NYxz,gp);
194 //gM = eM / ( 2. * ( 1. + nu ) );
195 //kM = eM / ( 3. * ( 1. - 2. * nu ) );
196
197 // instanciate the variables defined in DruckerPragerPlasticitySM
198 IR_GIVE_FIELD(ir, initialYieldStress, _IFT_DruckerPragerPlasticitySM_iys); // initial yield stress under pure shear
199 IR_GIVE_FIELD(ir, alpha, _IFT_DruckerPragerPlasticitySM_alpha); // friction coefficient
201 // this is valid for strain hardening/softening only (not for work hardening/softening)
202 kFactor = sqrt(1. / 3. + 2. * alphaPsi * alphaPsi);
203
205
206 switch ( hardeningType ) {
207 case 1: // linear hardening/softening
209 break;
210 case 2: // exponential hardening/softening
213 break;
214 default:
216 "must be 1 (linear hardening/softening) or 2 (exponential hardening/softening)");
217 }
218
219 yieldTol = 1.e-14;
221 newtonIter = 30;
223}
224
226DruckerPragerPlasticitySM :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp,
227 TimeStep *tStep) const
228{
229 auto status = static_cast< DruckerPragerPlasticitySMStatus * >( this->giveStatus(gp) );
230
231 // Initialize temp variables for this gauss point
232 const_cast<DruckerPragerPlasticitySM*>(this)->initTempStatus(gp);
233
234 // subtract stress independent part
235 // note: eigenStrains (temperature) is not contained in mechanical strain stored in gp
236 // therefore it is necessary to subtract always the total eigen strain value
237 auto thermalStrain = this->computeStressIndependentStrainVector_3d(gp, tStep, VM_Total);
238 auto strainVectorR = strain - thermalStrain;
239
240 // perform the local stress return and update the history variables
241 performLocalStressReturn(gp, strainVectorR);
242
243 // copy total strain vector to the temp status
244 status->letTempStrainVectorBe(strain);
245
246 // give back correct form of stressVector to giveRealStressVector
247 return status->giveTempStressVector();
248}
249
250void
251DruckerPragerPlasticitySM :: performLocalStressReturn(GaussPoint *gp, const FloatArrayF<6> &strain) const
252{
253 auto status = static_cast< DruckerPragerPlasticitySMStatus * >( giveStatus(gp) );
254
255 // split total strains in volumetric and deviatoric part
256 // elastic constants
257 double eM = LEMaterial.give(Ex, gp);
258 double nu = LEMaterial.give(NYxz, gp);
259 double gM = eM / ( 2. * ( 1. + nu ) );
260 double kM = eM / ( 3. * ( 1. - 2. * nu ) );
261
262 //auto [strainDeviator, volumetricStrain] = computeDeviatoricVolumetricSplit(strain); // c++17
263 auto tmp = computeDeviatoricVolumetricSplit(strain);
264 auto strainDeviator = tmp.first;
265 auto volumetricStrain = tmp.second;
266
267 // compute trial elastic strains
268 double volumetricElasticTrialStrain = volumetricStrain - status->giveVolumetricPlasticStrain();
269 auto plasticStrainDeviator = status->givePlasticStrainDeviator();
270 auto elasticStrainDeviator = strainDeviator - plasticStrainDeviator;
271
272 // compute trial stresses
273 double volumetricStress = 3. * kM * volumetricElasticTrialStrain;
274 auto stressDeviator = applyDeviatoricElasticStiffness(elasticStrainDeviator, gM);
275 // norm of trial stress deviator
276 double trialStressJTwo = computeSecondStressInvariant(stressDeviator);
277
278 // initialize hardening parameter
279 double kappa = status->giveKappa();
280 double tempKappa = kappa;
281
282 // choose and perform correct stress return and update state flag
283 if ( computeYieldValue(volumetricStress, trialStressJTwo, tempKappa, eM) / eM
284 > yieldTol ) {
285 //printf("*");
286 if ( checkForVertexCase(eM, gM, kM, trialStressJTwo, volumetricStress, tempKappa) ) {
287 performVertexReturn(eM, gM, kM, trialStressJTwo, stressDeviator, volumetricStress,
288 tempKappa, volumetricElasticTrialStrain, kappa);
289 status->letTempStateFlagBe(DruckerPragerPlasticitySMStatus :: DP_Vertex);
290 } else {
291 performRegularReturn(eM, gM, kM, trialStressJTwo, stressDeviator, volumetricStress, tempKappa);
292 status->letTempStateFlagBe(DruckerPragerPlasticitySMStatus :: DP_Yielding);
293 }
294 } else {
295 const int state_flag = status->giveStateFlag();
296 if ( state_flag == DruckerPragerPlasticitySMStatus :: DP_Elastic ) {
297 status->letTempStateFlagBe(DruckerPragerPlasticitySMStatus :: DP_Elastic);
298 } else {
299 status->letTempStateFlagBe(DruckerPragerPlasticitySMStatus :: DP_Unloading);
300 }
301 }
302
303 // update kappa
304 status->letTempKappaBe(tempKappa);
305
306 // compute full stresses from deviatoric and volumetric part and store them
307 auto stress = computeDeviatoricVolumetricSum(stressDeviator, volumetricStress);
308 status->letTempStressVectorBe(stress);
309
310 // compute and update plastic strains, volumetric and deviatoric part
311 elasticStrainDeviator = applyDeviatoricElasticCompliance(stressDeviator, gM);
312 plasticStrainDeviator = strainDeviator - elasticStrainDeviator;
313 status->letTempPlasticStrainDeviatorBe(plasticStrainDeviator);
314 status->letTempVolumetricPlasticStrainBe(volumetricStrain - volumetricStress / 3. / kM);
315}
316
317bool
318DruckerPragerPlasticitySM :: checkForVertexCase(double eM, double gM, double kM, double trialStressJTwo, double volumetricStress, double tempKappa) const
319{
320 // delta lambda max corresponds to the maximum value
321 // of the rate of the plastic multiplier for regular plastic flow
322 // and allows to distinguish between regular return and vertex case
323 double deltaLambdaMax = sqrt(trialStressJTwo) / gM;
324
325 // vertex case:
326 // yield value positive under the assumption of maximum regular plastic flow
327 double volConstant = 3. * kM * alphaPsi;
328 double yieldValue =
329 computeYieldValue(volumetricStress - volConstant * deltaLambdaMax,
330 0., tempKappa + kFactor * deltaLambdaMax, eM);
331 if ( yieldValue / eM > -yieldTol ) {
332 return true;
333 }
334
335 // regular case
336 return false;
337}
338
339void
340DruckerPragerPlasticitySM :: performRegularReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArrayF<6> &stressDeviator, double &volumetricStress, double &tempKappa) const
341{
342 // delta lambda max controls the maximum plastic flow, see below
343 double deltaLambdaMax = sqrt(trialStressJTwo) / gM;
344
345 // declare some constants for faster use
346 double volConstant = 3. * kM * alphaPsi;
347 double devConstant = sqrt(2.) * gM;
348 // yield value prime is derivative of yield value with respect to deltaLambda
349 double yieldValuePrimeZero = -9. * alpha * alphaPsi * kM - gM;
350
351 auto flowDir = stressDeviator * ( 1. / sqrt(2. * trialStressJTwo) );
352
353 // initialize Newton iteration
354 int iterationCount = 0;
355 double deltaLambda = 0.;
356 double deltaLambdaIncrement = 0.;
357 double yieldValue = computeYieldValue(volumetricStress, trialStressJTwo, tempKappa, eM);
358 double newtonError = fabs(yieldValue / eM);
359 //printf("\nnewtonError = %e\n", newtonError) ;
360 // Newton iteration to find deltaLambda
361 while ( newtonError > yieldTol ) {
362 if ( ++iterationCount > newtonIter ) {
363 OOFEM_ERROR("Newton iteration for deltaLambda (regular stress return) did not converge after newtonIter iterations. You might want to try increasing the optional parameter newtoniter or yieldtol in the material record of your input file.");
364 }
365
366 double yieldValuePrime = yieldValuePrimeZero - kFactor *computeYieldStressPrime(tempKappa, eM);
367 deltaLambdaIncrement = -yieldValue / yieldValuePrime;
368
369 // deltaLambdaMax may be exceeded if the yield stress has almost vanished
370 // If this happens, the stress deviator will evolve too much,
371 // and will then be on the other side of the hydrostatic axis.
372 // This causes the failure of the Newton-iteration and has to be avoided.
373 if ( deltaLambda + deltaLambdaIncrement > deltaLambdaMax ) {
374 OOFEM_LOG_DEBUG("Special case in Newton-iteration for regular return. This may cause loss of quadratic convergence.\n");
375 deltaLambdaIncrement = deltaLambdaMax - deltaLambda;
376 }
377
378 deltaLambda += deltaLambdaIncrement;
379 tempKappa += kFactor * deltaLambdaIncrement;
380 volumetricStress -= volConstant * deltaLambdaIncrement;
381
382 // auto plasticFlow = flowDir * (devConstant * deltaLambdaIncrement)
383 //stressDeviator -= plasticFlow;
384
385 stressDeviator += (-devConstant * deltaLambdaIncrement) * flowDir;
386 double tempJTwo = computeSecondStressInvariant(stressDeviator);
387 yieldValue = computeYieldValue(volumetricStress, tempJTwo, tempKappa, eM);
388 newtonError = fabs(yieldValue / eM);
389 //printf("newtonError = %e\n", newtonError) ;
390 }
391
392 OOFEM_LOG_DEBUG("IterationCount in regular return = %d\n", iterationCount);
393
394 if ( deltaLambda < 0. ) {
395 OOFEM_ERROR("Fatal error in the Newton iteration for regular stress return. deltaLambda is evaluated as negative, but should always be positive. This is most likely due to a softening law with local snapback, which is physically inadmissible.n");
396 }
397}
398
399void
400DruckerPragerPlasticitySM :: performVertexReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArrayF<6> &stressDeviator, double &volumetricStress, double &tempKappa, double volumetricElasticTrialStrain, double kappa) const
401{
402 // declare some constants for faster use
403 // yield value prime is derivative of yield value with respect to deltaLambda
404 double yieldValuePrimeZero = 3. * alpha;
405 // contribution of deviatoric strain to hardening
406 double deviatorContribution = trialStressJTwo / 3. / gM / gM;
407 // in the vertex case, deviatoric stresses are zero
408 stressDeviator = zeros<6>();
409 volumetricStress = 3. * kM * volumetricElasticTrialStrain;
410
411 // initialize Newton iteration
412 int iterationCount = 0;
413 double deltaVolumetricStress = 0.;
414 double deltaVolumetricStressIncrement = 0.;
415 double deltaKappa = sqrt(deviatorContribution);
416 tempKappa = kappa + deltaKappa;
417 double yieldValue = computeYieldValue(volumetricStress, 0., tempKappa, eM);
418 double newtonError = fabs(yieldValue / eM);
419
420 // Newton iteration to find deltaLambda
421 while ( newtonError > yieldTol ) {
422 if ( ++iterationCount > newtonIter ) {
423 OOFEM_ERROR("Newton iteration for deltaLambda (vertex stress return) did not converge after newtonIter iterations. You might want to try increasing the optional parameter newtoniter or yieldtol in the material record of your input file.");
424 }
425
426 // exclude division by zero
427 double yieldValuePrime;
428 if ( deltaKappa == 0. ) {
429 yieldValuePrime = yieldValuePrimeZero
430 - sqrt(2.) / 3. / kM *computeYieldStressPrime(tempKappa, eM);
431 } else {
432 yieldValuePrime = yieldValuePrimeZero
433 - 2. / 9. / kM / kM *computeYieldStressPrime(tempKappa, eM)
434 * deltaVolumetricStress / deltaKappa;
435 }
436
437 deltaVolumetricStressIncrement = -yieldValue / yieldValuePrime;
438 deltaVolumetricStress += deltaVolumetricStressIncrement;
439 volumetricStress += deltaVolumetricStressIncrement;
440 deltaKappa = sqrt(2. / 9. / kM / kM * deltaVolumetricStress * deltaVolumetricStress
441 + deviatorContribution);
442 tempKappa = kappa + deltaKappa;
443 yieldValue = computeYieldValue(volumetricStress, 0., tempKappa, eM);
444 newtonError = fabs(yieldValue / eM);
445 OOFEM_LOG_DEBUG("NewtonError in iteration %d in vertex return = %e\n", iterationCount, newtonError);
446 }
447
448 OOFEM_LOG_DEBUG("Done iteration in vertex return, after %d\n", iterationCount);
449
450 if ( deltaKappa < 0. ) {
451 OOFEM_ERROR("Fatal error in the Newton iteration for vertex stress return. deltaKappa is evaluated as negative, but should always be positive. This is most likely due to a softening law with a local snapback, which is physically inadmissible.");
452 }
453}
454
455double
456DruckerPragerPlasticitySM :: computeYieldValue(double volumetricStress,
457 double JTwo,
458 double kappa,
459 double eM) const
460{
461 return 3. * alpha * volumetricStress + sqrt(JTwo) - computeYieldStressInShear(kappa, eM);
462}
463
464double
465DruckerPragerPlasticitySM :: computeYieldStressInShear(double kappa, double eM) const
466{
467 double yieldStress;
468 switch ( hardeningType ) {
469 case 1: // linear hardening/softening.
470 yieldStress = initialYieldStress + hardeningModulus * eM * kappa;
471 if ( yieldStress < 0. ) {
472 yieldStress = 0.;
473 //printf("Yield stress zero reached in computeYieldStressInShear.\n") ;
474 }
475 return yieldStress;
476 case 2: // exponential hardening
477 return limitYieldStress - ( limitYieldStress - initialYieldStress ) * exp(-kappa / kappaC);
478 default:
479 //StructuralMaterial :: OOFEM_ERROR( "Case failed: choose linear hardening/softening (1), exponential hardening/softening (2) in input file.") ;
480 OOFEM_ERROR("Case failed: choose linear hardening/softening (1), exponential hardening/softening (2) in input file.");
481 }
482}
483
484double
485DruckerPragerPlasticitySM :: computeYieldStressPrime(double kappa, double eM) const
486{
487 switch ( hardeningType ) {
488 case 1: // linear hardening/softening.
489 // if the limit value for kappa is exceeded in the softening case, the derivative is zero
490 if ( ( hardeningModulus < 0. ) && ( kappa >= -initialYieldStress / hardeningModulus / eM ) ) {
491 return 0.0;
492 } else {
493 return eM * hardeningModulus;
494 }
495 case 2: // exponential hardening
496 return ( limitYieldStress - initialYieldStress ) / kappaC *exp(-kappa / kappaC);
497 default:
498 //StructuralMaterial :: OOFEM_ERROR( "Case failed: choose linear hardening/softening (1), exponential hardening/softening (2) in input file.") ;
499 OOFEM_ERROR("Case failed: choose linear hardening/softening (1), exponential hardening/softening (2) in input file.");
500 }
501}
502
503
505DruckerPragerPlasticitySM :: give3dMaterialStiffnessMatrix(MatResponseMode mode,
506 GaussPoint *gp,
507 TimeStep *tStep) const
508{
509 switch ( mode ) {
510 case ElasticStiffness:
511 return LEMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep);
512
513 case SecantStiffness:
514 return LEMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep);
515
516 case TangentStiffness:
517 switch ( ( static_cast< DruckerPragerPlasticitySMStatus * >( this->giveStatus(gp) ) )
518 ->giveTempStateFlag() ) {
519 case DruckerPragerPlasticitySMStatus :: DP_Elastic: // elastic stiffness
520 case DruckerPragerPlasticitySMStatus :: DP_Unloading: // elastic stiffness
521 return LEMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep);
522 case DruckerPragerPlasticitySMStatus :: DP_Yielding:
523 // elasto-plastic stiffness for regular case
524 //printf("\nAssembling regular algorithmic stiffness matrix.") ;
525 return giveRegAlgorithmicStiffMatrix(mode, gp, tStep);
526 case DruckerPragerPlasticitySMStatus :: DP_Vertex:
527 // elasto-plastic stiffness for vertex case
528 //printf("\nAssembling vertex case algorithmic stiffness matrix.") ;
529 return giveVertexAlgorithmicStiffMatrix(mode, gp, tStep);
530 default:
531 OOFEM_ERROR("Case did not match.");
532 }
533
534 break;
535
536 default:
537 OOFEM_ERROR("Switch failed: Only elastic and tangent stiffness are supported.");
538 }
539 // return FloatMatrixF<6,6>();
540}
541
543DruckerPragerPlasticitySM :: giveRegAlgorithmicStiffMatrix(MatResponseMode mode,
544 GaussPoint *gp,
545 TimeStep *tStep) const
546{
547 auto status = static_cast< DruckerPragerPlasticitySMStatus * >( this->giveStatus(gp) );
548
549 const auto &stressVector = status->giveTempStressVector();
550
551 auto deviatoricStress = computeDeviator(stressVector);
552
553 double normOfStress = sqrt( 2. * computeSecondStressInvariant(deviatoricStress) );
554 // elastic constants
555 double eM = LEMaterial.give(Ex, gp);
556 double nu = LEMaterial.give(NYxz, gp);
557 double gM = eM / ( 2. * ( 1. + nu ) );
558 double kM = eM / ( 3. * ( 1. - 2. * nu ) );
559
560 auto flowDir = deviatoricStress / normOfStress;
561
562 double kappa = status->giveKappa();
563 double tempKappa = status->giveTempKappa();
564 double deltaKappa = tempKappa - kappa;
565 double deltaLambdaStar = sqrt(2.) * gM * deltaKappa / kFactor / normOfStress;
566 double hStar = kFactor * computeYieldStressPrime(tempKappa, eM);
567
568 //exclude division by zero
569 if ( hStar == 0. ) {
570 OOFEM_ERROR("computeYieldStressPrime is zero. This happens mainly due to excessive softening.");
571 }
572
573 double a_const = 1. + deltaLambdaStar;
574 double b_const = 3. * alpha * alphaPsi * kM / hStar - deltaLambdaStar / 3.;
575 double c_const = 3. * sqrt(2.) * alphaPsi * kM / 2. / hStar;
576 double d_const = sqrt(2.) * alpha * gM / hStar;
577 double e_const = gM / hStar - deltaLambdaStar;
578
579 FloatMatrixF<6,6> A_Matrix;
580
581 for ( int i = 1; i < 7; i++ ) {
582 A_Matrix.at(i, i) = a_const;
583 }
584
585 for ( int i = 1; i < 4; i++ ) {
586 for ( int j = 1; j < 4; j++ ) {
587 A_Matrix.at(i, j) += b_const;
588 }
589 }
590
591 for ( int i = 1; i < 4; i++ ) {
592 for ( int j = 1; j < 4; j++ ) {
593 A_Matrix.at(i, j) += c_const * flowDir.at(j);
594 }
595
596 for ( int j = 4; j < 7; j++ ) {
597 A_Matrix.at(i, j) += 2. *c_const *flowDir.at(j);
598 }
599 }
600
601 for ( int i = 1; i < 7; i++ ) {
602 for ( int j = 1; j < 4; j++ ) {
603 A_Matrix.at(i, j) += d_const * flowDir.at(i);
604 }
605 }
606
607 for ( int i = 1; i < 7; i++ ) {
608 for ( int j = 1; j < 4; j++ ) {
609 A_Matrix.at(i, j) += e_const * flowDir.at(i) * flowDir.at(j);
610 }
611
612 // account for engineering notation
613 for ( int j = 4; j < 7; j++ ) {
614 A_Matrix.at(i, j) += 2. *e_const *flowDir.at(i) * flowDir.at(j);
615 }
616 }
617
618 auto De = LEMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep);
619
620 // answer is A_Matrix^-1 * De
621 return dot(inv(A_Matrix), De);
622}
623
625DruckerPragerPlasticitySM :: giveVertexAlgorithmicStiffMatrix(MatResponseMode mode,
626 GaussPoint *gp,
627 TimeStep *tStep) const
628{
629 auto status = static_cast< DruckerPragerPlasticitySMStatus * >( this->giveStatus(gp) );
630
631 double tempKappa = status->giveTempKappa();
632 double deltaKappa = tempKappa - status->giveKappa();
633 // elastic constants
634 double eM = LEMaterial.give(Ex, gp);
635 double nu = LEMaterial.give(NYxz, gp);
636 //double gM = eM / ( 2. * ( 1. + nu ) );
637 double kM = eM / ( 3. * ( 1. - 2. * nu ) );
638
639 if ( deltaKappa <= 0. ) {
640 // This case occurs in the first iteration of a step.
641 // printf("deltaKappa<=0. for vertex case algorithmic stiffness, i.e. continuum tangent stiffness. Since the continuum tangent stiffness does not exist at the vertex, elastic stiffness is used instead. This will cause the loss of quadratic convergence.\n") ;
642 return LEMaterial.give3dMaterialStiffnessMatrix( mode, gp, tStep);
643
644 }
645
646 double deltaVolumetricPlasticStrain =
647 status->giveTempVolumetricPlasticStrain() - status->giveVolumetricPlasticStrain();
648 double HBar = computeYieldStressPrime(tempKappa, eM);
649
650 // compute elastic trial strain deviator of latest temp-state
651 auto strainDeviator = computeDeviator(status->giveTempStrainVector());
652
653 auto elasticStrainDeviator = strainDeviator - FloatArrayF<6>(status->givePlasticStrainDeviator());
654
655 double a_const =
656 kM * HBar / ( HBar * deltaVolumetricPlasticStrain + 9. / 2. * alpha * kM * deltaKappa );
657
658 if ( ( HBar * deltaVolumetricPlasticStrain + 9. / 2. * alpha * kM * deltaKappa ) == 0. ) {
659 OOFEM_ERROR("Tangent type is singular, material ID %d\n", this->giveNumber() );
660 }
661 // compute the algorithmic tangent stiffness
662
663
664 FloatMatrixF<6,6> answer;
665 for ( int i = 1; i < 4; i++ ) {
666 for ( int j = 1; j < 4; j++ ) {
667 answer.at(i, j) = deltaVolumetricPlasticStrain;
668 }
669 }
670
671 for ( int i = 1; i < 4; i++ ) {
672 for ( int j = 1; j < 4; j++ ) {
673 answer.at(i, j) += elasticStrainDeviator.at(j);
674 }
675
676 for ( int j = 4; j < 7; j++ ) {
677 answer.at(i, j) += .5 * elasticStrainDeviator.at(j);
678 }
679 }
680
681 return a_const * answer;
682}
683
684int
685DruckerPragerPlasticitySM :: giveIPValue(FloatArray &answer,
686 GaussPoint *gp,
688 TimeStep *tStep)
689{
690 const auto status = static_cast< DruckerPragerPlasticitySMStatus * >( giveStatus(gp) );
691
692 switch ( type ) {
693 case IST_PlasticStrainTensor:
694 answer = status->givePlasticStrainVector();
695 return 1;
696
697 case IST_DamageTensor:
698 answer.resize(6);
699 answer.zero();
700 answer.at(1) = answer.at(2) = answer.at(3) = status->giveKappa();
701 return 1;
702
703 default:
704 return StructuralMaterial :: giveIPValue(answer, gp, type, tStep);
705 }
706}
707
708std::unique_ptr<MaterialStatus>
709DruckerPragerPlasticitySM :: CreateStatus(GaussPoint *gp) const
710{
711 return std::make_unique<DruckerPragerPlasticitySMStatus>(gp);
712}
713
714
715double
716DruckerPragerPlasticitySM :: predictRelativeComputationalCost(GaussPoint *gp)
717{
718 auto status = static_cast< DruckerPragerPlasticitySMStatus * >( giveStatus(gp) );
719 int state_flag = status->giveStateFlag();
720
721 if ( ( state_flag == DruckerPragerPlasticitySMStatus :: DP_Vertex ) ||
722 ( state_flag == DruckerPragerPlasticitySMStatus :: DP_Yielding ) ) {
723 return 20.;
724 } else {
725 return 1.0;
726 }
727}
728
729} // end namespace oofem
730
731#undef PRINTFDP
#define REGISTER_Material(class)
virtual int read(int *data, std::size_t count)=0
Reads count integer values into array pointed by data.
virtual int write(const int *data, std::size_t count)=0
Writes count integer values from array pointed by data.
double volumetricPlasticStrain
Volumetric plastic strain.
int state_flag
Indicates the state (i.e. elastic, yielding, vertex, unloading) of the Gauss point.
FloatArrayF< 6 > plasticStrainDeviator
Deviatoric of plastic strain.
DruckerPragerPlasticitySM(int n, Domain *d)
Constructor.
double initialYieldStress
Parameter of all three laws, this is the initial value of the yield stress in pure shear.
double computeYieldValue(double meanStress, double JTwo, double kappa, double eM) const
int newtonIter
Maximum number of iterations for stress return.
void performVertexReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArrayF< 6 > &stressDeviator, double &volumetricStress, double &tempKappa, double volumetricElasticTrialStrain, double kappa) const
double kFactor
Scalar factor between rate of plastic multiplier and rate of hardening variable.
virtual double computeYieldStressPrime(double kappa, double eM) const
FloatMatrixF< 6, 6 > giveVertexAlgorithmicStiffMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
double limitYieldStress
Parameter of the exponential hardening law.
double hardeningModulus
Hardening modulus normalized with the elastic modulus, parameter of the linear hardening/softening la...
bool checkForVertexCase(double eM, double gM, double kM, double trialStressJTwo, double volumetricStress, double tempKappa) const
FloatMatrixF< 6, 6 > giveRegAlgorithmicStiffMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
double alpha
Friction coefficient, parameter of the yield criterion.
double alphaPsi
Dilatancy coefficient, parameter of the flow rule.
void performLocalStressReturn(GaussPoint *gp, const FloatArrayF< 6 > &strain) const
double kappaC
Parameter of the exponential laws.
void performRegularReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArrayF< 6 > &stressDeviator, double &volumetricStress, double &tempKappa) const
IsotropicLinearElasticMaterial LEMaterial
Associated linear elastic material.
virtual double computeYieldStressInShear(double kappa, double eM) const
int giveNumber() const
Definition femcmpnn.h:104
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
double at(std::size_t i, std::size_t j) const
GaussPoint * gp
Associated integration point.
virtual MaterialStatus * giveStatus(GaussPoint *gp) const
Definition material.C:206
virtual void initTempStatus(GaussPoint *gp) const
Definition material.C:221
const FloatArray & giveTempStressVector() const
Returns the const pointer to receiver's temporary stress vector.
StructuralMaterialStatus(GaussPoint *g)
Constructor. Creates new StructuralMaterialStatus with IntegrationPoint g.
FloatArray tempStrainVector
Temporary strain vector in reduced form (to find balanced state).
FloatArray tempStressVector
Temporary stress vector in reduced form (increments are used mainly in nonlinear analysis).
FloatArray stressVector
Equilibrated stress vector in reduced form.
FloatArray strainVector
Equilibrated strain vector in reduced form.
static FloatArrayF< 6 > computeDeviatoricVolumetricSum(const FloatArrayF< 6 > &dev, double mean)
static FloatArrayF< 6 > applyDeviatoricElasticCompliance(const FloatArrayF< 6 > &stress, double EModulus, double nu)
StructuralMaterial(int n, Domain *d)
static FloatArrayF< 6 > applyDeviatoricElasticStiffness(const FloatArrayF< 6 > &strain, double EModulus, double nu)
static double computeSecondStressInvariant(const FloatArrayF< 6 > &s)
static FloatArrayF< 6 > computeDeviator(const FloatArrayF< 6 > &s)
static std::pair< FloatArrayF< 6 >, double > computeDeviatoricVolumetricSplit(const FloatArrayF< 6 > &s)
FloatArrayF< 6 > computeStressIndependentStrainVector_3d(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const
#define THROW_CIOERR(e)
#define _IFT_DruckerPragerPlasticitySM_ht
#define _IFT_DruckerPragerPlasticitySM_iys
Initial yield stress under pure shear.
#define _IFT_DruckerPragerPlasticitySM_lys
#define _IFT_DruckerPragerPlasticitySM_newtoniter
#define _IFT_DruckerPragerPlasticitySM_kc
#define _IFT_DruckerPragerPlasticitySM_yieldtol
#define _IFT_DruckerPragerPlasticitySM_alpha
Friction coefficient.
#define _IFT_DruckerPragerPlasticitySM_hm
#define _IFT_DruckerPragerPlasticitySM_alphapsi
Dilatancy coefficient.
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define OOFEM_LOG_DEBUG(...)
Definition logger.h:144
#define NYxz
Definition matconst.h:51
#define Ex
Definition matconst.h:59
long ContextMode
Definition contextmode.h:43
double dot(const FloatArray &x, const FloatArray &y)
FloatMatrixF< N, N > inv(const FloatMatrixF< N, N > &mat, double zeropiv=1e-24)
Computes the inverse.
FloatArrayF< N > zeros()
For more readable code.
@ CIO_IOERR
General IO error.

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011