6from sympy.printing
import ccode
11x, y, z = symbols(
'x,y,z')
18 coords = symbols(
'x,y,z')[:nsd]
20 coords = [Symbol(
"x_%d" % d)
for d
in range(nsd)]
32 for d
in range(0, nsd):
41 raise RuntimeError(
"Bernstein only implemented in 1D, 2D, and 3D")
47 b1, b2, b3 = x, y, 1 - x - y
48 for o1
in range(0, order + 1):
49 for o2
in range(0, order + 1):
50 for o3
in range(0, order + 1):
51 if o1 + o2 + o3 == order:
52 aij = Symbol(
"a_%d_%d_%d" % (o1, o2, o3))
53 fac = factorial(order) / (factorial(o1) *
54 factorial(o2) * factorial(o3))
55 sum += aij * fac * pow(b1, o1) * \
56 pow(b2, o2) * pow(b3, o3)
57 basis.append(fac * pow(b1, o1) *
58 pow(b2, o2) * pow(b3, o3))
62 b1, b2, b3, b4 = x, y, z, 1 - x - y - z
63 for o1
in range(0, order + 1):
64 for o2
in range(0, order + 1):
65 for o3
in range(0, order + 1):
66 for o4
in range(0, order + 1):
67 if o1 + o2 + o3 + o4 == order:
68 aij = Symbol(
"a_%d_%d_%d_%d" % (o1, o2, o3, o4))
70 order) / (factorial(o1) * factorial(o2) * factorial(o3) * factorial(o4))
72 pow(b1, o1) * pow(b2, o2) * \
73 pow(b3, o3) * pow(b4, o4)
74 basis.append(fac * pow(b1, o1) * pow(b2, o2) *
75 pow(b3, o3) * pow(b4, o4))
78 return sum, coeff, basis
82 h = Rational(1, order)
86 for i
in range(0, order + 1):
88 for j
in range(0, order + 1):
94 for i
in range(0, order + 1):
96 for j
in range(0, order + 1):
98 for k
in range(0, order + 1):
101 set.append((x, y, z))
107 A = zeros(len(equations))
110 for j
in range(0, len(coeffs)):
112 for i
in range(0, len(equations)):
114 d, _ = reduced(e, [c])
138 ex = pol.subs(x, p[0])
140 ex = ex.subs(y, p[1])
142 ex = ex.subs(z, p[2])
152 b = eye(len(equations))
156 for i
in range(0, len(equations)):
158 for j
in range(0, len(coeffs)):
159 Ni = Ni.subs(coeffs[j], xx[j, i])
166 parser = argparse.ArgumentParser(
168 formatter_class=argparse.RawDescriptionHelpFormatter)
169 parser.add_argument(
"output", type=str, help=
"path to the output folder")
170 return parser.parse_args()
173if __name__ ==
"__main__":
178 orders = [0, 1, 2, 3, 4]
181 cpp =
"#include \"auto_p_bases.hpp\"\n\n\n"
183 "namespace polyfem {\nnamespace autogen " +
"{\nnamespace " +
"{\n"
185 hpp =
"#pragma once\n\n#include <Eigen/Dense>\n#include \"p_n_bases.hpp\"\n#include <cassert>\n\n"
186 hpp = hpp +
"namespace polyfem {\nnamespace autogen " +
"{\n"
189 print(str(dim) +
"D")
190 suffix =
"_2d" if dim == 2
else "_3d"
192 unique_nodes =
"void p_nodes" + suffix + \
193 "(const int p, Eigen::MatrixXd &val)"
195 unique_fun =
"void p_basis_value" + suffix + \
196 "(const int p, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)"
197 dunique_fun =
"void p_grad_basis_value" + suffix + \
198 "(const int p, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)"
200 hpp = hpp + unique_nodes +
";\n\n"
202 hpp = hpp + unique_fun +
";\n\n"
203 hpp = hpp + dunique_fun +
";\n\n"
205 unique_nodes = unique_nodes +
"{\nswitch(p)" +
"{\n"
207 unique_fun = unique_fun +
"{\nswitch(p)" +
"{\n"
208 dunique_fun = dunique_fun +
"{\nswitch(p)" +
"{\n"
211 vertices = [[0, 0], [1, 0], [0, 1]]
213 vertices = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]]
216 print(
"\t-processing " + str(order))
219 def fe():
return None
225 fe.points = [[1./3., 1./3.]]
227 fe.points = [[1./3., 1./3., 1./3.]]
231 current_indices = list(range(0, len(fe.points)))
235 for i
in range(0, dim + 1):
237 for ii
in current_indices:
239 for dd
in range(0, dim):
240 norm = norm + (vv[dd] - fe.points[ii][dd]) ** 2
244 current_indices.remove(ii)
248 for i
in range(0, order - 1):
249 for ii
in current_indices:
250 if fe.points[ii][1] != 0
or (dim == 3
and fe.points[ii][2] != 0):
253 if abs(fe.points[ii][0] - (i + 1) / order) < 1e-10:
255 current_indices.remove(ii)
259 for i
in range(0, order - 1):
260 for ii
in current_indices:
261 if fe.points[ii][0] + fe.points[ii][1] != 1
or (dim == 3
and fe.points[ii][2] != 0):
264 if abs(fe.points[ii][1] - (i + 1) / order) < 1e-10:
266 current_indices.remove(ii)
270 for i
in range(0, order - 1):
271 for ii
in current_indices:
272 if fe.points[ii][0] != 0
or (dim == 3
and fe.points[ii][2] != 0):
275 if abs(fe.points[ii][1] - (1 - (i + 1) / order)) < 1e-10:
277 current_indices.remove(ii)
282 for i
in range(0, order - 1):
283 for ii
in current_indices:
284 if fe.points[ii][0] != 0
or fe.points[ii][1] != 0:
287 if abs(fe.points[ii][2] - (i + 1) / order) < 1e-10:
289 current_indices.remove(ii)
293 for i
in range(0, order - 1):
294 for ii
in current_indices:
295 if fe.points[ii][0] + fe.points[ii][2] != 1
or fe.points[ii][1] != 0:
298 if abs(fe.points[ii][0] - (1 - (i + 1) / order)) < 1e-10:
300 current_indices.remove(ii)
304 for i
in range(0, order - 1):
305 for ii
in current_indices:
306 if fe.points[ii][1] + fe.points[ii][2] != 1
or fe.points[ii][0] != 0:
309 if abs(fe.points[ii][1] - (1 - (i + 1) / order)) < 1e-10:
311 current_indices.remove(ii)
315 nn = max(0, order - 2)
316 npts = int(nn * (nn + 1) / 2)
319 for i
in range(0, npts):
320 for ii
in current_indices:
321 if abs(fe.points[ii][2]) > 1e-10:
325 current_indices.remove(ii)
329 for i
in range(0, npts):
330 for ii
in current_indices:
331 if abs(fe.points[ii][1]) > 1e-10:
335 current_indices.remove(ii)
340 for i
in range(0, npts):
341 for ii
in current_indices:
342 if (abs(fe.points[ii][0]) < 1e-10) | (abs(fe.points[ii][1]) < 1e-10) | (abs(fe.points[ii][2]) < 1e-10):
345 if abs((fe.points[ii][0] + fe.points[ii][1] + fe.points[ii][2]) - 1) > 1e-10:
349 current_indices.remove(ii)
351 for i
in range(0, len(tmp)):
352 indices.append(tmp[(i + 2) % len(tmp)])
356 for i
in range(0, npts):
357 for ii
in current_indices:
358 if abs(fe.points[ii][0]) > 1e-10:
362 current_indices.remove(ii)
364 tmp.sort(reverse=
True)
368 for ii
in current_indices:
372 nodes =
"void p_" + str(order) +
"_nodes" + suffix +
"(Eigen::MatrixXd &res) {\n res.resize(" + str(
373 len(indices)) +
", " + str(dim) +
"); res << \n"
374 unique_nodes = unique_nodes +
"\tcase " + \
375 str(order) +
": " +
"p_" + str(order) + \
376 "_nodes" + suffix +
"(val); break;\n"
379 nodes = nodes + ccode(fe.points[ii][0]) +
", " + ccode(fe.points[ii][1]) + (
380 (
", " + ccode(fe.points[ii][2]))
if dim == 3
else "") +
",\n"
382 nodes = nodes +
";\n}"
385 func =
"void p_" + str(order) +
"_basis_value" + suffix + \
386 "(const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &result_0)"
387 dfunc =
"void p_" + str(order) +
"_basis_grad_value" + suffix + \
388 "(const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)"
390 unique_fun = unique_fun +
"\tcase " + str(order) +
": " +
"p_" + str(
391 order) +
"_basis_value" + suffix +
"(local_index, uv, val); break;\n"
392 dunique_fun = dunique_fun +
"\tcase " + str(order) +
": " +
"p_" + str(
393 order) +
"_basis_grad_value" + suffix +
"(local_index, uv, val); break;\n"
398 default_base =
"p_n_basis_value_3d(p, local_index, uv, val);" if dim == 3
else "p_n_basis_value_2d(p, local_index, uv, val);"
399 default_dbase =
"p_n_basis_grad_value_3d(p, local_index, uv, val);" if dim == 3
else "p_n_basis_grad_value_2d(p, local_index, uv, val);"
400 default_nodes =
"p_n_nodes_3d(p, val);" if dim == 3
else "p_n_nodes_2d(p, val);"
402 base =
"auto x=uv.col(0).array();\nauto y=uv.col(1).array();"
404 base = base +
"\nauto z=uv.col(2).array();"
409 base = base +
"result_0.resize(x.size(),1);\n"
411 base = base +
"switch(local_index){\n"
413 "val.resize(uv.rows(), uv.cols());\n Eigen::ArrayXd result_0(uv.rows());\n" + \
414 "switch(local_index){\n"
416 for i
in range(0, fe.nbf()):
417 real_index = indices[i]
421 simplify(fe.N[real_index])).replace(
" = 1;",
".setOnes();") +
"} break;\n"
422 dbase = dbase +
"\tcase " + str(i) +
": {" + \
423 "{" +
pretty_print.C99_print(simplify(diff(fe.N[real_index], x))).replace(
" = 0;",
".setZero();").replace(
" = 1;",
".setOnes();").replace(
" = -1;",
".setConstant(-1);") +
"val.col(0) = result_0; }" \
424 "{" +
pretty_print.C99_print(simplify(diff(fe.N[real_index], y))).replace(
" = 0;",
".setZero();").replace(
425 " = 1;",
".setOnes();").replace(
" = -1;",
".setConstant(-1);") +
"val.col(1) = result_0; }"
428 dbase = dbase +
"{" +
pretty_print.C99_print(simplify(diff(fe.N[real_index], z))).replace(
" = 0;",
".setZero();").replace(
429 " = 1;",
".setOnes();").replace(
" = -1;",
".setConstant(-1);") +
"val.col(2) = result_0; }"
431 dbase = dbase +
"} break;\n"
433 base = base +
"\tdefault: assert(false);\n}"
434 dbase = dbase +
"\tdefault: assert(false);\n}"
436 cpp = cpp + func +
"{\n\n"
437 cpp = cpp + base +
"}\n"
439 cpp = cpp + dfunc +
"{\n\n"
440 cpp = cpp + dbase +
"}\n\n\n" + nodes +
"\n\n\n"
442 unique_nodes = unique_nodes +
"\tdefault: "+default_nodes+
"\n}}"
444 unique_fun = unique_fun +
"\tdefault: "+default_base+
"\n}}"
445 dunique_fun = dunique_fun +
"\tdefault: "+default_dbase+
"\n}}"
447 cpp = cpp +
"}\n\n" + unique_nodes +
"\n" + unique_fun + \
448 "\n\n" + dunique_fun +
"\n" +
"\nnamespace " +
"{\n"
451 hpp = hpp +
"\nstatic const int MAX_P_BASES = " + str(max(orders)) +
";\n"
453 cpp = cpp +
"\n}}}\n"
456 path = os.path.abspath(args.output)
459 with open(os.path.join(path,
"auto_p_bases.cpp"),
"w")
as file:
462 with open(os.path.join(path,
"auto_p_bases.hpp"),
"w")
as file:
__init__(self, nsd, order)
create_matrix(equations, coeffs)
create_point_set(order, nsd)
bernstein_space(order, nsd)