OOFEM 3.0
Loading...
Searching...
No Matches
rankinemat.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
35#include "rankinemat.h"
37#include "gausspoint.h"
38#include "floatmatrix.h"
39#include "floatarray.h"
40#include "intarray.h"
41#include "stressvector.h"
42#include "strainvector.h"
43#include "mathfem.h"
44#include "contextioerr.h"
45#include "datastream.h"
46#include "classfactory.h"
47
48namespace oofem {
50
51// constructor
52RankineMat :: RankineMat(int n, Domain *d) : StructuralMaterial(n, d)
53{
55}
56
57
58// specifies whether a given material mode is supported by this model
59bool
60RankineMat :: hasMaterialModeCapability(MaterialMode mode) const
61{
62 return mode == _PlaneStress || mode == _1dMat;
63}
64
65
66// reads the model parameters from the input file
67void
68RankineMat :: initializeFrom(InputRecord &ir)
69{
70 StructuralMaterial :: initializeFrom(ir);
71 linearElasticMaterial->initializeFrom(ir); // takes care of elastic constants
72
73 E = static_cast< IsotropicLinearElasticMaterial * >(linearElasticMaterial)->giveYoungsModulus();
74 nu = static_cast< IsotropicLinearElasticMaterial * >(linearElasticMaterial)->givePoissonsRatio();
75
76 IR_GIVE_FIELD(ir, sig0, _IFT_RankineMat_sig0); // uniaxial yield stress
77
78 H0 = 0.;
79 IR_GIVE_OPTIONAL_FIELD(ir, H0, _IFT_RankineMat_h); // hardening modulus
80
81 plasthardtype = 0;
82 IR_GIVE_OPTIONAL_FIELD(ir, plasthardtype, _IFT_RankineMat_plasthardtype); // type of plastic hardening (0=linear, 1=exponential, 2= prepeak hardening + linear softening )
83
84 delSigY = 0.;
85 if ( plasthardtype == 0 ) {
86 //no extra required variables
87 } else if ( plasthardtype == 1 ) {
88 IR_GIVE_FIELD(ir, delSigY, _IFT_RankineMat_delsigy); // final increment of yield stress (at infinite cumulative plastic strain)
89 } else if ( plasthardtype == 2 ) {
91 ep = ep - sig0 / E; // user input is strain at peak stress sig0 and is converted to plastic strain at peak stress sig0
92 md = 1. / log(50. * E * ep / sig0); // exponent used on the 1st plasticity branch
93 } else {
94 throw ValueInputException(ir, _IFT_RankineMat_plasthardtype, "Plasticity hardening type is unknown");
95 }
96
97 yieldtol = 1.e-10;
98 IR_GIVE_OPTIONAL_FIELD(ir, yieldtol, _IFT_RankineMat_yieldtol); // relative tolerance in yield condition
99
100 damlaw = 0;
101 IR_GIVE_OPTIONAL_FIELD(ir, damlaw, _IFT_RankineMat_damlaw); // type of damage law (0=exponential, 1=exponential and damage starts after peak stress sig0)
102
103 if ( damlaw == 0 ) {
104 a = 0.;
105 IR_GIVE_OPTIONAL_FIELD(ir, a, _IFT_RankineMat_a); // coefficient in damage law
106 } else if ( damlaw == 1 ) {
107 IR_GIVE_FIELD(ir, param1, _IFT_RankineMat_param1); // coefficient in damage law
108 IR_GIVE_FIELD(ir, param2, _IFT_RankineMat_param2); // coefficient in damage law. If b<1 use only stiffmode=1
109 } else if ( damlaw == 2 ) {
110 IR_GIVE_FIELD(ir, param1, _IFT_RankineMat_param1); // coefficients in damage law
115 } else if ( damlaw == 3 ) {
116 IR_GIVE_FIELD(ir, param1, _IFT_RankineMat_param1); // coefficients in damage law
119 } else {
120 throw ValueInputException(ir, _IFT_RankineMat_damlaw, "Damage law is unknown");
121 }
122
123 double gf = 0.;
124 IR_GIVE_OPTIONAL_FIELD(ir, gf, _IFT_RankineMat_gf); // dissipated energy per unit VOLUME
125
126 if ( ( a != 0. ) && ( gf != 0 ) ) {
127 throw ValueInputException(ir, _IFT_RankineMat_gf, "parameters a and gf cannot be prescribed simultaneously");
128 }
129
130 if ( gf > 0. ) {
131 // evaluate parameter "a" from given "gf"
132 double A = H0 * ( 1. + H0 / E );
133 double B = sig0 * ( 1. + H0 / E );
134 double C = 0.5 * sig0 * sig0 / E - gf;
135 if ( C >= 0. ) {
136 OOFEM_ERROR("parameter gf is too low");
137 }
138
139 double kappaf = ( -B + sqrt(B * B - 4. * A * C) ) / ( 2. * A );
140 a = 1. / kappaf;
141 }
142}
143
144
145std::unique_ptr<MaterialStatus>
146RankineMat :: CreateStatus(GaussPoint *gp) const
147{
148 return std::make_unique<RankineMatStatus>(gp);
149}
150
151
152// computes the stress vector corresponding to given (final) strain
154RankineMat :: giveRealStressVector_1d(const FloatArrayF<1> &totalStrain, GaussPoint *gp, TimeStep *tStep) const
155{
156 auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) );
157
158 // initialization
159 this->initTempStatus(gp);
160
161 // elastoplasticity
162 this->performPlasticityReturn(gp, totalStrain);
163
164 // damage
165 double omega = computeDamage(gp, tStep);
166 FloatArray answer;
167 answer.beScaled(1. - omega, status->giveTempEffectiveStress());
168
169 // store variables in status
170 status->setTempDamage(omega);
171 status->letTempStrainVectorBe(totalStrain);
172 status->letTempStressVectorBe(answer);
173#ifdef keep_track_of_dissipated_energy
174 double gf = sig0 * sig0 / E; // only estimated, but OK for this purpose
175 status->computeWork_1d(gp, gf);
176#endif
177 return answer;
178}
179
180
182RankineMat :: giveRealStressVector_PlaneStress(const FloatArrayF<3> &totalStrain,
183 GaussPoint *gp, TimeStep *tStep) const
184{
185 auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) );
186
187 // initialization
188 this->initTempStatus(gp);
189
190 // elastoplasticity
191 this->performPlasticityReturn(gp, totalStrain);
192
193 // damage
194 double omega = computeDamage(gp, tStep);
195 FloatArray answer;
196 answer.beScaled(1. - omega, status->giveTempEffectiveStress());
197
198 // store variables in status
199 status->setTempDamage(omega);
200 status->letTempStrainVectorBe(totalStrain);
201 status->letTempStressVectorBe(answer);
202#ifdef keep_track_of_dissipated_energy
203 double gf = sig0 * sig0 / E; // only estimated, but OK for this purpose
204 status->computeWork_PlaneStress(gp, gf);
205#endif
206 return answer;
207}
208
209
210double
211RankineMat :: evalYieldFunction(const FloatArray &sigPrinc, const double kappa) const
212{
213 return sigPrinc.at(1) - evalYieldStress(kappa);
214}
215
216
217double
218RankineMat :: evalYieldStress(const double kappa) const
219{
220 double yieldStress = 0.;
221 if ( plasthardtype == 0 ) { // linear hardening
222 yieldStress = sig0 + H0 * kappa;
223 } else if ( plasthardtype == 1 ) { // exponential hardening
224 if ( delSigY == 0. ) {
225 yieldStress = sig0;
226 } else {
227 yieldStress = sig0 + delSigY * ( 1. - exp(-H0 * kappa / delSigY) );
228 }
229 } else if ( plasthardtype == 2 ) { // exponential hardening before the peak stress sig0 and linear after the peak stress sig0
230 if ( kappa <= ep ) {
231 //1st branch in the rankine variation 2 trying to match the 1st branch of the smooth extended damage law reported by Grassl and Jirasek (2010)
232 yieldStress = 50. *E *kappa *exp(-pow ( kappa / ep, md ) / md);
233 } else { //linear hardening branch
234 yieldStress = sig0 + H0 * kappa;
235 }
236 }
237 return yieldStress;
238}
239
240double
241RankineMat :: evalPlasticModulus(const double kappa) const
242{
243 double plasticModulus = 0.;
244 if ( plasthardtype == 0 ) { // linear hardening
245 plasticModulus = H0;
246 } else if ( plasthardtype == 1 ) { // exponential hardening
247 plasticModulus = H0 * exp(-H0 * kappa / delSigY);
248 } else if ( plasthardtype == 2 ) { // exponential hardening before the peak stress sig0 and linear after the peak stress sig0
249 if ( kappa <= ep ) { //1st branch of yield stress
250 double aux = pow(kappa / ep, md);
251 plasticModulus = 50. *E *exp(-aux / md) * ( 1. - aux );
252 } else { //2nd branch of yield stress
253 plasticModulus = H0;
254 }
255 }
256 return plasticModulus;
257}
258
259
260// computes the stress according to elastoplasticity
261// (return of trial stress to the yield surface)
262void
263RankineMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain) const
264{
265 double kappa, tempKappa, H;
266 RankineMatStatus *status = static_cast< RankineMatStatus * >( this->giveStatus(gp) );
267 MaterialMode mode = gp->giveMaterialMode();
268 // get the initial plastic strain and initial kappa from the status
269 FloatArray tempPlasticStrain = status->givePlasticStrain();
270 kappa = tempKappa = status->giveCumulativePlasticStrain();
271
272 // elastic predictor
273 StrainVector elStrain(totalStrain, mode);
274 elStrain.subtract(tempPlasticStrain);
275 StressVector finalStress(mode);
276 elStrain.applyElasticStiffness(finalStress, E, nu);
277 FloatArray sigPrinc;
278 FloatMatrix nPrinc;
279 // get principal trial stresses (ordered) and principal stress directions
280 finalStress.computePrincipalValDir(sigPrinc, nPrinc);
281 double ftrial = evalYieldFunction(sigPrinc, tempKappa);
282 if ( mode == _1dMat ) { //1d case
284 if ( ftrial > 0. ) {
285 double f = ftrial;
286 // calculate the increment of cumulative plastic strain
287 int i = 1;
288 do {
289 i = i + 1;
290 if ( i > 1000 ) {
291 printf("kappa, ftrial: %g %g\n", kappa, ftrial);
292 OOFEM_ERROR("no convergence of regular stress return algorithm");
293 }
294
295 double ddKappa = f / ( E + evalPlasticModulus(tempKappa) );
296 finalStress.at(1) -= E * ddKappa;
297 tempKappa += ddKappa;
298 f = finalStress.at(1) - evalYieldStress(tempKappa);
299 } while ( fabs(f) > yieldtol * sig0 );
300 }
301
302 tempPlasticStrain.at(1) = tempKappa;
303 //End of Dimitris change
304 } else { //Plane stress case
305 double difPrincTrialStresses = sigPrinc.at(1) - sigPrinc.at(2);
306 double tanG = E / ( 2. * ( 1. + nu ) );
307
308 // plastic corrector - regular case
309 bool vertex_case = false;
310 if ( ftrial > 0. ) {
311 double f = ftrial;
312 double Enu = E / ( 1. - nu * nu );
313 // calculate the increment of cumulative plastic strain
314 int i = 1;
315 do {
316 if ( i++ > 50 ) {
317 finalStress.computePrincipalValDir(sigPrinc, nPrinc);
318 sigPrinc.pY();
319 printf("kappa, ftrial: %g %g\n", kappa, ftrial);
320 OOFEM_ERROR("no convergence of regular stress return algorithm");
321 }
322
323 H = evalPlasticModulus(tempKappa);
324 double ddKappa = f / ( Enu + H );
325 sigPrinc.at(1) -= Enu * ddKappa;
326 sigPrinc.at(2) -= nu * Enu * ddKappa;
327 tempKappa += ddKappa;
328 f = evalYieldFunction(sigPrinc, tempKappa);
329 } while ( fabs(f) > yieldtol * sig0 );
330
331 if ( sigPrinc.at(2) > sigPrinc.at(1) ) {
332 // plastic corrector - vertex case
333 // ---------------------------------
334 vertex_case = true;
335 // recompute trial principal stresses
336 finalStress.computePrincipalValDir(sigPrinc, nPrinc);
337 // calculate the increment of cumulative plastic strain
338 double sigstar = ( sigPrinc.at(1) - nu * sigPrinc.at(2) ) / ( 1. - nu );
339 double alpha = E / ( 1. - nu );
340 double dkap0 = ( sigPrinc.at(1) - sigPrinc.at(2) ) * ( 1. + nu ) / E;
341 tempKappa = kappa;
342 f = sigstar - evalYieldStress(tempKappa);
343 double dkap1 = 0.;
344 H = evalPlasticModulus(tempKappa);
345 double C = alpha + H * ( 1. + sqrt(2.) ) / 2.;
346 i = 1;
347 do {
348 if ( i++ > 20 ) {
349 finalStress.computePrincipalValDir(sigPrinc, nPrinc);
350 sigPrinc.pY();
351 printf("kappa, ftrial: %g %g\n", kappa, ftrial);
352 OOFEM_ERROR("no convergence of vertex stress return algorithm");
353 }
354
355 dkap1 += f / C;
356 tempKappa = kappa + sqrt( dkap1 * dkap1 + ( dkap1 - dkap0 ) * ( dkap1 - dkap0 ) );
357 f = sigstar - evalYieldStress(tempKappa) - alpha * dkap1;
358 double aux = dkap1 * dkap1 + ( dkap1 - dkap0 ) * ( dkap1 - dkap0 );
359 H = evalPlasticModulus(tempKappa);
360 if ( aux > 0. ) {
361 C = alpha + H * ( 2. * dkap1 - dkap0 ) / sqrt(aux);
362 } else {
363 C = alpha + H *sqrt(2.);
364 }
365 } while ( fabs(f) > yieldtol * sig0 );
366
367 sigPrinc.at(1) = sigPrinc.at(2) = sigstar - alpha * dkap1;
368 status->setDKappa(dkap1, dkap1 - dkap0);
369 }
370
371 // principal stresses
372 double sig1 = sigPrinc.at(1);
373 double sig2 = sigPrinc.at(2);
374 // compose the stress in global coordinates
375 // the first subscript refers to coordinate
376 // the second subscript refers to eigenvalue
377 double n11 = nPrinc.at(1, 1);
378 double n12 = nPrinc.at(1, 2);
379 double n21 = nPrinc.at(2, 1);
380 double n22 = nPrinc.at(2, 2);
381 finalStress.at(1) = sig1 * n11 * n11 + sig2 * n12 * n12;
382 finalStress.at(2) = sig1 * n21 * n21 + sig2 * n22 * n22;
383 finalStress.at(3) = sig1 * n11 * n21 + sig2 * n12 * n22;
384 // add the increment of plastic strain
385 if ( !vertex_case ) {
386 tempPlasticStrain.at(1) += ( tempKappa - kappa ) * n11 * n11;
387 tempPlasticStrain.at(2) += ( tempKappa - kappa ) * n21 * n21;
388 tempPlasticStrain.at(3) += 2. * ( tempKappa - kappa ) * n11 * n21;
389 } else {
390 double dkap1 = status->giveDKappa(1);
391 double dkap2 = status->giveDKappa(2);
392 tempPlasticStrain.at(1) += dkap1 * n11 * n11 + dkap2 * n12 * n12;
393 tempPlasticStrain.at(2) += dkap1 * n21 * n21 + dkap2 * n22 * n22;
394 tempPlasticStrain.at(3) += 2. * ( dkap1 * n11 * n21 + dkap2 * n12 * n22 );
395 }
396
397 // evaluate the tangent shear stiffness
398 if ( difPrincTrialStresses != 0. ) {
399 double factor = ( sig1 - sig2 ) / difPrincTrialStresses;
400 if ( factor > 0. && factor <= 1. ) {
401 tanG *= factor;
402 }
403 }
404 }
405
406 status->setTangentShearStiffness(tanG); // store shear stiffness.Used in 2d/3d cases
407 }
408
409 // store the effective stress, plastic strain and cumulative plastic strain
410 status->letTempEffectiveStressBe(finalStress);
411 status->letTempPlasticStrainBe(tempPlasticStrain);
412 status->setTempCumulativePlasticStrain(tempKappa);
413}
414
415double
416RankineMat :: computeDamageParam(double tempKappa) const
417{
418 double tempDam = 0.;
419 if ( tempKappa > 0. ) {
420 if ( damlaw == 0 ) {
421 tempDam = 1.0 - exp(-a * tempKappa);
422 } else if ( damlaw == 1 && tempKappa > ep ) {
423 tempDam = 1.0 - exp( -param1 * pow( ( tempKappa - ep ) / ep, param2 ) );
424 } else if ( damlaw == 2 && tempKappa > ep ) {
425 tempDam = 1.0 - param5 *exp( -param1 *pow ( ( tempKappa - ep ) / ep, param2 ) ) - ( 1. - param5 ) * exp( -param3 * pow( ( tempKappa - ep ) / ep, param4 ) );
426 } else if ( damlaw == 3 ) {
427 tempDam = 1.0 - (sig0 / (sig0+H0*tempKappa)) * ( (1.-param3)*exp(-param1*tempKappa) + param3*exp(-param2*tempKappa) );
428 }
429 }
430
431 return tempDam;
432}
433
434double
435RankineMat :: computeDamageParamPrime(double tempKappa) const
436{
437 double tempDam = 0.;
438 if ( tempKappa >= 0. ) {
439 if ( damlaw == 0 ) {
440 tempDam = a * exp(-a * tempKappa);
441 } else if ( damlaw == 1 && tempKappa >= ep ) {
442 tempDam = param1 * param2 * pow( ( tempKappa - ep ) / ep, param2 - 1 ) / ep *exp( -param1 *pow ( ( tempKappa - ep ) / ep, param2 ) );
443 } else if ( damlaw == 2 && tempKappa >= ep ) {
444 tempDam = param5 * param1 * param2 * pow( ( tempKappa - ep ) / ep, param2 - 1 ) / ep *exp( -param1 *pow ( ( tempKappa - ep ) / ep, param2 ) ) + ( 1. - param5 ) * param3 * param4 * pow( ( tempKappa - ep ) / ep, param4 - 1 ) / ep *exp( -param3 *pow ( ( tempKappa - ep ) / ep, param4 ) );
445 } else if ( damlaw == 3 ) {
446 tempDam = (sig0 / (sig0+H0*tempKappa)) * ( (1.-param3)*param1*exp(-param1*tempKappa) + param3*param2*exp(-param2*tempKappa) ) + (sig0*H0 / (sig0+H0*tempKappa)*(sig0+H0*tempKappa)) * ( (1.-param3)*exp(-param1*tempKappa) + param3*exp(-param2*tempKappa) );
447 }
448 }
449
450 return tempDam;
451}
452
453double
454RankineMat :: computeDamage(GaussPoint *gp, TimeStep *tStep) const
455{
456 auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) );
457 double dam = status->giveDamage();
458 double tempKappa = computeCumPlastStrain(gp, tStep);
459 double tempDam = computeDamageParam(tempKappa);
460 if ( dam > tempDam ) {
461 tempDam = dam;
462 }
463
464 return tempDam;
465}
466
467double RankineMat :: computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const
468{
469 RankineMatStatus *status = static_cast< RankineMatStatus * >( this->giveStatus(gp) );
470 return status->giveTempCumulativePlasticStrain();
471}
472
473// returns the consistent (algorithmic) stiffness matrix
475RankineMat :: givePlaneStressStiffMtrx(MatResponseMode mode,
476 GaussPoint *gp,
477 TimeStep *tStep) const
478{
479 auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) );
480 double tempKappa = status->giveTempCumulativePlasticStrain();
481 double gprime = computeDamageParamPrime(tempKappa);
482 return evaluatePlaneStressStiffMtrx(mode, gp, tStep, gprime);
483}
484
486RankineMat :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
487{
488 if ( mode == ElasticStiffness ) {
489 return {E};
490 } else if ( mode == SecantStiffness ) {
491 auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) );
492 double om = status->giveTempDamage();
493 return {E * (1.0 - om)};
494 } else {
495 OOFEM_ERROR("unknown type of stiffness (secant stiffness not implemented for 1d)");
496 }
497}
498
499// this method is also used by the gradient version,
500// with gprime replaced by gprime*m and evaluated for kappa hat
502RankineMat :: evaluatePlaneStressStiffMtrx(MatResponseMode mode,
503 GaussPoint *gp,
504 TimeStep *tStep, double gprime) const
505{
506 auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) );
507 if ( mode == ElasticStiffness || mode == SecantStiffness ) {
508 // start from the elastic stiffness
509 auto d = this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep);
510 if ( mode == SecantStiffness ) {
511 // transform to secant stiffness
512 double damage = status->giveTempDamage();
513 d *= 1. - damage;
514 }
515 return d;
516 }
517
518 // check the unloading condition
519 double kappa = status->giveCumulativePlasticStrain();
520 double tempKappa = status->giveTempCumulativePlasticStrain();
521 if ( tempKappa <= kappa ) { // tangent matrix requested, but unloading takes place - use secant
522 auto d = this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep);
523 double damage = status->giveTempDamage();
524 return d * (1. - damage);
525 }
526
527 // tangent stiffness requested, loading
528
529 // elastoplastic tangent matrix in principal stress coordinates
530 FloatMatrixF<3,3> answer;
531
532 double eta1, eta2, dkap2;
533 double dkap1 = status->giveDKappa(1);
534 double H = evalPlasticModulus(tempKappa);
535
536 if ( dkap1 == 0. ) {
537 // regular case
538
539 double Enu = E / ( 1. - nu * nu );
540 double aux = Enu / ( Enu + H );
541 answer.at(1, 1) = aux * H;
542 answer.at(1, 2) = answer.at(2, 1) = nu * aux * H;
543 answer.at(2, 2) = aux * ( E + H );
544 answer.at(3, 3) = status->giveTangentShearStiffness();
545 eta1 = aux;
546 eta2 = nu * aux;
547 } else {
548 // vertex case
549
550 dkap2 = status->giveDKappa(2);
551 double denom = E * dkap1 + H * ( 1. - nu ) * ( dkap1 + dkap2 );
552 eta1 = E * dkap1 / denom;
553 eta2 = E * dkap2 / denom;
554 answer.at(1, 1) = answer.at(2, 1) = H * eta1;
555 answer.at(1, 2) = answer.at(2, 2) = H * eta2;
556 answer.at(3, 3) = 0.; //E*1.e-6; // small stiffness, to suppress singularity
557 }
558
559 // the elastoplastic stiffness has been computed
560 // now add the effect of damage
561
562 double damage = status->giveTempDamage();
563 answer *= 1. - damage;
564
565 FloatArray sigPrinc(2);
566 FloatMatrix nPrinc(2, 2);
567 StressVector effStress(status->giveTempEffectiveStress(), _PlaneStress);
568 effStress.computePrincipalValDir(sigPrinc, nPrinc);
569 // sometimes the method is called with gprime=0., then we can save some work
570 if ( gprime != 0. ) {
571 FloatMatrixF<3,3> correction;
572 correction.at(1, 1) = sigPrinc.at(1) * eta1;
573 correction.at(1, 2) = sigPrinc.at(1) * eta2;
574 correction.at(2, 1) = sigPrinc.at(2) * eta1;
575 correction.at(2, 2) = sigPrinc.at(2) * eta2;
576 correction *= gprime; // input parameter gprime used here
577 answer -= correction;
578 }
579
580 // transform to global coordinates
581 auto T = givePlaneStressVectorTranformationMtrx(nPrinc, true);
582 return unrotate(answer, T);
583}
584
585// derivatives of final kappa with respect to final strain
586void
587RankineMat :: computeEta(FloatArray &answer, RankineMatStatus *status)
588{
589 FloatArray eta(3);
590 double dkap1 = status->giveDKappa(1);
591 double kap = status->giveTempCumulativePlasticStrain();
592 double H = evalPlasticModulus(kap);
593
594 // evaluate in principal coordinates
595
596 if ( dkap1 == 0. ) {
597 // regular case
598 double Estar = E / ( 1. - nu * nu );
599 double aux = Estar / ( H + Estar );
600 eta.at(1) = aux;
601 eta.at(2) = nu * aux;
602 eta.at(3) = 0.;
603 } else {
604 // vertex case
605 double dkap2 = status->giveDKappa(2);
606 double denom = E * dkap1 + H * ( 1. - nu ) * ( dkap1 + dkap2 );
607 eta.at(1) = E * dkap1 / denom;
608 eta.at(2) = E * dkap2 / denom;
609 eta.at(3) = 0.;
610 }
611
612 // transform to global coordinates
613
614 FloatArray sigPrinc(2);
615 FloatMatrix nPrinc(2, 2);
616 StressVector effStress(status->giveTempEffectiveStress(), _PlaneStress);
617 effStress.computePrincipalValDir(sigPrinc, nPrinc);
618
620 answer.beProductOf(T, eta);
621}
622
623int
624RankineMat :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
625{
626 RankineMatStatus *status = static_cast< RankineMatStatus * >( this->giveStatus(gp) );
627 if ( type == IST_PlasticStrainTensor ) {
628 const FloatArray ep = status->givePlasDef();
629 answer.resize(6);
630 answer.at(1) = ep.at(1);
631 answer.at(2) = ep.at(2);
632 answer.at(3) = 0.;
633 answer.at(4) = 0.;
634 answer.at(5) = 0.;
635 answer.at(6) = ep.at(3);
636 return 1;
637 } else if ( type == IST_CumPlasticStrain ) {
638 answer.resize(1);
639 answer.at(1) = status->giveCumulativePlasticStrain();
640 return 1;
641 } else if ( type == IST_DamageScalar ) {
642 answer.resize(1);
643 answer.at(1) = status->giveDamage();
644 return 1;
645 } else if ( type == IST_DamageTensor ) {
646 answer.resize(6);
647 answer.zero();
648 answer.at(1) = answer.at(2) = answer.at(3) = status->giveDamage();
649 return 1;
650
651#ifdef keep_track_of_dissipated_energy
652 } else if ( type == IST_StressWorkDensity ) {
653 answer.resize(1);
654 answer.at(1) = status->giveStressWork();
655 return 1;
656 } else if ( type == IST_DissWorkDensity ) {
657 answer.resize(1);
658 answer.at(1) = status->giveDissWork();
659 return 1;
660 } else if ( type == IST_FreeEnergyDensity ) {
661 answer.resize(1);
662 answer.at(1) = status->giveStressWork() - status->giveDissWork();
663 return 1;
664
665#endif
666 } else {
667 return StructuralMaterial :: giveIPValue(answer, gp, type, tStep);
668 }
669}
670
671
672//=============================================================================
673// RANKINE MATERIAL STATUS
674//=============================================================================
675
676RankineMatStatus :: RankineMatStatus(GaussPoint *g) :
678{
679 damage = tempDamage = 0.;
680 kappa = tempKappa = 0.;
681 dKappa1 = dKappa2 = 0.;
682 tanG = 0.;
683 //effStress.resize(3);
684 //tempEffStress.resize(3);
685#ifdef keep_track_of_dissipated_energy
687 dissWork = tempDissWork = 0.0;
688#endif
689}
690
691
692void
693RankineMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) const
694{
695 StructuralMaterialStatus :: printOutputAt(file, tStep);
696
697 fprintf(file, "status { ");
698 /*
699 * // this would not be correct, since the status is already updated and kappa is now the "final" value
700 * if ( tempKappa > kappa ) {
701 * fprintf(file, " Yielding, ");
702 * } else {
703 * fprintf(file, " Unloading, ");
704 * }
705 */
706 fprintf(file, "kappa %g, damage %g ", kappa, tempDamage);
707#ifdef keep_track_of_dissipated_energy
708 fprintf(file, ", dissW %g, freeE %g, stressW %g ", this->dissWork, ( this->stressWork ) - ( this->dissWork ), this->stressWork);
709#endif
710#if 0
711 // print the plastic strain
712 fprintf(file, " plastic_strains ");
713 for ( auto &val : plasticStrain ) {
714 fprintf( file, " %.4e", val );
715 }
716#endif
717 // print the cumulative plastic strain
718 fprintf(file, "}\n");
719}
720
721
722// initializes temporary variables based on their values at the previous equlibrium state
723void RankineMatStatus :: initTempStatus()
724{
725 StructuralMaterialStatus :: initTempStatus();
726
727 if ( plasticStrain.giveSize() == 0 ) {
728 plasticStrain.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) );
729 plasticStrain.zero();
730 }
731
735#ifdef keep_track_of_dissipated_energy
738#endif
739}
740
741
742// updates internal variables when equilibrium is reached
743void
744RankineMatStatus :: updateYourself(TimeStep *tStep)
745{
746 StructuralMaterialStatus :: updateYourself(tStep);
747
751#ifdef keep_track_of_dissipated_energy
754#endif
755}
756
757
758void
759RankineMatStatus :: saveContext(DataStream &stream, ContextMode mode)
760{
761 StructuralMaterialStatus :: saveContext(stream, mode);
762
764 if ( ( iores = plasticStrain.storeYourself(stream) ) != CIO_OK ) {
765 THROW_CIOERR(iores);
766 }
767
768 if ( !stream.write(kappa) ) {
770 }
771
772 if ( !stream.write(damage) ) {
774 }
775
776#ifdef keep_track_of_dissipated_energy
777 if ( !stream.write(stressWork) ) {
779 }
780
781 if ( !stream.write(dissWork) ) {
783 }
784#endif
785}
786
787
788void
789RankineMatStatus :: restoreContext(DataStream &stream, ContextMode mode)
790{
791 StructuralMaterialStatus :: restoreContext(stream, mode);
792
794 if ( ( iores = plasticStrain.restoreYourself(stream) ) != CIO_OK ) {
795 THROW_CIOERR(iores);
796 }
797
798 if ( !stream.read(kappa) ) {
800 }
801
802 if ( !stream.read(damage) ) {
804 }
805
806#ifdef keep_track_of_dissipated_energy
807 if ( !stream.read(stressWork) ) {
809 }
810
811 if ( !stream.read(dissWork) ) {
813 }
814#endif
815}
816
817
818#ifdef keep_track_of_dissipated_energy
819void
820RankineMatStatus :: computeWork_PlaneStress(GaussPoint *gp, double gf)
821{
822 // int n = deps.giveSize(); // would not work for gradient version
823 int n = 3;
824
825 // strain increment
826 FloatArray deps;
828
829 // increment of stress work density
830 double dSW = ( tempStressVector.dotProduct(deps, n) + stressVector.dotProduct(deps, n) ) / 2.;
832
833 // elastically stored energy density
834 FloatArray tempElasticStrainVector;
835 tempElasticStrainVector.beDifferenceOf(tempStrainVector, tempPlasticStrain, n);
836 double We = tempStressVector.dotProduct(tempElasticStrainVector, n) / 2.;
837
838 // dissipative work density
840 // to avoid extremely small negative dissipation due to round-off error
841 // (note: gf is the dissipation density at complete failure, per unit volume)
842 if ( fabs(tempDissWork) < 1.e-12 * gf ) {
843 tempDissWork = 0.;
844 }
845}
846
847void
848RankineMatStatus :: computeWork_1d(GaussPoint *gp, double gf)
849{
850 // int n = deps.giveSize(); // would not work for gradient version
851 int n = 1;
852
853
854 // strain increment
855 FloatArray deps;
857
858 // increment of stress work density
859 double dSW = ( tempStressVector.dotProduct(deps, n) + stressVector.dotProduct(deps, n) ) / 2.;
861
862 // elastically stored energy density
863 FloatArray tempElasticStrainVector;
864 tempElasticStrainVector.beDifferenceOf(tempStrainVector, tempPlasticStrain, n);
865 double We = tempStressVector.dotProduct(tempElasticStrainVector, n) / 2.;
866
867 // dissipative work density
869 // to avoid extremely small negative dissipation due to round-off error
870 // (note: gf is the dissipation density at complete failure, per unit volume)
871 if ( fabs(tempDissWork) < 1.e-12 * gf ) {
872 tempDissWork = 0.;
873 }
874}
875
876#endif
877} // end namespace oofem
#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.
void resize(Index s)
Definition floatarray.C:94
virtual void pY() const
Definition floatarray.C:802
double & at(Index i)
Definition floatarray.h:202
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Definition floatarray.C:403
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void beScaled(double s, const FloatArray &b)
Definition floatarray.C:208
void subtract(const FloatArray &src)
Definition floatarray.C:320
double at(std::size_t i, std::size_t j) const
double at(std::size_t i, std::size_t j) const
MaterialMode giveMaterialMode()
Returns corresponding material mode of receiver.
Definition gausspoint.h:190
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
double giveTempDamage() const
Definition rankinemat.h:244
double tempStressWork
Non-equilibrated density of total work done by stresses on strain increments.
Definition rankinemat.h:231
FloatArray tempPlasticStrain
Plastic strain (final).
Definition rankinemat.h:197
double giveStressWork()
Returns the density of total work of stress on strain increments.
Definition rankinemat.h:293
void setTangentShearStiffness(double value)
Definition rankinemat.h:279
FloatArray plasticStrain
Plastic strain (initial).
Definition rankinemat.h:194
double giveDamage() const
Definition rankinemat.h:243
double tempKappa
Cumulative plastic strain (final).
Definition rankinemat.h:209
double giveTempCumulativePlasticStrain() const
Definition rankinemat.h:247
const FloatArray & giveTempEffectiveStress() const
Definition rankinemat.h:262
const FloatArray & givePlasticStrain() const
Definition rankinemat.h:241
double tempDamage
Damage (final).
Definition rankinemat.h:222
const FloatArray & givePlasDef()
Definition rankinemat.h:281
double giveDKappa(int i) const
Definition rankinemat.h:249
double tempDissWork
Non-equilibrated density of dissipated work.
Definition rankinemat.h:235
void letTempEffectiveStressBe(FloatArray values)
Definition rankinemat.h:268
void setTempCumulativePlasticStrain(double value)
Definition rankinemat.h:270
double stressWork
Density of total work done by stresses on strain increments.
Definition rankinemat.h:229
void letTempPlasticStrainBe(FloatArray values)
Definition rankinemat.h:264
double kappa
Cumulative plastic strain (initial).
Definition rankinemat.h:206
double giveCumulativePlasticStrain() const
Definition rankinemat.h:246
double damage
Damage (initial).
Definition rankinemat.h:219
double giveDissWork()
Returns the density of dissipated work.
Definition rankinemat.h:299
void setDKappa(double val1, double val2)
Definition rankinemat.h:272
double tanG
Tangent shear stiffness (needed for tangent matrix).
Definition rankinemat.h:225
double dissWork
Density of dissipated work.
Definition rankinemat.h:233
virtual double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const
Definition rankinemat.C:467
double param3
coefficient required when damlaw=2
Definition rankinemat.h:131
double a
Parameter that controls damage evolution (a=0 turns damage off).
Definition rankinemat.h:113
double H0
Initial hardening modulus.
Definition rankinemat.h:98
double evalYieldStress(const double kappa) const
Definition rankinemat.C:218
double computeDamage(GaussPoint *gp, TimeStep *tStep) const
Definition rankinemat.C:454
double md
Exponent in hardening law–Used only if plasthardtype=2.
Definition rankinemat.h:119
LinearElasticMaterial * linearElasticMaterial
Reference to the basic elastic material.
Definition rankinemat.h:89
double computeDamageParamPrime(double tempKappa) const
Definition rankinemat.C:435
double param1
coefficient required when damlaw=1 or 2
Definition rankinemat.h:125
double ep
Total strain at peak stress sig0–Used only if plasthardtype=2.
Definition rankinemat.h:116
double yieldtol
Relative tolerance in yield condition.
Definition rankinemat.h:110
double delSigY
Final increment of yield stress (at infinite cumulative plastic strain).
Definition rankinemat.h:104
double evalPlasticModulus(const double kappa) const
Definition rankinemat.C:241
int damlaw
type of damage law (0=exponential, 1=exponential and damage starts after peak stress sig0)
Definition rankinemat.h:122
double param5
coefficient required when damlaw=2
Definition rankinemat.h:137
int plasthardtype
Type of plastic hardening (0=linear, 1=exponential).
Definition rankinemat.h:101
double evalYieldFunction(const FloatArray &sigPrinc, const double kappa) const
Definition rankinemat.C:211
FloatMatrixF< 3, 3 > evaluatePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep, double gprime) const
Definition rankinemat.C:502
double sig0
Initial (uniaxial) yield stress.
Definition rankinemat.h:107
double param4
coefficient required when damlaw=2
Definition rankinemat.h:134
double param2
coefficient required when damlaw=1 or 2
Definition rankinemat.h:128
double nu
Poisson's ratio.
Definition rankinemat.h:95
double E
Young's modulus.
Definition rankinemat.h:92
double computeDamageParam(double tempKappa) const
Definition rankinemat.C:416
void performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain) const
Definition rankinemat.C:263
void applyElasticStiffness(StressVector &stress, const double EModulus, const double nu) const
void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir) const override
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 FloatMatrixF< 3, 3 > givePlaneStressVectorTranformationMtrx(const FloatMatrixF< 2, 2 > &base, bool transpose=false)
StructuralMaterial(int n, Domain *d)
#define THROW_CIOERR(e)
#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
long ContextMode
Definition contextmode.h:43
FloatMatrixF< M, M > unrotate(FloatMatrixF< N, N > &a, const FloatMatrixF< M, N > &r)
Computes .
@ CIO_IOERR
General IO error.
#define _IFT_RankineMat_delsigy
Definition rankinemat.h:58
#define _IFT_RankineMat_yieldtol
Definition rankinemat.h:59
#define _IFT_RankineMat_param3
Definition rankinemat.h:65
#define _IFT_RankineMat_damlaw
Definition rankinemat.h:62
#define _IFT_RankineMat_ep
Definition rankinemat.h:61
#define _IFT_RankineMat_plasthardtype
Definition rankinemat.h:57
#define _IFT_RankineMat_h
Definition rankinemat.h:55
#define _IFT_RankineMat_sig0
Definition rankinemat.h:54
#define _IFT_RankineMat_a
Definition rankinemat.h:56
#define _IFT_RankineMat_param1
Definition rankinemat.h:63
#define _IFT_RankineMat_param5
Definition rankinemat.h:67
#define _IFT_RankineMat_param4
Definition rankinemat.h:66
#define _IFT_RankineMat_gf
Definition rankinemat.h:60
#define _IFT_RankineMat_param2
Definition rankinemat.h:64

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