PolyFEM
Loading...
Searching...
No Matches
diff_elastic_energy.py
Go to the documentation of this file.
1
import
sympy
as
sp
2
from
sympy.printing
import
ccode
3
import
pretty_print
4
import
argparse
5
import
os
6
import
numpy
as
np
7
from
pathlib
import
Path
8
9
10
class
AMIPSEnergy
:
11
def
__init__
(self, use_rest_pose, dim):
12
self.
use_rest_pose
= use_rest_pose
13
self.
dim
= dim
14
15
def
parameters
(self):
16
return
[]
17
18
def
get_standard
(self):
19
if
self.
use_rest_pose
:
20
return
sp.eye(self.
dim
)
21
22
if
self.
dim
== 2:
23
standard = sp.Matrix([
24
[1, 0],
25
[sp.Rational(1, 2), sp.sqrt(3) / 2]
26
])
27
else
:
28
standard = sp.Matrix([
29
[1, 0, 0],
30
[sp.Rational(1, 2), sp.sqrt(3) / 2, 0],
31
[sp.Rational(1, 2),
32
sp.Rational(1, 2) / sp.sqrt(3), sp.sqrt(3) / 2]
33
])
34
standard = standard.inv().T
35
36
return
standard
37
38
def
eval
(self, p, t, el_id, def_grad):
39
if
self.
use_rest_pose
:
40
power = 1
if
self.
dim
== 2
else
sp.Rational(2, 3)
41
else
:
42
power = 2
if
self.
dim
== 2
else
sp.Rational(5, 3)
43
44
standard = self.
get_standard
()
45
46
if
not
self.
use_rest_pose
:
47
def_grad = def_grad @ standard
48
49
det = def_grad.det()
50
51
# if det <= 0:
52
# return sp.nan
53
54
powJ = det**power
55
return
(def_grad.T @ def_grad).trace() / powJ
56
57
58
class
VolumePenaltyEnergy
:
59
def
__init__
(self, dim):
60
self.
dim
= dim
61
self.
k_
= sp.Symbol(
'k'
)
62
63
def
parameters
(self):
64
return
[
"k"
]
65
66
def
eval
(self, p, t, el_id, def_grad):
67
k = self.
k_
68
69
J = def_grad.det()
70
log_J = sp.log(J)
71
72
val = k / 2.0 * ((J * J - 1) / 2.0 - log_J)
73
74
return
val
75
76
77
def
compute_energy
(energy):
78
dim = energy.dim
79
F = sp.Matrix(dim, dim,
lambda
i, j: sp.Symbol(f
"F{i}{j}"
))
80
p = sp.MatrixSymbol(
'p'
, dim, 1)
81
t = sp.Symbol(
't'
)
82
el_id = sp.Symbol(
'el_id'
)
83
84
E = energy.eval(p, t, el_id, F)
85
E = sp.simplify(E)
86
87
x = sp.Matrix([F[i, j]
for
i
in
range(dim)
for
j
in
range(dim)])
88
grad = sp.Matrix([sp.diff(E, v)
for
v
in
x])
89
hess = grad.jacobian(x)
90
91
return
E, grad, hess
92
93
94
energies = {
95
"VolumePenalty2d"
:
VolumePenaltyEnergy
(dim=2),
96
"VolumePenalty3d"
:
VolumePenaltyEnergy
(dim=3),
97
"AMIPS2d"
:
AMIPSEnergy
(use_rest_pose=
False
, dim=2),
98
"AMIPS2drest"
:
AMIPSEnergy
(use_rest_pose=
True
, dim=2),
99
"AMIPS3d"
:
AMIPSEnergy
(use_rest_pose=
False
, dim=3),
100
"AMIPS3drest"
:
AMIPSEnergy
(use_rest_pose=
True
, dim=3),
101
}
102
103
104
def
parse_args
():
105
parser = argparse.ArgumentParser(
106
description=__doc__,
107
formatter_class=argparse.RawDescriptionHelpFormatter)
108
parser.add_argument(
"output"
, type=str, help=
"path to the output folder"
)
109
return
parser.parse_args()
110
111
112
if
__name__ ==
"__main__"
:
113
args =
parse_args
()
114
path = Path(os.path.abspath(args.output))
115
116
for
name, energy
in
energies.items():
117
E, grad, hess =
compute_energy
(energy)
118
dim = energy.dim
119
120
file = path / f
"{name}.hpp"
121
122
fparams =
"(const RowVectorNd &p, const double t, const int el_id, const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3>& F"
123
for
param
in
energy.parameters():
124
fparams += f
", const double {param}"
125
fparams +=
")"
126
127
with
open(file,
"w"
)
as
f:
128
f.write(f
"// Auto-generated code for {name} energy\n"
)
129
f.write(f
"#pragma once\n"
)
130
f.write(
"#include <Eigen/Dense>\n\n"
)
131
f.write(
"namespace polyfem {\n"
)
132
f.write(f
" namespace autogen {{\n"
)
133
134
# f.write(f" inline double {name}_energy{fparams} {{\n")
135
# for i in range(dim):
136
# for j in range(dim):
137
# f.write(f" const double F{i*dim + j} = F({i}, {j});\n")
138
# f.write(f" const double {pretty_print.C99_print(sp.sympify(E))}\n")
139
# f.write(f" return result_0;\n")
140
# f.write(" }\n\n")
141
142
f.write(
143
f
" Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> {name}_gradient{fparams} {{\n"
)
144
f.write(
145
f
" Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> grad({dim},{dim});\n"
)
146
for
i
in
range(dim):
147
for
j
in
range(dim):
148
f.write(
149
f
" const double F{i}{j} = F({i}, {j});\n"
)
150
f.write(f
" std::array<double, {dim*dim}> result_0;\n"
)
151
f.write(
152
f
" {pretty_print.C99_print(sp.sympify(grad))};\n"
)
153
for
i
in
range(dim):
154
for
j
in
range(dim):
155
idx = i * dim + j
156
f.write(f
" grad({i}, {j}) = result_0[{idx}];\n"
)
157
f.write(
" return grad;\n"
)
158
f.write(
" }\n\n"
)
159
160
f.write(
161
f
" inline Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 9, 9> {name}_hessian{fparams} {{\n"
)
162
f.write(
163
f
" Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 9, 9> hess({dim*dim},{dim*dim});\n"
)
164
f.write(f
" std::array<double, {dim**4}> result_0;\n"
)
165
for
i
in
range(dim):
166
for
j
in
range(dim):
167
f.write(
168
f
" const double F{i}{j} = F({i}, {j});\n"
)
169
f.write(
170
f
" {pretty_print.C99_print(sp.sympify(hess))};\n"
)
171
for
i
in
range(dim*dim):
172
for
j
in
range(dim*dim):
173
f.write(
174
f
" hess({i}, {j}) = result_0[{i*dim*dim+j}];\n"
)
175
f.write(
" return hess;\n"
)
176
f.write(
" }\n"
)
177
f.write(
" }\n"
)
178
f.write(
"}\n"
)
diff_elastic_energy.AMIPSEnergy
Definition
diff_elastic_energy.py:10
diff_elastic_energy.AMIPSEnergy.get_standard
get_standard(self)
Definition
diff_elastic_energy.py:18
diff_elastic_energy.AMIPSEnergy.use_rest_pose
use_rest_pose
Definition
diff_elastic_energy.py:12
diff_elastic_energy.AMIPSEnergy.parameters
parameters(self)
Definition
diff_elastic_energy.py:15
diff_elastic_energy.AMIPSEnergy.__init__
__init__(self, use_rest_pose, dim)
Definition
diff_elastic_energy.py:11
diff_elastic_energy.AMIPSEnergy.dim
dim
Definition
diff_elastic_energy.py:13
diff_elastic_energy.AMIPSEnergy.eval
eval(self, p, t, el_id, def_grad)
Definition
diff_elastic_energy.py:38
diff_elastic_energy.VolumePenaltyEnergy
Definition
diff_elastic_energy.py:58
diff_elastic_energy.VolumePenaltyEnergy.__init__
__init__(self, dim)
Definition
diff_elastic_energy.py:59
diff_elastic_energy.VolumePenaltyEnergy.dim
dim
Definition
diff_elastic_energy.py:60
diff_elastic_energy.VolumePenaltyEnergy.k_
k_
Definition
diff_elastic_energy.py:61
diff_elastic_energy.VolumePenaltyEnergy.parameters
parameters(self)
Definition
diff_elastic_energy.py:63
diff_elastic_energy.VolumePenaltyEnergy.eval
eval(self, p, t, el_id, def_grad)
Definition
diff_elastic_energy.py:66
diff_elastic_energy.compute_energy
compute_energy(energy)
Definition
diff_elastic_energy.py:77
diff_elastic_energy.parse_args
parse_args()
Definition
diff_elastic_energy.py:104
src
polyfem
autogen
diff_elastic_energy.py
Generated by
1.9.8