OOFEM 3.0
Loading...
Searching...
No Matches
mazarsmodel.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 "mazarsmodel.h"
36#include "gausspoint.h"
37#include "floatmatrix.h"
38#include "floatarray.h"
39#include "mathfem.h"
40#include "datastream.h"
41#include "contextioerr.h"
43#include "classfactory.h"
44
45namespace oofem {
46#define _MAZARS_MODEL_ITER_TOL 1.e-15
47#define _MAZARS_MODEL_MAX_ITER 400.
48
50
51MazarsMaterial :: MazarsMaterial(int n, Domain *d) : IsotropicDamageMaterial1(n, d)
52{
53 // force the loading / unloading control according to max. reached damage level
55}
56
57
58void
59MazarsMaterial :: initializeFrom(InputRecord &ir)
60{
61 int ver;
62
63 // Note: IsotropicDamageMaterial1 :: initializeFrom is not activated
64 // because we do not always read ef and the equivalent strain type
65 // cannot be selected
66 // IsotropicDamageMaterial1 :: initializeFrom(ir);
67
69 this->softType = ST_Mazars;
70
71 IsotropicDamageMaterial :: initializeFrom(ir);
72 RandomMaterialExtensionInterface :: initializeFrom(ir);
73 linearElasticMaterial->initializeFrom(ir);
74 // E and nu are made available for direct access
77
78 ver = 0;
80 if ( ver == 1 ) {
82 } else if ( ver == 0 ) {
84 } else {
85 throw ValueInputException(ir, _IFT_MazarsMaterial_version, "unknown version");
86 }
87
90
91 this->Bc = ( Ac - 1.0 ) / ( Ac * e0 ); // default value, ensures smooth curve
93
94 beta = 1.06;
96
97 if ( this->modelVersion == maz_original ) {
100 } else if ( this->modelVersion == maz_modTension ) {
101 // in case of modified model read ef instead of At, Bt
103 }
104
105 // ask for optional "reference length"
106 hReft = hRefc = 0.; // default values 0 => no adjustment for element size is used
109
110 this->mapper.initializeFrom(ir);
111}
112
113
114double
115MazarsMaterial :: computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const
116{
117 double posNorm = 0.0;
118 FloatArray principalStrains, strainb;
119
120 if ( strain.isEmpty() ) {
121 return 0.;
122 }
123
124 StructuralMaterial :: giveFullSymVectorForm( strainb, strain, gp->giveMaterialMode() );
125 // if plane stress mode -> compute strain in z-direction from condition of zero stress in corresponding direction
126 int ndim = giveNumberOfSpatialDimensions(gp);
127 if ( ndim == 2 ) {
128 strainb.at(3) = -nu * ( strainb.at(1) + strainb.at(2) ) / ( 1. - nu );
129 } else if ( ndim == 1 ) {
130 strainb.at(2) = -nu *strainb.at(1);
131 strainb.at(3) = -nu *strainb.at(1);
132 }
133
134 if ( ndim == 1 ) {
135 principalStrains.resize(3);
136 for ( int i = 1; i <= 3; i++ ) {
137 principalStrains.at(i) = strainb.at(i);
138 }
139 } else {
140 this->computePrincipalValues(principalStrains, strainb, principal_strain);
141 }
142
143 /*
144 * // simple check
145 * double i1 = strainb.at(1)+strainb.at(2)+strainb.at(3) - principalStrains.at(1)-principalStrains.at(2)-principalStrains.at(3);
146 * double i2 = strainb.at(1)*strainb.at(3)+strainb.at(2)*strainb.at(3)+strainb.at(1)*strainb.at(2) -
147 * 0.25*(strainb.at(4)*strainb.at(4)+strainb.at(5)*strainb.at(5)+strainb.at(6)*strainb.at(6)) -
148 * principalStrains.at(1)*principalStrains.at(3)+principalStrains.at(2)*principalStrains.at(3)+principalStrains.at(1)*principalStrains.at(2);
149 * if ((fabs(i1) > 1.e-6) || (fabs(i2) > 1.e-6)) {
150 * printf("v");
151 * }
152 * // end simple check
153 */
154 for ( int i = 1; i <= 3; i++ ) {
155 if ( principalStrains.at(i) > 0.0 ) {
156 posNorm += principalStrains.at(i) * principalStrains.at(i);
157 }
158 }
159
160 return sqrt(posNorm);
161}
162
163/*
164 * void
165 * MazarsMaterial :: giveNormalElasticStiffnessMatrix(FloatMatrix &answer,
166 * MatResponseMode rMode,
167 * GaussPoint *gp, TimeStep *tStep)
168 * {
169 * //
170 * // return Elastic Stiffness matrix for normal Stresses
171 * LinearElasticMaterial *lMat = this->giveLinearElasticMaterial();
172 * FloatMatrix de;
173 * int i, j;
174 *
175 * answer.resize(3, 3);
176 * lMat->give3dMaterialStiffnessMatrix(de, rMode, gp, tStep);
177 * // copy first 3x3 submatrix to answer
178 * for ( i = 1; i <= 3; i++ ) {
179 * for ( j = 1; j <= 3; j++ ) {
180 * answer.at(i, j) = de.at(i, j);
181 * }
182 * }
183 * }
184 */
185
186int
187MazarsMaterial :: giveNumberOfSpatialDimensions(GaussPoint *gp) const
188{
189 if ( gp->giveMaterialMode() == _1dMat ) {
190 return 1;
191 } else if ( gp->giveMaterialMode() == _PlaneStress ) {
192 return 2;
193 } else {
194 return 3;
195 }
196}
197
198void
199MazarsMaterial :: giveNormalBlockOfElasticCompliance(FloatMatrix &answer, GaussPoint *gp) const
200{
201 int ndim = giveNumberOfSpatialDimensions(gp);
202 answer.resize(ndim, ndim);
203 for ( int i = 1; i <= ndim; i++ ) {
204 for ( int j = 1; j <= ndim; j++ ) {
205 if ( i == j ) {
206 answer.at(i, j) = 1. / E;
207 } else {
208 answer.at(i, j) = -nu / E;
209 }
210 }
211 }
212}
213
214double
215MazarsMaterial :: computeDamageParam(double kappa, const FloatArray &strain, GaussPoint *gp) const
216{
217 // positive_flag = 0, negat_count = 0;
218 FloatMatrix de, ce;
219 FloatArray sigp, epsti, epsi;
220 double gt, gc, alpha_t, alpha_c, alpha, eqStrain2;
221
222 if ( kappa <= this->e0 ) { // strain below damage threshold
223 return 0.0;
224 }
225
226 // strain above damage threshold
227
228 int ndim = giveNumberOfSpatialDimensions(gp);
229 if ( !strain.isEmpty() ) {
230 this->computePrincipalValues(epsi, strain, principal_strain);
231 } else {
232 epsi.resize(ndim);
233 epsi.zero();
234 }
235
236 // construct the normal block of elastic compliance matrix
238 // compute the normal block of elastic stiffness matrix
239 de.beInverseOf(ce);
240
241 // compute principal stresses
242 sigp.beProductOf(de, epsi);
243 // take positive part
244 for ( int i = 1; i <= ndim; i++ ) {
245 if ( sigp.at(i) < 0. ) {
246 sigp.at(i) = 0.;
247 }
248 }
249
250 // compute principal strains due to positive stresses
251 epsti.beProductOf(ce, sigp);
252
253 // extend strains to 3 dimensions
254 if ( ndim == 2 ) {
255 epsi.resize(3);
256 epsti.resize(3);
257 epsi.at(3) = -nu * ( epsi.at(1) + epsi.at(2) ) / ( 1. - nu );
258 epsti.at(3) = -nu * ( epsti.at(1) + epsti.at(2) ) / ( 1. - nu );
259 } else if ( ndim == 1 ) {
260 epsi.resize(3);
261 epsti.resize(3);
262 epsi.at(2) = epsi.at(3) = -nu *epsi.at(1);
263 epsti.at(2) = epsti.at(3) = -nu *epsti.at(1);
264 }
265
266 /* the following section "improves" biaxial compression
267 * // but it may lead to convergence problems, probably due to the condition > 1.e-6
268 * // therefore it was commented out by Milan Jirasek on 22 Nov 2009
269 *
270 * positive_flag = negat_count = 0;
271 * for ( i = 1; i <= 3; i++ ) {
272 * if ( sigp.at(i) > 1.e-6 ) {
273 * positive_flag = 1;
274 * break;
275 * } else if ( sigp.at(i) < 1.e-6 ) {
276 * negat_count++;
277 * }
278 * }
279 *
280 * if ( ( positive_flag == 0 ) && ( negat_count > 1 ) ) {
281 * // adjust equivalent strain to improve biaxial compression
282 * double f = 0.0, g = 0.0;
283 * for ( i = 1; i <= 3; i++ ) {
284 * if ( sigp.at(i) < 0 ) {
285 * f += sigp.at(i) * sigp.at(i);
286 * g += fabs( sigp.at(i) );
287 * }
288 * }
289 *
290 * f = sqrt(f) / g;
291 * kappa *= f;
292 * }
293 *
294 * // test adjusted kappa
295 * if ( kappa < this->e0 ) {
296 * omega = 0.0;
297 * return;
298 * }
299 * // end of section that improves biaxial compression
300 */
301
302 // evaluation of damage functions
303 gt = computeGt(kappa, gp);
304 gc = computeGc(kappa, gp);
305
306 // evaluation of factors alpha_t and alpha_c
307 alpha = 0.0;
308 eqStrain2 = 0.0;
309 for ( int i = 1; i <= 3; i++ ) {
310 if ( epsi.at(i) > 0.0 ) {
311 eqStrain2 += epsi.at(i) * epsi.at(i);
312 alpha += epsti.at(i) * epsi.at(i);
313 }
314 }
315
316 if ( eqStrain2 > 0. ) {
317 alpha /= eqStrain2;
318 }
319
320 if ( alpha > 1. ) {
321 alpha = 1.;
322 } else if ( alpha < 0. ) {
323 alpha = 0.;
324 }
325
326 if ( this->beta == 1. ) {
327 alpha_t = alpha;
328 alpha_c = 1. - alpha;
329 } else if ( alpha <= 0. ) {
330 alpha_t = 0.;
331 alpha_c = 1.;
332 } else if ( alpha < 1. ) {
333 alpha_t = pow(alpha, this->beta);
334 alpha_c = pow( ( 1. - alpha ), this->beta );
335 } else {
336 alpha_t = 1.;
337 alpha_c = 0.;
338 }
339
340 auto omega = alpha_t * gt + alpha_c * gc;
341 if ( omega > 1.0 ) {
342 omega = 1.0;
343 }
344 return omega;
345}
346
347// evaluation of tensile damage
348double MazarsMaterial :: computeGt(double kappa, GaussPoint *gp) const
349{
350 double gt;
351 if ( hReft <= 0. ) { // material law considered as independent of element size
352 if ( this->modelVersion == maz_modTension ) { // exponential softening
353 gt = 1.0 - ( this->e0 / kappa ) * exp( ( this->e0 - kappa ) / this->ef );
354 } else { // maz_original
355 gt = 1.0 - ( 1.0 - this->At ) * this->e0 / kappa - this->At *exp( -this->Bt * ( kappa - this->e0 ) );
356 }
357
358 return gt;
359 }
360
361 // tension objectivity (material law dependent on element size)
362 int nite = 0;
363 double aux, hCurrt, kappaRefT, dgt, R;
364 MazarsMaterialStatus *status = static_cast< MazarsMaterialStatus * >( this->giveStatus(gp) );
365 hCurrt = status->giveLe();
366 kappaRefT = kappa;
367 do {
368 if ( this->modelVersion == maz_modTension ) {
369 gt = 1.0 - ( this->e0 / kappaRefT ) * exp( ( this->e0 - kappaRefT ) / this->ef );
370 dgt = this->e0 / kappaRefT / kappaRefT + this->e0 / kappaRefT / this->ef;
371 dgt *= exp( ( this->e0 - kappaRefT ) / this->ef );
372 } else { // maz_original
373 gt = 1.0 - ( 1.0 - this->At ) * this->e0 / kappaRefT - this->At *exp( -this->Bt * ( kappaRefT - this->e0 ) );
374 dgt = ( 1.0 - this->At ) * this->e0 / kappaRefT / kappaRefT + this->At *exp( -this->Bt * ( kappaRefT - this->e0 ) ) * this->Bt;
375 }
376
377 aux = 1 + gt * ( hReft / hCurrt - 1.0 );
378 R = kappaRefT * aux - kappa;
379 if ( fabs(R) <= _MAZARS_MODEL_ITER_TOL ) {
380 if ( ( gt < 0. ) || ( gt > 1.0 ) ) {
381 OOFEM_ERROR("gt out of range ");
382 }
383
384 return gt * ( hReft * kappaRefT ) / ( hCurrt * kappa );
385 }
386
387 aux += dgt * kappaRefT * ( hReft / hCurrt - 1.0 );
388 kappaRefT += -R / aux;
389 } while ( nite++ < _MAZARS_MODEL_MAX_ITER );
390
391 OOFEM_ERROR("tension objectivity iteration internal error - no convergence");
392}
393
394// evaluation of compression damage
395double MazarsMaterial :: computeGc(double kappa, GaussPoint *gp) const
396{
397 double gc;
398 if ( hRefc <= 0. ) { // material law considered as independent of element size
399 gc = 1.0 - ( 1.0 - this->Ac ) * this->e0 / kappa - this->Ac *exp( -this->Bc * ( kappa - this->e0 ) );
400 return gc;
401 }
402
403 // compression objectivity (material law dependent on element size)
404 int nite = 0;
405 double aux, hCurrc, kappaRefC, dgc, R;
406 MazarsMaterialStatus *status = static_cast< MazarsMaterialStatus * >( this->giveStatus(gp) );
407 hCurrc = status->giveLec();
408 kappaRefC = kappa;
409 do {
410 gc = 1.0 - ( 1.0 - this->Ac ) * this->e0 / kappaRefC - this->Ac *exp( -this->Bc * ( kappaRefC - this->e0 ) );
411 aux = 1 + gc * ( hRefc / hCurrc - 1.0 );
412 R = kappaRefC * aux - kappa;
413 if ( fabs(R) <= _MAZARS_MODEL_ITER_TOL ) {
414 return gc * ( hRefc * kappaRefC ) / ( hCurrc * kappa );
415 }
416
417 dgc = ( 1.0 - this->Ac ) * this->e0 / kappaRefC / kappaRefC + this->Ac *exp( -this->Bc * ( kappaRefC - this->e0 ) ) * this->Bc;
418 aux += dgc * kappaRefC * ( hRefc / hCurrc - 1.0 );
419 kappaRefC += -R / aux;
420 } while ( nite++ < _MAZARS_MODEL_MAX_ITER );
421
422 OOFEM_ERROR("compression objectivity iteration internal error - no convergence");
423}
424
425void
426MazarsMaterial :: initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) const
427{
428 int indmin = 1, indmax = 1;
429 double le;
430 FloatArray principalStrains, crackPlaneNormal(3);
431 FloatMatrix principalDir(3, 3);
432 MazarsMaterialStatus *status = static_cast< MazarsMaterialStatus * >( this->giveStatus(gp) );
433
434 if ( ( kappa > this->e0 ) && ( status->giveDamage() == 0. ) ) {
435 //printf (":");
436
437
438 if ( gp->giveMaterialMode() == _1dMat ) {
439 crackPlaneNormal.zero();
440 crackPlaneNormal.at(1) = 1.0;
441 le = gp->giveElement()->giveCharacteristicLength(crackPlaneNormal);
442 status->setLe(le);
443 status->setLec(le);
444 return;
445 }
446
447
448 if ( gp->giveMaterialMode() == _PlaneStress ) {
449 principalDir.resize(2, 2);
450 }
451
452 this->computePrincipalValDir(principalStrains, principalDir, totalStrainVector, principal_strain);
453 if ( gp->giveMaterialMode() == _PlaneStress ) {
454 if ( principalStrains.at(1) > principalStrains.at(2) ) {
455 indmax = 1;
456 indmin = 2;
457 } else {
458 indmax = 2;
459 indmin = 1;
460 }
461 } else {
462 // find index of max and min positive principal strains
463 for ( int i = 2; i <= 3; i++ ) {
464 if ( principalStrains.at(i) > principalStrains.at(indmax) ) {
465 indmax = i;
466 }
467
468 if ( principalStrains.at(i) < principalStrains.at(indmin) ) {
469 indmin = i;
470 }
471 }
472 }
473
474 for ( int i = 1; i <= principalStrains.giveSize(); i++ ) {
475 crackPlaneNormal.at(i) = principalDir.at(i, indmax);
476 }
477
478 le = gp->giveElement()->giveCharacteristicLength(crackPlaneNormal);
479 // remember le in cooresponding status for tension
480 status->setLe(le);
481
482 for ( int i = 1; i <= principalStrains.giveSize(); i++ ) {
483 crackPlaneNormal.at(i) = principalDir.at(i, indmin);
484 }
485
486 le = gp->giveElement()->giveCharacteristicLength(crackPlaneNormal);
487 // remember le in cooresponding status for compression
488 status->setLec(le);
489
490 }
491}
492
493
494MazarsMaterialStatus :: MazarsMaterialStatus(GaussPoint *g) :
496{}
497
498void
499MazarsMaterialStatus :: saveContext(DataStream &stream, ContextMode mode)
500{
501 IsotropicDamageMaterial1Status :: saveContext(stream, mode);
502
503 if ( !stream.write(lec) ) {
505 }
506}
507
508void
509MazarsMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode)
510{
511 IsotropicDamageMaterial1Status :: restoreContext(stream, mode);
512
513 if ( !stream.read(lec) ) {
515 }
516}
517} // end namespace oofem
#define REGISTER_Material(class)
virtual int read(int *data, std::size_t count)=0
Reads count integer values into array pointed by data.
virtual int write(const int *data, std::size_t count)=0
Writes count integer values from array pointed by data.
virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane)
Definition element.h:938
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
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
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
bool beInverseOf(const FloatMatrix &src)
double at(std::size_t i, std::size_t j) const
MaterialMode giveMaterialMode()
Returns corresponding material mode of receiver.
Definition gausspoint.h:190
Element * giveElement()
Returns corresponding element to receiver.
Definition gausspoint.h:187
IsotropicDamageMaterial1Status(GaussPoint *g)
Constructor.
Definition idm1.C:1492
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
IsotropicDamageMaterial1(int n, Domain *d)
Constructor.
Definition idm1.C:70
static MMAContainingElementProjection mapper
Mapper used to map internal variables in adaptivity.
Definition idm1.h:241
MaterialStatus * giveStatus(GaussPoint *gp) const override
Definition idm1.C:1392
EquivStrainType equivStrainType
Parameter specifying the definition of equivalent strain.
Definition idm1.h:194
double ef
Determines ductility -> corresponds to fracturing strain.
Definition idm1.h:147
double giveLe() const
Returns characteristic length stored in receiver.
double giveDamage() const
Returns the last equilibrated damage level.
void setLe(double ls)
Sets characteristic length to given value.
LinearElasticMaterial * linearElasticMaterial
Reference to bulk (undamaged) material.
enum oofem::IsotropicDamageMaterial::loaUnloCriterium llcriteria
double lec
Characteristic element length for compression, fixed as square from element size (for 2d).
Definition mazarsmodel.h:66
void setLec(double ls)
Sets characteristic length to given value.
Definition mazarsmodel.h:75
double giveLec()
Returns characteristic length stored in receiver.
Definition mazarsmodel.h:73
double E
Elastic parameters.
Definition mazarsmodel.h:96
double computeGt(double kappa, GaussPoint *gp) const
double beta
Beta coefficient reducing the effect of shear; default val = 1.06.
double computeGc(double kappa, GaussPoint *gp) const
double At
Model parameters related to the shape of uniaxial stress-strain diagrams.
Definition mazarsmodel.h:98
void giveNormalBlockOfElasticCompliance(FloatMatrix &answer, GaussPoint *gp) const
enum oofem::MazarsMaterial::mazarsModelVariant modelVersion
double hReft
Reference elem-length for objectivity.
int giveNumberOfSpatialDimensions(GaussPoint *gp) const
static void computePrincipalValues(FloatArray &answer, const FloatArray &s, stressStrainPrincMode mode)
Common functions for convenience.
static void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir, const FloatArray &s, stressStrainPrincMode mode)
#define THROW_CIOERR(e)
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define _IFT_IsotropicLinearElasticMaterial_n
#define _IFT_IsotropicLinearElasticMaterial_e
#define _MAZARS_MODEL_ITER_TOL
Definition mazarsmodel.C:46
#define _MAZARS_MODEL_MAX_ITER
Definition mazarsmodel.C:47
#define _IFT_MazarsMaterial_ac
Definition mazarsmodel.h:47
#define _IFT_MazarsMaterial_ef
Definition mazarsmodel.h:52
#define _IFT_MazarsMaterial_at
Definition mazarsmodel.h:50
#define _IFT_MazarsMaterial_beta
Definition mazarsmodel.h:49
#define _IFT_MazarsMaterial_version
Definition mazarsmodel.h:45
#define _IFT_MazarsMaterial_hrefc
Definition mazarsmodel.h:55
#define _IFT_MazarsMaterial_e0
Definition mazarsmodel.h:46
#define _IFT_MazarsMaterial_hreft
Definition mazarsmodel.h:54
#define _IFT_MazarsMaterial_bc
Definition mazarsmodel.h:48
#define _IFT_MazarsMaterial_bt
Definition mazarsmodel.h:51
long ContextMode
Definition contextmode.h:43
@ principal_strain
For computing principal strains from engineering strains.
@ CIO_IOERR
General IO error.
oofem::oofegGraphicContext gc[OOFEG_LAST_LAYER]

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