OOFEM 3.0
Loading...
Searching...
No Matches
idm1.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 "idm1.h"
37#include "gausspoint.h"
38#include "floatmatrix.h"
39#include "floatarray.h"
40#include "datastream.h"
41#include "contextioerr.h"
42#include "mathfem.h"
43#include "strainvector.h"
44#include "stressvector.h"
45#include "classfactory.h"
46#include "dynamicinputrecord.h"
47#include "engngm.h"
48#include "crosssection.h"
49#include "oofemtxtinputrecord.h"
50
51namespace oofem {
53
54#ifdef IDM_USE_MMAClosestIPTransfer
55MMAClosestIPTransfer IsotropicDamageMaterial1 :: mapper;
56#endif
57
58#ifdef IDM_USE_MMAContainingElementProjection
59MMAContainingElementProjection IsotropicDamageMaterial1 :: mapper;
60#endif
61
62#ifdef IDM_USE_MMAShapeFunctProjection
63MMAShapeFunctProjection IsotropicDamageMaterial1 :: mapper;
64#endif
65
66#ifdef IDM_USE_MMALeastSquareProjection
67MMALeastSquareProjection IsotropicDamageMaterial1 :: mapper;
68#endif
69
70IsotropicDamageMaterial1 :: IsotropicDamageMaterial1(int n, Domain *d) : IsotropicDamageMaterial(n, d),
72{
73 // deleted by parent, where linearElasticMaterial instance declared
75}
76
77
78IsotropicDamageMaterial1 :: ~IsotropicDamageMaterial1()
79{
80 if ( sourceElemSet ) {
81 delete sourceElemSet;
82 }
83}
84
85void
86IsotropicDamageMaterial1 :: initializeFrom(InputRecord &ir)
87{
88 int equivStrainTypeRecord;
89 IsotropicDamageMaterial :: initializeFrom(ir);
90 RandomMaterialExtensionInterface :: initializeFrom(ir);
91 linearElasticMaterial->initializeFrom(ir);
92
93 checkSnapBack = 1; //check by default
95
96 // specify the type of formula for equivalent strain
97 equivStrainTypeRecord = 0; // default
99 if ( equivStrainTypeRecord == 0 ) {
101 } else if ( equivStrainTypeRecord == 1 ) {
103 } else if ( equivStrainTypeRecord == 2 ) {
105 } else if ( equivStrainTypeRecord == 3 ) {
108 } else if ( equivStrainTypeRecord == 4 ) {
110 } else if ( equivStrainTypeRecord == 5 ) {
112 } else if ( equivStrainTypeRecord == 6 ) {
114 } else if ( equivStrainTypeRecord == 7 ) {
117 } else {
118 throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_equivstraintype, "Unknown equivStrainType");
119 }
120
121 // specify the type of formula for damage evolution law
123 if ( ( damageLaw != 6 ) && ( damageLaw != 7 ) ) {
125 }
126
127 //applies only in this class
128 switch ( damageLaw ) {
129 case 0: // exponential softening - default
136 } else {
137 this->softType = ST_Exponential;
139 }
140
141 break;
142 case 1: // linear softening law
149 } else {
150 this->softType = ST_Linear;
152 }
153
154 break;
155 case 2: // bilinear softening
156 gf = 0.;
157 gft = 0.;
158 ek = 0.;
159 wf = 0.;
160 wk = 0.;
161 sk = 0.;
165 // Gft is for the bilinear law, and corresponds to the total energy required to fail the specimen
167
169 // ek is for the bilinear law, and corresponds to the strain at the knee point
171 } else {
172 double dumWf1, E;
173
174 // wk is for the bilinear law, and corresponds to the crack opening at the knee point
177
178 dumWf1 = 2. * gf / ( e0 * E );
179 if ( dumWf1 < wk ) {
180 throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_wk, "Bilinear softening: wk is larger then gf allows");
181 }
182 sk = ( e0 * E ) * ( 1 - wk / dumWf1 );
183 wf = 2. * ( gft - e0 * E * wk / 2.0 ) / sk;
184
185 // for computational purposes
186 gf = 0.;
187 gft = 0.;
188 }
190 double E;
191
194 // wk is for the bilinear law, and corresponds to the crack opening at the knee point
196 // sk is for the bilinear law, and corresponds to the stress at the knee point
199
200 if ( wk < 0.0 || wk > wf ) {
201 throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_wk, "Bilinear softening: wk must be in interval <0;wf>");
202 }
203 if ( sk < 0.0 || sk > e0 * E ) {
204 throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_sk, "Bilinear softening: sk must be in interval <0;ft>");
205 }
207 double dummy, E;
210 // wkwf is for the bilinear law, and corresponds to the ratio of crack opening at the knee point and max crack opening
212 if ( dummy < 0.0 || dummy > 1.0 ) {
213 throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_wkwf, "Bilinear softening: wk/wf ratio (wkwf) must be in interval <0;1>");
214 } else {
215 wk = dummy * wf;
216 }
217 // sk is for the bilinear law, and corresponds to the ratio of stress at the knee point an tensile strength
219 if ( dummy < 0.0 || dummy > 1.0 ) {
220 throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_skft, "Bilinear softening: sk/ft ratio (skft) must be in interval <0;1>");
221 } else {
223 sk = dummy * e0 * E;
224 }
225 } else {
226 throw ValueInputException(ir, "none", "Bilinear softening for ef not implemented");
227 }
228
229 // check if the model is reduced to linear softening
230 if ( gf == 0.0 && gft != 0 ) {
231 OOFEM_WARNING("Bilinear softening: parameters defined as for Linear_Cohesive_Crack");
233 gf = gft;
234 } else if ( gft < gf ) {
235 throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_gft, "Bilinear softening: gft < gf");
236 } else if ( wk == 0.0 && wf != 0 ) {
237 OOFEM_WARNING("Bilinear softening: parameters defined as for Linear_Cohesive_Crack");
239 } else if ( wf < wk ) {
240 throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_wf, "Bilinear softening: wf < wk");
241 } else if ( gf == 0 && sk == 0.0 ) {
242 OOFEM_WARNING("Bilinear softening: parameters defined as for Linear_Cohesive_Crack");
244 wf = wk;
245 }
246
247 break;
248 case 3:
250 c1 = 3.;
252 c2 = 6.93;
258 double E;
260 double aux = c1 * c1 * c1 / ( c2 * c2 * c2 * c2 );
261 aux *= ( 6. - ( c2 * c2 * c2 + 3. * c2 * c2 + 6. * c2 + 6. ) * exp(-c2) );
262 aux += ( 1. - exp(-c2) ) / c2;
263 aux -= 0.5 * ( 1. + c1 * c1 * c1 ) * exp(-c2);
264 wf = gf / ( aux * E * e0 );
265 } else {
266 throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_wf, "wf or gf must be specified for Hordijk softening law");
267 }
268 break;
269 case 4:
270 this->softType = ST_Mazars;
273 break;
274 case 5:
275 this->softType = ST_Smooth;
276 md = 1.;
278 break;
279 case 6:
281 break;
282 case 7:
284 double E; // auxiliary input variables
288 this->md = 1. / log(E * this->ep / this->ft);
289 this->e0 = ep * pow(md, 1. / md);
291 this->s1 = e1 * exp( -pow(e1 / e0, md) );
292 this->ef = -e1 / ( 1. - md * pow(e1 / e0, md) );
295 break;
296 case 8: // power-exponential softening
300 break;
301
302 case 9: // double exponential softening
307 break;
308 case 10: // modified power-exponential softening
312 break;
313 case 11: // trilinear softening
320 break;
321
322 default:
324 }
325
327 int ecsm = 0;
329 switch ( ecsm ) {
331 break;
333 break;
334 case 3: ecsMethod = ECSM_Oliver1;
335 break;
337 break;
338 default: ecsMethod = ECSM_Projection;
339 }
340 }
341
342 if ( permStrain == 4 ) {
344 //IR_GIVE_FIELD(ir, ps_H, _IFT_IsotropicDamageMaterial1_h);
345 }
346
347 this->mapper.initializeFrom(ir);
348}
349
350
351void
352IsotropicDamageMaterial1 :: giveInputRecord(DynamicInputRecord &input)
353{
354 // Done first so that record name is overwritten afterwards by femcomponent:
355 this->linearElasticMaterial->giveInputRecord(input);
356 this->mapper.giveInputRecord(input);
357 IsotropicDamageMaterial :: giveInputRecord(input);
358 RandomMaterialExtensionInterface :: giveInputRecord(input);
359
362 if ( ( damageLaw != 6 ) && ( damageLaw != 7 ) ) {
364 }
365 switch ( damageLaw ) {
366 case 0: // exponential softening - default
370 } else if ( this->softType == ST_Exponential ) {
372 }
373 break;
374 case 1:
375 if ( this->softType == ST_Linear_Cohesive_Crack ) {
376 if ( this->wf != 0.0 ) {
378 } else if ( this->gf != 0.0 ) {
380 } else {
382 }
383 }
384 break;
385 case 2:
386 if ( this->softType == ST_BiLinear_Cohesive_Crack ) {
389 if ( this->ek != 0.0 ) {
391 } else {
393 }
394 } else if ( this->wk != 0.0 ) {
398 }
399 break;
400 case 3:
402 break;
403 case 4:
406 break;
407 case 5:
409 break;
410 case 7:
416 break;
417 case 8:
420 break;
421 case 11: // Trilinear softening
427 break;
428 }
431 }
432}
433
434
435double
436IsotropicDamageMaterial1 :: computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const
437{
438 auto lmat = this->linearElasticMaterial;
439
440 if ( strain.isEmpty() ) {
441 return 0.;
442 }
443
444 FloatArray fullStrain;
445 StructuralMaterial :: giveFullSymVectorForm( fullStrain, strain, gp->giveMaterialMode() );
446 // if plane stress mode -> compute strain in z-direction from condition of zero stress in corresponding direction
447 if ( gp->giveMaterialMode() == _PlaneStress ) {
448 double nu = lmat->give(NYxz, gp);
449 fullStrain.at(3) = -nu * ( fullStrain.at(1) + fullStrain.at(2) ) / ( 1. - nu );
450 } else if ( gp->giveMaterialMode() == _1dMat ) {
451 double nu = lmat->give(NYxz, gp);
452 fullStrain.at(2) = -nu *fullStrain.at(1);
453 fullStrain.at(3) = -nu *fullStrain.at(1);
454 }
455
456 if ( this->equivStrainType == EST_Mazars ) {
457 double posNorm = 0.0;
458 FloatArray principalStrains;
459
460 this->computePrincipalValues(principalStrains, fullStrain, principal_strain);
461
462 for ( int i = 1; i <= 3; i++ ) {
463 if ( principalStrains.at(i) > 0.0 ) {
464 posNorm += principalStrains.at(i) * principalStrains.at(i);
465 }
466 }
467
468 return sqrt(posNorm);
469 } else if ( ( this->equivStrainType == EST_Rankine_Smooth ) || ( this->equivStrainType == EST_Rankine_Standard ) ) {
470 // EST_Rankine equiv strain measure
471 double sum = 0.;
472 FloatArray stress, fullStress, principalStress;
473 FloatMatrix de;
474
475 lmat->giveStiffnessMatrix(de, SecantStiffness, gp, tStep);
476 stress.beProductOf(de, strain);
477 StructuralMaterial :: giveFullSymVectorForm( fullStress, stress, gp->giveMaterialMode() );
478 this->computePrincipalValues(principalStress, fullStress, principal_stress);
479 for ( int i = 1; i <= 3; i++ ) {
480 if ( principalStress.at(i) > 0.0 ) {
481 if ( this->equivStrainType == EST_Rankine_Smooth ) {
482 sum += principalStress.at(i) * principalStress.at(i);
483 } else if ( sum < principalStress.at(i) ) {
484 sum = principalStress.at(i);
485 }
486 } else if ( sum < principalStress.at(i) ) {
487 sum = principalStress.at(i);
488 }
489 }
490
491 if ( this->equivStrainType == EST_Rankine_Smooth ) {
492 sum = sqrt(sum);
493 }
494
495 return sum / lmat->give('E', gp);
497 // equivalent strain expressions based on elastic energy
498 FloatMatrix de;
499 FloatArray stress;
500 double sum;
501
502 lmat->giveStiffnessMatrix(de, SecantStiffness, gp, tStep);
503 if ( this->equivStrainType == EST_ElasticEnergy ) {
504 // standard elastic energy
505 stress.beProductOf(de, strain);
506 sum = strain.dotProduct(stress);
507 } else if ( this->equivStrainType == EST_ElasticEnergyPositiveStress ) {
508 // elastic energy corresponding to positive part of stress
509 FloatArray fullStress, principalStress;
510 StructuralMaterial :: giveFullSymVectorForm( fullStress, stress, gp->giveMaterialMode() );
511 this->computePrincipalValues(principalStress, fullStress, principal_stress);
512 // TO BE FINISHED
513 sum = 0.;
514 OOFEM_ERROR("Elastic energy corresponding to positive part of stress not finished");
515 } else {
516 // elastic energy corresponding to positive part of strain
517 // TO BE DONE
518 sum = 0.;
519 OOFEM_ERROR("Elastic energy corresponding to positive part of strain not finished");
520 }
521
522 return sqrt( sum / lmat->give('E', gp) );
523 } else if ( this->equivStrainType == EST_Mises ) {
524 double nu = lmat->give(NYxz, NULL);
525 FloatArray principalStrains;
526
527 this->computePrincipalValues(principalStrains, fullStrain, principal_strain);
528 double I1e, J2e;
529 this->computeStrainInvariants(principalStrains, I1e, J2e);
530 double a, b, c;
531 a = ( k - 1 ) * I1e / ( 2 * k * ( 1 - 2 * nu ) );
532 b = ( k - 1 ) * ( k - 1 ) * I1e * I1e / ( ( 1 - 2 * nu ) * ( 1 - 2 * nu ) );
533 c = 12 * k * J2e / ( ( 1 + nu ) * ( 1 + nu ) );
534 return a + 1 / ( 2 * k ) * sqrt(b + c);
535 } else if ( this->equivStrainType == EST_Griffith ) {
536 double kappa1 = 0.0, kappa2 = 0.0;
537 FloatArray stress, fullStress, principalStress;
538 FloatMatrix de;
539 lmat->giveStiffnessMatrix(de, SecantStiffness, gp, tStep);
540 stress.beProductOf(de, strain);
541 StructuralMaterial :: giveFullSymVectorForm( fullStress, stress, gp->giveMaterialMode() );
542 this->computePrincipalValues(principalStress, fullStress, principal_stress);
543 double sum = 0., maxStress = 0.;
544 //Compute equivalent strain for Rankine's criterion
545 for ( int i = 1; i <= 3; i++ ) {
546 if ( principalStress.at(i) > 0.0 && sum < principalStress.at(i) ) {
547 sum = principalStress.at(i);
548 }
549 }
550 kappa1 = sum / lmat->give('E', gp);
551 //Compute equivalent strain for Griffith's criterion
552 // Check zero division first
553 maxStress = max( fabs( principalStress.at(1) ), fabs( principalStress.at(3) ) );
554 if ( maxStress == 0. || fabs( principalStress.at(3) ) < 1.e-6 * maxStress || fabs( principalStress.at(1) + principalStress.at(3) ) < 1.e-6 * maxStress ) {
555 //Skip evaluation
556 } else if ( principalStress.at(1) / principalStress.at(3) >= -0.33333 ) {
557 kappa2 = -( principalStress.at(1) - principalStress.at(3) ) * ( principalStress.at(1) - principalStress.at(3) ) / this->griff_n / ( principalStress.at(1) + principalStress.at(3) ) / lmat->give('E', gp);
558 }
559 return max(max(kappa1, 0.0), kappa2);
560 } else {
561 OOFEM_ERROR("unknown EquivStrainType");
562 return 0.;
563 }
564}
565
566//Computes derivative of the equivalent strain with regards to strain, used in tangent formulation
567void
568IsotropicDamageMaterial1 :: computeEta(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const
569{
571
572 if ( strain.isEmpty() ) {
573 answer.zero();
574 return;
575 }
576
577 if ( this->equivStrainType == EST_Mazars ) {
578 int dim = 0;
579 double posNorm = 0.0;
580 double nu = lmat->give(NYxz, gp);
581 FloatArray principalStrains;
583
584 if ( strain.giveSize() == 6 || gp->giveMaterialMode() == _3dMat ) {
585 dim = 3;
586 this->computePrincipalValDir(principalStrains, N, strain, principal_strain);
587 } else if ( gp->giveMaterialMode() == _1dMat ) {
588 dim = 1;
589 StrainVector fullStrain(strain, _1dMat);
590 fullStrain.computePrincipalValDir(principalStrains, N);
591 principalStrains.resizeWithValues(3);
592 principalStrains.at(2) = -nu *principalStrains.at(1);
593 principalStrains.at(3) = -nu *principalStrains.at(1);
594 } else if ( gp->giveMaterialMode() == _PlaneStress ) {
595 dim = 2;
596 StrainVector fullStrain(strain, _PlaneStress);
597 fullStrain.computePrincipalValDir(principalStrains, N);
598 principalStrains.resizeWithValues(3);
599 principalStrains.at(3) = -nu * ( principalStrains.at(1) + principalStrains.at(2) ) / ( 1. - nu );
600 } else if ( gp->giveMaterialMode() == _PlaneStrain ) {
601 dim = 3;
602 StrainVector fullStrain(strain, _PlaneStrain);
603 fullStrain.computePrincipalValDir(principalStrains, N);
604 } else {
605 dim = 0;
606 OOFEM_ERROR("Unknown material mode.");
607 }
608 FloatArray n(dim);
609 FloatMatrix Eta(dim, dim);
610 Eta.zero();
611
612 for ( int i = 1; i <= 3; i++ ) {
613 if ( i <= dim ) {
614 if ( principalStrains.at(i) > 0.0 ) {
615 n.beColumnOf(N, i);
616 Eta.plusDyadSymmUpper( n, principalStrains.at(i) );
617 }
618 }
619
620 if ( principalStrains.at(i) > 0.0 ) {
621 posNorm += principalStrains.at(i) * principalStrains.at(i);
622 }
623 }
624
625 Eta.symmetrized();
626
627 double kappa = sqrt(posNorm);
628
629 int numberOfEl = ( dim * ( dim - 1 ) / 2 + dim );
630 answer.resize(numberOfEl);
631
632 if ( kappa != 0 ) {
633 Eta.times(1. / kappa);
634 } else {
635 answer.zero();
636 return;
637 }
638
639 if ( strain.giveSize() == 6 || gp->giveMaterialMode() == _3dMat ) {
640 answer.at(1) = Eta.at(1, 1);
641 answer.at(2) = Eta.at(2, 2);
642 answer.at(3) = Eta.at(3, 3);
643 answer.at(4) = Eta.at(2, 3);
644 answer.at(5) = Eta.at(1, 3);
645 answer.at(6) = Eta.at(1, 2);
646 } else if ( gp->giveMaterialMode() == _1dMat ) {
647 answer.at(1) = Eta.at(1, 1);
648 } else if ( gp->giveMaterialMode() == _PlaneStress ) {
649 answer.at(1) = Eta.at(1, 1);
650 answer.at(2) = Eta.at(2, 2);
651 answer.at(3) = Eta.at(1, 2);
652 } else if ( gp->giveMaterialMode() == _PlaneStrain ) {
653 answer.resize(4);
654 answer.at(1) = Eta.at(1, 1);
655 answer.at(2) = Eta.at(2, 2);
656 answer.at(3) = Eta.at(3, 3);
657 answer.at(4) = Eta.at(1, 2);
658 }
659 } else if ( ( this->equivStrainType == EST_Rankine_Smooth ) || ( this->equivStrainType == EST_Rankine_Standard ) ) {
660 int index = 0, dim = 0;
661 double sum = 0.;
662 FloatArray stress, principalStress, eta;
663 FloatMatrix de, N, Eta;
664
665 lmat->giveStiffnessMatrix(de, SecantStiffness, gp, tStep);
666 stress.beProductOf(de, strain);
667
668 if ( strain.giveSize() == 6 || gp->giveMaterialMode() == _3dMat ) {
669 this->computePrincipalValDir(principalStress, N, strain, principal_stress);
670 dim = 3;
671 } else if ( gp->giveMaterialMode() == _1dMat ) {
672 StressVector fullStress(stress, _1dMat);
673 fullStress.computePrincipalValDir(principalStress, N);
674 principalStress.resizeWithValues(3);
675 dim = 1;
676 } else if ( gp->giveMaterialMode() == _PlaneStress ) {
677 StressVector fullStress(stress, _PlaneStress);
678 fullStress.computePrincipalValDir(principalStress, N);
679 principalStress.resizeWithValues(3);
680 dim = 2;
681 } else if ( gp->giveMaterialMode() == _PlaneStrain ) {
682 StressVector fullStress(stress, _PlaneStrain);
683 fullStress.computePrincipalValDir(principalStress, N);
684 dim = 3;
685 } else {
686 dim = 0;
687 OOFEM_ERROR("Unknown material mode.");
688 }
689
690 FloatArray n(dim);
691 n.zero();
692 Eta.resize(dim, dim);
693 Eta.zero();
694 for ( int i = 1; i <= 3; i++ ) {
695 if ( principalStress.at(i) > 0.0 ) {
696 if ( this->equivStrainType == EST_Rankine_Smooth ) {
697 sum += principalStress.at(i) * principalStress.at(i);
698 if ( i <= dim ) {
699 for ( int j = 1; j <= dim; j++ ) {
700 n.at(j) = N.at(j, i);
701 }
702 }
703
704 Eta.plusDyadSymmUpper( n, principalStress.at(i) );
705 } else if ( sum < principalStress.at(i) ) {
706 sum = principalStress.at(i);
707 index = i;
708 }
709 } else if ( sum < principalStress.at(i) ) {
710 sum = principalStress.at(i);
711 index = i;
712 }
713 }
714
715 Eta.symmetrized();
716
717 int numberOfEl = ( dim * ( dim - 1 ) / 2 + dim );
718 eta.resize(numberOfEl);
719
720 if ( this->equivStrainType == EST_Rankine_Smooth ) {
721 sum = sqrt(sum);
722 double kappa = sum / lmat->give('E', gp);
723
724 if ( kappa != 0 ) {
725 Eta.times(1. / kappa);
726 } else {
727 answer.zero();
728 return;
729 }
730
731 Eta.times( 1. / kappa / lmat->give('E', gp) / lmat->give('E', gp) );
732 } else if ( this->equivStrainType == EST_Rankine_Standard ) {
733 for ( int i = 1; i <= dim; i++ ) {
734 n.at(i) = N.at(i, index);
735 }
736
737 Eta.beDyadicProductOf(n, n);
738 Eta.times( 1. / lmat->give('E', gp) );
739 }
740
741 if ( strain.giveSize() == 6 || gp->giveMaterialMode() == _3dMat ) {
742 eta.at(1) = Eta.at(1, 1);
743 eta.at(2) = Eta.at(2, 2);
744 eta.at(3) = Eta.at(3, 3);
745 eta.at(4) = Eta.at(2, 3);
746 eta.at(5) = Eta.at(1, 3);
747 eta.at(6) = Eta.at(1, 2);
748 } else if ( gp->giveMaterialMode() == _1dMat ) {
749 eta.at(1) = Eta.at(1, 1);
750 } else if ( gp->giveMaterialMode() == _PlaneStress ) {
751 eta.at(1) = Eta.at(1, 1);
752 eta.at(2) = Eta.at(2, 2);
753 eta.at(3) = Eta.at(1, 2);
754 } else if ( gp->giveMaterialMode() == _PlaneStrain ) {
755 eta.resize(4);
756 eta.at(1) = Eta.at(1, 1);
757 eta.at(2) = Eta.at(2, 2);
758 eta.at(3) = Eta.at(3, 3);
759 eta.at(4) = 2. * Eta.at(1, 2);
760 }
761
762 answer.beProductOf(de, eta);
763 } else if ( this->equivStrainType == EST_ElasticEnergy ) {
764 FloatMatrix de;
765 FloatArray stress;
766 double sum;
767
768 lmat->giveStiffnessMatrix(de, SecantStiffness, gp, tStep);
769 // standard elastic energy
770 stress.beProductOf(de, strain);
771 sum = strain.dotProduct(stress);
772
773 double kappa = sqrt( sum / lmat->give('E', gp) );
774 answer = stress;
775 if ( kappa != 0 ) {
776 answer.times(1. / lmat->give('E', gp) / kappa);
777 } else {
778 answer.times(0.);
779 }
780 } else {
781 OOFEM_ERROR("unknown EquivStrainType");
782 }
783}
784
785void
786IsotropicDamageMaterial1 :: computeStrainInvariants(const FloatArray &strainVector, double &I1e, double &J2e)
787{
788 I1e = strainVector.at(1) + strainVector.at(2) + strainVector.at(3);
789 double s1 = strainVector.at(1) * strainVector.at(1);
790 double s2 = strainVector.at(2) * strainVector.at(2);
791 double s3 = strainVector.at(3) * strainVector.at(3);
792 J2e = 1. / 2. * ( s1 + s2 + s3 ) - 1. / 6. * ( I1e * I1e );
793}
794
795double
796IsotropicDamageMaterial1 :: computeDamageParam(double kappa, const FloatArray &strain, GaussPoint *gp) const
797{
798 if ( this->softType == ST_Disable_Damage ) { //dummy material with no damage
799 return 0.;
800 } else if ( isCrackBandApproachUsed() ) { // adjustment of softening law according to the element size, given crack opening or fracture energy
801 return computeDamageParamForCohesiveCrack(kappa, gp);
802 } else { // no adjustment according to element size, given fracturing strain
803 return damageFunction(kappa, gp);
804 }
805}
806
807double
808IsotropicDamageMaterial1 :: computeDamageParamForCohesiveCrack(double kappa, GaussPoint *gp) const
809{
810 const double e0 = this->give(e0_ID, gp); // e0 is the strain at the peak stress
811 const double E = this->linearElasticMaterial->give('E', gp);
812 const double gf = this->give(gf_ID, gp);
813 double wf = this->give(wf_ID, gp); // wf is the crack opening
814 double omega = 0.0;
815
816 if ( kappa > e0 ) {
817 if ( this->gf != 0. ) { //cohesive crack model
818 if ( softType == ST_Exponential_Cohesive_Crack ) { // exponential softening
819 wf = this->gf / E / e0; // wf is the crack opening
820 } else if ( softType == ST_Linear_Cohesive_Crack || softType == ST_BiLinear_Cohesive_Crack ) { // (bi)linear softening law
821 wf = 2. * gf / E / e0; // wf is the crack opening
822 } else {
823 OOFEM_ERROR("Gf unsupported for softening type softType = %d", softType);
824 }
825 } else if ( softType == ST_BiLinear_Cohesive_Crack ) {
826 wf = this->wk / ( e0 * E - this->sk ) * ( e0 * E );
827 } else if ( softType == ST_Trilinear_Cohesive_Crack ) {
828 wf = this->w_f;
829 }
830
831
832 auto status = static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) );
833 double Le = status->giveLe();
834 double ef = wf / Le; //ef is the fracturing strain /// FIXME CHANGES BEHAVIOR!
835 if ( ef < e0 ) { //check that no snapback occurs
836 double minGf = 0.;
837 OOFEM_WARNING("ef %e < e0 %e, this leads to material snapback in element %d, characteristic length %f", ef, e0, gp->giveElement()->giveGlobalNumber(), Le);
838 if ( gf != 0. ) { //cohesive crack
839 if ( softType == ST_Exponential_Cohesive_Crack ) { //exponential softening
840 minGf = E * e0 * e0 * Le;
841 } else if ( softType == ST_Linear_Cohesive_Crack || softType == ST_BiLinear_Cohesive_Crack ) { //(bi)linear softening law
842 minGf = E * e0 * e0 * Le / 2.;
843 } else {
844 OOFEM_WARNING("Gf unsupported for softening type softType = %d", softType);
845 }
846
847 if ( checkSnapBack ) {
848 OOFEM_ERROR("Material number %d, decrease e0, or increase Gf from %f to Gf=%f", this->giveNumber(), gf, minGf);
849 }
850 }
851
852 if ( checkSnapBack ) { //given fracturing strain
853 OOFEM_ERROR("Material number %d, increase ef %f to minimum e0 %f", this->giveNumber(), ef, e0);
854 }
855 }
856
857 if ( this->softType == ST_Linear_Cohesive_Crack ) {
858 if ( kappa < ef ) {
859 omega = ( ef / kappa ) * ( kappa - e0 ) / ( ef - e0 );
860 } else {
861 omega = 1.0; //maximum omega (maxOmega) is adjusted just for stiffness matrix in isodamagemodel.C
862 }
863 } else if ( this->softType == ST_BiLinear_Cohesive_Crack ) {
864 double gft = this->give(gft_ID, gp);
865 double ef, sigmak, epsf, ek;
866 if ( gft > 0.0 ) {
867 ek = this->give(ek_ID, gp);
868 ef = 2 * gf / E / e0 / Le; //the first part corresponds to linear softening
869 sigmak = E * e0 * ( ef - ek ) / ( ef - e0 );
870 epsf = 2 * ( gft - gf ) / sigmak / Le + ef;
871
872 if ( gft < gf ) {
873 OOFEM_ERROR("The total fracture energy gft %f must be greater than the initial fracture energy gf %f", gft, gf);
874 }
875 } else {
876 ek = this->wk / Le + ( this->sk ) / E;
877 ef = ( this->wk / ( e0 * E - this->sk ) * ( e0 * E ) ) / Le;
878 sigmak = this->sk;
879 epsf = this->wf / Le;
880 }
881 if ( ( ek > ef ) || ( ek < e0 ) ) {
882 OOFEM_WARNING("ek %f is not between e0 %f and ef %f", ek, e0, ef);
883 }
884
885 if ( kappa <= ek ) {
886 omega = 1.0 - ( ( e0 / kappa ) * ( ek - kappa ) / ( ek - e0 ) + ( ( sigmak / ( E * kappa ) ) * ( kappa - e0 ) / ( ek - e0 ) ) );
887 } else if ( kappa > ek && kappa <= epsf ) {
888 omega = 1.0 - ( ( sigmak / ( E * kappa ) ) * ( epsf - kappa ) / ( epsf - ek ) );
889 } else if ( kappa <= e0 ) {
890 omega = 0.0;
891 } else {
892 omega = maxOmega;
893 }
894 } else if ( this->softType == ST_Exponential_Cohesive_Crack ) {
895 // exponential cohesive crack - iteration needed
896 double R, Lhs, help;
897 int nite = 0;
898 // iteration to achieve objectivity
899 // we are looking for a state in which the elastic stress is equal to
900 // the stress from crack-opening relation
901 // ef has now the meaning of strain
902 do {
903 nite++;
904 help = omega * kappa / ef;
905 R = ( 1. - omega ) * kappa - e0 *exp(-help); //residuum
906 Lhs = kappa - e0 *exp(-help) * kappa / ef; //- dR / (d omega)
907 omega += R / Lhs;
908 if ( nite > 40 ) {
909 OOFEM_ERROR("algorithm not converging");
910 }
911 } while ( fabs(R) >= e0 * IDM1_ITERATION_LIMIT );
912 } else if ( this->softType == ST_Trilinear_Cohesive_Crack ) {
913 double eps_k = this->w_k/Le + this->f_k/E;
914 double eps_r = this->w_r/Le + this->f_r/E;
915 double eps_f = this->w_f/Le ;
916 double f_t = E*e0;
917 if ( kappa > e0 && kappa <= eps_k ) {
918 double slope=((f_k - f_t)/w_k);
919 omega = E/(E+slope*Le) - (f_t)/(kappa*(E+slope*Le));
920 } else if ( kappa > eps_k && kappa <= eps_r ) {
921 double slope=((f_r - f_k)/(w_r-w_k));
922 omega = E/(E+slope*Le) +(1.0/kappa)*(w_k*slope-f_k)/(Le*slope+E);
923 } else if ( kappa > eps_r && kappa <= eps_f ) {
924 double slope=(- f_r/(w_f-w_r));
925 omega = E/(E+slope*Le) +(1.0/kappa)*(w_r*slope-f_r)/(Le*slope+E);
926 } else {
927 omega = 1.0;
928 }
929 } else {
930 OOFEM_ERROR("Unknown softening type for cohesive crack model.");
931 }
932
933 if ( omega > 1.0 ) {
934 OOFEM_WARNING("damage parameter is %f, which is greater than 1, snap-back problems", omega);
935 omega = maxOmega;
936 if ( checkSnapBack ) {
937 OOFEM_ERROR("x");
938 }
939 }
940
941 if ( omega < 0.0 ) {
942 OOFEM_WARNING("damage parameter is %f, which is smaller than 0, snap-back problems", omega);
943 omega = 0.0;
944 if ( checkSnapBack ) {
945 OOFEM_ERROR("x");
946 }
947 }
948 }
949 return omega;
950}
951
952
953double
954IsotropicDamageMaterial1 :: damageFunction(double kappa, GaussPoint *gp) const
955{
956 const double e0 = this->give(e0_ID, gp);
957 double ef = 0.;
959 ef = this->give(ef_ID, gp); // ef is the fracturing strain
960 }
961
962 switch ( softType ) {
963 case ST_Linear:
964 if ( kappa <= e0 ) {
965 return 0.0;
966 } else if ( kappa < ef ) {
967 return ( ef / kappa ) * ( kappa - e0 ) / ( ef - e0 );
968 } else {
969 return 1.0; //maximum omega (maxOmega) is adjusted just for stiffness matrix in isodamagemodel.C
970 }
971
972 case ST_Exponential:
973 if ( kappa > e0 ) {
974 if ( permStrain == 4 ) {
975 return ( kappa - e0 * exp( -( kappa - e0 ) / ( ef - e0 ) ) ) / ( kappa + ps_alpha );
976 } else {
977 return 1.0 - ( e0 / kappa ) * exp( -( kappa - e0 ) / ( ef - e0 ) );
978 }
979 }
980 return 0.0;
981
983 if ( kappa > e0 ) {
984 return 1.0 - ( 1. - c2 ) * ( e0 / kappa ) * exp( -( kappa - e0 ) / ( ef - e0 ) ) - c2 * ( e0 / kappa ) * exp( -( kappa - e0 ) / ( e2 - e0 ) );
985 } else {
986 return 0.0;
987 }
988
990 if ( kappa > e0 ) {
991 return 1.0 - ( e0 / kappa ) * exp( -pow( ( kappa - e0 ) / ( ef - e0 ), md ) );
992 } else {
993 return 0.0;
994 }
995
997 if ( kappa > e0 ) {
998 return 1.0 - ( e0 / kappa ) * exp( -( pow(kappa, md) - pow(e0, md) ) / ( pow(ef, md) - pow(e0, md) ) );
999 } else {
1000 return 0.0;
1001 }
1002
1003 case ST_Mazars:
1004 return 1.0 - ( 1.0 - At ) * e0 / kappa - At *exp( -Bt * ( kappa - e0 ) );
1005
1006 case ST_Smooth:
1007 return 1.0 - exp( -pow(kappa / e0, md) );
1008
1009 case ST_SmoothExtended:
1010 // a special damage law used in Grassl and Jirasek (2010)
1011 if ( kappa <= e1 ) {
1012 return 1.0 - exp( -pow(kappa / e0, md) );
1013 } else {
1014 return 1.0 - s1 *exp( -( kappa - e1 ) / ( ef * ( 1. + pow( ( kappa - e1 ) / e2, nd ) ) ) ) / kappa;
1015 }
1016 default:
1017 OOFEM_WARNING(":damageFunction ... undefined softening type %d\n", softType);
1018 }
1019
1020 return 0.; // to make the compiler happy
1021}
1022
1023double
1024IsotropicDamageMaterial1 :: damageFunctionPrime(double kappa, GaussPoint *gp) const
1025{
1026 const double e0 = this->give(e0_ID, gp);
1027 double ef = 0.;
1028 const double E = this->linearElasticMaterial->give('E', gp);
1029 IsotropicDamageMaterial1Status *status = static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) );
1030 const double Le = status->giveLe();
1031
1033 ef = this->give(ef_ID, gp); // ef is the fracturing strain
1034 }
1035
1036 switch ( softType ) {
1037 case ST_Linear:
1038 {
1039 if ( kappa <= e0 ) {
1040 return 0.0;
1041 } else if ( kappa < ef ) {
1042 return ( ef * e0 ) / ( ef - e0 ) / ( kappa * kappa );
1043 } else {
1044 return 0.0; //maximum omega (maxOmega) is adjusted just for stiffness matrix in isodamagemodel.C
1045 }
1046 } break;
1047 case ST_Exponential:
1048 {
1049 if ( kappa > e0 ) {
1050 // return ( e0 / ( kappa * kappa ) ) * exp( -( kappa - e0 ) / ( ef - e0 ) + e0 / ( kappa * ( ef - e0 ) ) ) * exp( -( kappa - e0 ) / ( ef - e0 ) );
1051 return ( e0 / ( ef - e0 ) / kappa + e0 / ( kappa * kappa ) ) * exp( -( kappa - e0 ) / ( ef - e0 ) );
1052 } else {
1053 return 0.0;
1054 }
1055 } break;
1056 case ST_Mazars:
1057 {
1058 return ( 1.0 - At ) * e0 / kappa / kappa - At *Bt *exp( -Bt * ( kappa - e0 ) );
1059 } break;
1060 case ST_Smooth:
1061 {
1062 return md / e0 *pow(kappa, md - 1.) * exp( -pow(kappa / e0, md) );
1063 } break;
1064 case ST_SmoothExtended:
1065 {
1066 // a special damage law used in Grassl and Jirasek (2010)
1067 if ( kappa <= 0 ) {
1068 return 0;
1069 } else if ( kappa <= e1 ) {
1070 return exp( -pow(kappa / e0, md) ) * md / pow(e0, md) * pow(kappa, md - 1.);
1071 } else {
1072 double a = ( ( ef * ( 1. + pow( ( kappa - e1 ) / e2, nd ) ) ) - ef * nd * pow( ( kappa - e1 ) / e2, nd ) ) / ( ef * ( 1. + pow( ( kappa - e1 ) / e2, nd ) ) ) / ( ef * ( 1. + pow( ( kappa - e1 ) / e2, nd ) ) );
1073 double answer = s1 * exp( -( kappa - e1 ) / ( ef * ( 1. + pow( ( kappa - e1 ) / e2, nd ) ) ) ) / kappa / kappa + s1 *exp( -( kappa - e1 ) / ( ef * ( 1. + pow( ( kappa - e1 ) / e2, nd ) ) ) ) / kappa * a;
1074 return answer;
1075 }
1076 } break;
1078 {
1079 double wf = 2. * gf / E / e0; // wf is the crack opening
1080 if ( kappa <= e0 ) {
1081 return 0.0;
1082 } else if ( kappa < wf / Le ) {
1083 return ( e0 / ( kappa * kappa ) / ( 1. - Le * e0 / wf ) );
1084 } else {
1085 return 0.0;
1086 }
1087 } break;
1089 {
1090 if ( kappa > e0 ) {
1091 ef = gf / E / e0 / Le;
1092 double omega = status->giveTempDamage();
1093 double help = exp(omega * kappa / ef);
1094 double ret = -( ( omega * ef - ef ) * help - omega * e0 ) / ( ef * kappa * help - e0 * kappa );
1095 if ( std :: isnan(ret) ) {
1096 return 0.;
1097 }
1098 return ret;
1099 } else {
1100 return 0.0;
1101 }
1102 } break;
1104 {
1105 double Le = status->giveLe();
1106 const double E = this->linearElasticMaterial->give('E', gp);
1107 double eps_k = this->w_k/Le + this->f_k/E;
1108 double eps_r = this->w_r/Le + this->f_r/E;
1109 double eps_f = this->w_f/Le ;
1110 double f_t = E*e0;
1111 if ( kappa <= e0 ) {
1112 return 0.0;
1113 } else if ( kappa > e0 && kappa <= eps_k ) {
1114 double slope=((f_k - f_t)/w_k);
1115 return (f_t)/(E+slope*Le)*(1.0/(kappa*kappa));
1116 } else if ( kappa > eps_k && kappa <= eps_r ) {
1117 double slope=((f_r - f_k)/(w_r-w_k));
1118 return -(w_k*slope-f_k)/(Le*slope+E)*(1.0/(kappa*kappa));
1119 } else if ( kappa > eps_r && kappa <= eps_f ) {
1120 double slope=(- f_r/(w_f-w_r));
1121 return -(w_r*slope-f_r)/(Le*slope+E)*(1.0/(kappa*kappa));
1122 } else {
1123 return 0.0;
1124 }
1125 } break;
1126 default:
1127 OOFEM_ERROR("undefined softening type %d\n", softType);
1128 }
1129
1130 return 0.; // to make the compiler happy
1131}
1132
1133double
1134IsotropicDamageMaterial1 :: complianceFunction(double kappa, GaussPoint *gp) const
1135{
1136 double om = damageFunction(kappa, gp);
1137 return om / ( 1. - om );
1138}
1139
1140double
1141IsotropicDamageMaterial1 :: evaluatePermanentStrain(double kappa, double omega) const
1142{
1143 switch ( permStrain ) {
1144 case 1:
1145 return 0.;
1146
1147 break;
1148 case 2:
1149 return 0.;
1150
1151 break;
1152 case 3:
1153 return 0.;
1154
1155 break;
1156 case 4:
1157 return ps_alpha * omega / ( 1. - omega );
1158
1159 break;
1160 default:
1161 return 0.;
1162 }
1163 ;
1164}
1165
1166
1167void
1168IsotropicDamageMaterial1 :: initDamaged(double kappa, FloatArray &strainVector, GaussPoint *gp) const
1169{
1170 auto status = static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) );
1171 int indx = 1;
1172 double le = 0.;
1173 double E = this->linearElasticMaterial->give('E', gp);
1174 FloatArray principalStrains, crackPlaneNormal, fullStrain, crackVect;
1175 FloatMatrix principalDir;
1176
1177 const double e0 = this->give(e0_ID, gp);
1178 const double ef = this->give(ef_ID, gp);
1179 const double gf = this->give(gf_ID, gp);
1180 double wf = this->give(wf_ID, gp);
1181
1182 if ( softType == ST_Disable_Damage ) {
1183 return;
1184 }
1186 wf = this->w_f;
1187 }
1188
1189 if ( gf != 0. ) { //cohesive crack model
1190 if ( softType == ST_Exponential_Cohesive_Crack ) { // exponential softening
1191 wf = gf / E / e0; // wf is the crack opening
1192 } else if ( softType == ST_Linear_Cohesive_Crack || softType == ST_BiLinear_Cohesive_Crack ) { // (bi) linear softening law
1193 wf = 2. * gf / E / e0; // wf is the crack opening
1194 } else {
1195 OOFEM_ERROR("Gf unsupported for softening type softType = %d", softType);
1196 }
1197 } else if ( softType == ST_BiLinear_Cohesive_Crack ) {
1198 wf = this->wk / ( e0 * E - this->sk ) * ( e0 * E );
1199 }
1200
1201 StructuralMaterial :: giveFullSymVectorForm( fullStrain, strainVector, gp->giveMaterialMode() );
1202
1203
1204 if ( ( kappa > e0 ) && ( ( status->giveDamage() == 0. ) || ( status->giveLe() == 0.0 ) ) ) {
1205 // zero Le can happen after adaptive update; need to recompute Le
1206 this->computePrincipalValDir(principalStrains, principalDir, fullStrain, principal_strain);
1207 // find index of max positive principal strain
1208 for ( int i = 2; i <= 3; i++ ) {
1209 if ( principalStrains.at(i) > principalStrains.at(indx) ) {
1210 indx = i;
1211 }
1212 }
1213
1214 crackPlaneNormal.beColumnOf(principalDir, indx);
1215
1216 // find index with minimal value but non-zero for plane-stress condition - this is the crack direction
1217 indx = 1;
1218 for ( int i = 2; i <= 3; i++ ) {
1219 if ( principalStrains.at(i) < principalStrains.at(indx) && fabs( principalStrains.at(i) ) > 1.e-10 ) {
1220 indx = i;
1221 }
1222 }
1223
1224 // Use orientation of the worst inclusion for Griffith criterion in compression.
1225 if ( this->equivStrainType == EST_Griffith ) {
1226 FloatArray stress, fullStress, principalStress, crackV(3); // , crackPlaneN(3);
1227 FloatMatrix de;
1229 lmat->giveStiffnessMatrix( de, SecantStiffness, gp, domain->giveEngngModel()->giveCurrentStep() );
1230 stress.beProductOf(de, strainVector);
1231 StructuralMaterial :: giveFullSymVectorForm( fullStress, stress, gp->giveMaterialMode() );
1232 this->computePrincipalValDir(principalStress, principalDir, fullStress, principal_stress);
1233 if ( principalStress.at(1) <= 1.e-10 && principalStress.at(2) <= 1.e-10 && principalStress.at(3) <= 1.e-10 ) {
1234 int indexMax = principalStress.giveIndexMaxElem();
1235 int indexMin = principalStress.giveIndexMinElem();
1236 int indexMid = 0;
1237 if ( indexMin + indexMax == 3 ) {
1238 indexMid = 3;
1239 } else if ( indexMin + indexMax == 4 ) {
1240 indexMid = 2;
1241 } else if ( indexMin + indexMax == 5 ) {
1242 indexMid = 1;
1243 }
1244
1245 //inclination from maximum compressive stress (plane sig_1 and sig_3)
1246 double twoPsi = ( principalStress.at(indexMin) - principalStress.at(indexMax) ) / 2. / ( principalStress.at(indexMax) + principalStress.at(indexMin) );
1247 double psi = acos(twoPsi) / 2.;
1248 for ( int i = 1; i <= 3; i++ ) {
1249 crackV.at(i) = principalDir.at(i, indexMin);
1250 // crackPlaneN = principalDir.at(i, indexMax);
1251 }
1252
1253 //rotate around indexMid axis
1254 //see http://en.wikipedia.org/wiki/Rotation_matrix and Rodrigues' rotation formula
1255 FloatMatrix ux(3, 3), dyadU(3, 3), unitMtrx(3, 3), rotMtrx(3, 3);
1256 FloatArray u(3);
1257 ux.zero();
1258 ux.at(1, 2) = -principalDir.at(3, indexMid);
1259 ux.at(1, 3) = principalDir.at(2, indexMid);
1260 ux.at(2, 1) = principalDir.at(3, indexMid);
1261 ux.at(2, 3) = -principalDir.at(1, indexMid);
1262 ux.at(3, 1) = -principalDir.at(2, indexMid);
1263 ux.at(3, 2) = principalDir.at(1, indexMid);
1264 u.at(1) = principalDir.at(1, indexMid);
1265 u.at(2) = principalDir.at(2, indexMid);
1266 u.at(3) = principalDir.at(3, indexMid);
1267 dyadU.beDyadicProductOf(u, u);
1268 unitMtrx.beUnitMatrix();
1269 unitMtrx.times( cos(psi) );
1270 ux.times( sin(psi) );
1271 dyadU.times( 1. - cos(psi) );
1272 rotMtrx.zero();
1273 rotMtrx.add(unitMtrx);
1274 rotMtrx.add(ux);
1275 rotMtrx.add(dyadU);
1276 crackV.rotatedWith(rotMtrx, 'n');
1277 for ( int i = 1; i <= 3; i++ ) {
1278 principalDir.at(i, indx) = crackV.at(i);
1279 }
1280
1281 crackPlaneNormal.rotatedWith(rotMtrx, 'n');
1282 }
1283 }
1284
1285
1286 crackVect.beColumnOf(principalDir, indx);
1287
1288 status->setCrackVector(crackVect);
1289
1290 if ( isCrackBandApproachUsed() ) { // le needed only if the crack band approach is used
1291 le = gp->giveElement()->giveCharacteristicSize(gp, crackPlaneNormal, ecsMethod);
1292 // store le in corresponding status
1293 status->setLe(le);
1294 }
1295
1296 // compute and store the crack angle (just for postprocessing)
1297 double ca = M_PI / 2.;
1298 if ( crackPlaneNormal.at(1) != 0.0 ) {
1299 ca = atan( crackPlaneNormal.at(2) / crackPlaneNormal.at(1) );
1300 }
1301
1302 status->setCrackAngle(ca);
1303
1304 if ( this->gf != 0. && e0 >= ( wf / le ) ) { // case for a given fracture energy
1305 OOFEM_WARNING("Fracturing strain %e is lower than the elastic strain e0=%e, possible snap-back. Element number %d, wf %e, le %e", wf / le, e0, gp->giveElement()->giveLabel(), wf, le);
1306 if ( checkSnapBack ) {
1307 OOFEM_ERROR("x");
1308 }
1309 } else if ( wf == 0. && e0 >= ef ) {
1310 OOFEM_WARNING( "Fracturing strain ef=%e is lower than the elastic strain e0=%f, possible snap-back. Increase fracturing strain to %f. Element number %d", ef, e0, e0, gp->giveElement()->giveLabel() );
1311 if ( checkSnapBack ) {
1312 OOFEM_ERROR("x");
1313 }
1314 } else if ( ef == 0. && e0 * le >= wf ) {
1315 OOFEM_WARNING( "Crack opening at zero stress wf=%f is lower than the elastic displacement w0=%f, possible snap-back. Increase crack opening wf to %f. Element number %d", wf, e0 * le, e0 * le, gp->giveElement()->giveLabel() );
1316 if ( checkSnapBack ) {
1317 OOFEM_ERROR("x");
1318 }
1319 }
1320 }
1321}
1322
1323double
1324IsotropicDamageMaterial1 :: give(int aProperty, GaussPoint *gp) const
1325{
1326 double answer;
1327 if ( static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) )->_giveProperty(aProperty, answer) ) {
1328 return answer;
1329 } else if ( aProperty == e0_ID ) {
1330 return this->e0;
1331 } else if ( aProperty == ef_ID ) {
1332 return this->ef;
1333 } else if ( aProperty == ek_ID ) {
1334 return this->ek;
1335 } else if ( aProperty == gf_ID ) {
1336 return this->gf;
1337 } else if ( aProperty == wf_ID ) {
1338 return this->wf;
1339 } else if ( aProperty == gft_ID ) {
1340 return this->gft;
1341 } else {
1342 return IsotropicDamageMaterial :: give(aProperty, gp);
1343 }
1344}
1345
1346
1347Interface *
1348IsotropicDamageMaterial1 :: giveInterface(InterfaceType type)
1349{
1350 if ( type == MaterialModelMapperInterfaceType ) {
1351 return static_cast< MaterialModelMapperInterface * >(this);
1352 } else {
1353 return nullptr;
1354 }
1355}
1356
1357void
1359{
1360 if ( ( mode & CM_Definition ) ) {
1361 DynamicInputRecord input;
1362 this->giveInputRecord(input);
1363 if ( !stream.write(input.giveRecordInTXTFormat()
1364 ) ) {
1366 }
1367 }
1368}
1369
1370
1371void
1373{
1374 if ( ( mode & CM_Definition ) ) {
1375 std::string input;
1376 if ( !stream.read(input) ) {
1378 }
1379 OOFEMTXTInputRecord ir(0, input);
1380 this->initializeFrom(ir);
1381 }
1382}
1383
1384
1385std::unique_ptr<MaterialStatus>
1386IsotropicDamageMaterial1 :: CreateStatus(GaussPoint *gp) const
1387{
1388 return std::make_unique<IsotropicDamageMaterial1Status>(gp);
1389}
1390
1392IsotropicDamageMaterial1 :: giveStatus(GaussPoint *gp) const
1393{
1394 if ( !gp->hasMaterialStatus()) {
1395 gp->setMaterialStatus(this->CreateStatus(gp));
1396 this->_generateStatusVariables(gp);
1397 }
1398 return static_cast<MaterialStatus*>(gp->giveMaterialStatus());
1399}
1400
1401
1402int
1403IsotropicDamageMaterial1 :: MMI_map(GaussPoint *gp, Domain *oldd, TimeStep *tStep)
1404{
1405 int result;
1406 FloatArray intVal;
1407 IntArray toMap(3);
1408 IsotropicDamageMaterial1Status *status = static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) );
1409
1410
1411 toMap.at(1) = ( int ) IST_MaxEquivalentStrainLevel;
1412 toMap.at(2) = ( int ) IST_DamageTensor;
1413 toMap.at(3) = ( int ) IST_StrainTensor;
1414
1415
1416 if ( sourceElemSet == NULL ) {
1417 sourceElemSet = new Set(0, oldd);
1418 IntArray el;
1419 // compile source list to contain all elements on old odmain with the same material id
1420 for ( int i = 1; i <= oldd->giveNumberOfElements(); i++ ) {
1421 if ( oldd->giveElement(i)->giveCrossSection()->giveMaterial(gp)->giveNumber() == this->giveNumber() ) {
1422 // add oldd domain element to source list
1423 el.followedBy(i, 10);
1424 }
1425 }
1426 sourceElemSet->setElementList(el);
1427 }
1428
1429 // Set up source element set if not set up by user
1430 this->mapper.init(oldd, toMap, gp, * sourceElemSet, tStep);
1431
1432 result = mapper.mapVariable(intVal, gp, IST_MaxEquivalentStrainLevel, tStep);
1433 if ( result ) {
1434 status->setTempKappa( intVal.at(1) );
1435 }
1436
1437 result = mapper.mapVariable(intVal, gp, IST_DamageTensor, tStep);
1438 if ( result ) {
1439 status->setTempDamage( intVal.at(1) );
1440 }
1441
1442#ifdef IDM_USE_MAPPEDSTRAIN
1443 result = mapper.mapVariable(intVal, gp, IST_StrainTensor, tStep);
1444 if ( result ) {
1445 FloatArray sr;
1446 this->giveReducedSymVectorForm( sr, intVal, gp->giveMaterialMode() );
1447 status->letTempStrainVectorBe(sr);
1448 }
1449
1450#endif
1451 status->updateYourself(tStep);
1452
1453 if ( result ) {
1454 FloatArray sr;
1455 this->giveReducedSymVectorForm( sr, intVal, gp->giveMaterialMode() );
1456 status->letTempStrainVectorBe(sr);
1457 }
1458
1459 return result;
1460}
1461
1462
1463
1464
1465int
1466IsotropicDamageMaterial1 :: MMI_update(GaussPoint *gp, TimeStep *tStep, FloatArray *estrain)
1467{
1468 int result = 1;
1469 FloatArray intVal;
1470
1471 // now update all internal vars accordingly
1472#ifdef IDM_USE_MAPPEDSTRAIN
1473 IsotropicDamageMaterial1Status *status = static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) );
1474 FloatArray strain = status->giveStrainVector();
1475 this->giveRealStressVector(intVal, gp, strain, tStep);
1476#else
1477 this->giveRealStressVector(intVal, gp, * estrain, tStep);
1478#endif
1479 gp->updateYourself(tStep);
1480 return result;
1481}
1482
1483
1484int
1485IsotropicDamageMaterial1 :: MMI_finish(TimeStep *tStep)
1486{
1487 this->mapper.finish(tStep);
1488 return 1;
1489}
1490
1491
1492IsotropicDamageMaterial1Status :: IsotropicDamageMaterial1Status(GaussPoint *g) :
1494{}
1495
1496Interface *
1497IsotropicDamageMaterial1Status :: giveInterface(InterfaceType type)
1498{
1500 return static_cast< RandomMaterialStatusExtensionInterface * >(this);
1501 } else {
1502 return NULL;
1503 }
1504}
1505} // end namespace oofem
#define N(a, b)
#define E(a, b)
#define REGISTER_Material(class)
virtual Material * giveMaterial(IntegrationPoint *ip) const =0
hidden by virtual oofem::Material* TransportCrossSection::giveMaterial() const
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.
int giveNumberOfElements() const
Returns number of elements in domain.
Definition domain.h:463
Element * giveElement(int n)
Definition domain.C:165
std::string giveRecordInTXTFormat() const override
void setField(int item, InputFieldType id)
int giveGlobalNumber() const
Definition element.h:1129
virtual double giveCharacteristicSize(GaussPoint *gp, FloatArray &normalToCrackPlane, ElementCharSizeMethod method)
Definition element.h:965
CrossSection * giveCrossSection()
Definition element.C:534
int giveLabel() const
Definition element.h:1125
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
int giveNumber() const
Definition femcmpnn.h:104
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void resizeWithValues(Index s, std::size_t allocChunk=0)
Definition floatarray.C:103
void beColumnOf(const FloatMatrix &mat, int col)
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void rotatedWith(FloatMatrix &r, char mode)
Definition floatarray.C:814
int giveIndexMinElem(void)
Definition floatarray.C:492
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
bool isEmpty() const
Returns true if receiver is empty.
Definition floatarray.h:265
int giveIndexMaxElem(void)
Definition floatarray.C:508
void times(double s)
Definition floatarray.C:834
void times(double f)
void add(const FloatMatrix &a)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void zero()
Zeroes all coefficient of receiver.
void beDyadicProductOf(const FloatArray &vec1, const FloatArray &vec2)
void plusDyadSymmUpper(const FloatArray &a, double dV)
double at(std::size_t i, std::size_t j) const
bool hasMaterialStatus(IntegrationPointStatusIDType key=IPSID_Default) const
Definition gausspoint.h:206
IntegrationPointStatus * setMaterialStatus(std::unique_ptr< IntegrationPointStatus > ptr, IntegrationPointStatusIDType key=IPSID_Default)
Definition gausspoint.h:213
MaterialMode giveMaterialMode()
Returns corresponding material mode of receiver.
Definition gausspoint.h:190
void updateYourself(TimeStep *tStep)
Definition gausspoint.C:127
IntegrationPointStatus * giveMaterialStatus(IntegrationPointStatusIDType key=IPSID_Default)
Definition gausspoint.h:204
Element * giveElement()
Returns corresponding element to receiver.
Definition gausspoint.h:187
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
void followedBy(const IntArray &b, int allocChunk=0)
Definition intarray.C:94
int & at(std::size_t i)
Definition intarray.h:104
SofteningType softType
Parameter specifying the type of softening (damage law).
Definition idm1.h:211
double e0
Equivalent strain at stress peak (or a similar parameter).
Definition idm1.h:145
double wf
Determines ductility -> corresponds to crack opening in the cohesive crack model.
Definition idm1.h:149
static MMAContainingElementProjection mapper
Mapper used to map internal variables in adaptivity.
Definition idm1.h:241
double md
Parameter used in "smooth damage law".
Definition idm1.h:216
double ek
Determines the softening for the bilinear law -> corresponds to the strain at the knee point.
Definition idm1.h:163
void initializeFrom(InputRecord &ir) override
Definition idm1.C:86
void saveContext(DataStream &stream, ContextMode mode) override
Definition idm1.C:1358
double griff_n
Parameter used in Griffith's criterion.
Definition idm1.h:200
double wk
Determines the softening for the bilinear law -> corresponds to the crack opening at the knee point.
Definition idm1.h:166
void giveInputRecord(DynamicInputRecord &input) override
Definition idm1.C:352
double ps_alpha
Parameters used by the model with permanent strain.
Definition idm1.h:227
double k
Parameter used in Mises definition of equivalent strain.
Definition idm1.h:197
MaterialStatus * giveStatus(GaussPoint *gp) const override
Definition idm1.C:1392
static void computeStrainInvariants(const FloatArray &strainVector, double &I1e, double &J2e)
Definition idm1.C:786
bool isCrackBandApproachUsed() const
Definition idm1.h:271
EquivStrainType equivStrainType
Parameter specifying the definition of equivalent strain.
Definition idm1.h:194
double computeDamageParamForCohesiveCrack(double kappa, GaussPoint *gp) const
Definition idm1.C:808
std::unique_ptr< MaterialStatus > CreateStatus(GaussPoint *gp) const override
Definition idm1.C:1386
ElementCharSizeMethod ecsMethod
Method used for evaluation of characteristic element size.
Definition idm1.h:230
Set * sourceElemSet
Cached source element set used to map internal variables (adaptivity), created on demand.
Definition idm1.h:233
double c1
Parameters used in Hordijk's softening law.
Definition idm1.h:172
double sk
Determines the softening for the bilinear law -> corresponds to the stress at the knee point.
Definition idm1.h:169
double w_k
Parameters used in Trilinear_Cohesive_Crack softening law.
Definition idm1.h:175
void restoreContext(DataStream &stream, ContextMode mode) override
Definition idm1.C:1372
double At
Parameters used in Mazars damage law.
Definition idm1.h:214
double ef
Determines ductility -> corresponds to fracturing strain.
Definition idm1.h:147
double give(int aProperty, GaussPoint *gp) const override
Definition idm1.C:1324
int damageLaw
Temporary parameter reading type of softening law, used in other isotropic damage material models.
Definition idm1.h:203
double damageFunction(double kappa, GaussPoint *gp) const
Definition idm1.C:954
double gft
Determines the softening for the bilinear law -> corresponds to the total fracture energy.
Definition idm1.h:160
int checkSnapBack
Check possible snap back flag.
Definition idm1.h:221
double e1
Parameters used if softType = 7 (extended smooth damage law).
Definition idm1.h:219
double ep
auxiliary input variablesfor softType == ST_SmoothExtended
Definition idm1.h:224
IsotropicDamageMaterialStatus(GaussPoint *g)
Constructor.
void updateYourself(TimeStep *tStep) override
void setTempKappa(double newKappa)
Sets the temp scalar measure of the largest strain level to given value.
double giveLe() const
Returns characteristic length stored in receiver.
double giveTempDamage() const
Returns the temp. damage level.
void setTempDamage(double newDamage)
Sets the temp damage level to given value.
double maxOmega
Maximum limit on omega. The purpose is elimination of a too compliant material which may cause conver...
LinearElasticMaterial * linearElasticMaterial
Reference to bulk (undamaged) material.
int permStrain
Indicator of the type of permanent strain formulation (0 = standard damage with no permanent strain).
IsotropicDamageMaterial(int n, Domain *d)
Constructor.
void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) const override
virtual double give(int aProperty, GaussPoint *gp) const
Definition material.C:51
void _generateStatusVariables(GaussPoint *) const
void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir) const override
void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir) const override
const FloatArray & giveStrainVector() const
Returns the const pointer to receiver's strain vector.
void letTempStrainVectorBe(const FloatArray &v)
Assigns tempStrainVector to given vector v.
static void computePrincipalValues(FloatArray &answer, const FloatArray &s, stressStrainPrincMode mode)
Common functions for convenience.
static void giveReducedSymVectorForm(FloatArray &answer, const FloatArray &vec, MaterialMode matMode)
Converts the full unsymmetric Voigt vector (2nd order tensor) to reduced form.
virtual void giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
static void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir, const FloatArray &s, stressStrainPrincMode mode)
#define THROW_CIOERR(e)
#define CM_Definition
Definition contextmode.h:47
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
#define _IFT_IsotropicDamageMaterial1_nd
Definition idm1.h:101
#define _IFT_IsotropicDamageMaterial1_wkwf
Definition idm1.h:89
#define _IFT_IsotropicDamageMaterial1_w_f
Definition idm1.h:110
#define _IFT_IsotropicDamageMaterial1_k
Definition idm1.h:83
#define _IFT_IsotropicDamageMaterial1_gft
Definition idm1.h:98
#define _IFT_IsotropicDamageMaterial1_ek
Definition idm1.h:96
#define _IFT_IsotropicDamageMaterial1_c1
Definition idm1.h:104
#define IDM1_ITERATION_LIMIT
Definition idm1.h:116
#define _IFT_IsotropicDamageMaterial1_gf
Definition idm1.h:97
#define _IFT_IsotropicDamageMaterial1_Bt
Definition idm1.h:87
#define _IFT_IsotropicDamageMaterial1_wk
Definition idm1.h:94
#define _IFT_IsotropicDamageMaterial1_f_k
Definition idm1.h:111
#define _IFT_IsotropicDamageMaterial1_n
Definition idm1.h:103
#define _IFT_IsotropicDamageMaterial1_md
Definition idm1.h:84
#define _IFT_IsotropicDamageMaterial1_w_r
Definition idm1.h:109
#define _IFT_IsotropicDamageMaterial1_e0
Definition idm1.h:78
#define _IFT_IsotropicDamageMaterial1_equivstraintype
Definition idm1.h:81
#define _IFT_IsotropicDamageMaterial1_ecsm
Definition idm1.h:85
#define _IFT_IsotropicDamageMaterial1_sk
Definition idm1.h:93
#define _IFT_IsotropicDamageMaterial1_ep
Definition idm1.h:99
#define _IFT_IsotropicDamageMaterial1_ef
Definition idm1.h:79
#define _IFT_IsotropicDamageMaterial1_e2
Definition idm1.h:100
#define _IFT_IsotropicDamageMaterial1_wf
Definition idm1.h:80
#define _IFT_IsotropicDamageMaterial1_skft
Definition idm1.h:91
#define _IFT_IsotropicDamageMaterial1_w_k
Definition idm1.h:108
#define _IFT_IsotropicDamageMaterial1_e1
Definition idm1.h:95
#define _IFT_IsotropicDamageMaterial1_c2
Definition idm1.h:105
#define _IFT_IsotropicDamageMaterial1_ft
Definition idm1.h:88
#define _IFT_IsotropicDamageMaterial1_alphaps
Definition idm1.h:106
#define _IFT_IsotropicDamageMaterial1_f_r
Definition idm1.h:112
#define _IFT_IsotropicDamageMaterial1_At
Definition idm1.h:86
#define _IFT_IsotropicDamageMaterial1_damageLaw
Definition idm1.h:82
#define _IFT_IsotropicDamageMaterial1_checkSnapBack
Definition idm1.h:102
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define _IFT_IsotropicLinearElasticMaterial_e
#define NYxz
Definition matconst.h:51
#define ek_ID
Definition matconst.h:86
#define e0_ID
Definition matconst.h:83
#define wf_ID
Definition matconst.h:87
#define gf_ID
Definition matconst.h:85
#define ef_ID
Definition matconst.h:84
#define gft_ID
Definition matconst.h:88
#define M_PI
Definition mathfem.h:52
long ContextMode
Definition contextmode.h:43
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
@ principal_strain
For computing principal strains from engineering strains.
@ principal_stress
For computing principal stresses.
double sum(const FloatArray &x)
@ RandomMaterialStatusExtensionInterfaceType
@ MaterialModelMapperInterfaceType
@ ECSM_SquareRootOfArea
@ ECSM_ProjectionCentered
@ 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