5from sympy.printing
import ccode
10x, y, z = symbols(
'x,y,z')
17 coords = symbols(
'x,y,z')[:nsd]
19 coords = [Symbol(
"x_%d" % d)
for d
in range(nsd)]
31 for d
in range(0, nsd):
39 h = Rational(1, order)
43 for i
in range(0, order + 1):
48 for i
in range(0, order + 1):
50 for j
in range(0, order + 1):
55 for i
in range(0, order + 1):
57 for j
in range(0, order + 1):
59 for k
in range(0, order + 1):
85 for j
in range(order + 1):
88 for m
in range(order+1):
92 vx *= (x - xm)/(xj - xm)
96 for i
in range(order + 1):
103 for j
in range(order + 1):
107 for m
in range(order+1):
111 vx *= (x - xm)/(xj - xm)
112 vy *= (y - xm)/(xj - xm)
117 for i
in range(order + 1):
118 for j
in range(order + 1):
119 N.append(Ntmpx[i]*Ntmpy[j])
125 for j
in range(order + 1):
130 for m
in range(order+1):
134 vx *= (x - xm)/(xj - xm)
135 vy *= (y - xm)/(xj - xm)
136 vz *= (z - xm)/(xj - xm)
142 for i
in range(order + 1):
143 for j
in range(order + 1):
144 for l
in range(order + 1):
145 N.append(Ntmpx[i]*Ntmpy[j]*Ntmpz[l])
151 parser = argparse.ArgumentParser(
153 formatter_class=argparse.RawDescriptionHelpFormatter)
154 parser.add_argument(
"output", type=str, help=
"path to the output folder")
155 return parser.parse_args()
158if __name__ ==
"__main__":
160 path = os.path.abspath(args.output)
163 orders = [0, 1, 2, 3, -2]
166 namev = f
"auto_q_bases_{dim}d_val"
167 namen = f
"auto_q_bases_{dim}d_nodes"
168 nameg = f
"auto_q_bases_{dim}d_grad"
170 cppv = f
"#include \"{namev}.hpp\"\n\n\n"
172 "namespace polyfem {\nnamespace autogen " +
"{\nnamespace " +
"{\n"
174 cppn = f
"#include \"{namen}.hpp\"\n\n\n"
176 "namespace polyfem {\nnamespace autogen " +
"{\nnamespace " +
"{\n"
178 cppg = f
"#include \"{nameg}.hpp\"\n\n\n"
180 "namespace polyfem {\nnamespace autogen " +
"{\nnamespace " +
"{\n"
182 cppg =
"#include <Eigen/Dense>\n#include <cassert>\n namespace polyfem {\nnamespace autogen {"
186 hppv =
"#pragma once\n\n#include <Eigen/Dense>\n#include <cassert>\n\n"
187 hppv = hppv +
"namespace polyfem {\nnamespace autogen " +
"{\n"
189 hppn =
"#pragma once\n\n#include <Eigen/Dense>\n#include <cassert>\n\n"
190 hppn = hppn +
"namespace polyfem {\nnamespace autogen " +
"{\n"
192 hppg =
"#pragma once\n\n#include <Eigen/Dense>\n#include <cassert>\n\n"
193 hppg = hppg +
"namespace polyfem {\nnamespace autogen " +
"{\n"
195 print(str(dim) +
"D")
196 suffix =
"_2d" if dim == 2
else (
"_3d" if dim == 3
else "_1d")
198 unique_nodes =
"void q_nodes" + suffix + \
199 "(const int q, Eigen::MatrixXd &val)"
201 unique_fun =
"void q_basis_value" + suffix + \
202 "(const int q, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)"
203 dunique_fun =
"void q_grad_basis_value" + suffix + \
204 "(const int q, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)"
206 hppn = hppn + unique_nodes +
";\n\n"
208 hppv = hppv + unique_fun +
";\n\n"
209 hppg = hppg + dunique_fun +
";\n\n"
211 unique_nodes = unique_nodes +
"{\nswitch(q)" +
"{\n"
213 unique_fun = unique_fun +
"{\nswitch(q)" +
"{\n"
214 dunique_fun = dunique_fun +
"{\nswitch(q)" +
"{\n"
217 vertices = [[0], [1]]
219 vertices = [[0, 0], [1, 0], [1, 1], [0, 1]]
221 vertices = [[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0],
222 [0, 0, 1], [1, 0, 1], [1, 1, 1], [0, 1, 1]]
225 orderss = orders + [4, 5, 6]
228 for order
in orderss:
229 print(
"\t-processing " + str(order))
232 def fe():
return None
240 fe.points = [[1./2., 1./2.]]
242 fe.points = [[1./2., 1./2., 1./2.]]
244 def fe():
return None
253 for eta_a
in [-1, 1]:
254 tmp = (1/4*(2*x*xi_a-xi_a+1))*(2*eta_a*y -
255 eta_a+1)*(2*eta_a*y+2*x*xi_a-eta_a-xi_a-1)
257 fe.points.append([(xi_a+1)/2, (eta_a+1)/2])
259 for eta_a
in [-1, 1]:
260 tmp = -2*x*(x-1)*(2*eta_a*y-eta_a+1)
262 fe.points.append([1/2, (eta_a+1)/2])
265 tmp = -2*y*(y-1)*(2*x*xi_a-xi_a+1)
267 fe.points.append([(xi_a+1)/2, 1/2])
269 assert (len(fe.points) == 8)
270 assert (len(fe.N) == 8)
278 for eta_a
in [-1, 1]:
279 for zeta_a
in [-1, 1]:
280 tmp = (1/8*(2*x*xi_a-xi_a+1))*(2*eta_a*y-eta_a+1)*(2*z*zeta_a-zeta_a+1)*(
281 2*eta_a*y+2*x*xi_a+2*z*zeta_a-eta_a-xi_a-zeta_a-2)
284 [(xi_a+1)/2, (eta_a+1)/2, (zeta_a+1)/2])
286 for eta_a
in [-1, 1]:
287 for zeta_a
in [-1, 1]:
288 tmp = -x*(x-1)*(2*eta_a*y-eta_a+1) * \
289 (2*z*zeta_a-zeta_a+1)
291 fe.points.append([1/2, (eta_a+1)/2, (zeta_a+1)/2])
294 for zeta_a
in [-1, 1]:
295 tmp = -y*(y-1)*(2*x*xi_a-xi_a+1) * \
296 (2*z*zeta_a-zeta_a+1)
298 fe.points.append([(xi_a+1)/2, 1/2, (zeta_a+1)/2])
301 for eta_a
in [-1, 1]:
302 tmp = -z*(z-1)*(2*x*xi_a-xi_a+1) * \
305 fe.points.append([(xi_a+1)/2, (eta_a+1)/2, 1/2])
307 assert (len(fe.points) == 20)
308 assert (len(fe.N) == 20)
314 current_indices = list(range(0, len(fe.points)))
319 for i
in range(0, 2**dim):
322 for ii
in current_indices:
324 for dd
in range(0, dim):
325 norm = norm + (vv[dd] - fe.points[ii][dd]) ** 2
329 current_indices.remove(ii)
333 for i
in range(0, abs(order) - 1):
334 for ii
in current_indices:
335 if fe.points[ii][1] != 0
or (dim == 3
and fe.points[ii][2] != 0):
338 if abs(fe.points[ii][0] - (i + 1) / abs(order)) < 1e-10:
340 current_indices.remove(ii)
344 for i
in range(0, abs(order) - 1):
345 for ii
in current_indices:
346 if fe.points[ii][0] != 1
or (dim == 3
and fe.points[ii][2] != 0):
349 if abs(fe.points[ii][1] - (i + 1) / abs(order)) < 1e-10:
351 current_indices.remove(ii)
355 for i
in range(0, abs(order) - 1):
356 for ii
in current_indices:
357 if fe.points[ii][1] != 1
or (dim == 3
and fe.points[ii][2] != 0):
360 if abs(fe.points[ii][0] - (1 - (i + 1) / abs(order))) < 1e-10:
362 current_indices.remove(ii)
366 for i
in range(0, abs(order) - 1):
367 for ii
in current_indices:
368 if fe.points[ii][0] != 0
or (dim == 3
and fe.points[ii][2] != 0):
371 if abs(fe.points[ii][1] - (1 - (i + 1) / abs(order))) < 1e-10:
373 current_indices.remove(ii)
378 for i
in range(0, abs(order) - 1):
379 for ii
in current_indices:
380 if fe.points[ii][0] != 0
or fe.points[ii][1] != 0:
383 if abs(fe.points[ii][2] - (i + 1) / abs(order)) < 1e-10:
385 current_indices.remove(ii)
389 for i
in range(0, abs(order) - 1):
390 for ii
in current_indices:
391 if fe.points[ii][0] != 1
or fe.points[ii][1] != 0:
394 if abs(fe.points[ii][2] - (1 - (i + 1) / abs(order))) < 1e-10:
396 current_indices.remove(ii)
400 for i
in range(0, abs(order) - 1):
401 for ii
in current_indices:
402 if fe.points[ii][0] != 1
or fe.points[ii][1] != 1:
405 if abs(fe.points[ii][2] - (1 - (i + 1) / abs(order))) < 1e-10:
407 current_indices.remove(ii)
411 for i
in range(0, abs(order) - 1):
412 for ii
in current_indices:
413 if fe.points[ii][0] != 0
or fe.points[ii][1] != 1:
416 if abs(fe.points[ii][2] - (1 - (i + 1) / abs(order))) < 1e-10:
418 current_indices.remove(ii)
422 for i
in range(0, abs(order) - 1):
423 for ii
in current_indices:
424 if fe.points[ii][1] != 0
or fe.points[ii][2] != 1:
427 if abs(fe.points[ii][0] - (i + 1) / abs(order)) < 1e-10:
429 current_indices.remove(ii)
433 for i
in range(0, abs(order) - 1):
434 for ii
in current_indices:
435 if fe.points[ii][0] != 1
or fe.points[ii][2] != 1:
438 if abs(fe.points[ii][1] - (i + 1) / abs(order)) < 1e-10:
440 current_indices.remove(ii)
444 for i
in range(0, abs(order) - 1):
445 for ii
in current_indices:
446 if fe.points[ii][1] != 1
or fe.points[ii][2] != 1:
449 if abs(fe.points[ii][0] - (1 - (i + 1) / abs(order))) < 1e-10:
451 current_indices.remove(ii)
455 for i
in range(0, abs(order) - 1):
456 for ii
in current_indices:
457 if fe.points[ii][0] != 0
or fe.points[ii][2] != 1:
460 if abs(fe.points[ii][1] - (1 - (i + 1) / abs(order))) < 1e-10:
462 current_indices.remove(ii)
466 nn = max(0, abs(order) - 1)
471 for i
in range(0, npts):
472 for ii
in current_indices:
473 if abs(fe.points[ii][0]) > 1e-10:
477 current_indices.remove(ii)
479 tmp.sort(reverse=
True)
484 for i
in range(0, npts):
485 for ii
in current_indices:
486 if abs(fe.points[ii][0] - 1) > 1e-10:
490 current_indices.remove(ii)
495 for i
in range(0, npts):
496 for ii
in current_indices:
497 if abs(fe.points[ii][1]) > 1e-10:
501 current_indices.remove(ii)
505 for i
in range(0, npts):
506 for ii
in current_indices:
507 if abs(fe.points[ii][1]-1) > 1e-10:
511 current_indices.remove(ii)
515 for i
in range(0, npts):
516 for ii
in current_indices:
517 if abs(fe.points[ii][2]) > 1e-10:
521 current_indices.remove(ii)
525 for i
in range(0, npts):
526 for ii
in current_indices:
527 if abs(fe.points[ii][2]-1) > 1e-10:
531 current_indices.remove(ii)
534 for i
in range(0, abs(order)):
535 for ii
in current_indices:
536 if abs(fe.points[ii][0] - (i / abs(order))) < 1e-10:
538 current_indices.remove(ii)
542 for ii
in current_indices:
545 orderN = str(order)
if order >= 0
else "m"+str(-order)
547 nodes =
"void q_" + orderN +
"_nodes" + suffix + \
548 "(Eigen::MatrixXd &res) {\n res.resize(" + \
549 str(len(indices)) +
", " + str(dim) +
"); res << \n"
550 unique_nodes = unique_nodes +
"\tcase " + \
551 str(order) +
": " +
"q_" + orderN + \
552 "_nodes" + suffix +
"(val); break;\n"
554 eextern = eextern + \
555 f
"extern \"C++\" void q_{orderN}_basis_grad_value_3d(const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val);\n"
558 nodes = nodes + ccode(fe.points[ii][0]) + (
"" if dim == 1
else (
", " + ccode(fe.points[ii][1]) + (
559 (
", " + ccode(fe.points[ii][2]))
if dim == 3
else ""))) +
",\n"
561 nodes = nodes +
";\n}"
564 func =
"void q_" + orderN +
"_basis_value" + suffix + \
565 "(const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &result_0)"
566 dfunc =
"void q_" + orderN +
"_basis_grad_value" + suffix + \
567 "(const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)"
569 unique_fun = unique_fun +
"\tcase " + \
570 str(order) +
": " +
"q_" + orderN +
"_basis_value" + \
571 suffix +
"(local_index, uv, val); break;\n"
572 dunique_fun = dunique_fun +
"\tcase " + \
573 str(order) +
": " +
"q_" + orderN +
"_basis_grad_value" + \
574 suffix +
"(local_index, uv, val); break;\n"
579 base =
"auto x=uv.col(0).array();"
581 base = base +
"\nauto y=uv.col(1).array();"
583 base = base +
"\nauto z=uv.col(2).array();"
588 base = base +
"result_0.resize(x.size(),1);\n"
590 base = base +
"switch(local_index){\n"
592 "val.resize(uv.rows(), uv.cols());\n Eigen::ArrayXd result_0(uv.rows());\n" + \
593 "switch(local_index){\n"
595 for i
in range(0, fe.nbf()):
596 real_index = indices[i]
601 simplify(fe.N[real_index])).replace(
" = 1;",
".setOnes();") +
"} break;\n"
602 dbase = dbase +
"\tcase " + str(i) +
": {" + \
603 "{" +
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; }" \
604 "{" +
pretty_print.C99_print(simplify(diff(fe.N[real_index], y))).replace(
" = 0;",
".setZero();").replace(
605 " = 1;",
".setOnes();").replace(
" = -1;",
".setConstant(-1);") +
"val.col(1) = result_0; }"
606 dbase = dbase +
"{" +
pretty_print.C99_print(simplify(diff(fe.N[real_index], z))).replace(
" = 0;",
".setZero();").replace(
607 " = 1;",
".setOnes();").replace(
" = -1;",
".setConstant(-1);") +
"val.col(2) = result_0; }"
610 simplify(fe.N[real_index])).replace(
" = 1;",
".setOnes();") +
"} break;\n"
611 dbase = dbase +
"\tcase " + str(i) +
": {" + \
612 "{" +
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; }" \
613 "{" +
pretty_print.C99_print(simplify(diff(fe.N[real_index], y))).replace(
" = 0;",
".setZero();").replace(
614 " = 1;",
".setOnes();").replace(
" = -1;",
".setConstant(-1);") +
"val.col(1) = result_0; }"
617 simplify(fe.N[real_index])).replace(
" = 1;",
".setOnes();") +
"} break;\n"
618 dbase = dbase +
"\tcase " + str(i) +
": {" + \
619 "{" +
pretty_print.C99_print(simplify(diff(fe.N[real_index], x))).replace(
" = 0;",
".setZero();").replace(
620 " = 1.0;",
".setOnes();").replace(
" = -1.0;",
".setConstant(-1);") +
"val.col(0) = result_0; }"
622 dbase = dbase +
"} break;\n"
624 base = base +
"\tdefault: assert(false);\n}"
625 dbase = dbase +
"\tdefault: assert(false);\n}"
627 cppv = cppv + func +
"{\n\n"
628 cppv = cppv + base +
"}\n"
630 cppg = cppg + dfunc +
"{\n\n"
631 cppg = cppg + dbase +
"}\n\n"
632 cppn = cppn + nodes +
"\n\n"
635 with open(os.path.join(path, f
"{nameg}_{order}.cpp"),
"w")
as file:
636 file.write(cppg+
"}}")
637 cppg =
"#include <Eigen/Dense>\n#include <cassert>\n namespace polyfem {\nnamespace autogen {"
641 unique_nodes = unique_nodes +
"\tdefault: assert(false);\n}}"
643 unique_fun = unique_fun +
"\tdefault: assert(false);\n}}"
644 dunique_fun = dunique_fun +
"\tdefault: assert(false);\n}}"
646 cppv = cppv +
"}\n\n"
647 cppn = cppn +
"}\n\n"
649 cppg = cppg +
"}\n\n"
651 cppn = cppn + unique_nodes +
"\n}}\n"
652 cppv = cppv + unique_fun +
"\n}}\n"
653 cppg = cppg + dunique_fun +
"\n}}\n"
654 hppv = hppv +
"\n}}\n"
655 hppn = hppn +
"\n}}\n"
656 hppg = hppg +
"\n}}\n"
659 tcppg = f
"#include \"{nameg}.hpp\"\n\n\n"
660 tcppg = tcppg +
"namespace polyfem {\nnamespace autogen {\n"
661 tcppg = tcppg + eextern +
"\n"
665 with open(os.path.join(path, f
"{namev}.cpp"),
"w")
as file:
667 with open(os.path.join(path, f
"{namen}.cpp"),
"w")
as file:
669 with open(os.path.join(path, f
"{nameg}.cpp"),
"w")
as file:
672 with open(os.path.join(path, f
"{namev}.hpp"),
"w")
as file:
674 with open(os.path.join(path, f
"{namen}.hpp"),
"w")
as file:
676 with open(os.path.join(path, f
"{nameg}.hpp"),
"w")
as file:
679 hpp =
"#pragma once\n\n#include <Eigen/Dense>\n#include <cassert>\n\n"
681 hpp = hpp + f
"#include \"auto_q_bases_{dim}d_val.hpp\"\n"
682 hpp = hpp + f
"#include \"auto_q_bases_{dim}d_nodes.hpp\"\n"
683 hpp = hpp + f
"#include \"auto_q_bases_{dim}d_grad.hpp\"\n"
684 hpp = hpp +
"\n\nnamespace polyfem {\nnamespace autogen " +
"{\n"
685 hpp = hpp +
"\nstatic const int MAX_Q_BASES = " + str(max(orders)) +
";\n"
689 with open(os.path.join(path,
"auto_q_bases.hpp"),
"w")
as file:
__init__(self, nsd, order)
create_point_set(order, nsd)