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

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:29 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011