19#ifndef B2VISOELASTITY_H_
20#define B2VISOELASTITY_H_
22#include "b2solid_mechanics.H"
24#include "utils/b2linear_algebra.H"
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;
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;
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());
72 T d_stress_d_strain_tmp[21];
73 T* C = d_stress_d_strain ? d_stress_d_strain : d_stress_d_strain_tmp;
77 std::fill_n(C, 21, T(0));
79 cmatrix[0][0] = T(1) / E[0];
80 cmatrix[1][1] = T(1) / E[1];
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);
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;
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];
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];
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);
127 double stress_0[6] = {};
128 if (only_deviatoric_viscosity) {
129 const T strain_vol = (strain[0] + strain[1] + strain[2]) / 3;
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]);
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]);
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; }
147 mult_mlp_v6(C, strain, stress_0);
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); }
154 for (
int i = 0; i != 6; ++i) { stress[i] += relative_moduli[n] * stress_0[i]; }
156 if (equilibrium_solution) {
158 for (
int i = 0; i != 6; ++i) {
159 internal_viscous_stress(i, n) = stress_0[i];
160 etmp += stress_0[i] * strain[i];
162 stored_energy_per_unit_volume += 0.5 * etmp * relative_moduli[n];
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; }
175 if (equilibrium_solution) {
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; }
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]
187 stored_energy_per_unit_volume += relative_moduli[j] * 0.5 * etmp;
189 dissipated_energy_per_unit_volume += relative_moduli[j] * etmp / relaxation_time[j];
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;
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,
209 for (
int i = 0; i != 6; ++i) { I_dd_C_dd_I += C_dd_I[i]; }
211 for (
int j = 0; j != 6; ++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);
217 for (; i < 6; ++i, ++C) { *C = s * (*C - C_dd_I[i] - C_dd_I[j] + I_dd_C_dd_I); }
220 for (
int i = 0; i != 21; ++i) { C[i] *= s; }
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());
246 T d_stress_d_strain_tmp[21];
247 T* C = d_stress_d_strain ? d_stress_d_strain : d_stress_d_strain_tmp;
251 std::fill_n(C, 21, T(0));
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);
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;
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];
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];
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);
302 if (only_deviatoric_viscosity) {
303 const T strain_vol = (strain[0] + strain[1] + strain[2]) / 3;
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]);
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]);
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; }
321 mult_mlp_v6(C, strain, stress_0);
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); }
328 for (
int i = 0; i != 6; ++i) { stress[i] += relative_moduli(i, n) * stress_0[i]; }
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);
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; }
348 if (equilibrium_solution) {
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; }
355 for (
int i = 0; i != 3; ++i) {
356 strain_tmp[i + 3] = internal_viscous_stress_ptr[i - 3] / G[i];
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];
369 if (d_stress_d_strain) {
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;
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,
387 for (
int i = 0; i != 6; ++i) { I_dd_C_dd_I += C_dd_I[i]; }
389 for (
int j = 0; j != 6; ++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);
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);
400 for (
int j = 0; j != 6; ++j) {
401 for (
int i = j; i != 6; ++i, ++C) { *C *= 0.5 * (s[i] + s[j]); }
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());
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);
428 mult_mlp_v8(d_stress_d_strain_0, strain, stress_0);
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); }
434 for (
int i = 0; i != 8; ++i) { stress[i] += relative_moduli[n] * stress_0[i]; }
436 if (equilibrium_solution) {
438 for (
int i = 0; i != 8; ++i) {
439 internal_viscous_stress(i, n) = stress_0[i];
440 etmp += stress_0[i] * strain[i];
442 stored_energy_per_unit_volume += 0.5 * etmp * relative_moduli[n];
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; }
455 if (equilibrium_solution) {
457 mult_mlp_v8(inv_d_stress_d_strain_0, internal_viscous_stress_ptr - 8, strain_tmp);
459 for (
int i = 0; i != 8; ++i) {
460 etmp += strain_tmp[i] * internal_viscous_stress_ptr[i - 8];
462 stored_energy_per_unit_volume += relative_moduli[j] * 0.5 * etmp;
464 dissipated_energy_per_unit_volume += relative_moduli[j] * etmp / relaxation_time[j];
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;
475 for (
int i = 0; i != 36; ++i) { d_stress_d_strain[i] = d_stress_d_strain_0[i] * s; }
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());
491 if (equilibrium_solution) {
492 stored_energy_per_unit_volume = T(0);
493 dissipated_energy_per_unit_volume = T(0);
495 T stress_0 = strain * E;
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];
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;
516 dissipated_energy_per_unit_volume += relative_moduli[j] * etmp / relaxation_time[j];
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;
527 d_stress_d_strain = E * s;
531class ViscoElasticParameterIdentification {
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_;
542 freq_start = freq_start_;
543 freq_end = freq_end_;
544 x.resize(nb_maxwell_element_ * 2);
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);
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);
556 void get_relativ_modulus(
557 std::vector<double>& relative_moduli, std::vector<double>& relaxation_time,
558 const bool modulus_at_relaxation_ =
true);
561 double f(
const double w,
const unsigned int w_level);
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);
567 static double myfunc(
unsigned n,
const double* x,
double* grad,
void* my_func_data);
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);
573 static double myfunc_log(
unsigned n,
const double* x,
double* grad,
void* my_func_data);
575 static const int max_level = 12;
576 static const unsigned int pow_max_level = 4096;
577 int nb_maxwell_element;
580 bool logarithm_precision;
581 double epsilon_integration;
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;
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