PolyFEM
Loading...
Searching...
No Matches
generate_mooney_rivlin.py
Go to the documentation of this file.
1from sympy import symbols, trace, det, log, Pow, Rational, MatrixSymbol, Matrix, ccode
2from pretty_print import C99_print_tensor
3import re
4
5c1, c2, c3, d1 = symbols("c1 c2 c3 d1")
6
7
9 ret = s.replace("[", "(").replace("]", ")")
10
11 def replace_pow_with_x_times_x(match):
12 return match.group(1) + '*' + match.group(1)
13 # Regular expression pattern to match "pow(x, 2)" where x is a variable
14 pattern = r'pow\‍(([^,]+), 2\‍)'
15 # Use re.sub to replace all occurrences
16 ret = re.sub(pattern, replace_pow_with_x_times_x, ret)
17 return ret
18
19
20def mr_energy(F_):
21 # Right cauchy green tensor
22 RCG = F_ @ F_.T
23 def first(X): return Pow(det(F_), Rational(-2, dim)) * trace(X)
24
25 def second(X): return Pow(det(F_), Rational(-4, dim)) * \
26 Rational(1, 2) * (trace(X)*trace(X) - trace(X*X))
27 energy = c1 * (first(RCG) - dim) + c2 * (second(RCG) - dim) + c3 * \
28 (first(RCG) - dim) * (second(RCG) - dim) + \
29 d1 * log(det(F_)) * log(det(F_))
30 return energy
31
32
33print(R"""
34#include "auto_mooney_rivlin_gradient_hessian.hpp"
35
36namespace polyfem {
37 namespace autogen {
38
39
40template<>
41void generate_gradient_templated(const double c1, const double c2, const double c3, const double d1, const Eigen::Matrix<double, 2, 2> &def_grad, Eigen::Matrix<double, 2, 2> &gradient)
42{
43""")
44
45
46dim = 2
47F = MatrixSymbol('def_grad', dim, dim)
48F_ = Matrix(F)
49
50energy = mr_energy(F_)
51grad = energy.diff(F_)
52hess = grad.diff(F_)
53
54print(optimizations(C99_print_tensor(grad, "gradient")))
55
56
57print(R"""
58}
59
60template <>
61void generate_hessian_templated(const double c1, const double c2, const double c3, const double d1, const Eigen::Matrix<double, 2, 2> &def_grad, Eigen::Matrix<double, 4, 4> &hessian)
62{
63""")
64
65print(optimizations(C99_print_tensor(hess, "hessian")))
66
67print(R"""
68}
69
70template <>
71void generate_gradient_templated(const double c1, const double c2, const double c3, const double d1, const Eigen::Matrix<double, 3, 3> &def_grad, Eigen::Matrix<double, 3, 3> &gradient){
72
73""")
74
75dim = 3
76F = MatrixSymbol('def_grad', dim, dim)
77F_ = Matrix(F)
78
79energy = mr_energy(F_)
80grad = energy.diff(F_)
81hess = grad.diff(F_)
82
83print(optimizations(C99_print_tensor(grad, "gradient")))
84
85print(R"""
86}
87
88template <>
89void generate_hessian_templated(const double c1, const double c2, const double c3, const double d1, const Eigen::Matrix<double, 3, 3> &def_grad, Eigen::Matrix<double, 9, 9> &hessian)
90{
91""")
92
93print(optimizations(C99_print_tensor(hess, "hessian")))
94
95print(R"""
96}
97
98void generate_gradient(const double c1, const double c2, const double c3, const double d1, const Eigen::MatrixXd &def_grad, Eigen::MatrixXd &gradient)
99{
100 int dim = def_grad.rows();
101
102if (dim == 2)
103{
104 Eigen::Matrix<double, 2, 2> temp;
105 generate_gradient_templated<2>(c1, c2, c3, d1, def_grad, temp);
106 gradient = temp;
107}
108if (dim == 3)
109{
110 Eigen::Matrix<double, 3, 3> temp;
111 generate_gradient_templated<3>(c1, c2, c3, d1, def_grad, temp);
112 gradient = temp;
113}
114}
115
116void generate_hessian(const double c1, const double c2, const double c3, const double d1, const Eigen::MatrixXd &def_grad, Eigen::MatrixXd &hessian)
117{
118 int dim = def_grad.rows();
119
120if (dim == 2)
121{
122 Eigen::Matrix<double, 4, 4> temp;
123 generate_hessian_templated<2>(c1, c2, c3, d1, def_grad, temp);
124 hessian = temp;
125}
126if (dim == 3)
127{
128 Eigen::Matrix<double, 9, 9> temp;
129 generate_hessian_templated<3>(c1, c2, c3, d1, def_grad, temp);
130 hessian = temp;
131}
132}
133}
134}
135 """)