PolyFEM
Loading...
Searching...
No Matches
eigs.py
Go to the documentation of this file.
1from sympy import *
2from sympy.matrices import *
3import os
4import re
5import argparse
6
7# local
8import pretty_print
9
10
11def sqr(a):
12 return a * a
13
14
16 tmp = Piecewise((0.0, x >= 1.0), (pi, x <= -1.0), (acos(x), True))
17 return tmp.subs(x, x)
18
19
20def eigs_2d(mat):
21 a = mat[0, 0] + mat[1, 1]
22 delta = (mat[0, 0] - mat[1, 1])**2 + 4 * mat[0, 1]**2
23
24 tmp1 = Piecewise(
25 (a / 2, delta < 1e-10),
26 ((a - sqrt(delta)) / 2.0, True)
27 )
28
29 tmp2 = Piecewise(
30 (a / 2, delta < 1e-10),
31 ((a + sqrt(delta)) / 2.0, True)
32 )
33
34 return tmp1.subs(delta, delta), tmp2.subs(delta, delta)
35
36
37def eigs_3d(mat):
38 b = mat[0] + mat[4] + mat[8]
39 t = sqr(mat[1]) + sqr(mat[2]) + sqr(mat[5])
40 p = 0.5 * (sqr(mat[0] - mat[4]) + sqr(mat[0] - mat[8]) + sqr(mat[4] - mat[8]))
41 p += 3.0 * t
42 q = 18.0 * (mat[0] * mat[4] * mat[8] + 3.0 * mat[1] * mat[2] * mat[5])
43 q += 2.0 * (mat[0] * sqr(mat[0]) + mat[4] * sqr(mat[4]) + mat[8] * sqr(mat[8]))
44 q += 9.0 * b * t
45 q -= 3.0 * (mat[0] + mat[4]) * (mat[0] + mat[8]) * (mat[4] + mat[8])
46 q -= 27.0 * (mat[0] * sqr(mat[5]) + mat[4] * sqr(mat[2]) + mat[8] * sqr(mat[1]))
47
48 delta = trunc_acos(0.5 * q / sqrt(p * sqr(p)))
49 p = 2.0 * sqrt(p)
50
51 tmp1 = Piecewise(
52 (b / 3.0, p < 1e-10),
53 ((b + p * cos(delta / 3.0)) / 3.0, True)
54 )
55
56 tmp2 = Piecewise(
57 (b / 3.0, p < 1e-10),
58 ((b + p * cos((delta + 2.0 * pi) / 3.0)) / 3.0, True)
59 )
60
61 tmp3 = Piecewise(
62 (b / 3.0, p < 1e-10),
63 ((b + p * cos((delta - 2.0 * pi) / 3.0)) / 3.0, True)
64 )
65
66 return tmp1.subs(p, p), tmp2.subs(p, p), tmp3.subs(p, p)
67
68
70 parser = argparse.ArgumentParser(
71 description=__doc__,
72 formatter_class=argparse.RawDescriptionHelpFormatter)
73 parser.add_argument("output", type=str, help="path to the output folder")
74 return parser.parse_args()
75
76
77if __name__ == "__main__":
78 args = parse_args()
79
80 dims = [2, 3]
81
82 cpp = "#include <polyfem/autogen/auto_eigs.hpp>\n\n\n"
83 hpp = "#pragma once\n\n#include <Eigen/Dense>\n\n"
84 cpp = cpp + "namespace polyfem {\nnamespace autogen " + "{\n"
85 hpp = hpp + "namespace polyfem {\nnamespace autogen " + "{\n"
86
87 hpp = hpp + "template<typename T>\nT int_pow(T val, int exp) { T res = exp <=0 ? T(0.): val; for(int i = 1; i < exp; ++i) res = res*val; return res; }\n\n"
88
89 lambdaa = Symbol('lambda', real=True)
90
91 for dim in dims:
92 print("processing " + str(dim))
93
94 M = zeros(dim, dim)
95
96 for i in range(0, dim):
97 for j in range(0, dim):
98 if i <= j:
99 M[i, j] = Symbol('m[' + str(i) + ',' + str(j) + ']', real=True)
100 else:
101 M[i, j] = Symbol('m[' + str(j) + ',' + str(i) + ']', real=True)
102
103 if dim == 2:
104 lambdas = eigs_2d(M)
105 else:
106 lambdas = eigs_3d(M)
107
108 # lambdas = simplify(lambdas)
109
111
112 c99 = re.sub(r"m\[(\d{1}),(\d{1})\]", r'm(\1,\2)', c99)
113 c99 = re.sub(r"result_(\d{1})", r'res(\1)', c99)
114 c99 = c99.replace("0.0", "T(0)")
115 c99 = c99.replace(" M_PI", " T(M_PI)")
116
117 signature = "template<typename T>\nvoid eigs_" + str(dim) + "d(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> &m, "
118 signature += "Eigen::Matrix<T, Eigen::Dynamic, 1, 0, 3, 1> &res)"
119
120 hpp = hpp + signature + " {\nres.resize(" + str(dim) + ");\n" + c99 + "\n}\n\n"
121
122 cpp = cpp + "\n"
123 hpp = hpp + "\n"
124
125 cpp = cpp + "\n}}\n"
126 hpp = hpp + "\n}}\n"
127
128 path = os.path.abspath(args.output)
129
130 print("saving...")
131 with open(os.path.join(path, "auto_eigs.cpp"), "w") as file:
132 file.write(cpp)
133
134 with open(os.path.join(path, "auto_eigs.hpp"), "w") as file:
135 file.write(hpp)
136
137 print("done!")
parse_args()
Definition eigs.py:69
sqr(a)
Definition eigs.py:11
trunc_acos(x)
Definition eigs.py:15
eigs_2d(mat)
Definition eigs.py:20
eigs_3d(mat)
Definition eigs.py:37
C99_print(expr)