OOFEM 3.0
Loading...
Searching...
No Matches
b3solidmat.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 "b3solidmat.h"
36#include "mathfem.h"
37#include "gausspoint.h"
38#include "timestep.h"
39#include "contextioerr.h"
40#include "datastream.h"
41#include "classfactory.h"
42#include "engngm.h"
43#include "b3mat.h"
44
45namespace oofem {
47
48void
49B3SolidMaterial :: initializeFrom(InputRecord &ir)
50{
51 // ph!!!
52 //KelvinChainMaterial :: initializeFrom(ir);
53
54 //
55 // NOTE
56 //
57 // this material model is unit-dependent!
58 // units must be in MPa, m???, MN.
59 //
60
61 double fc = -1.0, c = -1.0, wc = -1.0, ac = -1.0, alpha1 = 1.0, alpha2 = 1.0;
62 double initHum; //MPS shrinkage parameter - initial value of humidity (range 0.2-0.98)
63 double finalHum; //MPS shrinkage parameter - final value of humidity (range 0.2-0.98)
64
65 // EmoduliMode has to be set first because characteristic times are computed from RheoChM initialization
66 this->EmoduliMode = 0;
67 // retardation spectrum or least square method is used. Retardation spectrum is default (EmoduliMode==0)
69
70 // characteristic time, usually 1 for analysis running in days
71 this->lambda0 = 1.;
73
74 KelvinChainMaterial :: initializeFrom(ir);
75
76 int mode = 0;
78
79 if ( mode == 0 ) { // default - estimate model parameters q1,..,q5 from composition
80 IR_GIVE_FIELD(ir, fc, _IFT_B3Material_fc); // 28-day standard cylinder compression strength [MPa]
81 IR_GIVE_FIELD(ir, c, _IFT_B3Material_cc); // cement content of concrete [kg/m^3]
82 IR_GIVE_FIELD(ir, wc, _IFT_B3Material_wc); // ratio (by weight) of water to cementitious material
83 IR_GIVE_FIELD(ir, ac, _IFT_B3Material_ac); // ratio (by weight) of aggregate to cement
84 IR_GIVE_FIELD(ir, t0, _IFT_B3Material_t0); // age when drying begins [days]
85 } else { // read model parameters for creep
90 }
91
92 // default value = 0; it can be used for basic creep without any external fields
93 this->MicroPrestress = 0; //if = 1 computation exploiting Microprestress solidification theory is done;
95
96 // is MPS theory used?
97 if ( this->MicroPrestress == 1 ) {
98 // microprestress-sol-theory: read data for microprestress evaluation
99 // constant c0 [MPa^-1 * day^-1]
101 // constant c1 (=C1*R*T/M)
103 // t0- necessary for the initial value of microprestress = S0 (age when drying begins)
104 // IR_GIVE_FIELD(ir, t0, _IFT_B3Material_t0);
105 this->tS0 = this->relMatAge;
106
107 // microprestress-sol-theory: read data for inverse desorption isotherm
111 }
112
113 // read shrinkage mode
114 int shm = 0;
116 this->shMode = ( b3ShModeType ) shm;
117
118 if ( this->shMode == B3_PointShrinkage ) { // #2 in enumerator
119
120 if ( this->MicroPrestress == 0 ) {
121 throw ValueInputException(ir, _IFT_B3SolidMaterial_microprestress, "to use B3_PointShrinkageMPS - MicroPrestress must be = 1"); //or else no external fiels would be found
122 }
123
124 kSh = -1;
125 initHum = -1;
126 finalHum = -1;
127
131
132 // either kSh or initHum and finalHum must be given in input record
133 if ( !( ( this->kSh != -1 ) || ( ( initHum != -1 ) && ( finalHum != -1 ) ) ) ) {
134 throw ValueInputException(ir, "none", "either kSh or initHum and finalHum must be given in input record");
135 }
136
137 if ( ( initHum < 0.2 || initHum > 0.98 ) && this->kSh == -1 ) {
138 throw ValueInputException(ir, _IFT_B3SolidMaterial_initialhumidity, "initital humidity out of range (0.2 - 0.98)");
139 }
140 if ( ( finalHum < 0.2 || finalHum > 0.98 ) && this->kSh == -1 ) {
141 throw ValueInputException(ir, _IFT_B3SolidMaterial_finalhumidity, "final humidity out of range (0.2 - 0.98)");
142 }
143
144
145 if ( this->kSh == -1 ) { // predict kSh from composition
146 IR_GIVE_OPTIONAL_FIELD(ir, alpha1, _IFT_B3Material_alpha1); // influence of cement type
147 IR_GIVE_OPTIONAL_FIELD(ir, alpha2, _IFT_B3Material_alpha2); // influence of curing type
148 this->kSh = alpha1 * alpha2 * ( 1 - pow(finalHum, 3.) ) * ( 0.019 * pow(wc * c, 2.1) * pow(fc, -0.28) + 270 ) * 1.e-6 / fabs(initHum - finalHum);
149 }
150
151 } else if ( this->shMode == B3_AverageShrinkage ) {
152 IR_GIVE_FIELD(ir, ks, _IFT_B3Material_ks); // cross-section shape factor
153 /*
154 * use ks = 1.0 for an infinite slab
155 * = 1.15 for an infinite cylinder
156 * = 1.25 for an infinite square prism
157 * = 1.30 for a sphere
158 * = 1.55 for a cube
159 */
160 IR_GIVE_FIELD(ir, hum, _IFT_B3Material_hum); // relative humidity of the environment
161 IR_GIVE_FIELD(ir, vs, _IFT_B3Material_vs); // volume-to-surface ratio (in m???)
162 if ( mode == 0 ) { // default mode - estimate model parameters kt, EpsSinf, q5 from composition
163 IR_GIVE_OPTIONAL_FIELD(ir, alpha1, _IFT_B3Material_alpha1); // influence of cement type
164 IR_GIVE_OPTIONAL_FIELD(ir, alpha2, _IFT_B3Material_alpha2); // influence of curing type
165 } else { // read model parameters
166 IR_GIVE_FIELD(ir, t0, _IFT_B3Material_t0); // age when drying begins [days]
170 }
171 }
172
173 // evaluate the total water content [kg/m^3]
174 w = wc * c;
175 // estimate the conventional modulus ??? what if fc is not given ???
176 E28 = 4733. * sqrt(fc);
177 // estimate parameters from composition
178 if ( mode == 0 ) {
179 this->predictParametersFrom(fc, c, wc, ac, t0, alpha1, alpha2);
180 }
181}
182
183void
184B3SolidMaterial :: predictParametersFrom(double fc, double c, double wc, double ac,
185 double t0, double alpha1, double alpha2)
186{
187 /*
188 * Prediction of model parameters - estimation from concrete composition
189 * and strength
190 *
191 * fc - 28-day standard cylinder compression strength in MPa
192 * c - cement content of concrete in kg/m^3
193 * wc - ratio (by weight) of water to cementitious material
194 * ac - ratio (by weight) of aggregate to cement
195 * t0 - age when drying begins (in days)
196 * alpha1, alpha2 - influence of cement type and curing
197 *
198 * The prediction of the material parameters of the present model
199 * is restricted to Portland cement concretes with the following
200 * parameter ranges:
201 *
202 * 2500 <= fc <= 10000 [psi] (psi = 6895 Pa)
203 * 10 <= c <= 45 [lb ft-3] (lb ft-3 = 16.03 kg m-3)
204 * 0.3 <= wc <= 0.85
205 * 2.5 <= ac <= 13.5
206 *
207 *
208 * alpha1 = 1.0 for type I cement;
209 * = 0.85 for type II cement;
210 * = 1.1 for type III cement;
211 *
212 * alpha2 = 0.75 for steam-cured specimens;
213 * = 1.2 for specimens sealed during curing;
214 * = 1.0 for specimens cured in water or 100% relative humidity.
215 *
216 */
217
218 // Basic creep parameters
219
220 // q1 = 0.6e6 / E28; // replaced by the formula dependent on fc
221 q1 = 126.74271 / sqrt(fc) * 1e-6;
222 q2 = 185.4 * pow(c, 0.5) * pow(fc, -0.9) * 1.e-6;
223 q3 = 0.29 * pow(wc, 4.) * q2;
224 q4 = 20.3 * pow(ac, -0.7) * 1.e-6;
225
226 // Shrinkage parameters
227
228 if ( this->shMode == B3_AverageShrinkage ) {
229 kt = 85000 * pow(t0, -0.08) * pow(fc, -0.25); // 85000-> result in [days/m^2] or 8.5-> result in [days/cm^2]
230 EpsSinf = alpha1 * alpha2 * ( 1.9e-2 * pow(w, 2.1) * pow(fc, -0.28) + 270. ); // exponent corrected: -0.25 -> -0.28
231
232 // Drying creep parameter
233 q5 = 7.57e5 * ( 1. / fc ) * pow(EpsSinf, -0.6);
234 }
235
236 char buff [ 1024 ];
237 sprintf(buff, "q1=%lf q2=%lf q3=%lf q4=%lf q5=%lf kt=%lf EpsSinf=%lf", q1, q2, q3, q4, q5, kt, EpsSinf);
238 OOFEM_LOG_DEBUG("B3mat[%d]: estimated params: %s\n", this->number, buff);
239}
240
241
242double
243B3SolidMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) const
244{
245 /*
246 * This function returns the incremental modulus for the given time increment.
247 * The modulus may also depend on the specimen geometry (gp - dependence).
248 *
249 * It is stored as "Einc" for further expected requests from other gaussPoints that correspond to the same material.
250 *
251 * Note: time -1 refers to the previous time.
252 */
253
254 // !!! chartime exponents are assumed to be equal to 1 !!!
255
256 double chainStiffness = 0.;
257
258 double v = computeSolidifiedVolume(tStep);
259 double eta = this->computeFlowTermViscosity(gp, tStep); //evaluated in the middle of the time-step
260
262 double t_halfstep = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor;
263 this->updateEparModuli( t_halfstep, gp, tStep );
264
265 if ( this->EmoduliMode == 0 ) { //retardation spectrum used
266 double sum;
267 // compute compliance of the Kelvin chain
268 sum = 1. / KelvinChainMaterial :: giveEModulus(gp, tStep);
269 // add compliance of non-aging spring
270 sum += 1. / EspringVal;
271 // convert to stiffness
272 chainStiffness = 1. / sum;
273
274 } else { //least-squares method used
275 chainStiffness = KelvinChainMaterial :: giveEModulus(gp, tStep);
276 }
277
278 return 1. / ( q1 + 1. / (chainStiffness * v) + 0.5 * ( tStep->giveTimeIncrement() / timeFactor ) / eta );
279}
280
281
282void
283B3SolidMaterial :: updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *tStep) const
284{
285 /*
286 * Since the elastic moduli are constant in time it is necessary to update them only once
287 * on the beginning of the computation
288 */
289 if ( this->EparVal.isEmpty() ) {
290 RheoChainMaterial :: updateEparModuli(tPrime, gp, tStep);
291 }
292}
293
294void
295B3SolidMaterial :: computeCharTimes()
296{
297 /*
298 * This function generates discrete characteristic times
299 * according to rules which guarantee a good approximation
300 * of the relaxation or creep function by the Dirichlet series
301 */
302
303 double Tau1;
304 int j;
305
306 if ( this->begOfTimeOfInterest == -1. ) {
307 this->begOfTimeOfInterest = 0.001 * lambda0;
308 }
309
310 if ( this->endOfTimeOfInterest == -1. ) {
311 this->endOfTimeOfInterest = 10000. * lambda0;
312 }
313
314
315 // perhaps different values should be used for moduli computed by the least-squares method
316 // this gives really big mistakes for times near the interest boundary
317
318 //first retardation time found in given by formula 0.3 * begOfTimeOfInterest
319 Tau1 = 0.3 * this->begOfTimeOfInterest;
320
321 //last retardation time has to be bigger than 0.5 * endOfTimeOfInterest
322 this->endOfTimeOfInterest = RheoChainMaterial :: giveEndOfTimeOfInterest();
323
324 j = 1;
325 while ( 0.5 * this->endOfTimeOfInterest >= Tau1 * pow( 10.0, ( double ) ( j - 1 ) ) ) {
326 j++;
327 }
328
329
330 this->nUnits = j;
331
332 this->charTimes.resize(this->nUnits);
333 this->charTimes.zero();
334
335 for ( int mu = 1; mu <= this->nUnits; mu++ ) {
336 charTimes.at(mu) = Tau1 * pow(10., mu - 1);
337 }
338}
339
340
342B3SolidMaterial :: computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const
343{
344 /*
345 * If EmoduliMode == 0 then analysis of continuous retardation spectrum is used for
346 * computing characteristic coefficients (moduli) of Kelvin chain
347 * Else least-squares method is used
348 */
349 if ( this->EmoduliMode == 0 ) {
350 // constant "n" is assumed to be equal to 0.1 (typical value)
351
352 // modulus of elasticity of the first unit of Kelvin chain.
353 // (aging elastic spring with retardation time = 0)
354 double lambda0ToPowN = pow(lambda0, 0.1);
355 double tau0 = pow(2 * this->giveCharTime(1) / sqrt(10.0), 0.1);
356 this->EspringVal = 1. / ( q2 * log(1.0 + tau0 / lambda0ToPowN) - q2 * tau0 / ( 10.0 * lambda0ToPowN + 10.0 * tau0 ) );
357
358 // evaluation of moduli of elasticity for the remaining units
359 // (Solidifying kelvin units with retardation times tauMu)
360 FloatArray answer(nUnits);
361 for ( int mu = 1; mu <= this->nUnits; mu++ ) {
362 double tauMu = pow(2 * this->giveCharTime(mu), 0.1);
363 answer.at(mu) = 10. * pow(1 + tauMu / lambda0ToPowN, 2) / ( log(10.0) * q2 * ( tauMu / lambda0ToPowN ) * ( 0.9 + tauMu / lambda0ToPowN ) );
364 this->charTimes.at(mu) *= 1.35;
365 }
366
367 answer.at(nUnits) /= 1.2; // modulus of the last unit is reduced
368 return answer;
369
370 } else { // moduli computed using the least-squares method
371
372 return KelvinChainMaterial :: computeCharCoefficients(tPrime, gp, tStep);
373
374 }
375}
376
377double
378B3SolidMaterial :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const
379// compute the value of the creep function of the non-aging solidifying constituent
380// corresponding to the given load duration (in days)
381// t-t_prime = duration of loading
382
383{
384 //double lambda0 = 1.0; // standard value [day]
385 double n = 0.1; // standard value
386 return q2 * log( 1 + pow( (t-t_prime) / lambda0, n) );
387}
388
389
390void
391B3SolidMaterial :: giveShrinkageStrainVector(FloatArray &answer,
392 GaussPoint *gp,
393 TimeStep *tStep,
394 ValueModeType mode) const
395{
396 FloatArray prevAnswer;
397
398 if ( this->shMode == B3_NoShrinkage ) {
399 answer.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) );
400 answer.zero();
401 return;
402 }
403
404 if ( ( mode != VM_Total ) && ( mode != VM_Incremental ) ) {
405 OOFEM_ERROR("unsupported mode");
406 }
407
408 if ( this->shMode == B3_AverageShrinkage ) {
409 this->computeTotalAverageShrinkageStrainVector(answer, gp, tStep);
410
411 if ( ( mode == VM_Incremental ) && ( !tStep->isTheFirstStep() ) ) {
412 this->computeTotalAverageShrinkageStrainVector( prevAnswer, gp, tStep->givePreviousStep() );
413 answer.subtract(prevAnswer);
414 }
415 } else {
416 this->computePointShrinkageStrainVector(answer, gp, tStep);
417 }
418}
419
420void
421B3SolidMaterial :: computeTotalAverageShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const
422{
423 /*
424 * returns average shrinkage strain vector of cross section at drying
425 */
426
427 double TauSh, St, kh, help, E607, Et0Tau, EpsShInf, EpsSh;
428 double time = this->relMatAge - this->castingTime + tStep->giveTargetTime() / timeFactor;
429 int size;
430 FloatArray fullAnswer;
431 MaterialMode mode = gp->giveMaterialMode();
432
433 if ( ( mode == _3dShell ) || ( mode == _3dBeam ) || ( mode == _2dPlate ) || ( mode == _2dBeam ) ) {
434 size = 12;
435 } else {
436 size = 6;
437 }
438
439 fullAnswer.resize(size);
440 fullAnswer.zero();
441
442 // size dependence
443 TauSh = kt * pow(ks * 2.0 * vs, 2.);
444 // time curve
445 St = tanh( pow( ( time - t0 ) / TauSh, 1. / 2. ) );
446 // humidity dependence
447 if ( hum <= 0.98 ) {
448 kh = 1. - pow(hum, 3);
449 } else if ( hum == 1 ) {
450 kh = -0.2; // swelling in water
451 } else {
452 // linear interpolation for 0.98 <= h <= 1.
453 help = 1. - pow(0.98, 3);
454 kh = help + ( -0.2 - help ) / ( 1. - 0.98 ) * ( hum - 0.98 );
455 }
456
457 // time dependence of ultimate shrinkage
458 E607 = E28 * pow(607 / ( 4. + 0.85 * 607 ), 0.5);
459 Et0Tau = E28 * pow( ( t0 + TauSh ) / ( 4. + 0.85 * ( t0 + TauSh ) ), 0.5 );
460
461 EpsShInf = EpsSinf * E607 / Et0Tau;
462 // mean shrinkage in the cross section:
463 EpsSh = -EpsShInf * kh * St;
464
465 fullAnswer.at(1) = fullAnswer.at(2) = fullAnswer.at(3) = EpsSh * 1.e-6;
466
467 StructuralMaterial :: giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() );
468}
469
470
471void
472B3SolidMaterial :: computePointShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const
473{
474 /* dEpsSh/dt = kSh * dh/dt (h = humidity)
475 * ->> EpsSh = kSh * h_difference
476 */
477 double humDiff, EpsSh;
478 int size;
479 FloatArray fullAnswer;
480 MaterialMode mode = gp->giveMaterialMode();
481
482 if ( ( mode == _3dShell ) || ( mode == _3dBeam ) || ( mode == _2dPlate ) || ( mode == _2dBeam ) ) {
483 size = 12;
484 } else {
485 size = 6;
486 }
487
488 humDiff = this->giveHumidityIncrement(gp, tStep);
489 EpsSh = humDiff * kSh;
490
491 fullAnswer.resize(size);
492 fullAnswer.zero();
493 fullAnswer.at(1) = fullAnswer.at(2) = fullAnswer.at(3) = EpsSh;
494
495 StructuralMaterial :: giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() );
496}
497
498
499double
500B3SolidMaterial :: computeSolidifiedVolume(TimeStep *tStep) const
501// compute the relative volume of the solidified material at given age (in days)
502{
503 double m, alpha;
504 double v; //return value
505 double atAge; // (equivalent age)
506
507 // standard values of exponents - empirical constants
508 m = 0.5;
509 //lambda0 = 1; //[day]
510 alpha = q3 / q2;
511
512 atAge = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor;
513 v = 1 / ( alpha + pow(lambda0 / atAge, m) );
514
515 return v;
516}
517
518
519double
520B3SolidMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) const
521//used for evaluation of the flow term viscosity (term containing q4)
522{
523 if ( this->MicroPrestress == 1 ) {
524 double S = this->computeMicroPrestress(gp, tStep, 0); //microprestress in the middle of the time-step
525 return 1. / ( q4 * c0 * S );
526 //static_cast< B3SolidMaterialStatus* >( gp->giveMaterialStatus() )->setMPS(S);
527 } else if ( this->MicroPrestress == 0 ) {
528 double tHalfStep = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor;
529 return 1. * tHalfStep / q4;
530 } else {
531 OOFEM_ERROR("mode is not supported");
532 }
533}
534
535
536void
537B3SolidMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const
538//
539// computes the strain due to creep at constant stress during the increment
540// (in fact, the INCREMENT of creep strain is computed for mode == VM_Incremental)
541//
542{
543 auto status = static_cast< KelvinChainMaterialStatus * >( this->giveStatus(gp) );
544
545 // !!! chartime exponents are assumed to be equal to 1 !!!
546 if ( mode == VM_Incremental ) {
547 double v = computeSolidifiedVolume(tStep);
548 double eta = this->computeFlowTermViscosity(gp, tStep); //evaluated too in the middle of the time-step
549
550 FloatArray help, reducedAnswer;
551 // sigma = status->giveStressVector(); //stress vector at the beginning of time-step
552 auto sigma = status->giveViscoelasticStressVector(); //stress vector at the beginning of time-step
553 FloatMatrix C;
554 this->giveUnitComplianceMatrix(C, gp, tStep);
555 reducedAnswer.resize( C.giveNumberOfRows() );
556 reducedAnswer.zero();
557
558 reducedAnswer.beProductOf(C, sigma);
559 reducedAnswer.times( tStep->giveTimeIncrement() / ( timeFactor * eta ) );
560
561 //computes non-aging creep component of the Kelvin Chain
562 KelvinChainMaterial :: giveEigenStrainVector(help, gp, tStep, mode);
563
564 help.times(1 / v);
565 reducedAnswer.add(help);
566
567 answer = reducedAnswer;
568 } else {
569 /* error - total mode not implemented yet */
570 OOFEM_ERROR("mode is not supported");
571 }
572}
573
574
575double
576B3SolidMaterial :: inverse_sorption_isotherm(double w) const
577// Function calculates relative humidity from water content (inverse relation form sorption isotherm).
578// Relative humidity (phi) is from range 0.2 - 0.98 !!!
579// sorption isotherm by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions,
580// PhD-thesis, Technical University of Denmark, Lyngby.
581// w (kg/kg) ... water content
582// phi ... relative humidity
583// w_h, n, a ... constants obtained from experiments
584{
585 // relative humidity
586 double phi = exp( a * ( 1.0 - pow( ( w_h / w ), ( n ) ) ) );
587
588 /*
589 * if ( ( phi < 0.2 ) || ( phi > 0.98 ) ) {
590 * OOFEM_ERROR("Relative humidity h = %e (w=%e) is out of range", phi, w);
591 * }
592 */
593
594 return phi;
595}
596
597
598double
599B3SolidMaterial :: computeMicroPrestress(GaussPoint *gp, TimeStep *tStep, int option) const
600{
601 //return 1.;//!!!!!!!!!!!!!!!!!!!!!!!!!!
602 /* numerically solves non-linear differential equation in form:
603 * dS/dt + c0*S^2 = -c1/h * dh/dt
604 * where "S" is the microprestress, "c0" and "c1" constants and "h" humidity
605 *
606 * If option == 0, microprestress is evaluated in the middle of the time step (used for stiffnesses)
607 * If option == 1, MPS is evaluated at the end of the time step. (Used for updating)
608 */
609 //UNCOMMENT THIS SECTION TO USE GENERALIZED TRAPEZOIDAL RULE
610 /* new value of S - "Stemp" is computed using the generalized trapezoidal rule
611 * with weights "1-alpha" and "alpha".
612 */
613
614 /*double S, Stemp; // old and new microprestress
615 * double humOld, humNew; // previous and new value of humidity
616 * double a, b, c, D; // auxiliary parameters used for solving quadratic equation
617 *
618 * double alpha = 0.5; // 0 for forward Euler method, 1 for backward, 0.5 for trapezoidal rule
619 * double deltaT;
620 * deltaT = tStep->giveTimeIncrement()/timeFactor;
621 *
622 * if(tStep->isTheFirstStep()){
623 * // if the time step is the first one, ask for an initial microprestress
624 * S = this->giveInitMicroPrestress();
625 * } else {
626 * B3SolidMaterialStatus *status = static_cast< B3SolidMaterialStatus * >( this->giveStatus(gp) );
627 * S = status->giveMPS();
628 * }
629 *
630 * humOld = this->giveHumidity(gp, tStep) - this->giveHumidityIncrement(gp, tStep);
631 *
632 * if (option == 1) {
633 * humNew = this->giveHumidity(gp, tStep);
634 * } else if (option == 0) {
635 * deltaT /= 2;
636 * humNew = humOld + 0.5*(this->giveHumidityIncrement(gp, tStep)); //linearly approximated
637 * } else {
638 * OOFEM_ERROR("invalid option parameter");
639 * }
640 *
641 * a = c0 * alpha * deltaT;
642 * b = 1.;
643 * c = -S + c1* (1-alpha)*(humNew/humOld -1) + c1*alpha*(1- humOld/humNew) + deltaT*pow(S, 2.)*(1-alpha)*c0;
644 *
645 * D = pow(b, 2.) - 4 * a * c; // discriminant
646 * Stemp = ( -b + sqrt(D) )/ (2 * a); // only positive root of quadr. equation is solved
647 *
648 * return Stemp;*/
649
650 // THIS SECTION USES PARTICULAR SOLUTION OF THE GOVERNING DIFFERENTIAL EQUATION
651 double S, Stemp; // old and new microprestress
652 double humOld, humNew; // previous and new value of humidity
653 double A; // auxiliary variable
654 double RHS; // constant RHS of the diff equation
655 double dHdt; // first time difference of the humidity
656 double deltaT; // length of the time step
657
658 deltaT = tStep->giveTimeIncrement() / timeFactor;
659 if ( tStep->isTheFirstStep() ) {
660 // if the time step is the first one, ask for an initial microprestress
661 S = this->giveInitMicroPrestress();
662 } else {
663 B3SolidMaterialStatus *status = static_cast< B3SolidMaterialStatus * >( this->giveStatus(gp) );
664 S = status->giveMPS();
665 }
666
667 humOld = this->giveHumidity(gp, tStep) - this->giveHumidityIncrement(gp, tStep);
668 if ( option == 1 ) { // hum in the end of the time step
669 humNew = this->giveHumidity(gp, tStep);
670 } else if ( option == 0 ) { // hum in the middle of the time step
671 deltaT /= 2;
672 humNew = humOld + 0.5 * ( this->giveHumidityIncrement(gp, tStep) ); //linearly approximated
673 } else {
674 OOFEM_ERROR("invalid option parameter");
675 }
676
677 //following section is used if humidity remains constant
678 if ( ( humNew - humOld ) == 0. ) {
679 Stemp = 1 / ( 1 / S + c0 * deltaT );
680 } else { // the following section is used only if there is a change in humidity
681 dHdt = ( humNew - humOld ) / deltaT;
682 RHS = fabs(c1 * dHdt / humNew);
683 A = sqrt(RHS / c0);
684 Stemp = A * ( 1 - 2 * ( A - S ) / ( ( A - S ) + ( A + S ) * exp( 2 * deltaT * sqrt(RHS * c0) ) ) );
685 }
686
687 return Stemp;
688}
689
690
691double
692B3SolidMaterial :: giveInitMicroPrestress() const
693{
694 return 1 / ( c0 * tS0 );
695}
696
697
698double
699B3SolidMaterial :: giveHumidity(GaussPoint *gp, TimeStep *tStep) const //computes humidity at given TimeStep
700{
701 /* ask for humidity from external sources, if provided */
702 FieldManager *fm = domain->giveEngngModel()->giveContext()->giveFieldManager();
703 FieldPtr tf;
704
705 if ( ( tf = fm->giveField(FT_HumidityConcentration) ) ) {
706 // humidity field registered
707 FloatArray gcoords, et2;
708 int err;
709 gp->giveElement()->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() );
710 if ( ( err = tf->evaluateAt(et2, gcoords, VM_Total, tStep) ) ) {
711 OOFEM_ERROR("tf->evaluateAt failed, error value %d", err);
712 }
713
714 // convert water mass to relative humidity
715 return this->inverse_sorption_isotherm( et2.at(1) );
716 } else {
717 OOFEM_ERROR("external fields not found");
718 return 0.;
719 }
720
721}
722
723
724double
725B3SolidMaterial :: giveHumidityIncrement(GaussPoint *gp, TimeStep *tStep) const //computes humidity increment at given TimeStep
726{
727 /* ask for humidity from external sources, if provided */
728 FieldManager *fm = domain->giveEngngModel()->giveContext()->giveFieldManager();
729 FieldPtr tf;
730
731 if ( ( tf = fm->giveField(FT_HumidityConcentration) ) ) {
732 // humidity field registered
733 FloatArray gcoords, et2, ei2;
734 int err;
735 gp->giveElement()->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() );
736 if ( ( err = tf->evaluateAt(et2, gcoords, VM_Total, tStep) ) ) {
737 OOFEM_ERROR("tf->evaluateAt failed, error value %d", err);
738 }
739
740 if ( ( err = tf->evaluateAt(ei2, gcoords, VM_Incremental, tStep) ) ) {
741 OOFEM_ERROR("tf->evaluateAt failed, error value %d", err);
742 }
743
744 // convert water mass to relative humidity
745 return this->inverse_sorption_isotherm( et2.at(1) ) - this->inverse_sorption_isotherm( et2.at(1) - ei2.at(1) );
746 } else {
747 OOFEM_ERROR("external fields not found");
748 return 0.;
749 }
750}
751
752
753std::unique_ptr<MaterialStatus>
754B3SolidMaterial :: CreateStatus(GaussPoint *gp) const
755/*
756 * creates a new material status corresponding to this class
757 */
758{
759 return std::make_unique<B3SolidMaterialStatus>(gp, nUnits);
760}
761
762
763void
764B3SolidMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) const
765{
766 KelvinChainMaterial :: giveRealStressVector(answer, gp, reducedStrain, tStep);
767
768 B3SolidMaterialStatus *status = static_cast< B3SolidMaterialStatus * >( this->giveStatus(gp) );
769 if ( this->MicroPrestress == 1 ) {
770 status->setMPS( this->computeMicroPrestress(gp, tStep, 1) );
771 }
772}
773
774
775/****************************************************************************************/
776/********** B3SolidMaterialStatus - HUMIDITY ****************************************/
777
778
779B3SolidMaterialStatus :: B3SolidMaterialStatus(GaussPoint *g, int nunits) :
780 KelvinChainMaterialStatus(g, nunits) { }
781
782void
783B3SolidMaterialStatus :: updateYourself(TimeStep *tStep)
784{
787
788 KelvinChainMaterialStatus :: updateYourself(tStep);
789}
790
791
792void
793B3SolidMaterialStatus :: saveContext(DataStream &stream, ContextMode mode)
794{
795 KelvinChainMaterialStatus :: saveContext(stream, mode);
796
797 if ( !stream.write(microprestress_old) ) {
799 }
800}
801
802void
803B3SolidMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode)
804{
805 KelvinChainMaterialStatus :: restoreContext(stream, mode);
806
807 if ( !stream.read(microprestress_old) ) {
809 }
810}
811} // end namespace oofem
#define _IFT_B3Material_vs
Definition b3mat.h:61
#define _IFT_B3Material_EpsSinf
Definition b3mat.h:68
#define _IFT_B3Material_ncoeff
Definition b3mat.h:55
#define _IFT_B3Material_ac
Definition b3mat.h:48
#define _IFT_B3Material_alpha2
Definition b3mat.h:58
#define _IFT_B3Material_wc
Definition b3mat.h:47
#define _IFT_B3Material_q2
Definition b3mat.h:63
#define _IFT_B3Material_kt
Definition b3mat.h:67
#define _IFT_B3Material_q5
Definition b3mat.h:66
#define _IFT_B3Material_cc
Definition b3mat.h:46
#define _IFT_B3Material_q1
Definition b3mat.h:62
#define _IFT_B3Material_fc
Definition b3mat.h:45
#define _IFT_B3Material_q3
Definition b3mat.h:64
#define _IFT_B3Material_mode
Definition b3mat.h:43
#define _IFT_B3Material_q4
Definition b3mat.h:65
#define _IFT_B3Material_a
Definition b3mat.h:56
#define _IFT_B3Material_hum
Definition b3mat.h:60
#define _IFT_B3Material_wh
Definition b3mat.h:54
#define _IFT_B3Material_t0
Definition b3mat.h:49
#define _IFT_B3Material_shmode
Definition b3mat.h:44
#define _IFT_B3Material_alpha1
Definition b3mat.h:57
#define _IFT_B3Material_ks
Definition b3mat.h:59
#define _IFT_B3SolidMaterial_initialhumidity
Definition b3solidmat.h:49
#define _IFT_B3SolidMaterial_emodulimode
Definition b3solidmat.h:43
#define _IFT_B3SolidMaterial_finalhumidity
Definition b3solidmat.h:48
#define _IFT_B3SolidMaterial_c1
Definition b3solidmat.h:46
#define _IFT_B3SolidMaterial_microprestress
Definition b3solidmat.h:44
#define _IFT_B3SolidMaterial_c0
Definition b3solidmat.h:45
#define _IFT_B3SolidMaterial_lambda0
Definition b3solidmat.h:50
#define _IFT_B3SolidMaterial_ksh
Definition b3solidmat.h:47
#define REGISTER_Material(class)
void setMPS(double src)
Definition b3solidmat.h:73
double microprestress_old
Microprestresses.
Definition b3solidmat.h:61
double giveHumidity(GaussPoint *gp, TimeStep *tStep) const
Computes relative humidity at given time step and GP.
Definition b3solidmat.C:699
double computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) const
Evaluation of the flow term viscosity.
Definition b3solidmat.C:520
double n
Constant-exponent (obtained from experiments) n [Pedersen, 1990].
Definition b3solidmat.h:101
void computePointShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const
Evaluation of the shrinkageStrainVector. Shrinkage is fully dependent on humidity rate in given GP.
Definition b3solidmat.C:472
double a
Constant (obtained from experiments) A [Pedersen, 1990].
Definition b3solidmat.h:102
double inverse_sorption_isotherm(double w) const
Definition b3solidmat.C:576
double giveInitMicroPrestress() const
Computes initial value of the MicroPrestress.
Definition b3solidmat.C:692
double computeSolidifiedVolume(TimeStep *tStep) const
Evaluation of the relative volume of the solidified material.
Definition b3solidmat.C:500
enum oofem::B3SolidMaterial::b3ShModeType shMode
double lambda0
constant equal to one day in time units of analysis (eg. 86400 if the analysis runs in seconds)
Definition b3solidmat.h:92
double giveHumidityIncrement(GaussPoint *gp, TimeStep *tStep) const
Computes relative humidity increment at given time step and GP.
Definition b3solidmat.C:725
double EpsSinf
Additional parameters for average cross section shrinkage.
Definition b3solidmat.h:96
double computeMicroPrestress(GaussPoint *gp, TimeStep *tStep, int option) const
Definition b3solidmat.C:599
double tS0
MPS tS0 - necessary for the initial value of microprestress (age when the load is applied).
Definition b3solidmat.h:116
double w_h
Constant water content (obtained from experiments) w_h [Pedersen, 1990].
Definition b3solidmat.h:100
double EspringVal
elastic modulus of the aging spring (first member of Kelvin chain if retardation spectrum is used)
Definition b3solidmat.h:103
void predictParametersFrom(double, double, double, double, double, double, double)
Definition b3solidmat.C:184
void updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *tStep) const override
Update of partial moduli of individual chain units.
Definition b3solidmat.C:283
double c1
MPS constant c1 (=C1*R*T/M).
Definition b3solidmat.h:115
void computeTotalAverageShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const
Definition b3solidmat.C:421
double c0
MPS constant c0 [MPa^-1 * day^-1].
Definition b3solidmat.h:114
double kSh
MPS shrinkage parameter. Either this or inithum and finalhum must be given in input record.
Definition b3solidmat.h:117
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.
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
int number
Component number.
Definition femcmpnn.h:77
FieldPtr giveField(FieldType key)
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void add(const FloatArray &src)
Definition floatarray.C:218
void subtract(const FloatArray &src)
Definition floatarray.C:320
void times(double s)
Definition floatarray.C:834
int giveNumberOfRows() const
Returns number of rows of receiver.
MaterialMode giveMaterialMode()
Returns corresponding material mode of receiver.
Definition gausspoint.h:190
KelvinChainMaterialStatus(GaussPoint *g, int nunits)
Definition kelvinChM.C:290
virtual MaterialStatus * giveStatus(GaussPoint *gp) const
Definition material.C:206
double castingTime
Definition material.h:115
int nUnits
Number of (Maxwell or Kelvin) units in the rheologic chain.
Definition rheoChM.h:145
double relMatAge
Physical age of the material at castingTime.
Definition rheoChM.h:147
double giveCharTime(int) const
Access to the characteristic time of a given unit.
Definition rheoChM.C:396
double endOfTimeOfInterest
Time (age???) up to which the model should give a good approximation.
Definition rheoChM.h:160
FloatArray EparVal
Partial moduli of individual units.
Definition rheoChM.h:166
void giveUnitComplianceMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) const
Evaluation of elastic compliance matrix for unit Young's modulus.
Definition rheoChM.C:286
double begOfTimeOfInterest
Time from which the model should give a good approximation. Optional field. Default value is 0....
Definition rheoChM.h:158
FloatArray charTimes
Characteristic times of individual units (relaxation or retardation times).
Definition rheoChM.h:169
double giveTimeIncrement()
Returns solution step associated time increment.
Definition timestep.h:168
double giveTargetTime()
Returns target time.
Definition timestep.h:164
TimeStep * givePreviousStep()
Returns pointer to previous solution step.
Definition timestep.C:132
bool isTheFirstStep()
Definition timestep.C:148
#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 OOFEM_LOG_DEBUG(...)
Definition logger.h:144
#define S(p)
Definition mdm.C:469
long ContextMode
Definition contextmode.h:43
double sum(const FloatArray &x)
std::shared_ptr< Field > FieldPtr
Definition field.h:78
@ CIO_IOERR
General IO error.

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011