OOFEM 3.0
Loading...
Searching...
No Matches
kelvinChM.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## ## ## ## ##
6 * ## ## ## ## ## ## ## ##
7 * ##### ##### ## ###### ## ##
8 *
9 *
10 * OOFEM : Object Oriented Finite Element Code
11 *
12 * Copyright (C) 1993 - 2025 Borek Patzak
13 *
14 *
15 *
16 * Czech Technical University, Faculty of Civil Engineering,
17 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
18 *
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Lesser General Public
21 * License as published by the Free Software Foundation; either
22 * version 2.1 of the License, or (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
28 *
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32 */
33
34#include "mathfem.h"
35#include "kelvinChM.h"
36#include "floatarray.h"
37#include "floatmatrix.h"
38#include "gausspoint.h"
39#include "timestep.h"
40#include "contextioerr.h"
41
42
43namespace oofem {
44KelvinChainMaterial :: KelvinChainMaterial(int n, Domain *d) : RheoChainMaterial(n, d)
45{ }
46
48KelvinChainMaterial :: computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const
49{
50 /*
51 * This function computes the moduli of individual Kelvin units
52 * such that the corresponding Dirichlet series gives the best
53 * approximation of the actual compliance function J(t,t0) with t0 fixed.
54 *
55 * The optimal moduli are obtained using the least-square method.
56 *
57 * INPUTS:
58 * tPrime = age of material when load is applied
59 */
60
61 FloatArray rhs(this->nUnits);
62 FloatMatrix A(this->nUnits, this->nUnits);
63
64 const FloatArray &rTimes = this->giveDiscreteTimes();
65 int rSize = rTimes.giveSize();
66 FloatArray discreteComplianceFunctionVal(rSize);
67
68 // compute values of the compliance function at specified times rTimes
69 // (can be done directly, since the compliance function is available)
70
71 for ( int i = 1; i <= rSize; i++ ) {
72 discreteComplianceFunctionVal.at(i) = this->computeCreepFunction(tPrime + rTimes.at(i), tPrime, gp, tStep);
73 }
74
75 // assemble the matrix of the set of linear equations
76 // for computing the optimal compliances
77 // !!! chartime exponents are assumed to be equal to 1 !!!
78 for ( int i = 1; i <= this->nUnits; i++ ) {
79 double taui = this->giveCharTime(i);
80 for ( int j = 1; j <= this->nUnits; j++ ) {
81 double tauj = this->giveCharTime(j);
82 double sum = 0.;
83 for ( int r = 1; r <= rSize; r++ ) {
84 double tti = rTimes.at(r) / taui;
85 double ttj = rTimes.at(r) / tauj;
86 sum += ( 1. - exp(-tti) ) * ( 1. - exp(-ttj) );
87 }
88
89 A.at(i, j) = sum;
90 }
91
92 // assemble rhs
93 // !!! chartime exponents are assumed to be equal to 1 !!!
94 double sumRhs = 0.;
95 for ( int r = 1; r <= rSize; r++ ) {
96 double tti = rTimes.at(r) / taui;
97 sumRhs += ( 1. - exp(-tti) ) * discreteComplianceFunctionVal.at(r);
98 }
99
100 rhs.at(i) = sumRhs;
101 }
102
103 // solve the linear system
104 FloatArray answer;
105 A.solveForRhs(rhs, answer);
106
107 // convert compliances into moduli
108 for ( int i = 1; i <= this->nUnits; i++ ) {
109 answer.at(i) = 1. / answer.at(i);
110 }
111 return answer;
112}
113
114double
115KelvinChainMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) const
116{
117 /*
118 * This function returns the incremental modulus for the given time increment.
119 * Return value is the incremental E modulus of non-aging Kelvin chain without the first unit (elastic spring)
120 * The modulus may also depend on the specimen geometry (gp - dependence).
121 *
122 * Note: time -1 refers to the previous time.
123 */
124
125 double sum = 0.0; // return value
126
127 // the viscoelastic material does not exist yet
128 if ( ! Material :: isActivated( tStep ) ) {
129 OOFEM_ERROR("Attempted to evaluate E modulus at time lower than casting time");
130 }
131
133 double tPrime = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() );
134 this->updateEparModuli(tPrime, gp, tStep);
135
136 double deltaT = tStep->giveTimeIncrement();
137
138 // EparVal values were determined using the least-square method
139 for ( int mu = 1; mu <= nUnits; mu++ ) {
140 double tauMu = this->giveCharTime(mu);
141 double lambdaMu;
142 if ( deltaT / tauMu < 1.e-5 ) {
143 lambdaMu = 1 - 0.5 * ( deltaT / tauMu ) + 1 / 6 * ( pow(deltaT / tauMu, 2) ) - 1 / 24 * ( pow(deltaT / tauMu, 3) );
144 } else if ( deltaT / tauMu > 30 ) {
145 lambdaMu = tauMu / deltaT;
146 } else {
147 lambdaMu = ( 1.0 - exp(-deltaT / tauMu) ) * tauMu / deltaT;
148 }
149
150 double Dmu = this->giveEparModulus(mu);
151 sum += ( 1 - lambdaMu ) / Dmu;
152 }
153
154 // return sum;
155 // changed formulation to return stiffness instead of compliance
156 return 1. / sum;
157
158}
159
160void
161KelvinChainMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const
162//
163// computes the strain due to creep at constant stress during the increment
164// (in fact, the INCREMENT of creep strain is computed for mode == VM_Incremental)
165//
166{
167 auto status = static_cast< KelvinChainMaterialStatus * >( this->giveStatus(gp) );
168
169 // !!! chartime exponents are assumed to be equal to 1 !!!
170
171 if ( ! Material :: isActivated( tStep ) ) {
172 OOFEM_ERROR("Attempted to evaluate creep strain for time lower than casting time");
173 }
174
175 if ( mode == VM_Incremental ) {
176 FloatArray reducedAnswer;
177
178 for ( int mu = 1; mu <= nUnits; mu++ ) {
179 double beta;
180 if ( tStep->giveTimeIncrement() / this->giveCharTime(mu) > 30 ) {
181 beta = 0;
182 } else {
183 beta = exp( - tStep->giveTimeIncrement() / this->giveCharTime(mu) );
184 }
185
186 FloatArray *gamma = & status->giveHiddenVarsVector(mu); // JB
187 if ( gamma ) {
188 reducedAnswer.add(1.0 - beta, * gamma);
189 }
190 }
191
192 answer = reducedAnswer;
193 } else {
194 /* error - total mode not implemented yet */
195 OOFEM_ERROR("mode is not supported");
196 }
197}
198
199
200void
201KelvinChainMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) const
202{
203 RheoChainMaterial :: giveRealStressVector(answer, gp, reducedStrain, tStep);
204
205 this->computeHiddenVars(gp, tStep);
206}
207
208void
209KelvinChainMaterial :: computeHiddenVars(GaussPoint *gp, TimeStep *tStep) const
210{
211 /*
212 * Updates hidden variables used to effectively trace the load history
213 */
214
215 // !!! chartime exponents are assumed to be equal to 1 !!!
216
217 FloatArray help, delta_sigma;
218 KelvinChainMaterialStatus *status = static_cast< KelvinChainMaterialStatus * >( this->giveStatus(gp) );
219
220 // goes there if the viscoelastic material does not exist yet
221 if ( ! Material :: isActivated( tStep ) ) {
222 help.resize(StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) );
223 help.zero();
224 for ( int mu = 1; mu <= nUnits; mu++ ) {
225 status->letTempHiddenVarsVectorBe(mu, help);
226 }
227 return;
228 }
229
230 delta_sigma = status->giveTempStrainVector(); // gives updated strain vector (at the end of time-step)
231 delta_sigma.subtract( status->giveStrainVector() ); // strain increment in current time-step
232
233 // Subtract the stress-independent part of strain
234 auto deltaEps0 = this->computeStressIndependentStrainVector(gp, tStep, VM_Incremental);
235 if ( deltaEps0.giveSize() ) {
236 delta_sigma.subtract(deltaEps0); // should be equal to zero if there is no stress change during the time-step
237 }
238
239 // no need to worry about "zero-stiffness" for time < castingTime - this is done above
240 delta_sigma.times( this->giveEModulus(gp, tStep) ); // = delta_sigma
241
242 double deltaT = tStep->giveTimeIncrement();
243
244 for ( int mu = 1; mu <= nUnits; mu++ ) {
245 double betaMu;
246 double lambdaMu;
247 help = delta_sigma;
248 double tauMu = this->giveCharTime(mu);
249
250 if ( deltaT / tauMu < 1.e-5 ) {
251 betaMu = exp(-( deltaT ) / tauMu);
252 lambdaMu = 1 - 0.5 * ( deltaT / tauMu ) + 1 / 6 * ( pow(deltaT / tauMu, 2) ) - 1 / 24 * ( pow(deltaT / tauMu, 3) );
253 } else if ( deltaT / tauMu > 30 ) {
254 betaMu = 0;
255 lambdaMu = tauMu / deltaT;
256 } else {
257 betaMu = exp(-( deltaT ) / tauMu);
258 lambdaMu = ( 1.0 - betaMu ) * tauMu / deltaT;
259 }
260
261 help.times( lambdaMu / ( this->giveEparModulus(mu) ) );
262
263 FloatArray muthHiddenVarsVector = status->giveHiddenVarsVector(mu); //gamma_mu
264 if ( muthHiddenVarsVector.giveSize() ) {
265 muthHiddenVarsVector.times(betaMu);
266 muthHiddenVarsVector.add(help);
267 status->letTempHiddenVarsVectorBe(mu, muthHiddenVarsVector);
268 } else {
269 status->letTempHiddenVarsVectorBe(mu, help);
270 }
271 }
272}
273
274
275std::unique_ptr<MaterialStatus>
276KelvinChainMaterial :: CreateStatus(GaussPoint *gp) const
277{
278 return std::make_unique<KelvinChainMaterialStatus>(gp, nUnits);
279}
280
281void
282KelvinChainMaterial :: initializeFrom(InputRecord &ir)
283{
284 RheoChainMaterial :: initializeFrom(ir);
285 this->giveDiscreteTimes(); // Makes sure the new discrete times are evaluated.
286}
287
288/****************************************************************************************/
289
290KelvinChainMaterialStatus :: KelvinChainMaterialStatus(GaussPoint *g, int nunits) :
291 RheoChainMaterialStatus(g, nunits) { }
292
293void
294KelvinChainMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const
295{
296 RheoChainMaterialStatus :: printOutputAt(file, tStep);
297}
298
299
300void
301KelvinChainMaterialStatus :: updateYourself(TimeStep *tStep)
302{
303 RheoChainMaterialStatus :: updateYourself(tStep);
304}
305
306void
307KelvinChainMaterialStatus :: initTempStatus()
308{
309 RheoChainMaterialStatus :: initTempStatus();
310}
311
312void
313KelvinChainMaterialStatus :: saveContext(DataStream &stream, ContextMode mode)
314{
315 RheoChainMaterialStatus :: saveContext(stream, mode);
316}
317
318void
319KelvinChainMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode)
320{
321 RheoChainMaterialStatus :: restoreContext(stream, mode);
322}
323} // end namespace oofem
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 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
double at(std::size_t i, std::size_t j) const
bool solveForRhs(const FloatArray &b, FloatArray &answer, bool transpose=false)
MaterialMode giveMaterialMode()
Returns corresponding material mode of receiver.
Definition gausspoint.h:190
void computeHiddenVars(GaussPoint *gp, TimeStep *tStep) const
Definition kelvinChM.C:209
double giveEModulus(GaussPoint *gp, TimeStep *tStep) const override
Evaluation of the incremental modulus.
Definition kelvinChM.C:115
virtual MaterialStatus * giveStatus(GaussPoint *gp) const
Definition material.C:206
double castingTime
Definition material.h:115
RheoChainMaterialStatus(GaussPoint *g, int nunits)
Definition rheoChM.C:674
FloatArray & giveHiddenVarsVector(int i)
Definition rheoChM.h:103
void letTempHiddenVarsVectorBe(int i, FloatArray &valueArray)
Definition rheoChM.C:683
const FloatArray & giveDiscreteTimes() const
Definition rheoChM.C:260
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
RheoChainMaterial(int n, Domain *d)
Definition rheoChM.C:48
virtual double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const =0
Evaluation of the creep compliance function at time t when loading is acting from time t_prime.
double giveEparModulus(int iChain) const
Access to partial modulus of a given unit.
Definition rheoChM.C:303
virtual void updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *tStep) const
Update of partial moduli of individual chain units.
Definition rheoChM.C:313
FloatArray computeStressIndependentStrainVector(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override
Definition rheoChM.C:370
const FloatArray & giveStrainVector() const
Returns the const pointer to receiver's strain vector.
const FloatArray & giveTempStrainVector() const
Returns the const pointer to receiver's temporary strain vector.
double giveTimeIncrement()
Returns solution step associated time increment.
Definition timestep.h:168
double giveTargetTime()
Returns target time.
Definition timestep.h:164
#define OOFEM_ERROR(...)
Definition error.h:79
long ContextMode
Definition contextmode.h:43
double sum(const FloatArray &x)

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