b2api
B2000++ API Reference Manual, VERSION 4.6
 
Loading...
Searching...
No Matches
b2viscoelasticity.H
1//------------------------------------------------------------------------
2// b2visoelastity.H --
3//
4// written by Mathias Doreille
5// Neda Ebrahimi Pour <neda.ebrahimipour@dlr.de>
6//
7// (c) 2011, 2018 SMR Engineering & Development SA
8// 2502 Bienne, Switzerland
9//
10// (c) 2023 Deutsches Zentrum für Luft- und Raumfahrt (DLR) e.V.
11// Linder Höhe, 51147 Köln
12//
13// All Rights Reserved. Proprietary source code. The contents of
14// this file may not be disclosed to third parties, copied or
15// duplicated in any form, in whole or in part, without the prior
16// written permission of SMR.
17//------------------------------------------------------------------------
18
19#ifndef B2VISOELASTITY_H_
20#define B2VISOELASTITY_H_
21
22#include "b2solid_mechanics.H"
23#include "utils/b2exception.H"
24#include "utils/b2linear_algebra.H"
25#include "utils/b2object.H"
27#include "utils/b2type.H"
28
29namespace {
30
31template <typename T>
32inline void mult_mlp_v6(const T C[21], const T strain[6], T stress[6]) {
33 const b2000::b2linalg::Matrix<T, b2000::b2linalg::Mlower_packed_constref> C_tmp(6, C);
34 const b2000::b2linalg::Vector<T, b2000::b2linalg::Vdense_constref> strain_tmp(6, strain);
35 b2000::b2linalg::Vector<T, b2000::b2linalg::Vdense_ref> stress_tmp(6, stress);
36 stress_tmp = C_tmp * strain_tmp;
37}
38
39template <typename T>
40inline void mult_mlp_v8(const T C[36], const T strain[8], T stress[8]) {
41 const b2000::b2linalg::Matrix<T, b2000::b2linalg::Mlower_packed_constref> C_tmp(8, C);
42 const b2000::b2linalg::Vector<T, b2000::b2linalg::Vdense_constref> strain_tmp(8, strain);
43 b2000::b2linalg::Vector<T, b2000::b2linalg::Vdense_ref> stress_tmp(8, stress);
44 stress_tmp = C_tmp * strain_tmp;
45}
46
47} // namespace
48
49namespace b2000 {
50
51/* Reference:
52 * Computational Inelasticity, Juan C. Simó, Thomas J. R. Hughes, 1998.
53 * Section 10.3 (for the deviatoric viscosity only). The "full" elasticity is
54 * easily deduced.
55 *
56 * This is for linear viscoleasticity with the small strain
57 * assumption. The extension to finite strain (section 10.5 of the
58 * same book) is not implemented here.
59 */
60template <typename T>
61inline void visco_elastic_get_stress(
62 const T E[3], const T P[3], const T G[3], const bool shell, const T sh,
63 const std::vector<T>& relative_moduli, const std::vector<T>& relaxation_time,
64 const bool only_deviatoric_viscosity, b2linalg::Matrix<T>& internal_viscous_stress,
65 const T strain[6], const T delta_time, const EquilibriumSolution equilibrium_solution,
66 T stress[6], T d_stress_d_strain[21], T& stored_energy_per_unit_volume,
67 T& dissipated_energy_per_unit_volume) {
68 if (internal_viscous_stress.size2() == 0) {
69 internal_viscous_stress.resize(6, relative_moduli.size());
70 }
71
72 T d_stress_d_strain_tmp[21];
73 T* C = d_stress_d_strain ? d_stress_d_strain : d_stress_d_strain_tmp;
74
75 T ematrix[3][3];
76 T cmatrix[3][3];
77 std::fill_n(C, 21, T(0));
78 if (shell) {
79 cmatrix[0][0] = T(1) / E[0];
80 cmatrix[1][1] = T(1) / E[1];
81 cmatrix[2][2] = T(0);
82 cmatrix[0][1] = cmatrix[1][0] = -P[0] * cmatrix[0][0];
83 cmatrix[0][2] = cmatrix[2][0] = T(0);
84 cmatrix[1][2] = cmatrix[2][1] = T(0);
85
86 const T inv_det = T(1) / (cmatrix[0][0] * cmatrix[1][1] - cmatrix[0][1] * cmatrix[0][1]);
87 C[0] = cmatrix[1][1] * inv_det;
88 C[1] = -cmatrix[0][1] * inv_det;
89 C[6] = cmatrix[0][0] * inv_det;
90
91 // Set the diagonal values for the last 3 rows and columns.
92 C[15] = G[0];
93 C[18] = G[1] * sh;
94 C[20] = G[2] * sh;
95 } else {
96 cmatrix[0][0] = T(1) / E[0];
97 cmatrix[1][1] = T(1) / E[1];
98 cmatrix[2][2] = T(1) / E[2];
99 cmatrix[0][1] = cmatrix[1][0] = -P[0] * cmatrix[0][0];
100 cmatrix[0][2] = cmatrix[2][0] = -P[1] * cmatrix[0][0];
101 cmatrix[1][2] = cmatrix[2][1] = -P[2] * cmatrix[1][1];
102
103 // Invert the compliance matrix to obtain the first three
104 // columns and first three rows of the elasticity matrix.
105 invert_3_3(cmatrix, ematrix);
106
107 // Copy the 3x3 part of the elasticity matrix to the array.
108 C[0] = ematrix[0][0];
109 C[1] = ematrix[0][1];
110 C[2] = ematrix[0][2];
111 C[6] = ematrix[1][1];
112 C[7] = ematrix[1][2];
113 C[11] = ematrix[2][2];
114
115 // Set the diagonal values for the last 3 rows and columns.
116 C[15] = G[0];
117 C[18] = G[1];
118 C[20] = G[2];
119 }
120
121 if (stress || equilibrium_solution) {
122 if (stress) { std::fill_n(stress, 6, T(0)); }
123 if (equilibrium_solution) {
124 stored_energy_per_unit_volume = T(0);
125 dissipated_energy_per_unit_volume = T(0);
126 }
127 double stress_0[6] = {};
128 if (only_deviatoric_viscosity) {
129 const T strain_vol = (strain[0] + strain[1] + strain[2]) / 3;
130 if (stress) {
131 stress[0] = strain_vol * (C[0] + C[1] + C[2]);
132 stress[1] = strain_vol * (C[1] + C[6] + C[7]);
133 stress[2] = strain_vol * (C[2] + C[7] + C[11]);
134 }
135 if (equilibrium_solution) {
136 stored_energy_per_unit_volume =
137 0.5 * strain_vol * strain_vol
138 * (C[0] + C[1] + C[2] + C[1] + C[6] + C[7] + C[2] + C[7] + C[11]);
139 }
140 T strain_dev[6];
141 for (int i = 0; i != 3; ++i) { strain_dev[i] = strain[i] - strain_vol; }
142 for (int i = 3; i != 6; ++i) { strain_dev[i] = strain[i]; }
143 mult_mlp_v6(C, strain_dev, stress_0);
144 const T stress_0_vol = (stress_0[0] + stress_0[1] + stress_0[2]) / 3;
145 for (int i = 0; i != 3; ++i) { stress_0[i] -= stress_0_vol; }
146 } else {
147 mult_mlp_v6(C, strain, stress_0);
148 }
149
150 T dstress_0[6];
151 const size_t n = relaxation_time.size();
152 for (int i = 0; i != 6; ++i) { dstress_0[i] = stress_0[i] - internal_viscous_stress(i, n); }
153 if (stress) {
154 for (int i = 0; i != 6; ++i) { stress[i] += relative_moduli[n] * stress_0[i]; }
155 }
156 if (equilibrium_solution) {
157 T etmp = 0;
158 for (int i = 0; i != 6; ++i) {
159 internal_viscous_stress(i, n) = stress_0[i];
160 etmp += stress_0[i] * strain[i];
161 }
162 stored_energy_per_unit_volume += 0.5 * etmp * relative_moduli[n];
163 }
164
165 T* internal_viscous_stress_ptr = &internal_viscous_stress(0, 0);
166 for (size_t j = 0; j != n; ++j) {
167 const T dr = delta_time / relaxation_time[j];
168 const T a = exp(-dr);
169 const T b = (1 - a) / dr;
170 for (int i = 0; i != 6; ++i, ++internal_viscous_stress_ptr) {
171 const T h = a * *internal_viscous_stress_ptr + b * dstress_0[i];
172 if (equilibrium_solution) { *internal_viscous_stress_ptr = h; }
173 if (stress) { stress[i] += relative_moduli[j] * h; }
174 }
175 if (equilibrium_solution) {
176 T strain_tmp[3];
177 inner_product_3_1_NN(cmatrix, internal_viscous_stress_ptr - 6, strain_tmp);
178 if (only_deviatoric_viscosity) {
179 const T strain_tmp_vol = (strain_tmp[0] + strain_tmp[1] + strain_tmp[2]) / 3;
180 for (int i = 0; i != 3; ++i) { strain_tmp[i] -= strain_tmp_vol; }
181 }
182 T etmp = dot_3(strain_tmp, internal_viscous_stress_ptr - 6);
183 for (int i = 0; i != 3; ++i) {
184 etmp += internal_viscous_stress_ptr[i - 3] * internal_viscous_stress_ptr[i - 3]
185 / G[i];
186 }
187 stored_energy_per_unit_volume += relative_moduli[j] * 0.5 * etmp;
188 assert(etmp >= 0);
189 dissipated_energy_per_unit_volume += relative_moduli[j] * etmp / relaxation_time[j];
190 }
191 }
192 }
193
194 if (d_stress_d_strain) {
195 T s = relative_moduli.back();
196 for (size_t j = 0; j != relaxation_time.size(); ++j) {
197 const T dr = delta_time / relaxation_time[j];
198 s += relative_moduli[j] * (1 - exp(-dr)) / dr;
199 }
200 if (only_deviatoric_viscosity) {
201 const T C_dd_I[6] = {
202 (C[0] + C[1] + C[2]) / 3,
203 (C[1] + C[6] + C[7]) / 3,
204 (C[2] + C[7] + C[11]) / 3,
205 C[15] / 3,
206 C[18] / 3,
207 C[20] / 3};
208 T I_dd_C_dd_I = 0;
209 for (int i = 0; i != 6; ++i) { I_dd_C_dd_I += C_dd_I[i]; }
210 I_dd_C_dd_I /= 3;
211 for (int j = 0; j != 6; ++j) {
212 int i = j;
213 for (; i < 3; ++i, ++C) {
214 *C = (C_dd_I[i] + C_dd_I[j]) / 2
215 + s * (*C - C_dd_I[i] - C_dd_I[j] + I_dd_C_dd_I);
216 }
217 for (; i < 6; ++i, ++C) { *C = s * (*C - C_dd_I[i] - C_dd_I[j] + I_dd_C_dd_I); }
218 }
219 } else {
220 for (int i = 0; i != 21; ++i) { C[i] *= s; }
221 }
222 }
223}
224
225/* Reference:
226 * Computational Inelasticity, Juan C. Simó, Thomas J. R. Hughes, 1998.
227 * Section 10.3 (for the deviatoric viscosity only). The "full" elasticity is
228 * easily deduced.
229 *
230 * This is for linear orthotropic viscoleasticity with the small strain
231 * assumption. The extension to finite strain (section 10.5 of the
232 * same book) is not implemented here.
233 */
234template <typename T>
235inline void visco_elastic_get_stress(
236 const T E[3], const T P[3], const T G[3], const bool shell, const T sh,
237 const b2linalg::Matrix<T>& relative_moduli, const b2linalg::Matrix<T>& relaxation_time,
238 const bool only_deviatoric_viscosity, b2linalg::Matrix<T>& internal_viscous_stress,
239 const T strain[6], const T delta_time, const EquilibriumSolution equilibrium_solution,
240 T stress[6], T d_stress_d_strain[21], T& stored_energy_per_unit_volume,
241 T& dissipated_energy_per_unit_volume) {
242 if (internal_viscous_stress.size2() == 0) {
243 internal_viscous_stress.resize(6, relative_moduli.size2());
244 }
245
246 T d_stress_d_strain_tmp[21];
247 T* C = d_stress_d_strain ? d_stress_d_strain : d_stress_d_strain_tmp;
248
249 T ematrix[3][3];
250 T cmatrix[3][3];
251 std::fill_n(C, 21, T(0));
252 if (shell) {
253 cmatrix[0][0] = T(1) / E[0];
254 cmatrix[1][1] = T(1) / E[1];
255 cmatrix[2][2] = T(0);
256 cmatrix[0][1] = cmatrix[1][0] = -P[0] * cmatrix[0][0];
257 cmatrix[0][2] = cmatrix[2][0] = T(0);
258 cmatrix[1][2] = cmatrix[2][1] = T(0);
259
260 const T inv_det = 1 / (cmatrix[0][0] * cmatrix[1][1] - cmatrix[0][1] * cmatrix[0][1]);
261 C[0] = cmatrix[1][1] * inv_det;
262 C[1] = -cmatrix[0][1] * inv_det;
263 C[6] = cmatrix[0][0] * inv_det;
264
265 // Set the diagonal values for the last 3 rows and columns.
266 C[15] = G[0];
267 C[18] = G[1] * sh;
268 C[20] = G[2] * sh;
269 } else {
270 cmatrix[0][0] = T(1) / E[0];
271 cmatrix[1][1] = T(1) / E[1];
272 cmatrix[2][2] = T(1) / E[2];
273 cmatrix[0][1] = cmatrix[1][0] = -P[0] * cmatrix[0][0];
274 cmatrix[0][2] = cmatrix[2][0] = -P[1] * cmatrix[0][0];
275 cmatrix[1][2] = cmatrix[2][1] = -P[2] * cmatrix[1][1];
276
277 // Invert the compliance matrix to obtain the first three
278 // columns and first three rows of the elasticity matrix.
279 invert_3_3(cmatrix, ematrix);
280
281 // Copy the 3x3 part of the elasticity matrix to the array.
282 C[0] = ematrix[0][0];
283 C[1] = ematrix[0][1];
284 C[2] = ematrix[0][2];
285 C[6] = ematrix[1][1];
286 C[7] = ematrix[1][2];
287 C[11] = ematrix[2][2];
288
289 // Set the diagonal values for the last 3 rows and columns.
290 C[15] = G[0];
291 C[18] = G[1];
292 C[20] = G[2];
293 }
294
295 if (stress || equilibrium_solution) {
296 if (stress) { std::fill_n(stress, 6, T(0)); }
297 if (equilibrium_solution) {
298 stored_energy_per_unit_volume = T(0);
299 dissipated_energy_per_unit_volume = T(0);
300 }
301 T stress_0[6];
302 if (only_deviatoric_viscosity) {
303 const T strain_vol = (strain[0] + strain[1] + strain[2]) / 3;
304 if (stress) {
305 stress[0] = strain_vol * (C[0] + C[1] + C[2]);
306 stress[1] = strain_vol * (C[1] + C[6] + C[7]);
307 stress[2] = strain_vol * (C[2] + C[7] + C[11]);
308 }
309 if (equilibrium_solution) {
310 stored_energy_per_unit_volume =
311 0.5 * strain_vol * strain_vol
312 * (C[0] + C[1] + C[2] + C[1] + C[6] + C[7] + C[2] + C[7] + C[11]);
313 }
314 T strain_dev[6];
315 for (int i = 0; i != 3; ++i) { strain_dev[i] = strain[i] - strain_vol; }
316 for (int i = 3; i != 6; ++i) { strain_dev[i] = strain[i]; }
317 mult_mlp_v6(C, strain_dev, stress_0);
318 const T stress_0_vol = (stress_0[0] + stress_0[1] + stress_0[2]) / 3;
319 for (int i = 0; i != 3; ++i) { stress_0[i] -= stress_0_vol; }
320 } else {
321 mult_mlp_v6(C, strain, stress_0);
322 }
323
324 T dstress_0[6];
325 const size_t n = relaxation_time.size2();
326 for (int i = 0; i != 6; ++i) { dstress_0[i] = stress_0[i] - internal_viscous_stress(i, n); }
327 if (stress) {
328 for (int i = 0; i != 6; ++i) { stress[i] += relative_moduli(i, n) * stress_0[i]; }
329 }
330 if (equilibrium_solution) {
331 for (int i = 0; i != 6; ++i) {
332 internal_viscous_stress(i, n) = stress_0[i];
333 const T etmp = stress_0[i] * strain[i];
334 stored_energy_per_unit_volume += 0.5 * etmp * relative_moduli(i, n);
335 }
336 }
337
338 T* internal_viscous_stress_ptr = &internal_viscous_stress(0, 0);
339 for (size_t j = 0; j != n; ++j) {
340 for (int i = 0; i != 6; ++i, ++internal_viscous_stress_ptr) {
341 const T dr = delta_time / relaxation_time(i, j);
342 const T a = exp(-dr);
343 const T b = (1 - a) / dr;
344 const T h = a * *internal_viscous_stress_ptr + b * dstress_0[i];
345 if (equilibrium_solution) { *internal_viscous_stress_ptr = h; }
346 if (stress) { stress[i] += relative_moduli(i, j) * h; }
347 }
348 if (equilibrium_solution) {
349 T strain_tmp[6];
350 inner_product_3_1_NN(cmatrix, internal_viscous_stress_ptr - 6, strain_tmp);
351 if (only_deviatoric_viscosity) {
352 const T strain_tmp_vol = (strain_tmp[0] + strain_tmp[1] + strain_tmp[2]) / 3;
353 for (int i = 0; i != 3; ++i) { strain_tmp[i] -= strain_tmp_vol; }
354 }
355 for (int i = 0; i != 3; ++i) {
356 strain_tmp[i + 3] = internal_viscous_stress_ptr[i - 3] / G[i];
357 }
358 for (int i = 0; i != 6; ++i) {
359 stored_energy_per_unit_volume += relative_moduli(i, j) * 0.5 * strain_tmp[i]
360 * internal_viscous_stress_ptr[i - 6];
361 dissipated_energy_per_unit_volume += relative_moduli(i, j)
362 / relaxation_time(i, j) * strain_tmp[i]
363 * internal_viscous_stress_ptr[i - 6];
364 }
365 }
366 }
367 }
368
369 if (d_stress_d_strain) {
370 T s[6];
371 for (int i = 0; i != 6; ++i) {
372 s[i] = relative_moduli(i, relative_moduli.size2() - 1);
373 for (size_t j = 0; j != relaxation_time.size2(); ++j) {
374 const T dr = delta_time / relaxation_time(i, j);
375 s[i] += relative_moduli(i, j) * (1 - exp(-dr)) / dr;
376 }
377 }
378 if (only_deviatoric_viscosity) {
379 const T C_dd_I[6] = {
380 (C[0] + C[1] + C[2]) / 3,
381 (C[1] + C[6] + C[7]) / 3,
382 (C[2] + C[7] + C[11]) / 3,
383 C[15] / 3,
384 C[18] / 3,
385 C[20] / 3};
386 T I_dd_C_dd_I = 0;
387 for (int i = 0; i != 6; ++i) { I_dd_C_dd_I += C_dd_I[i]; }
388 I_dd_C_dd_I /= 3;
389 for (int j = 0; j != 6; ++j) {
390 int i = j;
391 for (; i < 3; ++i, ++C) {
392 *C = (C_dd_I[i] + C_dd_I[j]) / 2
393 + 0.5 * (s[i] + s[j]) * (*C - C_dd_I[i] - C_dd_I[j] + I_dd_C_dd_I);
394 }
395 for (; i < 6; ++i, ++C) {
396 *C = 0.5 * (s[i] + s[j]) * (*C - C_dd_I[i] - C_dd_I[j] + I_dd_C_dd_I);
397 }
398 }
399 } else {
400 for (int j = 0; j != 6; ++j) {
401 for (int i = j; i != 6; ++i, ++C) { *C *= 0.5 * (s[i] + s[j]); }
402 }
403 }
404 }
405}
406
407/*
408 * Same implementation for shell strain and shell stress
409 */
410template <typename T>
411inline void visco_elastic_get_stress(
412 const T d_stress_d_strain_0[36], const T inv_d_stress_d_strain_0[36],
413 const std::vector<T>& relative_moduli, const std::vector<T>& relaxation_time,
414 b2linalg::Matrix<T>& internal_viscous_stress, const T strain[8], const T delta_time,
415 const EquilibriumSolution equilibrium_solution, T stress[8], T d_stress_d_strain[36],
416 T& stored_energy_per_unit_volume, T& dissipated_energy_per_unit_volume) {
417 if (internal_viscous_stress.size2() == 0) {
418 internal_viscous_stress.resize(8, relative_moduli.size());
419 }
420
421 if (stress || equilibrium_solution) {
422 if (stress) { std::fill_n(stress, 8, T(0)); }
423 if (equilibrium_solution) {
424 stored_energy_per_unit_volume = T(0);
425 dissipated_energy_per_unit_volume = T(0);
426 }
427 T stress_0[8];
428 mult_mlp_v8(d_stress_d_strain_0, strain, stress_0);
429
430 T dstress_0[8];
431 const size_t n = relaxation_time.size();
432 for (int i = 0; i != 8; ++i) { dstress_0[i] = stress_0[i] - internal_viscous_stress(i, n); }
433 if (stress) {
434 for (int i = 0; i != 8; ++i) { stress[i] += relative_moduli[n] * stress_0[i]; }
435 }
436 if (equilibrium_solution) {
437 T etmp = 0;
438 for (int i = 0; i != 8; ++i) {
439 internal_viscous_stress(i, n) = stress_0[i];
440 etmp += stress_0[i] * strain[i];
441 }
442 stored_energy_per_unit_volume += 0.5 * etmp * relative_moduli[n];
443 }
444
445 T* internal_viscous_stress_ptr = &internal_viscous_stress(0, 0);
446 for (size_t j = 0; j != n; ++j) {
447 const T dr = delta_time / relaxation_time[j];
448 const T a = exp(-dr);
449 const T b = (1 - a) / dr;
450 for (int i = 0; i != 8; ++i, ++internal_viscous_stress_ptr) {
451 const T h = a * *internal_viscous_stress_ptr + b * dstress_0[i];
452 if (equilibrium_solution) { *internal_viscous_stress_ptr = h; }
453 if (stress) { stress[i] += relative_moduli[j] * h; }
454 }
455 if (equilibrium_solution) {
456 T strain_tmp[8];
457 mult_mlp_v8(inv_d_stress_d_strain_0, internal_viscous_stress_ptr - 8, strain_tmp);
458 T etmp = T(0);
459 for (int i = 0; i != 8; ++i) {
460 etmp += strain_tmp[i] * internal_viscous_stress_ptr[i - 8];
461 }
462 stored_energy_per_unit_volume += relative_moduli[j] * 0.5 * etmp;
463 assert(etmp >= 0);
464 dissipated_energy_per_unit_volume += relative_moduli[j] * etmp / relaxation_time[j];
465 }
466 }
467 }
468
469 if (d_stress_d_strain) {
470 T s = relative_moduli.back();
471 for (size_t j = 0; j != relaxation_time.size(); ++j) {
472 const T dr = delta_time / relaxation_time[j];
473 s += relative_moduli[j] * (1 - exp(-dr)) / dr;
474 }
475 for (int i = 0; i != 36; ++i) { d_stress_d_strain[i] = d_stress_d_strain_0[i] * s; }
476 }
477}
478
479// same implementation for rod
480template <typename T>
481inline void visco_elastic_get_stress(
482 const T E, const std::vector<T>& relative_moduli, const std::vector<T>& relaxation_time,
483 b2linalg::Vector<T>& internal_viscous_stress, const T strain, const T delta_time,
484 const EquilibriumSolution equilibrium_solution, T& stress, T& d_stress_d_strain,
485 T& stored_energy_per_unit_volume, T& dissipated_energy_per_unit_volume) {
486 if (internal_viscous_stress.size() == 0) {
487 internal_viscous_stress.resize(relative_moduli.size());
488 }
489
490 {
491 if (equilibrium_solution) {
492 stored_energy_per_unit_volume = T(0);
493 dissipated_energy_per_unit_volume = T(0);
494 }
495 T stress_0 = strain * E;
496 T dstress_0;
497 const size_t n = relaxation_time.size();
498 dstress_0 = stress_0 - internal_viscous_stress[n];
499 stress = relative_moduli[n] * stress_0;
500 if (equilibrium_solution) {
501 internal_viscous_stress[n] = stress_0;
502 stored_energy_per_unit_volume += 0.5 * stress_0 * strain * relative_moduli[n];
503 }
504
505 for (size_t j = 0; j != n; ++j) {
506 const T dr = delta_time / relaxation_time[j];
507 const T a = exp(-dr);
508 const T b = (1 - a) / dr;
509 const T h = a * internal_viscous_stress[j] + b * dstress_0;
510 if (equilibrium_solution) { internal_viscous_stress[j] = h; }
511 stress += relative_moduli[j] * h;
512 if (equilibrium_solution) {
513 const T etmp = internal_viscous_stress[j] * internal_viscous_stress[j] / E;
514 stored_energy_per_unit_volume += relative_moduli[j] * 0.5 * etmp;
515 assert(etmp >= 0);
516 dissipated_energy_per_unit_volume += relative_moduli[j] * etmp / relaxation_time[j];
517 }
518 }
519 }
520
521 {
522 T s = relative_moduli.back();
523 for (size_t j = 0; j != relaxation_time.size(); ++j) {
524 const T dr = delta_time / relaxation_time[j];
525 s += relative_moduli[j] * (1 - exp(-dr)) / dr;
526 }
527 d_stress_d_strain = E * s;
528 }
529}
530
531class ViscoElasticParameterIdentification {
532public:
533 ViscoElasticParameterIdentification(
534 int nb_maxwell_element_, double freq_start_, double freq_end_, bool logarithm_precision_,
535 double epsilon_integration_ = 1e-5, double tol_opt_ = 1e-5)
536 : scale_real(0), scale_imag(0), x_nlopt(nullptr), modulus_at_relaxation(0) {
537 nb_maxwell_element = nb_maxwell_element_;
538 freq_start = freq_start_;
539 logarithm_precision = logarithm_precision_;
540 epsilon_integration = epsilon_integration_;
541 tol_opt = tol_opt_;
542 freq_start = freq_start_;
543 freq_end = freq_end_;
544 x.resize(nb_maxwell_element_ * 2);
545 }
546
547 void set_expected_modulus_as_expresion(
548 const double modulus, const std::string& expresion_storage_modulus,
549 const std::string& expresion_loss_moduluis, bool loss_modulus_as_tan_modulus = false);
550
551 void set_expected_modulus_as_tabulated_values(
552 const double modulus, const std::vector<double>& storage_modulus,
553 const std::vector<double>& lose_modulus, bool loss_modulus_as_tan_modulus = false,
554 int interpolation_order = 1);
555
556 void get_relativ_modulus(
557 std::vector<double>& relative_moduli, std::vector<double>& relaxation_time,
558 const bool modulus_at_relaxation_ = true);
559
560private:
561 double f(const double w, const unsigned int w_level);
562
563 double adaptiveSimpsonsAux(
564 double a, double b, unsigned int a_level, unsigned int b_level, double epsilon, double S,
565 double fa, double fb, double fc);
566
567 static double myfunc(unsigned n, const double* x, double* grad, void* my_func_data);
568
569 double adaptiveSimpsonsAux_log(
570 double a, double b, unsigned int a_level, unsigned int b_level, double epsilon, double S,
571 double fa, double fb, double fc);
572
573 static double myfunc_log(unsigned n, const double* x, double* grad, void* my_func_data);
574
575 static const int max_level = 12;
576 static const unsigned int pow_max_level = 4096; // = 2 * max_level
577 int nb_maxwell_element;
578 double freq_start;
579 double freq_end;
580 bool logarithm_precision;
581 double epsilon_integration;
582 double tol_opt;
583 double scale_real;
584 double scale_imag;
585 std::pair<double, double> expected_value[pow_max_level + 1];
586 std::vector<double> x;
587 const double* x_nlopt;
588 bool modulus_at_relaxation;
589};
590
591} // namespace b2000
592
593#endif // B2VISOELASTITY_H_
csda< T > exp(const csda< T > &a)
Natural exponential of a csda number.
Definition b2csda.H:360
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
void inner_product_3_1_NN(const T a[3][3], const T b[3], T c[3])
Definition b2tensor_calculus.H:1027
T invert_3_3(const T a[3][3], T b[3][3])
Definition b2tensor_calculus.H:699
T dot_3(const T a[3], const T b[3])
Definition b2tensor_calculus.H:328