OOFEM 3.0
Loading...
Searching...
No Matches
idmgrad.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 "idmgrad.h"
36#include "gausspoint.h"
37#include "floatmatrix.h"
38#include "floatarray.h"
39#include "mathfem.h"
40#include "sparsemtrx.h"
42#include "error.h"
43#include "nonlocalmaterialext.h"
44#include "datastream.h"
45#include "contextioerr.h"
46#include "stressvector.h"
47#include "strainvector.h"
48#include "classfactory.h"
49
50namespace oofem {
52
53IsotropicGradientDamageMaterial :: IsotropicGradientDamageMaterial(int n, Domain *d) :
56{}
57
58
59void
60IsotropicGradientDamageMaterial :: initializeFrom(InputRecord &ir)
61{
62 IsotropicDamageMaterial1 :: initializeFrom(ir);
63 GradientDamageMaterialExtensionInterface :: initializeFrom(ir);
64
65 int formulationType = 0;
67 if ( formulationType == 0 ) {
69 } else if ( formulationType == 1 ) {
71 di_rho = 0.005;
72 di_eta = 5;
75 } else if ( formulationType == 2 ) {
77 } else {
78 throw ValueInputException(ir, _IFT_IsotropicGradientDamageMaterial_formulationType, "Unknown gradient damage formulation");
79 }
80
81
82 return this->mapper.initializeFrom(ir);
83}
84
86
87
88
89bool
90IsotropicGradientDamageMaterial :: hasMaterialModeCapability(MaterialMode mode) const
91{
92 return mode == _1dMat || mode == _PlaneStress || mode == _PlaneStrain || mode == _3dMat;
93}
94
95void
96IsotropicGradientDamageMaterial :: giveStiffnessMatrix(FloatMatrix &answer,
97 MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const
98//
99// Returns characteristic material stiffness matrix of the receiver
100//
101{
102 OOFEM_ERROR("Shouldn't be called.");
103}
104
105
106void
107IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
108{
110 double tempDamage;
111 if ( mode == ElasticStiffness ) {
112 tempDamage = 0.0;
113 } else {
114 tempDamage = status->giveTempDamage();
115 if ( tempDamage > 0.0 ) {
116 tempDamage = min(tempDamage, maxOmega);
117 }
118 }
119
120 this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep);
121 answer.times(1.0 - tempDamage);
122
123
124 /*
125 * FloatArray strainP, stressP, oldStrain, oldStress;
126 * oldStress = status->giveTempStressVector();
127 * oldStrain = status->giveTempStrainVector();
128 * strainP = oldStrain;
129 * double pert = 1.e-6 * strainP.at(1);
130 * strainP.at(1) += pert;
131 * double lddv;
132 * double mddv = status->giveTempNonlocalDamageDrivingVariable();
133 * this->giveRealStressVectorGradientDamage(stressP, lddv, gp, strainP, mddv, tStep);
134 * FloatMatrix stiff;
135 * stiff.resize(1,1);
136 * stiff.at(1,1) = (stressP.at(1) - oldStress.at(1))/pert;
137 * this->giveRealStressVectorGradientDamage(stressP, lddv, gp, oldStrain, mddv, tStep);
138 */
139}
140
141
142
143
144void
145IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
146{
148 FloatArray stress = status->giveTempStressVector();
149 if ( mode == TangentStiffness ) {
150 double nonlocalDamageDrivingVariable = status->giveTempNonlocalDamageDrivingVariable();
151 double gPrime = this->damageFunctionPrime(nonlocalDamageDrivingVariable, gp);
152 double tempDamage = status->giveTempDamage();
153 if ( tempDamage < 1. ) {
154 stress.times( 1. / ( 1 - tempDamage ) );
155 } else {
156 stress.times(0.);
157 }
158 answer=FloatMatrix::fromArray(stress, false);
159 if ( tempDamage > status->giveDamage() ) {
160 answer.times(-gPrime);
161 /*
162 * double lddv;
163 * FloatArray strainP, stressP, oldStrain, oldStress;
164 * oldStress = status->giveTempStressVector();
165 * oldStrain = status->giveTempStrainVector();
166 * double mddv = status->giveTempNonlocalDamageDrivingVariable();
167 * double pert = 1.e-6 * mddv;
168 * strainP = oldStrain;
169 * double mddvp = mddv + pert;
170 * this->giveRealStressVectorGradientDamage(stressP, lddv, gp, strainP, mddvp, tStep);
171 * FloatMatrix stiff;
172 * stiff.resize(1,1);
173 * stiff.at(1,1) = (stressP.at(1) -oldStress.at(1))/pert;
174 * this->giveRealStressVectorGradientDamage(stressP, lddv, gp, oldStrain, mddv, tStep);
175 */
176 } else {
177 answer.times(0.);
178 }
179 // zero block for now
180 } else {
181 answer=FloatMatrix::fromArray(stress, false);
182 answer.times(0);
183 }
184}
185
186
187void
188IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
189{
191
192 FloatArray eta, reducedStrain;
193 FloatArray totalStrain = status->giveTempStrainVector();
194 StructuralMaterial :: giveReducedSymVectorForm( reducedStrain, totalStrain, gp->giveMaterialMode() );
195 this->computeEta(eta, reducedStrain, gp, tStep);
196 answer=FloatMatrix::fromArray(eta, false);
197 if ( mode == TangentStiffness ) {
198 double tempDamage = status->giveTempDamage();
199 if ( tempDamage > status->giveDamage() ) {
200 answer.times(-1.);
201 /*
202 * FloatArray strainP, stressP, oldStrain, oldStress;
203 * oldStress = status->giveTempStressVector();
204 * oldStrain = status->giveTempStrainVector();
205 * double mddv = status->giveTempNonlocalDamageDrivingVariable();
206 * double lddv = status->giveTempLocalDamageDrivingVariable();
207 * double lddvp;
208 * strainP = oldStrain;
209 * double pert = 1.e-6 * strainP.at(1);
210 * strainP.at(1) += pert;
211 * this->giveRealStressVectorGradientDamage(stressP, lddvp, gp, strainP, mddv, tStep);
212 * FloatMatrix stiff;
213 * stiff.resize(1,1);
214 * stiff.at(1,1) = (lddvp - lddv) / pert;
215 * this->giveRealStressVectorGradientDamage(stressP, lddv, gp, oldStrain, mddv, tStep);
216 */
217
218
220 double iA = this->computeEikonalInternalLength_a(gp);
221 if ( iA != 0 ) {
222 answer.times(1. / iA);
223 } else {
224 answer.times(0);
225 }
226 }
227 }
228 } else {
229 answer.times(0);
230 }
231}
232
233
234
235void
236IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_dd_NN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
237{
240 double tempKappa = status->giveTempKappa();
241 double iA = this->computeEikonalInternalLength_a(gp);
242
243 answer.resize(1, 1);
244 answer.zero();
245
246 if ( iA != 0 ) {
247 answer.at(1, 1) += 1. / iA;
248 }
249
250 if ( mode == TangentStiffness ) {
251 if ( tempKappa > status->giveKappa() && iA != 0 ) {
252 double iAPrime = this->computeEikonalInternalLength_aPrime(gp);
253 double gPrime = this->damageFunctionPrime(tempKappa, gp);
254 double epsEqLocal = status->giveTempLocalDamageDrivingVariable();
255 double epsEqNonLocal = status->giveTempNonlocalDamageDrivingVariable();
256 answer.at(1, 1) += iAPrime / iA / iA * gPrime * ( epsEqNonLocal - epsEqLocal );
257 }
258 }
259 } else {
260 answer.clear();
261 }
262}
263
264double
265IsotropicGradientDamageMaterial :: computeEikonalInternalLength_a(GaussPoint *gp)
266{
268
269 double damage = status->giveTempDamage();
270 return sqrt(1. - damage) * internalLength;
271}
272
273double
274IsotropicGradientDamageMaterial :: computeEikonalInternalLength_b(GaussPoint *gp)
275{
277
278 double damage = status->giveTempDamage();
279 return sqrt(1. - damage) * internalLength;
280}
281
282
283double
284IsotropicGradientDamageMaterial :: computeEikonalInternalLength_aPrime(GaussPoint *gp)
285{
287
288 double damage = status->giveTempDamage();
289 return -0.5 / sqrt(1. - damage) * internalLength;
290}
291
292double
293IsotropicGradientDamageMaterial :: computeEikonalInternalLength_bPrime(GaussPoint *gp)
294{
296
297 double damage = status->giveTempDamage();
298 return -0.5 / sqrt(1. - damage) * internalLength;
299}
300
301
302
303void
304IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
305{
306 int n = this->giveDimension(gp);
307 answer.resize(n, n);
308 answer.beUnitMatrix();
309
313 double iL = this->computeInternalLength(gp);
314 answer.times(iL * iL);
316 double iB = this->computeEikonalInternalLength_b(gp);
317 answer.times(iB);
318 } else {
319 OOFEM_WARNING("Unknown internalLengthDependenceType");
320 }
321}
322
323
324void
325IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_dd_BN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
326{
327 if ( mode == TangentStiffness ) {
329 answer.clear();
332 double damage = status->giveTempDamage();
333 double tempKappa = status->giveTempKappa();
334 double iL = computeInternalLength(gp);
335 double nom = -di_eta * ( 1. - di_rho ) * exp(-di_eta * damage);
336 double denom = sqrt( ( 1. - exp(-di_eta) ) * ( ( 1. - di_rho ) * exp(-di_eta * damage) + di_rho - exp(-di_eta) ) );
337 double gPrime = this->damageFunctionPrime(tempKappa, gp);
338 double factor = iL * internalLength * nom / denom * gPrime;
340 if ( tempKappa > status->giveKappa() ) {
341 answer.times(factor);
342 } else {
343 answer.times(0.);
344 }
347 double tempKappa = status->giveTempKappa();
348
349 double iBPrime = this->computeEikonalInternalLength_bPrime(gp);
350 double gPrime = this->damageFunctionPrime(tempKappa, gp);
351
353
354 if ( tempKappa > status->giveKappa() ) {
355 answer.times(iBPrime * gPrime);
356 } else {
357 answer.times(0.);
358 }
359 } else {
360 OOFEM_WARNING("Unknown internalLengthDependenceType");
361 }
362 } else {
363 answer.clear();
364 }
365}
366
367
368int
369IsotropicGradientDamageMaterial :: giveDimension(GaussPoint *gp)
370{
371 if ( gp->giveMaterialMode() == _1dMat ) {
372 return 1;
373 } else if ( gp->giveMaterialMode() == _PlaneStress ) {
374 return 2;
375 } else if ( gp->giveMaterialMode() == _PlaneStrain ) {
376 return 3;
377 } else if ( gp->giveMaterialMode() == _3dMat ) {
378 return 3;
379 } else {
380 return 0;
381 }
382}
383
384void
385IsotropicGradientDamageMaterial :: giveNonlocalInternalForces_N_factor(double &answer, double nlDamageDrivingVariable, GaussPoint *gp, TimeStep *tStep)
386{
388 answer = nlDamageDrivingVariable - status->giveTempLocalDamageDrivingVariable();
389
391 double iA = this->computeEikonalInternalLength_a(gp);
392 if ( iA != 0 ) {
393 answer = answer / iA;
394 }
395 }
396}
397
398void
399IsotropicGradientDamageMaterial :: giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlDamageDrivingVariable_grad, GaussPoint *gp, TimeStep *tStep)
400{
401 answer = nlDamageDrivingVariable_grad;
403 double iB = this->computeEikonalInternalLength_b(gp);
404 answer.times(iB);
405 } else {
406 double iL = computeInternalLength(gp);
407 answer.times(iL * iL);
408 }
409}
410
411
412double
413IsotropicGradientDamageMaterial :: computeInternalLength(GaussPoint *gp)
414{
416 return internalLength;
419 double damage = status->giveTempDamage();
420 double factor = ( ( 1. - di_rho ) * exp(-di_eta * damage) + di_rho - exp(-di_eta) ) / ( 1. - exp(-di_eta) );
421 return internalLength * sqrt(factor);
422 } else {
423 OOFEM_WARNING("Unknown internalLengthDependenceType");
424 return 0.;
425 }
426}
427
428
429void
430IsotropicGradientDamageMaterial :: giveRealStressVectorGradientDamage(FloatArray &stress, double &localDamageDrivingVariable, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalDamageDrivingVariable, TimeStep *tStep)
431//
432// returns real stress vector in 3d stress space of receiver according to
433// previous level of stress and current
434// strain increment, the only way, how to correctly update gp records
435//
436{
437 auto status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) );
438 auto lmat = this->giveLinearElasticMaterial();
439 FloatArray reducedTotalStrainVector, strain;
440
441 FloatMatrix de;
442 double f, damage, tempKappa = 0.0;
443
444 this->initTempStatus(gp);
445
446 // subtract stress independent part
447 // note: eigenStrains (temperature) is not contained in mechanical strain stored in gp
448 // therefore it is necessary to subtract always the total eigen strain value
449 this->giveStressDependentPartOfStrainVector(reducedTotalStrainVector, gp, totalStrain, tStep, VM_Total);
450
451
452 // compute equivalent strain
453 localDamageDrivingVariable = this->computeEquivalentStrain(reducedTotalStrainVector, gp, tStep);
454
455 if ( llcriteria == idm_strainLevelCR ) {
456 // compute value of loading function if strainLevel crit apply
457 f = nonlocalDamageDrivingVariable - status->giveKappa();
458 if ( f <= 0.0 ) {
459 // damage does not grow
460 tempKappa = status->giveKappa();
461 damage = status->giveDamage();
462 } else {
463 // damage grow
464 tempKappa = nonlocalDamageDrivingVariable;
465 this->initDamaged(nonlocalDamageDrivingVariable, reducedTotalStrainVector, gp);
466 // evaluate damage parameter
467 damage = this->computeDamageParam(nonlocalDamageDrivingVariable, reducedTotalStrainVector, gp);
468 }
469 } else if ( llcriteria == idm_damageLevelCR ) {
470 // evaluate damage parameter first
471 tempKappa = nonlocalDamageDrivingVariable;
472 this->initDamaged(nonlocalDamageDrivingVariable, strain, gp);
473 damage = this->computeDamageParam(nonlocalDamageDrivingVariable, reducedTotalStrainVector, gp);
474 if ( damage < status->giveDamage() ) {
475 // unloading takes place
476 damage = status->giveDamage();
477 }
478 } else {
479 OOFEM_ERROR("unsupported loading/uloading criteria");
480 }
481
482
483 lmat->giveStiffnessMatrix(de, SecantStiffness, gp, tStep);
484 de.times(1.0 - damage);
485 stress.beProductOf(de, reducedTotalStrainVector);
486
487 // update gp
488 status->letTempStrainVectorBe(totalStrain);
489 status->letTempStressVectorBe(stress);
490 status->setTempLocalDamageDrivingVariable(localDamageDrivingVariable);
491 status->setTempNonlocalDamageDrivingVariable(nonlocalDamageDrivingVariable);
492 status->setTempKappa(tempKappa);
493 status->setTempDamage(damage);
494#ifdef keep_track_of_dissipated_energy
495 status->computeWork(gp);
496#endif
497}
498
499
500
501
502std::unique_ptr<MaterialStatus>
503IsotropicGradientDamageMaterial :: CreateStatus(GaussPoint *gp) const
504{
505 return std::make_unique<IsotropicGradientDamageMaterialStatus>(gp);
506}
507
508
509IsotropicGradientDamageMaterialStatus :: IsotropicGradientDamageMaterialStatus(GaussPoint *g) : IsotropicDamageMaterial1Status(g)
510{ }
511
512
513void
514IsotropicGradientDamageMaterialStatus :: initTempStatus()
515//
516// initializes temp variables according to variables form previous equlibrium state.
517// builds new crackMap
518//
519{
520 IsotropicDamageMaterial1Status :: initTempStatus();
521 GradientDamageMaterialStatusExtensionInterface :: initTempStatus();
522 this->tempDamage = this->damage;
523}
524
525
526
527void
528IsotropicGradientDamageMaterialStatus :: updateYourself(TimeStep *tStep)
529//
530// updates variables (nonTemp variables describing situation at previous equilibrium state)
531// after a new equilibrium state has been reached
532// temporary variables are having values corresponding to newly reched equilibrium.
533//
534{
535 IsotropicDamageMaterial1Status :: updateYourself(tStep);
536 GradientDamageMaterialStatusExtensionInterface :: updateYourself(tStep);
537}
538} // end namespace oofem
#define REGISTER_Material(class)
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void times(double s)
Definition floatarray.C:834
void times(double f)
static FloatMatrix fromArray(const FloatArray &vector, bool transpose=false)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
*Sets size of receiver to be an empty matrix It will have zero rows and zero columns size void clear()
void zero()
Zeroes all coefficient of receiver.
double at(std::size_t i, std::size_t j) const
void beUnitMatrix()
Sets receiver to unity matrix.
MaterialMode giveMaterialMode()
Returns corresponding material mode of receiver.
Definition gausspoint.h:190
IsotropicDamageMaterial1Status(GaussPoint *g)
Constructor.
Definition idm1.C:1492
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
double computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const override
Definition idm1.C:436
double computeDamageParam(double kappa, const FloatArray &strain, GaussPoint *gp) const override
Definition idm1.C:796
MaterialStatus * giveStatus(GaussPoint *gp) const override
Definition idm1.C:1392
void initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) const override
Definition idm1.C:1168
double damageFunctionPrime(double kappa, GaussPoint *gp) const override
Definition idm1.C:1024
void computeEta(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const override
Definition idm1.C:568
double damage
Damage level of material.
double giveKappa() const
Returns the last equilibrated scalar measure of the largest strain level.
double giveTempKappa() const
Returns the temp. scalar measure of the largest strain level.
double giveDamage() const
Returns the last equilibrated damage level.
double giveTempDamage() const
Returns the temp. damage level.
double tempDamage
Non-equilibrated damage level of material.
double maxOmega
Maximum limit on omega. The purpose is elimination of a too compliant material which may cause conver...
enum oofem::IsotropicDamageMaterial::loaUnloCriterium llcriteria
LinearElasticMaterial * giveLinearElasticMaterial() const
Returns reference to undamaged (bulk) material.
double computeEikonalInternalLength_a(GaussPoint *gp)
Definition idmgrad.C:265
int giveDimension(GaussPoint *gp)
Definition idmgrad.C:369
double computeEikonalInternalLength_b(GaussPoint *gp)
Definition idmgrad.C:274
GradientDamageFormulationType gradientDamageFormulationType
Definition idmgrad.h:66
double computeEikonalInternalLength_aPrime(GaussPoint *gp)
Definition idmgrad.C:284
double computeEikonalInternalLength_bPrime(GaussPoint *gp)
Definition idmgrad.C:293
double computeInternalLength(GaussPoint *gp)
Definition idmgrad.C:413
virtual void initTempStatus(GaussPoint *gp) const
Definition material.C:221
const FloatArray & giveTempStressVector() const
Returns the const pointer to receiver's temporary stress vector.
const FloatArray & giveTempStrainVector() const
Returns the const pointer to receiver's temporary strain vector.
void giveStressDependentPartOfStrainVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrainVector, TimeStep *tStep, ValueModeType mode) const
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
#define _IFT_IsotropicGradientDamageMaterial_formulationType
Definition idmgrad.h:43
#define _IFT_IsotropicGradientDamageMaterial_di_rho
Definition idmgrad.h:44
#define _IFT_IsotropicGradientDamageMaterial_di_eta
Definition idmgrad.h:45
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
FloatArrayF< N > min(const FloatArrayF< N > &a, const FloatArrayF< N > &b)

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