35 static scalar_type frobenius_product_trans(
const base_matrix &A,
36 const base_matrix &B) {
38 scalar_type res = scalar_type(0);
41 res += A(i, j) * B(j, i);
45 struct compute_invariants {
50 scalar_type i1_, i2_, i3_, j1_, j2_;
51 bool i1_c, i2_c, i3_c, j1_c, j2_c;
53 base_matrix di1, di2, di3, dj1, dj2;
54 bool di1_c, di2_c, di3_c, dj1_c, dj2_c;
56 base_tensor ddi1, ddi2, ddi3, ddj1, ddj2;
57 bool ddi1_c, ddi2_c, ddi3_c, ddj1_c, ddj2_c;
73 ddi1 = base_tensor(N, N, N, N);
77 inline scalar_type i1()
78 {
if (!i1_c) compute_i1();
return i1_; }
80 inline const base_matrix &grad_i1()
81 {
if (!di1_c) compute_di1();
return di1; }
83 inline const base_tensor &sym_grad_grad_i1()
84 {
if (!ddi1_c) compute_ddi1();
return ddi1; }
89 i2_ = (gmm::sqr(gmm::mat_trace(E))
90 - frobenius_product_trans(E, E)) / scalar_type(2);
97 gmm::scale(di2, i1());
99 gmm::add(gmm::scaled(E, -scalar_type(1)), di2);
103 void compute_ddi2() {
104 ddi2 = base_tensor(N, N, N, N);
107 ddi2(i,i,k,k) += scalar_type(1);
110 ddi2(i,j,j,i) -= scalar_type(1)/scalar_type(2);
111 ddi2(j,i,j,i) -= scalar_type(1)/scalar_type(2);
116 inline scalar_type i2()
117 {
if (!i2_c) compute_i2();
return i2_; }
119 inline const base_matrix &grad_i2()
120 {
if (!di2_c) compute_di2();
return di2; }
122 inline const base_tensor &sym_grad_grad_i2()
123 {
if (!ddi2_c) compute_ddi2();
return ddi2; }
128 i3_ = bgeot::lu_inverse(&(*(Einv.begin())), gmm::mat_nrows(Einv));
133 scalar_type det = i3();
138 gmm::scale(di3, det);
142 void compute_ddi3() {
143 ddi3 = base_tensor(N, N, N, N);
144 scalar_type det = i3() / scalar_type(2);
149 ddi3(i,j,k,l) = det*(Einv(j,i)*Einv(l,k) - Einv(j,k)*Einv(l,i)
150 + Einv(i,j)*Einv(l,k) - Einv(i,k)*Einv(l,j));
154 inline scalar_type i3()
155 {
if (!i3_c) compute_i3();
return i3_; }
157 inline const base_matrix &grad_i3()
158 {
if (!di3_c) compute_di3();
return di3; }
160 inline const base_tensor &sym_grad_grad_i3()
161 {
if (!ddi3_c) compute_ddi3();
return ddi3; }
165 j1_ = i1() * ::pow(gmm::abs(i3()), -scalar_type(1) / scalar_type(3));
171 gmm::add(gmm::scaled(grad_i3(), -i1() / (scalar_type(3) * i3())), dj1);
172 gmm::scale(dj1, ::pow(gmm::abs(i3()), -scalar_type(1) / scalar_type(3)));
176 void compute_ddj1() {
177 const base_matrix &di1_ = grad_i1();
178 const base_matrix &di3_ = grad_i3();
179 scalar_type coeff1 = scalar_type(1) / (scalar_type(3)*i3());
180 scalar_type coeff2 = scalar_type(4) * coeff1 * coeff1 * i1();
181 ddj1 = sym_grad_grad_i3();
182 gmm::scale(ddj1.as_vector(), -i1() * coeff1);
189 (di3_(i, j) * di3_(k, l)) * coeff2
190 - (di1_(i, j) * di3_(k, l) + di1_(k, l) * di3_(i, j)) * coeff1;
192 gmm::scale(ddj1.as_vector(),
193 ::pow(gmm::abs(i3()), -scalar_type(1)/scalar_type(3)));
197 inline scalar_type j1()
198 {
if (!j1_c) compute_j1();
return j1_; }
200 inline const base_matrix &grad_j1()
201 {
if (!dj1_c) compute_dj1();
return dj1; }
203 inline const base_tensor &sym_grad_grad_j1()
204 {
if (!ddj1_c) compute_ddj1();
return ddj1; }
208 j2_ = i2() * ::pow(gmm::abs(i3()), -scalar_type(2) / scalar_type(3));
214 gmm::add(gmm::scaled(grad_i3(), -scalar_type(2) * i2() / (scalar_type(3) * i3())), dj2);
215 gmm::scale(dj2, ::pow(gmm::abs(i3()), -scalar_type(2) / scalar_type(3)));
219 void compute_ddj2() {
220 const base_matrix &di2_ = grad_i2();
221 const base_matrix &di3_ = grad_i3();
222 scalar_type coeff1 = scalar_type(2) / (scalar_type(3)*i3());
223 scalar_type coeff2 = scalar_type(5)*coeff1*coeff1*i2() / scalar_type(2);
224 ddj2 = sym_grad_grad_i2();
225 gmm::add(gmm::scaled(sym_grad_grad_i3().as_vector(), -i2() * coeff1),
233 (di3_(i, j) * di3_(k, l)) * coeff2
234 - (di2_(i, j) * di3_(k, l) + di2_(k, l) * di3_(i, j)) * coeff1;
236 gmm::scale(ddj2.as_vector(),
237 ::pow(gmm::abs(i3()), -scalar_type(2)/scalar_type(3)));
242 inline scalar_type j2()
243 {
if (!j2_c) compute_j2();
return j2_; }
245 inline const base_matrix &grad_j2()
246 {
if (!dj2_c) compute_dj2();
return dj2; }
248 inline const base_tensor &sym_grad_grad_j2()
249 {
if (!ddj2_c) compute_ddj2();
return ddj2; }
252 compute_invariants(
const base_matrix &EE)
253 : E(EE), i1_c(false), i2_c(false), i3_c(false),
254 j1_c(false), j2_c(false), di1_c(false), di2_c(false), di3_c(false),
255 dj1_c(false), dj2_c(false), ddi1_c(false), ddi2_c(false),
256 ddi3_c(false), ddj1_c(false), ddj2_c(false)
258 N = gmm::mat_nrows(E);
259 i1_=i2_=i3_=j1_=j2_=0.;
270 int check_symmetry(
const base_tensor &t) {
276 if (gmm::abs(t(n,m,l,k) - t(l,k,n,m))>1e-5) flags &= (~1);
277 if (gmm::abs(t(n,m,l,k) - t(m,n,l,k))>1e-5) flags &= (~2);
278 if (gmm::abs(t(n,m,l,k) - t(n,m,k,l))>1e-5) flags &= (~4);
285 void abstract_hyperelastic_law::random_E(base_matrix &E) {
287 base_matrix Phi(N,N);
291 d = bgeot::lu_det(&(*(Phi.begin())), N);
292 }
while (d < scalar_type(0.01));
294 gmm::scale(E,-1.);
gmm::add(gmm::identity_matrix(),E);
298 void abstract_hyperelastic_law::test_derivatives
299 (
size_type N, scalar_type h,
const base_vector& param)
const {
300 base_matrix E(N,N), E2(N,N), DE(N,N);
303 for (
size_type count = 0; count < 100; ++count) {
304 random_E(E); random_E(DE);
308 base_matrix sigma1(N,N), sigma2(N,N);
309 getfem::base_tensor tdsigma(N,N,N,N);
310 base_matrix dsigma(N,N);
312 sigma(E, sigma1, param, scalar_type(1));
313 sigma(E2, sigma2, param, scalar_type(1));
315 scalar_type d = strain_energy(E2, param, scalar_type(1))
316 - strain_energy(E, param, scalar_type(1));
319 for (
size_type j=0; j < N; ++j) d2 += sigma1(i,j)*DE(i,j);
320 if (gmm::abs(d-d2)/(gmm::abs(d)+1e-40) > 1e-4) {
321 cout <<
"Test " << count <<
" wrong derivative of strain_energy, d="
322 << d/h <<
", d2=" << d2/h << endl;
326 grad_sigma(E,tdsigma,param, scalar_type(1));
332 dsigma(i,j) += tdsigma(i,j,k,m)*DE(k,m);
335 sigma2(i,j) -= sigma1(i,j);
336 if (gmm::abs(dsigma(i,j) - sigma2(i,j))
337 /(gmm::abs(dsigma(i,j)) + 1e-40) > 1.5e-4) {
338 cout <<
"Test " << count <<
" wrong derivative of sigma, i="
339 << i <<
", j=" << j <<
", dsigma=" << dsigma(i,j)/h
340 <<
", var sigma = " << sigma2(i,j)/h << endl;
346 GMM_ASSERT1(ok,
"Derivative test has failed");
350 (
const base_matrix& F,
const base_matrix &E,
351 base_matrix &cauchy_stress,
const base_vector ¶ms,
352 scalar_type det_trans)
const
355 base_matrix PK2(N,N);
356 sigma(E,PK2,params,det_trans);
357 base_matrix aux(N,N);
358 gmm::mult(F,PK2,aux);
359 gmm::mult(aux,gmm::transposed(F),cauchy_stress);
360 gmm::scale(cauchy_stress,scalar_type(1.0/det_trans));
365 (
const base_matrix& F,
const base_matrix& E,
366 const base_vector ¶ms, scalar_type det_trans,
367 base_tensor &grad_sigma_ul)
const
370 base_tensor Cse(N,N,N,N);
371 grad_sigma(E,Cse,params,det_trans);
372 scalar_type mult = 1.0/det_trans;
380 grad_sigma_ul(i,j,k,l) = 0.0;
385 grad_sigma_ul(i,j,k,l)+=
386 F(i,m)*F(j,n)*F(k,p)*F(l,q)*Cse(m,n,p,q);
388 grad_sigma_ul(i,j,k,l) *= mult;
392 scalar_type SaintVenant_Kirchhoff_hyperelastic_law::strain_energy
393 (
const base_matrix &E,
const base_vector ¶ms, scalar_type det_trans)
const {
395 if (det_trans <= scalar_type(0))
398 return gmm::sqr(gmm::mat_trace(E)) * params[0] / scalar_type(2)
399 + gmm::mat_euclidean_norm_sqr(E) * params[1];
402 void SaintVenant_Kirchhoff_hyperelastic_law::sigma
403 (
const base_matrix &E, base_matrix &result,
const base_vector ¶ms, scalar_type det_trans)
const {
404 gmm::copy(gmm::identity_matrix(), result);
405 gmm::scale(result, params[0] * gmm::mat_trace(E));
406 gmm::add(gmm::scaled(E, 2 * params[1]), result);
407 if (det_trans <= scalar_type(0)) {
408 gmm::add(gmm::scaled(E, 1e200), result);
411 void SaintVenant_Kirchhoff_hyperelastic_law::grad_sigma
412 (
const base_matrix &E, base_tensor &result,
const base_vector ¶ms, scalar_type)
const {
413 std::fill(result.begin(), result.end(), scalar_type(0));
417 result(i, i, l, l) += params[0];
418 result(i, l, i, l) += params[1]/scalar_type(2);
419 result(i, l, l, i) += params[1]/scalar_type(2);
420 result(l, i, i, l) += params[1]/scalar_type(2);
421 result(l, i, l, i) += params[1]/scalar_type(2);
426 const base_matrix& E,
427 const base_vector ¶ms,
428 scalar_type det_trans,
429 base_tensor &grad_sigma_ul)
const
432 base_tensor Cse(N,N,N,N);
433 grad_sigma(E,Cse,params,det_trans);
434 base_matrix Cinv(N,N);
435 gmm::mult(F,gmm::transposed(F),Cinv);
436 scalar_type mult=1.0/det_trans;
441 grad_sigma_ul(i, j, k, l)= (Cinv(i,j)*Cinv(k,l)*params[0] +
442 params[1]*(Cinv(i,k)*Cinv(j,l) + Cinv(i,l)*Cinv(j,k)))*mult;
445 SaintVenant_Kirchhoff_hyperelastic_law::SaintVenant_Kirchhoff_hyperelastic_law() {
449 scalar_type membrane_elastic_law::strain_energy
450 (
const base_matrix & ,
const base_vector & , scalar_type)
const {
452 GMM_ASSERT1(
false,
"To be done");
456 void membrane_elastic_law::sigma
457 (
const base_matrix &E, base_matrix &result,
const base_vector ¶ms, scalar_type det_trans)
const {
459 base_tensor tt(2,2,2,2);
460 size_type N = (gmm::mat_nrows(E) > 2)? 2 : gmm::mat_nrows(E);
461 grad_sigma(E,tt,params, det_trans);
467 result(i,j)+=tt(i,j,k,l)*E(k,l);
470 if(params[4]!=0) result(0,0)+=params[4];
472 if(params[5]!=0) result(1,1)+=params[5];
476 void membrane_elastic_law::grad_sigma
477 (
const base_matrix & , base_tensor &result,
478 const base_vector ¶ms, scalar_type)
const {
480 std::fill(result.begin(), result.end(), scalar_type(0));
481 scalar_type poisonXY=params[0]*params[1]/params[2];
483 scalar_type G=( params[3] == 0) ? params[0]/(2*(1+params[1])) : params[3];
484 std::fill(result.begin(), result.end(), scalar_type(0));
485 result(0,0,0,0) = params[0]/(1-params[1]*poisonXY);
488 result(0,0,1,1) = params[1]*params[0]/(1-params[1]*poisonXY);
489 result(1,1,0,0) = params[1]*params[0]/(1-params[1]*poisonXY);
492 result(1,1,1,1) = params[2]/(1-params[1]*poisonXY);
503 scalar_type Mooney_Rivlin_hyperelastic_law::strain_energy
504 (
const base_matrix &E,
const base_vector ¶ms
505 ,scalar_type det_trans)
const {
507 if (compressible && det_trans <= scalar_type(0))
return 1e200;
509 GMM_ASSERT1(N == 3,
"Mooney Rivlin hyperelastic law only defined "
510 "on dimension 3, sorry");
512 gmm::scale(C, scalar_type(2));
513 gmm::add(gmm::identity_matrix(), C);
514 compute_invariants ci(C);
516 scalar_type C1 = params[i++];
517 scalar_type W = C1 * (ci.j1() - scalar_type(3));
519 scalar_type C2 = params[i++];
520 W += C2 * (ci.j2() - scalar_type(3));
523 scalar_type D1 = params[i++];
524 W += D1 * gmm::sqr(sqrt(gmm::abs(ci.i3())) - scalar_type(1));
529 void Mooney_Rivlin_hyperelastic_law::sigma
530 (
const base_matrix &E, base_matrix &result,
531 const base_vector ¶ms, scalar_type det_trans)
const {
533 GMM_ASSERT1(N == 3,
"Mooney Rivlin hyperelastic law only defined "
534 "on dimension 3, sorry");
536 gmm::scale(C, scalar_type(2));
537 gmm::add(gmm::identity_matrix(), C);
538 compute_invariants ci(C);
541 scalar_type C1 = params[i++];
542 gmm::copy(gmm::scaled(ci.grad_j1(), scalar_type(2) * C1), result);
544 scalar_type C2 = params[i++];
545 gmm::add(gmm::scaled(ci.grad_j2(), scalar_type(2) * C2), result);
548 scalar_type D1 = params[i++];
549 scalar_type di3 = D1 - D1 / sqrt(gmm::abs(ci.i3()));
550 gmm::add(gmm::scaled(ci.grad_i3(), scalar_type(2) * di3), result);
553 if (det_trans <= scalar_type(0))
554 gmm::add(gmm::scaled(C, 1e200), result);
558 void Mooney_Rivlin_hyperelastic_law::grad_sigma
559 (
const base_matrix &E, base_tensor &result,
560 const base_vector ¶ms, scalar_type)
const {
562 GMM_ASSERT1(N == 3,
"Mooney Rivlin hyperelastic law only defined "
563 "on dimension 3, sorry");
565 gmm::scale(C, scalar_type(2));
566 gmm::add(gmm::identity_matrix(), C);
567 compute_invariants ci(C);
570 scalar_type C1 = params[i++];
571 gmm::copy(gmm::scaled(ci.sym_grad_grad_j1().as_vector(),
572 scalar_type(4)*C1), result.as_vector());
574 scalar_type C2 = params[i++];
575 gmm::add(gmm::scaled(ci.sym_grad_grad_j2().as_vector(),
576 scalar_type(4)*C2), result.as_vector());
579 scalar_type D1 = params[i++];
580 scalar_type di3 = D1 - D1 / sqrt(gmm::abs(ci.i3()));
581 gmm::add(gmm::scaled(ci.sym_grad_grad_i3().as_vector(),
582 scalar_type(4)*di3), result.as_vector());
585 scalar_type A22 = D1 / (scalar_type(2) * pow(gmm::abs(ci.i3()), 1.5));
586 const base_matrix &di = ci.grad_i3();
591 result(l1, l2, l3, l4) +=
592 scalar_type(4) * A22 * di(l1, l2) * di(l3, l4);
599 Mooney_Rivlin_hyperelastic_law::Mooney_Rivlin_hyperelastic_law
600 (
bool compressible_,
bool neohookean_)
601 : compressible(compressible_), neohookean(neohookean_)
604 if (compressible) ++nb_params_;
605 if (neohookean) --nb_params_;
612 scalar_type Neo_Hookean_hyperelastic_law::strain_energy
613 (
const base_matrix &E,
const base_vector ¶ms, scalar_type det_trans)
const {
614 if (det_trans <= scalar_type(0))
return 1e200;
616 GMM_ASSERT1(N == 3,
"Neo Hookean hyperelastic law only defined "
617 "on dimension 3, sorry");
619 gmm::scale(C, scalar_type(2));
620 gmm::add(gmm::identity_matrix(), C);
621 compute_invariants ci(C);
623 scalar_type lambda = params[0];
624 scalar_type mu = params[1];
625 scalar_type logi3 = log(ci.i3());
626 scalar_type W = mu/2 * (ci.i1() - scalar_type(3) - logi3);
628 W += lambda/8 * gmm::sqr(logi3);
630 W += lambda/4 * (ci.i3() - scalar_type(1) - logi3);
635 void Neo_Hookean_hyperelastic_law::sigma
636 (
const base_matrix &E, base_matrix &result,
637 const base_vector ¶ms , scalar_type det_trans)
const {
639 GMM_ASSERT1(N == 3,
"Neo Hookean hyperelastic law only defined "
640 "on dimension 3, sorry");
642 gmm::scale(C, scalar_type(2));
643 gmm::add(gmm::identity_matrix(), C);
644 compute_invariants ci(C);
646 scalar_type lambda = params[0];
647 scalar_type mu = params[1];
648 gmm::copy(gmm::scaled(ci.grad_i1(), mu), result);
651 (lambda/2 * log(ci.i3()) - mu) / ci.i3()), result);
654 lambda/2 - lambda/(2*ci.i3()) - mu / ci.i3()), result);
655 if (det_trans <= scalar_type(0))
656 gmm::add(gmm::scaled(C, 1e200), result);
659 void Neo_Hookean_hyperelastic_law::grad_sigma
660 (
const base_matrix &E, base_tensor &result,
661 const base_vector ¶ms, scalar_type)
const {
663 GMM_ASSERT1(N == 3,
"Neo Hookean hyperelastic law only defined "
664 "on dimension 3, sorry");
666 gmm::scale(C, scalar_type(2));
667 gmm::add(gmm::identity_matrix(), C);
668 compute_invariants ci(C);
670 scalar_type lambda = params[0];
671 scalar_type mu = params[1];
675 scalar_type logi3 = log(ci.i3());
676 gmm::copy(gmm::scaled(ci.sym_grad_grad_i3().as_vector(),
677 (lambda * logi3 - 2*mu) / ci.i3()),
679 coeff = (lambda + 2 * mu - lambda * logi3) / gmm::sqr(ci.i3());
681 gmm::copy(gmm::scaled(ci.sym_grad_grad_i3().as_vector(),
682 lambda - (lambda + 2 * mu) / ci.i3()),
684 coeff = (lambda + 2 * mu) / gmm::sqr(ci.i3());
687 const base_matrix &di = ci.grad_i3();
692 result(l1, l2, l3, l4) += coeff * di(l1, l2) * di(l3, l4);
698 Neo_Hookean_hyperelastic_law::Neo_Hookean_hyperelastic_law(
bool bonet_)
706 scalar_type generalized_Blatz_Ko_hyperelastic_law::strain_energy
707 (
const base_matrix &E,
const base_vector ¶ms, scalar_type det_trans)
const {
708 if (det_trans <= scalar_type(0))
return 1e200;
709 scalar_type a = params[0], b = params[1], c = params[2], d = params[3];
710 scalar_type n = params[4];
712 GMM_ASSERT1(N == 3,
"Generalized Blatz Ko hyperelastic law only defined "
713 "on dimension 3, sorry");
715 gmm::scale(C, scalar_type(2));
716 gmm::add(gmm::identity_matrix(), C);
717 compute_invariants ci(C);
719 return pow(a*ci.i1() + b*sqrt(gmm::abs(ci.i3()))
720 + c*ci.i2() / ci.i3() + d, n);
723 void generalized_Blatz_Ko_hyperelastic_law::sigma
724 (
const base_matrix &E, base_matrix &result,
725 const base_vector ¶ms, scalar_type det_trans)
const {
726 scalar_type a = params[0], b = params[1], c = params[2], d = params[3];
727 scalar_type n = params[4];
729 GMM_ASSERT1(N == 3,
"Generalized Blatz Ko hyperelastic law only defined "
730 "on dimension 3, sorry");
732 gmm::scale(C, scalar_type(2));
733 gmm::add(gmm::identity_matrix(), C);
734 compute_invariants ci(C);
736 scalar_type z = a*ci.i1() + b*sqrt(gmm::abs(ci.i3()))
737 + c*ci.i2() / ci.i3() + d;
738 scalar_type nz = n * pow(z, n-1.);
739 scalar_type di1 = nz * a;
740 scalar_type di2 = nz * c / ci.i3();
741 scalar_type di3 = nz *
742 (b / (2. * sqrt(gmm::abs(ci.i3()))) - c * ci.i2() / gmm::sqr(ci.i3()));
744 gmm::copy(gmm::scaled(ci.grad_i1(), di1 * 2.0), result);
745 gmm::add(gmm::scaled(ci.grad_i2(), di2 * 2.0), result);
746 gmm::add(gmm::scaled(ci.grad_i3(), di3 * 2.0), result);
747 if (det_trans <= scalar_type(0))
748 gmm::add(gmm::scaled(C, 1e200), result);
752 void generalized_Blatz_Ko_hyperelastic_law::grad_sigma
753 (
const base_matrix &E, base_tensor &result,
754 const base_vector ¶ms, scalar_type)
const {
755 scalar_type a = params[0], b = params[1], c = params[2], d = params[3];
756 scalar_type n = params[4];
758 GMM_ASSERT1(N == 3,
"Generalized Blatz Ko hyperelastic law only defined "
759 "on dimension 3, sorry");
761 gmm::scale(C, scalar_type(2));
762 gmm::add(gmm::identity_matrix(), C);
763 compute_invariants ci(C);
766 scalar_type z = a*ci.i1() + b*sqrt(gmm::abs(ci.i3()))
767 + c*ci.i2() / ci.i3() + d;
768 scalar_type nz = n * pow(z, n-1.);
769 scalar_type di1 = nz * a;
770 scalar_type di2 = nz * c / ci.i3();
771 scalar_type y = (b / (2. * sqrt(gmm::abs(ci.i3()))) - c * ci.i2() / gmm::sqr(ci.i3()));
772 scalar_type di3 = nz * y;
774 gmm::copy(gmm::scaled(ci.sym_grad_grad_i1().as_vector(),
775 scalar_type(4)*di1), result.as_vector());
776 gmm::add(gmm::scaled(ci.sym_grad_grad_i2().as_vector(),
777 scalar_type(4)*di2), result.as_vector());
778 gmm::add(gmm::scaled(ci.sym_grad_grad_i3().as_vector(),
779 scalar_type(4)*di3), result.as_vector());
781 scalar_type
nnz = n * (n-1.) * pow(z, n-2.);
783 A(0, 0) =
nnz * a * a;
784 A(1, 0) = A(0, 1) =
nnz * a * c / ci.i3();
785 A(2, 0) = A(0, 2) =
nnz * a * y;
786 A(1, 1) =
nnz * c * c / gmm::sqr(ci.i3());
787 A(2, 1) = A(1, 2) =
nnz * y * c / ci.i3() - nz * c / gmm::sqr(ci.i3());
788 A(2, 2) =
nnz * y * y + nz * (2. * c * ci.i2() / pow(ci.i3(), 3.) - b / (4. * pow(ci.i3(), 1.5)));
790 typedef const base_matrix * pointer_base_matrix__;
791 pointer_base_matrix__ di[3];
792 di[0] = &(ci.grad_i1());
793 di[1] = &(ci.grad_i2());
794 di[2] = &(ci.grad_i3());
802 result(l1, l2, l3, l4)
803 += 4. * A(j, k) * (*di[j])(l1, l2) * (*di[k])(l3, l4);
810 generalized_Blatz_Ko_hyperelastic_law::generalized_Blatz_Ko_hyperelastic_law() {
813 V[0] = 1.0; V[1] = 1.0, V[2] = 1.5; V[3] = -0.5; V[4] = 1.5;
817 scalar_type Ciarlet_Geymonat_hyperelastic_law::strain_energy
818 (
const base_matrix &E,
const base_vector ¶ms, scalar_type det_trans)
const {
819 if (det_trans <= scalar_type(0))
return 1e200;
821 scalar_type a = params[2];
822 scalar_type b = params[1]/scalar_type(2) - params[2];
823 scalar_type c = params[0]/scalar_type(4) - params[1]/scalar_type(2)
825 scalar_type d = params[0]/scalar_type(2) + params[1];
826 scalar_type e = -(scalar_type(3)*(a+b) + c);
828 gmm::copy(gmm::scaled(E, scalar_type(2)), C);
829 gmm::add(gmm::identity_matrix(), C);
830 scalar_type det = bgeot::lu_det(&(*(C.begin())), N);
832 + b * (gmm::sqr(gmm::mat_trace(C)) -
834 + c * det - d * log(det) / scalar_type(2) + e;
837 void Ciarlet_Geymonat_hyperelastic_law::sigma
838 (
const base_matrix &E, base_matrix &result,
const base_vector ¶ms, scalar_type det_trans)
const {
840 scalar_type a = params[2];
841 scalar_type b = params[1]/scalar_type(2) - params[2];
842 scalar_type c = params[0]/scalar_type(4) - params[1]/scalar_type(2)
844 scalar_type d = params[0]/scalar_type(2) + params[1];
846 if (a > params[1]/scalar_type(2)
847 || a < params[1]/scalar_type(2) - params[0]/scalar_type(4) || a < 0)
848 GMM_WARNING1(
"Inconsistent third parameter for Ciarlet-Geymonat "
850 gmm::copy(gmm::scaled(E, scalar_type(2)), C);
851 gmm::add(gmm::identity_matrix(), C);
852 gmm::copy(gmm::identity_matrix(), result);
853 gmm::scale(result, scalar_type(2) * (a + b * gmm::mat_trace(C)));
854 gmm::add(gmm::scaled(C, -scalar_type(2) * b), result);
855 if (det_trans <= scalar_type(0))
856 gmm::add(gmm::scaled(C, 1e200), result);
858 scalar_type det = bgeot::lu_inverse(&(*(C.begin())), N);
859 gmm::add(gmm::scaled(C, scalar_type(2) * c * det - d), result);
863 void Ciarlet_Geymonat_hyperelastic_law::grad_sigma
864 (
const base_matrix &E, base_tensor &result,
const base_vector ¶ms, scalar_type)
const {
867 scalar_type b2 = params[1] - params[2]*scalar_type(2);
868 scalar_type c = params[0]/scalar_type(4) - params[1]/scalar_type(2)
870 scalar_type d = params[0]/scalar_type(2) + params[1];
872 gmm::copy(gmm::scaled(E, scalar_type(2)), C);
873 gmm::add(gmm::identity_matrix(), C);
874 scalar_type det = bgeot::lu_inverse(&(*(C.begin())), N);
875 std::fill(result.begin(), result.end(), scalar_type(0));
878 result(i, i, j, j) += 2*b2;
879 result(i, j, i, j) -= b2;
880 result(i, j, j, i) -= b2;
883 result(i, j, k, l) +=
884 (C(i, k)*C(l, j) + C(i, l)*C(k, j)) * (d-scalar_type(2)*det*c)
885 + (C(i, j) * C(k, l)) * det*c*scalar_type(4);
893 int levi_civita(
int i,
int j,
int k) {
897 return static_cast<int>
898 (int(- 1)*(
static_cast<int>(pow(
double(ii-jj),2.))%3)
899 * (
static_cast<int> (pow(
double(ii-kk),
double(2)))%3 )
900 * (
static_cast<int> (pow(
double(jj-kk),
double(2)))%3)
901 * (pow(
double(jj-(ii%3))-
double(0.5),
double(2))-double(1.25)));
906 scalar_type plane_strain_hyperelastic_law::strain_energy
907 (
const base_matrix &E,
const base_vector ¶ms, scalar_type det_trans)
const {
908 GMM_ASSERT1(gmm::mat_nrows(E) == 2,
"Plane strain law is for 2D only.");
909 base_matrix E3D(3,3);
910 E3D(0,0)=E(0,0); E3D(1,0)=E(1,0); E3D(0,1)=E(0,1); E3D(1,1)=E(1,1);
911 return pl->strain_energy(E3D, params, det_trans);
914 void plane_strain_hyperelastic_law::sigma
915 (
const base_matrix &E, base_matrix &result,
const base_vector ¶ms, scalar_type det_trans)
const {
916 GMM_ASSERT1(gmm::mat_nrows(E) == 2,
"Plane strain law is for 2D only.");
917 base_matrix E3D(3,3), result3D(3,3);
918 E3D(0,0)=E(0,0); E3D(1,0)=E(1,0); E3D(0,1)=E(0,1); E3D(1,1)=E(1,1);
919 pl->sigma(E3D, result3D, params, det_trans);
920 result(0,0) = result3D(0,0); result(1,0) = result3D(1,0);
921 result(0,1) = result3D(0,1); result(1,1) = result3D(1,1);
924 void plane_strain_hyperelastic_law::grad_sigma
925 (
const base_matrix &E, base_tensor &result,
const base_vector ¶ms, scalar_type det_trans)
const {
926 GMM_ASSERT1(gmm::mat_nrows(E) == 2,
"Plane strain law is for 2D only.");
927 base_matrix E3D(3,3);
928 base_tensor result3D(3,3,3,3);
929 E3D(0,0)=E(0,0); E3D(1,0)=E(1,0); E3D(0,1)=E(0,1); E3D(1,1)=E(1,1);
930 pl->grad_sigma(E3D, result3D, params, det_trans);
931 result(0,0,0,0) = result3D(0,0,0,0); result(1,0,0,0) = result3D(1,0,0,0);
932 result(0,1,0,0) = result3D(0,1,0,0); result(1,1,0,0) = result3D(1,1,0,0);
933 result(0,0,1,0) = result3D(0,0,1,0); result(1,0,1,0) = result3D(1,0,1,0);
934 result(0,1,1,0) = result3D(0,1,1,0); result(1,1,1,0) = result3D(1,1,1,0);
935 result(0,0,0,1) = result3D(0,0,0,1); result(1,0,0,1) = result3D(1,0,0,1);
936 result(0,1,0,1) = result3D(0,1,0,1); result(1,1,0,1) = result3D(1,1,0,1);
937 result(0,0,1,1) = result3D(0,0,1,1); result(1,0,1,1) = result3D(1,0,1,1);
938 result(0,1,1,1) = result3D(0,1,1,1); result(1,1,1,1) = result3D(1,1,1,1);
953 struct nonlinear_elasticity_brick :
public virtual_brick {
955 phyperelastic_law AHL;
957 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
958 const model::varnamelist &vl,
959 const model::varnamelist &dl,
960 const model::mimlist &mims,
961 model::real_matlist &matl,
962 model::real_veclist &vecl,
963 model::real_veclist &,
965 build_version version)
const {
966 GMM_ASSERT1(mims.size() == 1,
967 "Nonlinear elasticity brick need a single mesh_im");
968 GMM_ASSERT1(vl.size() == 1,
969 "Nonlinear elasticity brick need a single variable");
970 GMM_ASSERT1(dl.size() == 1,
971 "Wrong number of data for nonlinear elasticity brick, "
972 << dl.size() <<
" should be 1 (vector).");
973 GMM_ASSERT1(matl.size() == 1,
"Wrong number of terms for nonlinear "
976 const model_real_plain_vector &u = md.real_variable(vl[0]);
977 const mesh_fem &mf_u = *(md.pmesh_fem_of_variable(vl[0]));
979 const mesh_fem *mf_params = md.pmesh_fem_of_variable(dl[0]);
980 const model_real_plain_vector ¶ms = md.real_variable(dl[0]);
981 const mesh_im &mim = *mims[0];
984 if (mf_params) sl = sl * mf_params->get_qdim() / mf_params->nb_dof();
985 GMM_ASSERT1(sl == AHL->nb_params(),
"Wrong number of coefficients for the "
986 "nonlinear constitutive elastic law");
988 mesh_region rg(region);
989 mf_u.linked_mesh().intersect_with_mpi_region(rg);
991 if (version & model::BUILD_MATRIX) {
993 GMM_TRACE2(
"Nonlinear elasticity stiffness matrix assembly");
995 (matl[0], mim, mf_u, u, mf_params, params, *AHL, rg);
999 if (version & model::BUILD_RHS) {
1000 asm_nonlinear_elasticity_rhs(vecl[0], mim,
1001 mf_u, u, mf_params, params, *AHL, rg);
1002 gmm::scale(vecl[0], scalar_type(-1));
1007 nonlinear_elasticity_brick(
const phyperelastic_law &AHL_)
1009 set_flags(
"Nonlinear elasticity brick",
false ,
1022 (
model &md,
const mesh_im &mim,
const std::string &varname,
1023 const phyperelastic_law &AHL,
const std::string &dataname,
1025 pbrick pbr = std::make_shared<nonlinear_elasticity_brick>(AHL);
1028 tl.push_back(model::term_description(varname, varname,
true));
1029 model::varnamelist dl(1, dataname);
1030 model::varnamelist vl(1, varname);
1031 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1,&mim), region);
1038 void compute_Von_Mises_or_Tresca(model &md,
1039 const std::string &varname,
1040 const phyperelastic_law &AHL,
1041 const std::string &dataname,
1042 const mesh_fem &mf_vm,
1043 model_real_plain_vector &VM,
1045 GMM_ASSERT1(gmm::vect_size(VM) == mf_vm.nb_dof(),
1046 "The vector has not the good size");
1047 const mesh_fem &mf_u = md.mesh_fem_of_variable(varname);
1048 const model_real_plain_vector &u = md.real_variable(varname);
1049 const mesh_fem *mf_params = md.pmesh_fem_of_variable(dataname);
1050 const model_real_plain_vector ¶ms = md.real_variable(dataname);
1053 if (mf_params) sl = sl * mf_params->get_qdim() / mf_params->nb_dof();
1054 GMM_ASSERT1(sl == AHL->nb_params(),
"Wrong number of coefficients for "
1055 "the nonlinear constitutive elastic law");
1057 unsigned N = unsigned(mf_u.linked_mesh().dim());
1058 unsigned NP = unsigned(AHL->nb_params()), NFem = mf_u.get_qdim();
1059 model_real_plain_vector GRAD(mf_vm.nb_dof()*NFem*N);
1060 model_real_plain_vector PARAMS(mf_vm.nb_dof()*NP);
1061 if (mf_params)
interpolation(*mf_params, mf_vm, params, PARAMS);
1063 base_matrix E(N, N), gradphi(NFem,N),gradphit(N,NFem), Id(N, N),
1064 sigmahathat(N,N),aux(NFem,N), sigma(NFem,NFem),
1067 if (!mf_params) gmm::copy(params, p);
1068 base_vector eig(NFem);
1069 base_vector ez(NFem);
1071 gmm::copy(gmm::identity_matrix(), Id);
1072 gmm::copy(gmm::identity_matrix(), IdNFem);
1073 for (
size_type i = 0; i < mf_vm.nb_dof(); ++i) {
1074 gmm::resize(gradphi,NFem,N);
1075 std::copy(GRAD.begin()+i*NFem*N, GRAD.begin()+(i+1)*NFem*N,
1077 gmm::copy(gmm::transposed(gradphit),gradphi);
1078 for (
unsigned int alpha = 0; alpha <N; ++alpha)
1079 gradphi(alpha, alpha)+=1;
1080 gmm::mult(gmm::transposed(gradphi), gradphi, E);
1081 gmm::add(gmm::scaled(Id, -scalar_type(1)), E);
1082 gmm::scale(E, scalar_type(1)/scalar_type(2));
1084 gmm::copy(gmm::sub_vector(PARAMS, gmm::sub_interval(i*NP,NP)), p);
1085 AHL->sigma(E, sigmahathat, p, scalar_type(1));
1086 if (NFem == 3 && N == 2) {
1088 for (
unsigned int l = 0; l <NFem; ++l) {
1090 for (
unsigned int m = 0; m <NFem; ++m)
1091 for (
unsigned int n = 0; n <NFem; ++n){
1092 ez[l]+=levi_civita(l,m,n)*gradphi(m,0)*gradphi(n,1);
1099 gmm::mult(aux, gmm::transposed(gradphi), sigma);
1103 if (NFem == 3 && N == 2) {
1105 for (
unsigned int ll = 0; ll <NFem; ++ll)
1106 for (
unsigned int ii = 0; ii <NFem; ++ii)
1107 for (
unsigned int jj = 0; jj <NFem; ++jj)
1108 gradphi(ll,2)+=(levi_civita(ll,ii,jj)*gradphi(ii,0)
1109 *gradphi(jj,1))/normEz;
1113 gmm::scale(sigma, scalar_type(1) / bgeot::lu_det(&(*(gradphi.begin())), NFem));
1117 gmm::add(gmm::scaled(IdNFem, -gmm::mat_trace(sigma) / NFem), sigma);
1124 gmm::symmetric_qr_algorithm(sigma, eig);
1125 std::sort(eig.begin(), eig.end());
1126 VM[i] = eig.back() - eig.front();
1132 void compute_sigmahathat(model &md,
1133 const std::string &varname,
1134 const phyperelastic_law &AHL,
1135 const std::string &dataname,
1136 const mesh_fem &mf_sigma,
1137 model_real_plain_vector &SIGMA) {
1138 const mesh_fem &mf_u = md.mesh_fem_of_variable(varname);
1139 const model_real_plain_vector &u = md.real_variable(varname);
1140 const mesh_fem *mf_params = md.pmesh_fem_of_variable(dataname);
1141 const model_real_plain_vector ¶ms = md.real_variable(dataname);
1144 if (mf_params) sl = sl * mf_params->get_qdim() / mf_params->nb_dof();
1145 GMM_ASSERT1(sl == AHL->nb_params(),
"Wrong number of coefficients for "
1146 "the nonlinear constitutive elastic law");
1148 unsigned N = unsigned(mf_u.linked_mesh().dim());
1149 unsigned NP = unsigned(AHL->nb_params()), NFem = mf_u.get_qdim();
1150 GMM_ASSERT1(mf_sigma.nb_dof() > 0,
"Bad mf_sigma");
1154 GMM_ASSERT1(((ratio == 1) || (ratio == N*N)) &&
1155 (gmm::vect_size(SIGMA) == mf_sigma.nb_dof()*ratio),
1156 "The vector has not the good size");
1158 model_real_plain_vector GRAD(mf_sigma.nb_dof()*ratio*NFem/N);
1159 model_real_plain_vector PARAMS(mf_sigma.nb_dof()*NP);
1162 getfem::mesh_trans_inv mti(mf_sigma.linked_mesh());
1164 for (
size_type i = 0; i < mf_sigma.nb_dof(); ++i)
1165 mti.add_point(mf_sigma.point_of_basic_dof(i));
1170 base_matrix E(N, N), gradphi(NFem,N),gradphit(N,NFem), Id(N, N),
1171 sigmahathat(N,N),aux(NFem,N), sigma(NFem,NFem),
1177 base_vector eig(NFem);
1178 base_vector ez(NFem);
1180 gmm::copy(gmm::identity_matrix(), IdNFem);
1185 for (
size_type i = 0; i < mf_sigma.nb_dof()/qqdim; ++i) {
1191 std::copy(GRAD.begin()+i*NFem*N, GRAD.begin()+(i+1)*NFem*N,
1194 gmm::copy(gmm::transposed(gradphit),gradphi);
1195 for (
unsigned int alpha = 0;
alpha <N; ++
alpha)
1196 gradphi(alpha, alpha) += scalar_type(1);
1197 gmm::mult(gmm::transposed(gradphi), gradphi, E);
1198 gmm::add(gmm::scaled(Id, -scalar_type(1)), E);
1199 gmm::scale(E, scalar_type(1)/scalar_type(2));
1201 gmm::copy(gmm::sub_vector(PARAMS, gmm::sub_interval(i*ratio*NP,NP)),p);
1203 AHL->sigma(E, sigmahathat, p, scalar_type(1));
1205 std::copy(sigmahathat.begin(), sigmahathat.end(), SIGMA.begin()+i*N*N);
1217 struct nonlinear_incompressibility_brick :
public virtual_brick {
1219 virtual void asm_real_tangent_terms(
const model &md,
size_type,
1220 const model::varnamelist &vl,
1221 const model::varnamelist &dl,
1222 const model::mimlist &mims,
1223 model::real_matlist &matl,
1224 model::real_veclist &vecl,
1225 model::real_veclist &veclsym,
1227 build_version version)
const {
1229 GMM_ASSERT1(matl.size() == 2,
"Wrong number of terms for nonlinear "
1230 "incompressibility brick");
1231 GMM_ASSERT1(dl.size() == 0,
"Nonlinear incompressibility brick need no "
1233 GMM_ASSERT1(mims.size() == 1,
"Nonlinear incompressibility brick need a "
1235 GMM_ASSERT1(vl.size() == 2,
"Wrong number of variables for nonlinear "
1236 "incompressibility brick");
1238 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
1239 const mesh_fem &mf_p = md.mesh_fem_of_variable(vl[1]);
1240 const model_real_plain_vector &u = md.real_variable(vl[0]);
1241 const model_real_plain_vector &p = md.real_variable(vl[1]);
1242 const mesh_im &mim = *mims[0];
1243 mesh_region rg(region);
1244 mim.linked_mesh().intersect_with_mpi_region(rg);
1246 if (version & model::BUILD_MATRIX) {
1249 asm_nonlinear_incomp_tangent_matrix(matl[0], matl[1],
1250 mim, mf_u, mf_p, u, p, rg);
1253 if (version & model::BUILD_RHS) {
1254 asm_nonlinear_incomp_rhs(vecl[0], veclsym[1], mim, mf_u, mf_p,u,p, rg);
1255 gmm::scale(vecl[0], scalar_type(-1));
1256 gmm::scale(veclsym[1], scalar_type(-1));
1261 nonlinear_incompressibility_brick() {
1262 set_flags(
"Nonlinear incompressibility brick",
1272 (
model &md,
const mesh_im &mim,
const std::string &varname,
1273 const std::string &multname,
size_type region) {
1274 pbrick pbr = std::make_shared<nonlinear_incompressibility_brick>();
1276 tl.push_back(model::term_description(varname, varname,
true));
1277 tl.push_back(model::term_description(varname, multname,
true));
1278 model::varnamelist vl(1, varname);
1279 vl.push_back(multname);
1280 model::varnamelist dl;
1281 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
1295 static void ga_init_scalar_(bgeot::multi_index &mi) { mi.resize(0); }
1296 static void ga_init_square_matrix_(bgeot::multi_index &mi,
size_type N)
1297 { mi.resize(2); mi[0] = mi[1] = N; }
1302 struct matrix_i2_operator :
public ga_nonlinear_operator {
1303 bool result_size(
const arg_list &args, bgeot::multi_index &sizes)
const {
1304 if (args.size() != 1 || args[0]->sizes().size() != 2
1305 || args[0]->sizes()[0] != args[0]->sizes()[1])
return false;
1306 ga_init_scalar_(sizes);
1311 void value(
const arg_list &args, base_tensor &result)
const {
1313 const base_tensor &t = *args[0];
1314 scalar_type tr = scalar_type(0);
1315 for (
size_type i = 0; i < N; ++i) tr += t[i*N+i];
1316 scalar_type tr2 = scalar_type(0);
1319 tr2 += t[i+ j*N] * t[j + i*N];
1320 result[0] = (tr*tr-tr2)/scalar_type(2);
1324 void derivative(
const arg_list &args,
size_type,
1325 base_tensor &result)
const {
1327 const base_tensor &t = *args[0];
1328 scalar_type tr = scalar_type(0);
1329 for (
size_type i = 0; i < N; ++i) tr += t[i*N+i];
1330 base_tensor::iterator it = result.begin();
1333 *it = ((i == j) ? tr : scalar_type(0)) - t[i*N+j];
1334 GMM_ASSERT1(it == result.end(),
"Internal error");
1339 base_tensor &result)
const {
1344 result[(N+1)*(i+N*N*j)] += scalar_type(1);
1345 result[(N+1)*N*j + i*(N*N*N + 1)] -= scalar_type(1);
1352 struct matrix_j1_operator :
public ga_nonlinear_operator {
1353 bool result_size(
const arg_list &args, bgeot::multi_index &sizes)
const {
1354 if (args.size() != 1 || args[0]->sizes().size() != 2
1355 || args[0]->sizes()[0] != args[0]->sizes()[1])
return false;
1356 ga_init_scalar_(sizes);
1361 void value(
const arg_list &args, base_tensor &result)
const {
1363 base_matrix M(N, N);
1364 gmm::copy(args[0]->as_vector(), M.as_vector());
1365 scalar_type det = bgeot::lu_det(&(*(M.begin())), N);
1366 scalar_type tr = scalar_type(0);
1367 for (
size_type i = 0; i < N; ++i) tr += M(i,i);
1369 result[0] = tr / pow(det, scalar_type(1)/scalar_type(3));
1375 void derivative(
const arg_list &args,
size_type,
1376 base_tensor &result)
const {
1378 base_matrix M(N, N);
1379 gmm::copy(args[0]->as_vector(), M.as_vector());
1380 scalar_type tr = scalar_type(0);
1381 for (
size_type i = 0; i < N; ++i) tr += M(i,i);
1382 scalar_type det = bgeot::lu_inverse(&(*(M.begin())), N);
1384 base_tensor::iterator it = result.begin();
1387 *it = (((i == j) ? scalar_type(1) : scalar_type(0))
1388 - tr*M(j,i)/scalar_type(3))
1389 / pow(det, scalar_type(1)/scalar_type(3));
1390 GMM_ASSERT1(it == result.end(),
"Internal error");
1392 std::fill(result.begin(), result.end(), 1.E200);
1398 base_tensor &result)
const {
1400 base_matrix M(N, N);
1401 gmm::copy(args[0]->as_vector(), M.as_vector());
1402 scalar_type tr = scalar_type(0);
1403 for (
size_type i = 0; i < N; ++i) tr += M(i,i);
1404 scalar_type det = bgeot::lu_inverse(&(*(M.begin())), N);
1406 base_tensor::iterator it = result.begin();
1411 *it = (- ((k == l) ? M(j, i) : scalar_type(0))
1413 - ((i == j) ? M(l, k) : scalar_type(0))
1414 + tr*M(j,i)*M(k,l)/ scalar_type(3))
1415 / (scalar_type(3)*pow(det, scalar_type(1)/scalar_type(3)));
1416 GMM_ASSERT1(it == result.end(),
"Internal error");
1418 std::fill(result.begin(), result.end(), 1.E200);
1424 struct matrix_j2_operator :
public ga_nonlinear_operator {
1425 bool result_size(
const arg_list &args, bgeot::multi_index &sizes)
const {
1426 if (args.size() != 1 || args[0]->sizes().size() != 2
1427 || args[0]->sizes()[0] != args[0]->sizes()[1])
return false;
1428 ga_init_scalar_(sizes);
1433 void value(
const arg_list &args, base_tensor &result)
const {
1435 base_matrix M(N, N);
1436 gmm::copy(args[0]->as_vector(), M.as_vector());
1437 scalar_type tr = scalar_type(0);
1438 for (
size_type i = 0; i < N; ++i) tr += M(i,i);
1439 scalar_type tr2 = scalar_type(0);
1442 tr2 += M(i,j)*M(j,i);
1443 scalar_type i2 = (tr*tr-tr2)/scalar_type(2);
1444 scalar_type det = bgeot::lu_det(&(*(M.begin())), N);
1446 result[0] = i2 / pow(det, scalar_type(2)/scalar_type(3));
1452 void derivative(
const arg_list &args,
size_type,
1453 base_tensor &result)
const {
1455 const base_tensor &t = *args[0];
1456 base_matrix M(N, N);
1457 gmm::copy(t.as_vector(), M.as_vector());
1458 scalar_type tr = scalar_type(0);
1459 for (
size_type i = 0; i < N; ++i) tr += M(i,i);
1460 scalar_type tr2 = scalar_type(0);
1463 tr2 += M(i,j)*M(j,i);
1464 scalar_type i2 = (tr*tr-tr2)/scalar_type(2);
1465 scalar_type det = bgeot::lu_inverse(&(*(M.begin())), N);
1466 base_tensor::iterator it = result.begin();
1469 *it = (((i == j) ? tr : scalar_type(0)) - t[j+N*i]
1470 - scalar_type(2)*i2*M(j,i)/(scalar_type(3)))
1471 / pow(det, scalar_type(2)/scalar_type(3));
1472 GMM_ASSERT1(it == result.end(),
"Internal error");
1477 base_tensor &result)
const {
1479 const base_tensor &t = *args[0];
1480 base_matrix M(N, N);
1481 gmm::copy(t.as_vector(), M.as_vector());
1482 scalar_type tr = scalar_type(0);
1483 for (
size_type i = 0; i < N; ++i) tr += M(i,i);
1484 scalar_type tr2 = scalar_type(0);
1487 tr2 += M(i,j)*M(j,i);
1488 scalar_type i2 = (tr*tr-tr2)/scalar_type(2);
1489 scalar_type det = bgeot::lu_inverse(&(*(M.begin())), N);
1490 base_tensor::iterator it = result.begin();
1495 *it = ( + (((i==j) && (k==l)) ? 1. : 0.)
1496 - (((i==l) && (k==j)) ? 1. : 0.)
1497 + 10.*i2*M(j,i)*M(l,k)/(9.)
1498 - 2.*(M(j,i)*(tr*((k==l) ? 1.:0.)-t[l+N*k]))/(3.)
1499 - 2.*(M(l,k)*(tr*((i==j) ? 1.:0.)-t[j+N*i]))/(3.)
1500 - 2.*i2*(M(j,i)*M(l,k)-M(j,k)*M(l,i))/(3.))
1501 / pow(det, scalar_type(2)/scalar_type(3));
1506 struct Right_Cauchy_Green_operator :
public ga_nonlinear_operator {
1507 bool result_size(
const arg_list &args, bgeot::multi_index &sizes)
const {
1508 if (args.size() != 1 || args[0]->sizes().size() != 2)
return false;
1509 ga_init_square_matrix_(sizes, args[0]->sizes()[1]);
1514 void value(
const arg_list &args, base_tensor &result)
const {
1516 size_type m = args[0]->sizes()[0], n = args[0]->sizes()[1];
1517 base_tensor::iterator it = result.begin();
1519 for (
size_type i = 0; i < n; ++i, ++it) {
1520 *it = scalar_type(0);
1522 *it += (*(args[0]))[i*m+k] * (*(args[0]))[j*m+k];
1528 void derivative(
const arg_list &args,
size_type,
1529 base_tensor &result)
const {
1530 size_type m = args[0]->sizes()[0], n = args[0]->sizes()[1];
1531 base_tensor::iterator it = result.begin();
1535 for (
size_type i = 0; i < n; ++i, ++it) {
1536 *it = scalar_type(0);
1537 if (l == i) *it += (*(args[0]))[j*m+k];
1538 if (l == j) *it += (*(args[0]))[i*m+k];
1540 GMM_ASSERT1(it == result.end(),
"Internal error");
1547 base_tensor &result)
const {
1548 size_type m = args[0]->sizes()[0], n = args[0]->sizes()[1];
1549 base_tensor::iterator it = result.begin();
1555 for (
size_type i = 0; i < n; ++i, ++it) {
1556 *it = scalar_type(0);
1558 if (l == i && p == j) *it += scalar_type(1);
1559 if (p == i && l == j) *it += scalar_type(1);
1562 GMM_ASSERT1(it == result.end(),
"Internal error");
1567 struct Left_Cauchy_Green_operator :
public ga_nonlinear_operator {
1568 bool result_size(
const arg_list &args, bgeot::multi_index &sizes)
const {
1569 if (args.size() != 1 || args[0]->sizes().size() != 2)
return false;
1570 ga_init_square_matrix_(sizes, args[0]->sizes()[0]);
1575 void value(
const arg_list &args, base_tensor &result)
const {
1577 size_type m = args[0]->sizes()[0], n = args[0]->sizes()[1];
1578 base_tensor::iterator it = result.begin();
1580 for (
size_type i = 0; i < m; ++i, ++it) {
1581 *it = scalar_type(0);
1583 *it += (*(args[0]))[k*m+i] * (*(args[0]))[k*m+j];
1589 void derivative(
const arg_list &args,
size_type,
1590 base_tensor &result)
const {
1591 size_type m = args[0]->sizes()[0], n = args[0]->sizes()[1];
1592 base_tensor::iterator it = result.begin();
1596 for (
size_type i = 0; i < m; ++i, ++it) {
1597 *it = scalar_type(0);
1598 if (k == i) *it += (*(args[0]))[l*m+j];
1599 if (k == j) *it += (*(args[0]))[l*m+i];
1601 GMM_ASSERT1(it == result.end(),
"Internal error");
1608 base_tensor &result)
const {
1609 size_type m = args[0]->sizes()[0], n = args[0]->sizes()[1];
1610 base_tensor::iterator it = result.begin();
1616 for (
size_type i = 0; i < m; ++i, ++it) {
1617 *it = scalar_type(0);
1619 if (k == i && o == j) *it += scalar_type(1);
1620 if (o == i && k == j) *it += scalar_type(1);
1623 GMM_ASSERT1(it == result.end(),
"Internal error");
1629 struct Green_Lagrangian_operator :
public ga_nonlinear_operator {
1630 bool result_size(
const arg_list &args, bgeot::multi_index &sizes)
const {
1631 if (args.size() != 1 || args[0]->sizes().size() != 2)
return false;
1632 ga_init_square_matrix_(sizes, args[0]->sizes()[1]);
1637 void value(
const arg_list &args, base_tensor &result)
const {
1639 size_type m = args[0]->sizes()[0], n = args[0]->sizes()[1];
1640 base_tensor::iterator it = result.begin();
1642 for (
size_type i = 0; i < n; ++i, ++it) {
1643 *it = scalar_type(0);
1645 *it += (*(args[0]))[i*m+k]*(*(args[0]))[j*m+k]*scalar_type(0.5);
1646 if (i == j) *it -= scalar_type(0.5);
1652 void derivative(
const arg_list &args,
size_type,
1653 base_tensor &result)
const {
1654 size_type m = args[0]->sizes()[0], n = args[0]->sizes()[1];
1655 base_tensor::iterator it = result.begin();
1659 for (
size_type i = 0; i < n; ++i, ++it) {
1660 *it = scalar_type(0);
1661 if (l == i) *it += (*(args[0]))[j*m+k]*scalar_type(0.5);
1662 if (l == j) *it += (*(args[0]))[i*m+k]*scalar_type(0.5);
1664 GMM_ASSERT1(it == result.end(),
"Internal error");
1671 base_tensor &result)
const {
1672 size_type m = args[0]->sizes()[0], n = args[0]->sizes()[1];
1673 base_tensor::iterator it = result.begin();
1679 for (
size_type i = 0; i < n; ++i, ++it) {
1680 *it = scalar_type(0);
1682 if (l == i && p == j) *it += scalar_type(0.5);
1683 if (p == i && l == j) *it += scalar_type(0.5);
1686 GMM_ASSERT1(it == result.end(),
"Internal error");
1692 struct Cauchy_stress_from_PK2 :
public ga_nonlinear_operator {
1693 bool result_size(
const arg_list &args, bgeot::multi_index &sizes)
const {
1694 if (args.size() != 2 || args[0]->sizes().size() != 2
1695 || args[1]->sizes().size() != 2
1696 || args[0]->sizes()[0] != args[0]->sizes()[1]
1697 || args[1]->sizes()[0] != args[0]->sizes()[1]
1698 || args[1]->sizes()[1] != args[0]->sizes()[1])
return false;
1699 ga_init_square_matrix_(sizes, args[0]->sizes()[1]);
1704 void value(
const arg_list &args, base_tensor &result)
const {
1706 base_matrix F(N, N), sigma(N,N), aux(N, N);
1707 gmm::copy(args[0]->as_vector(), sigma.as_vector());
1708 gmm::copy(args[1]->as_vector(), F.as_vector());
1709 gmm::add(gmm::identity_matrix(), F);
1711 gmm::mult(aux, gmm::transposed(F), sigma);
1712 scalar_type det = bgeot::lu_det(&(*(F.begin())), N);
1713 gmm::scale(sigma, scalar_type(1)/det);
1714 gmm::copy(sigma.as_vector(), result.as_vector());
1718 void derivative(
const arg_list &args,
size_type nder,
1719 base_tensor &result)
const {
1721 base_matrix F(N, N);
1722 gmm::copy(args[1]->as_vector(), F.as_vector());
1723 gmm::add(gmm::identity_matrix(), F);
1724 scalar_type det = bgeot::lu_det(&(*(F.begin())), N);
1726 base_tensor::iterator it = result.begin();
1734 *it = F(i,k) * F(j,l) / det;
1742 base_matrix sigma(N,N), aux(N,N), aux2(N,N);
1743 gmm::copy(args[0]->as_vector(), sigma.as_vector());
1744 gmm::mult(sigma, gmm::transposed(F), aux);
1746 bgeot::lu_inverse(&(*(F.begin())), N);
1750 for (
size_type i = 0; i < N; ++i, ++it) {
1751 *it = scalar_type(0);
1752 if (i == k) *it += aux(l, j) / det;
1753 if (l == j) *it += aux(k, i) / det;
1754 *it -= aux2(i,j) * F(l,k) / det;
1759 GMM_ASSERT1(it == result.end(),
"Internal error");
1764 base_tensor &)
const {
1765 GMM_ASSERT1(
false,
"Sorry, not implemented");
1770 struct AHL_wrapper_sigma :
public ga_nonlinear_operator {
1771 phyperelastic_law AHL;
1772 bool result_size(
const arg_list &args, bgeot::multi_index &sizes)
const {
1773 if (args.size() != 2 || args[0]->sizes().size() != 2
1774 || args[1]->size() != AHL->nb_params()
1775 || args[0]->sizes()[0] != args[0]->sizes()[1])
return false;
1776 ga_init_square_matrix_(sizes, args[0]->sizes()[0]);
1781 void value(
const arg_list &args, base_tensor &result)
const {
1783 base_vector params(AHL->nb_params());
1784 gmm::copy(args[1]->as_vector(), params);
1785 base_matrix Gu(N, N), E(N,N), sigma(N,N);
1786 gmm::copy(args[0]->as_vector(), Gu.as_vector());
1789 gmm::scale(E, scalar_type(0.5));
1790 gmm::add(gmm::identity_matrix(), Gu);
1791 scalar_type det = bgeot::lu_det(&(*(Gu.begin())), N);
1793 AHL->sigma(E, sigma, params, det);
1794 gmm::copy(sigma.as_vector(), result.as_vector());
1798 void derivative(
const arg_list &args,
size_type nder,
1799 base_tensor &result)
const {
1801 base_vector params(AHL->nb_params());
1802 gmm::copy(args[1]->as_vector(), params);
1803 base_tensor grad_sigma(N, N, N, N);
1804 base_matrix Gu(N, N), E(N,N);
1805 gmm::copy(args[0]->as_vector(), Gu.as_vector());
1808 gmm::scale(E, scalar_type(0.5));
1809 gmm::add(gmm::identity_matrix(), Gu);
1810 scalar_type det = bgeot::lu_det(&(*(Gu.begin())), N);
1812 GMM_ASSERT1(nder == 1,
"Sorry, the derivative of this hyperelastic "
1813 "law with respect to its parameters is not available.");
1815 AHL->grad_sigma(E, grad_sigma, params, det);
1817 base_tensor::iterator it = result.begin();
1821 for (
size_type i = 0; i < N; ++i, ++it) {
1822 *it = scalar_type(0);
1824 *it += grad_sigma(i,j,m,l) * Gu(k, m);
1826 GMM_ASSERT1(it == result.end(),
"Internal error");
1832 base_tensor &)
const {
1833 GMM_ASSERT1(
false,
"Sorry, second derivative not implemented");
1836 AHL_wrapper_sigma(
const phyperelastic_law &A) : AHL(A) {}
1841 struct AHL_wrapper_potential :
public ga_nonlinear_operator {
1842 phyperelastic_law AHL;
1843 bool result_size(
const arg_list &args, bgeot::multi_index &sizes)
const {
1844 if (args.size() != 2 || args[0]->sizes().size() != 2
1845 || args[1]->size() != AHL->nb_params()
1846 || args[0]->sizes()[0] != args[0]->sizes()[1])
return false;
1847 ga_init_scalar_(sizes);
1852 void value(
const arg_list &args, base_tensor &result)
const {
1854 base_vector params(AHL->nb_params());
1855 gmm::copy(args[1]->as_vector(), params);
1856 base_matrix Gu(N, N), E(N,N);
1857 gmm::copy(args[0]->as_vector(), Gu.as_vector());
1860 gmm::scale(E, scalar_type(0.5));
1861 gmm::add(gmm::identity_matrix(), Gu);
1862 scalar_type det = bgeot::lu_det(&(*(Gu.begin())), N);
1864 result[0] = AHL->strain_energy(E, params, det);
1868 void derivative(
const arg_list &args,
size_type nder,
1869 base_tensor &result)
const {
1871 base_vector params(AHL->nb_params());
1872 gmm::copy(args[1]->as_vector(), params);
1873 base_matrix Gu(N, N), E(N,N), sigma(N,N);
1874 gmm::copy(args[0]->as_vector(), Gu.as_vector());
1877 gmm::scale(E, scalar_type(0.5));
1878 gmm::add(gmm::identity_matrix(), Gu);
1879 scalar_type det = bgeot::lu_det(&(*(Gu.begin())), N);
1881 GMM_ASSERT1(nder == 1,
"Sorry, Cannot derive the potential with "
1882 "respect to law parameters.");
1884 AHL->sigma(E, sigma, params, det);
1886 gmm::copy(E.as_vector(), result.as_vector());
1891 void second_derivative(
const arg_list &args,
size_type nder1,
1892 size_type nder2, base_tensor &result)
const {
1895 base_vector params(AHL->nb_params());
1896 gmm::copy(args[1]->as_vector(), params);
1897 base_tensor grad_sigma(N, N, N, N);
1898 base_matrix Gu(N, N), E(N,N), sigma(N,N);
1899 gmm::copy(args[0]->as_vector(), Gu.as_vector());
1902 gmm::scale(E, scalar_type(0.5));
1903 gmm::add(gmm::identity_matrix(), Gu);
1904 scalar_type det = bgeot::lu_det(&(*(Gu.begin())), N);
1906 GMM_ASSERT1(nder1 == 1 && nder2 == 1,
"Sorry, Cannot derive the "
1907 "potential with respect to law parameters.");
1909 AHL->sigma(E, sigma, params, det);
1910 AHL->grad_sigma(E, grad_sigma, params, det);
1912 base_tensor::iterator it = result.begin();
1916 for (
size_type i = 0; i < N; ++i, ++it) {
1917 *it = scalar_type(0);
1918 if (i == k) *it += sigma(l,j);
1922 *it += grad_sigma(n,j,m,l) * Gu(k, m) * Gu(i, n);
1924 GMM_ASSERT1(it == result.end(),
"Internal error");
1928 AHL_wrapper_potential(
const phyperelastic_law &A) : AHL(A) {}
1935 struct Saint_Venant_Kirchhoff_sigma :
public ga_nonlinear_operator {
1936 bool result_size(
const arg_list &args, bgeot::multi_index &sizes)
const {
1937 if (args.size() != 2 || args[0]->sizes().size() != 2
1938 || args[1]->size() != 2
1939 || args[0]->sizes()[0] != args[0]->sizes()[1])
return false;
1940 ga_init_square_matrix_(sizes, args[0]->sizes()[0]);
1945 void value(
const arg_list &args, base_tensor &result)
const {
1947 scalar_type lambda = (*(args[1]))[0], mu = (*(args[1]))[1];
1948 base_matrix Gu(N, N), E(N,N);
1949 gmm::copy(args[0]->as_vector(), Gu.as_vector());
1952 gmm::scale(E, scalar_type(0.5));
1955 base_tensor::iterator it = result.begin();
1957 for (
size_type i = 0; i < N; ++i, ++it) {
1959 if (i == j) *it += lambda*trE;
1968 void derivative(
const arg_list &args,
size_type nder,
1969 base_tensor &result)
const {
1971 scalar_type lambda = (*(args[1]))[0], mu = (*(args[1]))[1], trE;
1972 base_matrix Gu(N, N), E(N,N);
1973 gmm::copy(args[0]->as_vector(), Gu.as_vector());
1977 gmm::scale(E, scalar_type(0.5));
1979 base_tensor::iterator it = result.begin();
1985 for (
size_type i = 0; i < N; ++i, ++it) {
1986 *it = scalar_type(0);
1987 if (i == j && k == l) *it += lambda;
1988 if (i == j) *it += lambda*Gu(k,l);
1989 if (i == k && j == l) *it += mu;
1990 if (i == l && j == k) *it += mu;
1991 if (i == l) *it += mu*Gu(k,j);
1992 if (l == j) *it += mu*Gu(k,i);
1999 for (
size_type i = 0; i < N; ++i, ++it) {
2000 *it = scalar_type(0);
if (i == j) *it += trE;
2004 for (
size_type i = 0; i < N; ++i, ++it) {
2008 default: GMM_ASSERT1(
false,
"Internal error");
2010 GMM_ASSERT1(it == result.end(),
"Internal error");
2015 base_tensor &)
const {
2016 GMM_ASSERT1(
false,
"Sorry, second derivative not implemented");
2022 static bool init_predef_operators() {
2024 ga_predef_operator_tab &PREDEF_OPERATORS
2027 PREDEF_OPERATORS.add_method
2028 (
"Matrix_i2", std::make_shared<matrix_i2_operator>());
2029 PREDEF_OPERATORS.add_method
2030 (
"Matrix_j1", std::make_shared<matrix_j1_operator>());
2031 PREDEF_OPERATORS.add_method
2032 (
"Matrix_j2", std::make_shared<matrix_j2_operator>());
2033 PREDEF_OPERATORS.add_method
2034 (
"Right_Cauchy_Green", std::make_shared<Right_Cauchy_Green_operator>());
2035 PREDEF_OPERATORS.add_method
2036 (
"Left_Cauchy_Green", std::make_shared<Left_Cauchy_Green_operator>());
2037 PREDEF_OPERATORS.add_method
2038 (
"Green_Lagrangian", std::make_shared<Green_Lagrangian_operator>());
2040 PREDEF_OPERATORS.add_method
2041 (
"Cauchy_stress_from_PK2", std::make_shared<Cauchy_stress_from_PK2>());
2043 PREDEF_OPERATORS.add_method
2044 (
"Saint_Venant_Kirchhoff_sigma",
2045 std::make_shared<Saint_Venant_Kirchhoff_sigma>());
2046 PREDEF_OPERATORS.add_method
2047 (
"Saint_Venant_Kirchhoff_PK2",
2048 std::make_shared<Saint_Venant_Kirchhoff_sigma>());
2049 PREDEF_OPERATORS.add_method
2050 (
"Saint_Venant_Kirchhoff_potential",
2051 std::make_shared<AHL_wrapper_potential>
2052 (std::make_shared<SaintVenant_Kirchhoff_hyperelastic_law>()));
2053 PREDEF_OPERATORS.add_method
2054 (
"Plane_Strain_Saint_Venant_Kirchhoff_sigma",
2055 std::make_shared<Saint_Venant_Kirchhoff_sigma>());
2056 PREDEF_OPERATORS.add_method
2057 (
"Plane_Strain_Saint_Venant_Kirchhoff_PK2",
2058 std::make_shared<Saint_Venant_Kirchhoff_sigma>());
2059 PREDEF_OPERATORS.add_method
2060 (
"Plane_Strain_Saint_Venant_Kirchhoff_potential",
2061 std::make_shared<AHL_wrapper_potential>
2062 (std::make_shared<SaintVenant_Kirchhoff_hyperelastic_law>()));
2064 phyperelastic_law gbklaw
2065 = std::make_shared<generalized_Blatz_Ko_hyperelastic_law>();
2066 PREDEF_OPERATORS.add_method
2067 (
"Generalized_Blatz_Ko_sigma",
2068 std::make_shared<AHL_wrapper_sigma>(gbklaw));
2069 PREDEF_OPERATORS.add_method
2070 (
"Generalized_Blatz_Ko_PK2",
2071 std::make_shared<AHL_wrapper_sigma>(gbklaw));
2072 PREDEF_OPERATORS.add_method
2073 (
"Generalized_Blatz_Ko_potential",
2074 std::make_shared<AHL_wrapper_potential>
2075 (std::make_shared<generalized_Blatz_Ko_hyperelastic_law>()));
2076 PREDEF_OPERATORS.add_method
2077 (
"Plane_Strain_Generalized_Blatz_Ko_sigma",
2078 std::make_shared<AHL_wrapper_sigma>
2079 (std::make_shared<plane_strain_hyperelastic_law>(gbklaw)));
2080 PREDEF_OPERATORS.add_method
2081 (
"Plane_Strain_Generalized_Blatz_Ko_PK2",
2082 std::make_shared<AHL_wrapper_sigma>
2083 (std::make_shared<plane_strain_hyperelastic_law>(gbklaw)));
2084 PREDEF_OPERATORS.add_method
2085 (
"Plane_Strain_Generalized_Blatz_Ko_potential",
2086 std::make_shared<AHL_wrapper_potential>
2087 (std::make_shared<plane_strain_hyperelastic_law>(gbklaw)));
2089 phyperelastic_law cigelaw
2090 = std::make_shared<Ciarlet_Geymonat_hyperelastic_law>();
2091 PREDEF_OPERATORS.add_method
2092 (
"Ciarlet_Geymonat_PK2", std::make_shared<AHL_wrapper_sigma>(cigelaw));
2093 PREDEF_OPERATORS.add_method
2094 (
"Ciarlet_Geymonat_sigma", std::make_shared<AHL_wrapper_sigma>(cigelaw));
2095 PREDEF_OPERATORS.add_method
2096 (
"Ciarlet_Geymonat_potential",
2097 std::make_shared<AHL_wrapper_potential>
2098 (std::make_shared<Ciarlet_Geymonat_hyperelastic_law>()));
2099 PREDEF_OPERATORS.add_method
2100 (
"Plane_Strain_Ciarlet_Geymonat_sigma",
2101 std::make_shared<AHL_wrapper_sigma>
2102 (std::make_shared<plane_strain_hyperelastic_law>(cigelaw)));
2103 PREDEF_OPERATORS.add_method
2104 (
"Plane_Strain_Ciarlet_Geymonat_PK2",
2105 std::make_shared<AHL_wrapper_sigma>
2106 (std::make_shared<plane_strain_hyperelastic_law>(cigelaw)));
2107 PREDEF_OPERATORS.add_method
2108 (
"Plane_Strain_Ciarlet_Geymonat_potential",
2109 std::make_shared<AHL_wrapper_potential>
2110 (std::make_shared<plane_strain_hyperelastic_law>(cigelaw)));
2112 phyperelastic_law morilaw
2113 = std::make_shared<Mooney_Rivlin_hyperelastic_law>();
2114 PREDEF_OPERATORS.add_method
2115 (
"Incompressible_Mooney_Rivlin_sigma",
2116 std::make_shared<AHL_wrapper_sigma>(morilaw));
2117 PREDEF_OPERATORS.add_method
2118 (
"Incompressible_Mooney_Rivlin_PK2",
2119 std::make_shared<AHL_wrapper_sigma>(morilaw));
2120 PREDEF_OPERATORS.add_method
2121 (
"Incompressible_Mooney_Rivlin_potential",
2122 std::make_shared<AHL_wrapper_potential>
2123 (std::make_shared<Mooney_Rivlin_hyperelastic_law>()));
2124 PREDEF_OPERATORS.add_method
2125 (
"Plane_Strain_Incompressible_Mooney_Rivlin_PK2",
2126 std::make_shared<AHL_wrapper_sigma>
2127 (std::make_shared<plane_strain_hyperelastic_law>(morilaw)));
2128 PREDEF_OPERATORS.add_method
2129 (
"Plane_Strain_Incompressible_Mooney_Rivlin_sigma",
2130 std::make_shared<AHL_wrapper_sigma>
2131 (std::make_shared<plane_strain_hyperelastic_law>(morilaw)));
2132 PREDEF_OPERATORS.add_method
2133 (
"Plane_Strain_Incompressible_Mooney_Rivlin_potential",
2134 std::make_shared<AHL_wrapper_potential>
2135 (std::make_shared<plane_strain_hyperelastic_law>(morilaw)));
2137 phyperelastic_law cmorilaw
2138 = std::make_shared<Mooney_Rivlin_hyperelastic_law>(
true);
2139 PREDEF_OPERATORS.add_method
2140 (
"Compressible_Mooney_Rivlin_sigma",
2141 std::make_shared<AHL_wrapper_sigma>(cmorilaw));
2142 PREDEF_OPERATORS.add_method
2143 (
"Compressible_Mooney_Rivlin_PK2",
2144 std::make_shared<AHL_wrapper_sigma>(cmorilaw));
2145 PREDEF_OPERATORS.add_method
2146 (
"Compressible_Mooney_Rivlin_potential",
2147 std::make_shared<AHL_wrapper_potential>
2148 (std::make_shared<Mooney_Rivlin_hyperelastic_law>(
true)));
2149 PREDEF_OPERATORS.add_method
2150 (
"Plane_Strain_Compressible_Mooney_Rivlin_PK2",
2151 std::make_shared<AHL_wrapper_sigma>
2152 (std::make_shared<plane_strain_hyperelastic_law>(cmorilaw)));
2153 PREDEF_OPERATORS.add_method
2154 (
"Plane_Strain_Compressible_Mooney_Rivlin_sigma",
2155 std::make_shared<AHL_wrapper_sigma>
2156 (std::make_shared<plane_strain_hyperelastic_law>(cmorilaw)));
2157 PREDEF_OPERATORS.add_method
2158 (
"Plane_Strain_Compressible_Mooney_Rivlin_potential",
2159 std::make_shared<AHL_wrapper_potential>
2160 (std::make_shared<plane_strain_hyperelastic_law>(cmorilaw)));
2162 phyperelastic_law ineolaw
2163 = std::make_shared<Mooney_Rivlin_hyperelastic_law>(
false,
true);
2164 PREDEF_OPERATORS.add_method
2165 (
"Incompressible_Neo_Hookean_sigma",
2166 std::make_shared<AHL_wrapper_sigma>(ineolaw));
2167 PREDEF_OPERATORS.add_method
2168 (
"Incompressible_Neo_Hookean_PK2",
2169 std::make_shared<AHL_wrapper_sigma>(ineolaw));
2170 PREDEF_OPERATORS.add_method
2171 (
"Incompressible_Neo_Hookean_potential",
2172 std::make_shared<AHL_wrapper_potential>
2173 (std::make_shared<Mooney_Rivlin_hyperelastic_law>(
false,
true)));
2174 PREDEF_OPERATORS.add_method
2175 (
"Plane_Strain_Incompressible_Neo_Hookean_sigma",
2176 std::make_shared<AHL_wrapper_sigma>
2177 (std::make_shared<plane_strain_hyperelastic_law>(ineolaw)));
2178 PREDEF_OPERATORS.add_method
2179 (
"Plane_Strain_Incompressible_Neo_Hookean_PK2",
2180 std::make_shared<AHL_wrapper_sigma>
2181 (std::make_shared<plane_strain_hyperelastic_law>(ineolaw)));
2182 PREDEF_OPERATORS.add_method
2183 (
"Plane_Strain_Incompressible_Neo_Hookean_potential",
2184 std::make_shared<AHL_wrapper_potential>
2185 (std::make_shared<plane_strain_hyperelastic_law>(ineolaw)));
2187 phyperelastic_law cneolaw
2188 = std::make_shared<Mooney_Rivlin_hyperelastic_law>(
true,
true);
2189 PREDEF_OPERATORS.add_method
2190 (
"Compressible_Neo_Hookean_sigma",
2191 std::make_shared<AHL_wrapper_sigma>(cneolaw));
2192 PREDEF_OPERATORS.add_method
2193 (
"Compressible_Neo_Hookean_PK2",
2194 std::make_shared<AHL_wrapper_sigma>(cneolaw));
2195 PREDEF_OPERATORS.add_method
2196 (
"Compressible_Neo_Hookean_potential",
2197 std::make_shared<AHL_wrapper_potential>
2198 (std::make_shared<Mooney_Rivlin_hyperelastic_law>(
true,
true)));
2199 PREDEF_OPERATORS.add_method
2200 (
"Plane_Strain_Compressible_Neo_Hookean_sigma",
2201 std::make_shared<AHL_wrapper_sigma>
2202 (std::make_shared<plane_strain_hyperelastic_law>(cneolaw)));
2203 PREDEF_OPERATORS.add_method
2204 (
"Plane_Strain_Compressible_Neo_Hookean_PK2",
2205 std::make_shared<AHL_wrapper_sigma>
2206 (std::make_shared<plane_strain_hyperelastic_law>(cneolaw)));
2207 PREDEF_OPERATORS.add_method
2208 (
"Plane_Strain_Compressible_Neo_Hookean_potential",
2209 std::make_shared<AHL_wrapper_potential>
2210 (std::make_shared<plane_strain_hyperelastic_law>(cneolaw)));
2212 phyperelastic_law cneobolaw
2213 = std::make_shared<Neo_Hookean_hyperelastic_law>(
true);
2214 PREDEF_OPERATORS.add_method
2215 (
"Compressible_Neo_Hookean_Bonet_sigma",
2216 std::make_shared<AHL_wrapper_sigma>(cneobolaw));
2217 PREDEF_OPERATORS.add_method
2218 (
"Compressible_Neo_Hookean_Bonet_PK2",
2219 std::make_shared<AHL_wrapper_sigma>(cneobolaw));
2220 PREDEF_OPERATORS.add_method
2221 (
"Compressible_Neo_Hookean_Bonet_potential",
2222 std::make_shared<AHL_wrapper_potential>
2223 (std::make_shared<Neo_Hookean_hyperelastic_law>(
true)));
2224 PREDEF_OPERATORS.add_method
2225 (
"Plane_Strain_Compressible_Neo_Hookean_Bonet_sigma",
2226 std::make_shared<AHL_wrapper_sigma>
2227 (std::make_shared<plane_strain_hyperelastic_law>(cneobolaw)));
2228 PREDEF_OPERATORS.add_method
2229 (
"Plane_Strain_Compressible_Neo_Hookean_Bonet_PK2",
2230 std::make_shared<AHL_wrapper_sigma>
2231 (std::make_shared<plane_strain_hyperelastic_law>(cneobolaw)));
2232 PREDEF_OPERATORS.add_method
2233 (
"Plane_Strain_Compressible_Neo_Hookean_Bonet_potential",
2234 std::make_shared<AHL_wrapper_potential>
2235 (std::make_shared<plane_strain_hyperelastic_law>(cneobolaw)));
2237 phyperelastic_law cneocilaw
2238 = std::make_shared<Neo_Hookean_hyperelastic_law>(
false);
2239 PREDEF_OPERATORS.add_method
2240 (
"Compressible_Neo_Hookean_Ciarlet_sigma",
2241 std::make_shared<AHL_wrapper_sigma>(cneocilaw));
2242 PREDEF_OPERATORS.add_method
2243 (
"Compressible_Neo_Hookean_Ciarlet_PK2",
2244 std::make_shared<AHL_wrapper_sigma>(cneocilaw));
2245 PREDEF_OPERATORS.add_method
2246 (
"Compressible_Neo_Hookean_Ciarlet_potential",
2247 std::make_shared<AHL_wrapper_potential>
2248 (std::make_shared<Neo_Hookean_hyperelastic_law>(
false)));
2249 PREDEF_OPERATORS.add_method
2250 (
"Plane_Strain_Compressible_Neo_Hookean_Ciarlet_sigma",
2251 std::make_shared<AHL_wrapper_sigma>
2252 (std::make_shared<plane_strain_hyperelastic_law>(cneocilaw)));
2253 PREDEF_OPERATORS.add_method
2254 (
"Plane_Strain_Compressible_Neo_Hookean_Ciarlet_PK2",
2255 std::make_shared<AHL_wrapper_sigma>
2256 (std::make_shared<plane_strain_hyperelastic_law>(cneocilaw)));
2257 PREDEF_OPERATORS.add_method
2258 (
"Plane_Strain_Compressible_Neo_Hookean_Ciarlet_potential",
2259 std::make_shared<AHL_wrapper_potential>
2260 (std::make_shared<plane_strain_hyperelastic_law>(cneocilaw)));
2266 bool predef_operators_nonlinear_elasticity_initialized
2267 = init_predef_operators();
2270 std::string adapt_law_name(
const std::string &lawname,
size_type N) {
2271 std::string adapted_lawname = lawname;
2273 for (
size_type i = 0; i < lawname.size(); ++i)
2274 if (adapted_lawname[i] ==
' ') adapted_lawname[i] =
'_';
2276 if (adapted_lawname.compare(
"SaintVenant_Kirchhoff") == 0) {
2277 adapted_lawname =
"Saint_Venant_Kirchhoff";
2278 }
else if (adapted_lawname.compare(
"Saint_Venant_Kirchhoff") == 0) {
2280 }
else if (adapted_lawname.compare(
"Generalized_Blatz_Ko") == 0) {
2281 if (N == 2) adapted_lawname =
"Plane_Strain_" + adapted_lawname;
2282 }
else if (adapted_lawname.compare(
"Ciarlet_Geymonat") == 0) {
2283 if (N == 2) adapted_lawname =
"Plane_Strain_" + adapted_lawname;
2284 }
else if (adapted_lawname.compare(
"Incompressible_Mooney_Rivlin") == 0) {
2285 if (N == 2) adapted_lawname =
"Plane_Strain_" + adapted_lawname;
2286 }
else if (adapted_lawname.compare(
"Compressible_Mooney_Rivlin") == 0) {
2287 if (N == 2) adapted_lawname =
"Plane_Strain_" + adapted_lawname;
2288 }
else if (adapted_lawname.compare(
"Incompressible_Neo_Hookean") == 0) {
2289 if (N == 2) adapted_lawname =
"Plane_Strain_" + adapted_lawname;
2290 }
else if (adapted_lawname.compare(
"Compressible_Neo_Hookean") == 0 ||
2291 adapted_lawname.compare(
"Compressible_Neo_Hookean_Bonet") == 0 ||
2292 adapted_lawname.compare(
"Compressible_Neo_Hookean_Ciarlet") == 0 ) {
2293 if (N == 2) adapted_lawname =
"Plane_Strain_" + adapted_lawname;
2295 GMM_ASSERT1(
false, lawname <<
" is not a known hyperelastic law");
2297 return adapted_lawname;
2302 (
model &md,
const mesh_im &mim,
const std::string &lawname,
2303 const std::string &varname,
const std::string ¶ms,
2305 std::string test_varname =
"Test_" + sup_previous_and_dot_to_varname(varname);
2307 GMM_ASSERT1(N >= 2 && N <= 3,
2308 "Finite strain elasticity brick works only in 2D or 3D");
2311 GMM_ASSERT1(mf,
"Finite strain elasticity brick can only be applied on "
2314 GMM_ASSERT1(Q == N,
"Finite strain elasticity brick can only be applied "
2315 "on a fem variable having the same dimension as the mesh");
2317 std::string adapted_lawname = adapt_law_name(lawname, N);
2319 std::string expr =
"((Id(meshdim)+Grad_"+varname+
")*(" + adapted_lawname
2320 +
"_PK2(Grad_"+varname+
","+params+
"))):Grad_" + test_varname;
2323 (md, mim, expr, region,
true,
false,
2324 "Finite strain elasticity brick for " + adapted_lawname +
" law");
2328 (
model &md,
const mesh_im &mim,
const std::string &varname,
2329 const std::string &multname,
size_type region) {
2330 std::string test_varname =
"Test_" + sup_previous_and_dot_to_varname(varname);
2331 std::string test_multname =
"Test_" + sup_previous_and_dot_to_varname(multname);
2334 =
"(" + test_multname+
")*(1-Det(Id(meshdim)+Grad_" + varname +
"))"
2335 +
"-(" + multname +
")*(Det(Id(meshdim)+Grad_" + varname +
")"
2336 +
"*((Inv(Id(meshdim)+Grad_" + varname +
"))':Grad_"
2337 + test_varname +
"))" ;
2339 (md, mim, expr, region,
true,
false,
2340 "Finite strain incompressibility brick");
2344 (
model &md,
const std::string &lawname,
const std::string &varname,
2345 const std::string ¶ms,
const mesh_fem &mf_vm,
2346 model_real_plain_vector &VM,
const mesh_region &rg) {
2349 std::string adapted_lawname = adapt_law_name(lawname, N);
2351 std::string expr =
"sqrt(3/2)*Norm(Deviator(Cauchy_stress_from_PK2("
2352 + adapted_lawname +
"_PK2(Grad_" + varname +
"," + params +
"),Grad_"
2354 ga_interpolation_Lagrange_fem(md, expr, mf_vm, VM, rg);
static T & instance()
Instance from the current thread.
virtual void grad_sigma_updated_lagrangian(const base_matrix &F, const base_matrix &E, const base_vector ¶ms, scalar_type det_trans, base_tensor &grad_sigma_ul) const
cauchy-truesdel tangent moduli, used in updated lagrangian
virtual void cauchy_updated_lagrangian(const base_matrix &F, const base_matrix &E, base_matrix &cauchy_stress, const base_vector ¶ms, scalar_type det_trans) const
True Cauchy stress (for Updated Lagrangian formulation)
Describe a finite element method linked to a mesh.
virtual dim_type get_qdim() const
Return the Q dimension.
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
Describe an integration method linked to a mesh.
const mesh & linked_mesh() const
Give a reference to the linked mesh of type mesh.
structure used to hold a set of convexes and/or convex faces.
`‘Model’' variables store the variables, the data and the description of a model.
size_type add_brick(pbrick pbr, const varnamelist &varnames, const varnamelist &datanames, const termlist &terms, const mimlist &mims, size_type region)
Add a brick to the model.
const mesh_fem * pmesh_fem_of_variable(const std::string &name) const
Gives a pointer to the mesh_fem of a variable if any.
A language for generic assembly of pde boundary value problems.
Model representation in Getfem.
Non-linear elasticty and incompressibility bricks.
size_type nnz(const L &l)
count the number of non-zero entries of a vector or matrix.
void copy(const L1 &l1, L2 &l2)
*/
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
void fill_random(L &l)
fill a vector or matrix with random value (uniform [-1,1]).
linalg_traits< M >::value_type mat_trace(const M &m)
Trace of a matrix.
number_traits< typename linalg_traits< M >::value_type >::magnitude_type mat_euclidean_norm(const M &m)
Euclidean norm of a matrix.
void clear(L &l)
clear (fill with zeros) a vector or matrix.
void resize(V &v, size_type n)
*/
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*/
void add(const L1 &l1, L2 &l2)
*/
number_traits< typename linalg_traits< M >::value_type >::magnitude_type mat_euclidean_norm_sqr(const M &m)
*/
void asm_nonlinear_elasticity_tangent_matrix(const MAT &K_, const mesh_im &mim, const getfem::mesh_fem &mf, const VECT1 &U, const getfem::mesh_fem *mf_data, const VECT2 &PARAMS, const abstract_hyperelastic_law &AHL, const mesh_region &rg=mesh_region::all_convexes())
Tangent matrix for the non-linear elasticity.
size_t size_type
used as the common size type in the library
size_type alpha(short_type n, short_type d)
Return the value of which is the number of monomials of a polynomial of variables and degree .
GEneric Tool for Finite Element Methods.
void compute_gradient(const mesh_fem &mf, const mesh_fem &mf_target, const VECT1 &UU, VECT2 &VV)
Compute the gradient of a field on a getfem::mesh_fem.
size_type APIDECL add_nonlinear_term(model &md, const mesh_im &mim, const std::string &expr, size_type region=size_type(-1), bool is_sym=false, bool is_coercive=false, const std::string &brickname="")
Add a nonlinear term given by the weak form language expression expr which will be assembled in regio...
size_type add_finite_strain_elasticity_brick(model &md, const mesh_im &mim, const std::string &lawname, const std::string &varname, const std::string ¶ms, size_type region=size_type(-1))
Add a finite strain elasticity brick to the model with respect to the variable varname (the displacem...
size_type add_finite_strain_incompressibility_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname, size_type region=size_type(-1))
Add a finite strain incompressibility term (for large strain elasticity) to the model with respect to...
size_type add_nonlinear_elasticity_brick(model &md, const mesh_im &mim, const std::string &varname, const phyperelastic_law &AHL, const std::string &dataname, size_type region=size_type(-1))
Add a nonlinear (large strain) elasticity term to the model with respect to the variable varname (dep...
size_type add_nonlinear_incompressibility_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname, size_type region=size_type(-1))
Add a nonlinear incompressibility term (for large strain elasticity) to the model with respect to the...
void compute_finite_strain_elasticity_Von_Mises(model &md, const std::string &lawname, const std::string &varname, const std::string ¶ms, const mesh_fem &mf_vm, model_real_plain_vector &VM, const mesh_region &rg=mesh_region::all_convexes())
Interpolate the Von-Mises stress of a field varname with respect to the nonlinear elasticity constitu...
void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target, const VECTU &U, VECTV &V, int extrapolation=0, double EPS=1E-10, mesh_region rg_source=mesh_region::all_convexes(), mesh_region rg_target=mesh_region::all_convexes())
interpolation/extrapolation of (mf_source, U) on mf_target.
std::shared_ptr< const virtual_brick > pbrick
type of pointer on a brick
virtual void grad_sigma_updated_lagrangian(const base_matrix &F, const base_matrix &E, const base_vector ¶ms, scalar_type det_trans, base_tensor &grad_sigma_ul) const
cauchy-truesdel tangent moduli, used in updated lagrangian