19#include <igl/per_face_normals.h>
24 using namespace assembler;
25 using namespace basis;
29 void flattened_tensor_coeffs(
const Eigen::MatrixXd &S, Eigen::MatrixXd &X)
33 X.resize(S.rows(), 3);
38 else if (S.cols() == 9)
41 X.resize(S.rows(), 6);
51 logger().error(
"Invalid tensor dimensions.");
59 Eigen::MatrixXi &
faces,
60 Eigen::MatrixXd &sidesets)
70 const Mesh3D &tmp_mesh =
dynamic_cast<const Mesh3D &
>(mesh);
73 for (
int f = 0; f < tmp_mesh.
n_faces(); ++f)
83 faces.resize(n_faces, 3);
84 sidesets.resize(n_pts, 1);
88 for (
int f = 0; f < tmp_mesh.
n_faces(); ++f)
95 for (
int i = 0; i < n_face_vertices; ++i)
97 if (n_face_vertices == 3)
98 faces.row(n_faces) << ((i + 1) % n_face_vertices + n_pts), (i + n_pts), (n_pts + n_face_vertices);
100 faces.row(n_faces) << (i + n_pts), ((i + 1) % n_face_vertices + n_pts), (n_pts + n_face_vertices);
104 for (
int i = 0; i < n_face_vertices; ++i)
107 sidesets(n_pts) = sideset;
113 sidesets(n_pts) = sideset;
120 const Mesh2D &tmp_mesh =
dynamic_cast<const Mesh2D &
>(mesh);
122 for (
int e = 0; e < tmp_mesh.
n_edges(); ++e)
128 pts.resize(n_siteset * 2, 2);
129 faces.resize(n_siteset, 2);
130 sidesets.resize(n_siteset, 1);
133 for (
int e = 0; e < tmp_mesh.
n_edges(); ++e)
140 faces.row(n_siteset) << 2 * n_siteset, 2 * n_siteset + 1;
141 sidesets(n_siteset) = sideset;
146 pts.conservativeResize(n_siteset * 2, 3);
147 pts.col(2).setZero();
153 const bool is_problem_scalar,
154 const std::vector<basis::ElementBases> &bases,
155 const std::vector<basis::ElementBases> &gbases,
156 const Eigen::MatrixXd &pts,
157 const Eigen::MatrixXi &
faces,
158 const Eigen::MatrixXd &fun,
159 const bool compute_avg,
160 Eigen::MatrixXd &result)
164 logger().error(
"Solve the problem first!");
169 const Mesh3D &mesh3d =
dynamic_cast<const Mesh3D &
>(mesh);
171 Eigen::MatrixXd points, uv;
172 Eigen::VectorXd weights;
175 if (!is_problem_scalar)
178 igl::AABB<Eigen::MatrixXd, 3> tree;
179 tree.init(pts,
faces);
181 result.resize(
faces.rows(), actual_dim);
182 result.setConstant(std::numeric_limits<double>::quiet_NaN());
193 const int face_id = mesh3d.
cell_face(e, lf);
214 for (
size_t j = 0; j < bs.
bases.size(); ++j)
219 for (
int d = 0; d < actual_dim; ++d)
221 for (
size_t g = 0; g < v.
global.size(); ++g)
223 loc_val(d) += (v.
global[g].val * v.
val.array() * fun(v.
global[g].index * actual_dim + d) * weights.array()).sum();
229 Eigen::RowVector3d C;
232 const double dist = tree.squared_distance(pts,
faces, bary, I, C);
233 assert(dist < 1e-16);
235 assert(std::isnan(result(I, 0)));
237 result.row(I) = loc_val / weights.sum();
239 result.row(I) = loc_val;
244 assert(counter == result.rows());
249 const bool is_problem_scalar,
250 const std::vector<basis::ElementBases> &bases,
251 const std::vector<basis::ElementBases> &gbases,
252 const Eigen::MatrixXd &pts,
253 const Eigen::MatrixXi &
faces,
254 const Eigen::MatrixXd &fun,
255 Eigen::MatrixXd &result)
259 logger().error(
"Solve the problem first!");
264 logger().error(
"This function works only on volumetric meshes!");
270 const Mesh3D &mesh3d =
dynamic_cast<const Mesh3D &
>(mesh);
272 Eigen::MatrixXd points;
275 if (!is_problem_scalar)
278 igl::AABB<Eigen::MatrixXd, 3> tree;
279 tree.init(pts,
faces);
281 result.resize(pts.rows(), actual_dim);
291 const int face_id = mesh3d.
cell_face(e, lf);
295 Eigen::RowVector3d C;
298 const double dist = tree.squared_distance(pts,
faces, bary, I, C);
311 Eigen::MatrixXd loc_val(points.rows(), actual_dim);
316 for (
size_t j = 0; j < bs.
bases.size(); ++j)
321 for (
int d = 0; d < actual_dim; ++d)
323 for (
size_t ii = 0; ii < b.
global().size(); ++ii)
324 loc_val.col(d) += b.
global()[ii].val * v.
val * fun(b.
global()[ii].index * actual_dim + d);
328 for (
int lv_id = 0; lv_id <
faces.cols(); ++lv_id)
330 const int v_id =
faces(I, lv_id);
331 const auto p = pts.row(v_id);
332 const auto &mapped =
vals.val;
336 for (
int n = 0; n < mapped.rows(); ++n)
338 if ((p - mapped.row(n)).norm() < 1e-10)
340 result.row(v_id) = loc_val.row(n);
354 const bool is_problem_scalar,
355 const std::vector<basis::ElementBases> &bases,
356 const std::vector<basis::ElementBases> &gbases,
358 const Eigen::MatrixXd &pts,
359 const Eigen::MatrixXi &
faces,
360 const Eigen::MatrixXd &fun,
362 const bool compute_avg,
363 Eigen::MatrixXd &result,
364 Eigen::MatrixXd &stresses,
365 Eigen::MatrixXd &mises,
366 const bool skip_orientation)
369 mesh, is_problem_scalar, bases, gbases,
371 pts,
faces, fun, Eigen::MatrixXd::Zero(pts.rows(), pts.cols()), t,
372 compute_avg, result, stresses, mises, skip_orientation);
377 const bool is_problem_scalar,
378 const std::vector<basis::ElementBases> &bases,
379 const std::vector<basis::ElementBases> &gbases,
381 const Eigen::MatrixXd &pts,
382 const Eigen::MatrixXi &
faces,
383 const Eigen::MatrixXd &fun,
384 const Eigen::MatrixXd &disp,
386 const bool compute_avg,
387 Eigen::MatrixXd &result,
388 Eigen::MatrixXd &stresses,
389 Eigen::MatrixXd &mises,
390 bool skip_orientation)
394 logger().error(
"Solve the problem first!");
397 if (disp.size() <= 0)
399 logger().error(
"Solve the problem first!");
404 logger().error(
"This function works only on volumetric meshes!");
407 if (is_problem_scalar)
409 logger().error(
"Define a tensor problem!");
413 std::vector<std::pair<std::string, Eigen::MatrixXd>> tmp_t, tmp_s;
416 assert(!is_problem_scalar);
418 const Mesh3D &mesh3d =
dynamic_cast<const Mesh3D &
>(mesh);
420 Eigen::MatrixXd normals;
421 igl::per_face_normals((pts + disp).eval(),
faces, normals);
423 Eigen::MatrixXd points, uv, tmp_n, loc_v;
424 Eigen::VectorXd weights;
426 const int actual_dim = 3;
428 igl::AABB<Eigen::MatrixXd, 3> tree;
429 tree.init(pts,
faces);
431 result.resize(
faces.rows(), actual_dim);
432 result.setConstant(std::numeric_limits<double>::quiet_NaN());
434 stresses.resize(
faces.rows(), actual_dim * actual_dim);
435 stresses.setConstant(std::numeric_limits<double>::quiet_NaN());
437 mises.resize(
faces.rows(), 1);
438 mises.setConstant(std::numeric_limits<double>::quiet_NaN());
449 const int face_id = mesh3d.
cell_face(e, lf);
454 Eigen::RowVector3d C;
457 const double dist = tree.squared_distance(pts,
faces, bary, I, C);
476 for (
int lv_id = 0; lv_id <
faces.cols(); ++lv_id)
478 const int v_id =
faces(I, lv_id);
479 const auto p = pts.row(v_id);
480 const auto &mapped =
vals.val;
481 assert(mapped.rows() ==
faces.cols());
483 for (
int n = 0; n < mapped.rows(); ++n)
485 if ((p - mapped.row(n)).norm() < 1e-10)
493 if (count ==
faces.cols())
511 Eigen::RowVector3d tet_n;
515 for (
int n = 0; n <
vals.jac_it.size(); ++n)
517 Eigen::RowVector3d tmp = tmp_n *
vals.jac_it[n];
525 Eigen::MatrixXd loc_val = tmp_t[0].second, local_mises = tmp_s[0].second;
526 Eigen::VectorXd tmp(loc_val.cols());
527 const double tmp_mises = (local_mises.array() * weights.array()).sum();
529 for (
int d = 0; d < loc_val.cols(); ++d)
530 tmp(d) = (loc_val.col(d).array() * weights.array()).sum();
531 const Eigen::MatrixXd tensor = Eigen::Map<Eigen::MatrixXd>(tmp.data(), 3, 3);
533 const Eigen::RowVector3d tmpn = normals.row(I);
534 const Eigen::RowVector3d tmptf = tmpn * tensor;
535 if (skip_orientation || tmpn.dot(tet_n) > 0)
537 assert(std::isnan(result(I, 0)));
538 assert(std::isnan(stresses(I, 0)));
539 assert(std::isnan(mises(I)));
541 result.row(I) = tmptf;
542 stresses.row(I) = tmp;
543 mises(I) = tmp_mises;
547 result.row(I) /= weights.sum();
548 stresses.row(I) /= weights.sum();
549 mises(I) /= weights.sum();
556 assert(counter == result.rows());
561 const bool is_problem_scalar,
563 const std::vector<basis::ElementBases> &bases,
564 const std::vector<basis::ElementBases> &gbases,
565 const Eigen::VectorXi &disc_orders,
566 const std::map<int, Eigen::MatrixXd> &polys,
567 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
572 const Eigen::MatrixXd &fun,
573 std::vector<assembler::Assembler::NamedMatrix> &result_scalar,
574 std::vector<assembler::Assembler::NamedMatrix> &result_tensor,
575 const bool use_sampler,
576 const bool boundary_only)
578 result_scalar.clear();
579 result_tensor.clear();
583 logger().error(
"Solve the problem first!");
586 if (is_problem_scalar)
588 logger().error(
"Define a tensor problem!");
592 assert(!is_problem_scalar);
595 std::vector<Eigen::MatrixXd> avg_scalar;
597 Eigen::MatrixXd areas(n_bases, 1);
600 std::vector<std::pair<std::string, Eigen::MatrixXd>> tmp_s;
601 Eigen::MatrixXd local_val;
604 for (
int i = 0; i < int(bases.size()); ++i)
608 Eigen::MatrixXd local_pts;
630 vals.compute(i, actual_dim == 3, bases[i], gbases[i]);
632 const double area = (
vals.det.array() *
quadrature.weights.array()).sum();
639 for (
size_t j = 0; j < bs.
bases.size(); ++j)
642 if (b.
global().size() > 1)
645 auto &global = b.
global().front();
646 areas(global.index) += area;
649 if (avg_scalar.empty())
651 avg_scalar.resize(tmp_s.size());
652 for (
auto &m : avg_scalar)
654 m.resize(n_bases, 1);
659 for (
int k = 0; k < tmp_s.size(); ++k)
661 local_val = tmp_s[k].second;
663 for (
size_t j = 0; j < bs.
bases.size(); ++j)
666 if (b.
global().size() > 1)
669 auto &global = b.
global().front();
670 avg_scalar[k](global.index) += local_val(j) * area;
675 for (
auto &m : avg_scalar)
677 m.array() /= areas.array();
680 result_scalar.resize(tmp_s.size());
681 for (
int k = 0; k < tmp_s.size(); ++k)
683 result_scalar[k].first = tmp_s[k].first;
685 avg_scalar[k], result_scalar[k].second, use_sampler, boundary_only);
693 const std::vector<basis::ElementBases> &basis,
695 const Eigen::MatrixXd &fun,
696 Eigen::MatrixXd &result)
705 logger().error(
"Solve the problem first!");
710 logger().error(
"This function works only on volumetric meshes!");
714 const Mesh3D &mesh3d =
dynamic_cast<const Mesh3D &
>(mesh);
716 result.resize(mesh3d.
n_vertices(), actual_dim);
722 std::vector<AssemblyValues> tmp;
723 std::vector<bool> marked(mesh3d.
n_vertices(),
false);
724 for (
int i = 0; i < int(basis.size()); ++i)
727 Eigen::MatrixXd local_pts;
728 std::vector<int> vertices;
734 vertices.assign(vtx.begin(), vtx.end());
740 vertices.assign(vtx.begin(), vtx.end());
743 assert((
int)vertices.size() == (
int)local_pts.rows());
745 Eigen::MatrixXd local_res = Eigen::MatrixXd::Zero(local_pts.rows(), actual_dim);
747 for (
size_t j = 0; j < bs.
bases.size(); ++j)
751 for (
int d = 0; d < actual_dim; ++d)
753 for (
size_t ii = 0; ii < b.
global().size(); ++ii)
754 local_res.col(d) += b.
global()[ii].val * tmp[j].val * fun(b.
global()[ii].index * actual_dim + d);
758 for (
size_t lv = 0; lv < vertices.size(); ++lv)
760 int v = vertices[lv];
763 assert((result.row(v) - local_res.row(lv)).norm() < 1e-6);
767 result.row(v) = local_res.row(lv);
776 const bool is_problem_scalar,
777 const std::vector<basis::ElementBases> &bases,
778 const std::vector<basis::ElementBases> &gbases,
779 const Eigen::VectorXi &disc_orders,
781 const Eigen::MatrixXd &fun,
783 Eigen::MatrixXd &result,
784 Eigen::VectorXd &von_mises)
793 logger().error(
"Solve the problem first!");
796 if (is_problem_scalar)
798 logger().error(
"Define a tensor problem!");
803 assert(!is_problem_scalar);
805 Eigen::MatrixXd local_val, local_stress, local_mises;
807 int num_quadr_pts = 0;
808 result.resize(disc_orders.sum(), actual_dim == 2 ? 3 : 6);
810 von_mises.resize(disc_orders.sum(), 1);
821 f.get_quadrature(disc_orders(e), quadr);
826 f.get_quadrature(disc_orders(e), quadr);
834 f.get_quadrature(disc_orders(e), quadr);
839 f.get_quadrature(disc_orders(e), quadr);
847 std::vector<std::pair<std::string, Eigen::MatrixXd>> tmp_s, tmp_t;
852 local_mises = tmp_s[0].second;
853 local_val = tmp_t[0].second;
855 if (num_quadr_pts + local_val.rows() >= result.rows())
857 result.conservativeResize(
858 std::max(num_quadr_pts + local_val.rows() + 1, 2 * result.rows()),
860 von_mises.conservativeResize(result.rows(), von_mises.cols());
862 flattened_tensor_coeffs(local_val, local_stress);
863 result.block(num_quadr_pts, 0, local_stress.rows(), local_stress.cols()) = local_stress;
864 von_mises.block(num_quadr_pts, 0, local_mises.rows(), local_mises.cols()) = local_mises;
865 num_quadr_pts += local_val.rows();
867 result.conservativeResize(num_quadr_pts, result.cols());
868 von_mises.conservativeResize(num_quadr_pts, von_mises.cols());
873 const bool is_problem_scalar,
874 const std::vector<basis::ElementBases> &bases,
875 const Eigen::VectorXi &disc_orders,
876 const std::map<int, Eigen::MatrixXd> &polys,
877 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
880 const Eigen::MatrixXd &fun,
881 Eigen::MatrixXd &result,
882 const bool use_sampler,
883 const bool boundary_only)
886 if (!is_problem_scalar)
889 polys, polys_3d, sampler, n_points,
890 fun, result, use_sampler, boundary_only);
895 const int actual_dim,
896 const std::vector<basis::ElementBases> &basis,
897 const Eigen::VectorXi &disc_orders,
898 const std::map<int, Eigen::MatrixXd> &polys,
899 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
902 const Eigen::MatrixXd &fun,
903 Eigen::MatrixXd &result,
904 const bool use_sampler,
905 const bool boundary_only)
909 logger().error(
"Solve the problem first!");
913 std::vector<AssemblyValues> tmp;
915 result.resize(n_points, actual_dim);
919 Eigen::MatrixXi vis_faces_poly, vis_edges_poly;
921 for (
int i = 0; i < int(basis.size()); ++i)
924 Eigen::MatrixXd local_pts;
938 sampler.
sample_polyhedron(polys_3d.at(i).first, polys_3d.at(i).second, local_pts, vis_faces_poly, vis_edges_poly);
940 sampler.
sample_polygon(polys.at(i), local_pts, vis_faces_poly, vis_edges_poly);
965 Eigen::MatrixXd local_res = Eigen::MatrixXd::Zero(local_pts.rows(), actual_dim);
967 for (
size_t j = 0; j < bs.
bases.size(); ++j)
971 for (
int d = 0; d < actual_dim; ++d)
973 for (
size_t ii = 0; ii < b.
global().size(); ++ii)
974 local_res.col(d) += b.
global()[ii].val * tmp[j].val * fun(b.
global()[ii].index * actual_dim + d);
978 result.block(index, 0, local_res.rows(), actual_dim) = local_res;
979 index += local_res.rows();
985 const bool is_problem_scalar,
986 const std::vector<basis::ElementBases> &bases,
987 const std::vector<basis::ElementBases> &gbases,
989 const Eigen::MatrixXd &local_pts,
990 const Eigen::MatrixXd &fun,
991 Eigen::MatrixXd &result,
992 Eigen::MatrixXd &result_grad)
995 if (!is_problem_scalar)
998 local_pts, fun, result, result_grad);
1003 const int actual_dim,
1004 const std::vector<basis::ElementBases> &bases,
1005 const std::vector<basis::ElementBases> &gbases,
1007 const Eigen::MatrixXd &local_pts,
1008 const Eigen::MatrixXd &fun,
1009 Eigen::MatrixXd &result,
1010 Eigen::MatrixXd &result_grad)
1012 if (fun.size() <= 0)
1014 logger().error(
"Solve the problem first!");
1018 assert(local_pts.cols() == mesh.
dimension());
1019 assert(fun.cols() == 1);
1027 result.resize(
vals.val.rows(), actual_dim);
1030 result_grad.resize(
vals.val.rows(), mesh.
dimension() * actual_dim);
1031 result_grad.setZero();
1033 const int n_loc_bases = int(
vals.basis_values.size());
1035 for (
int i = 0; i < n_loc_bases; ++i)
1037 const auto &
val =
vals.basis_values[i];
1039 for (
size_t ii = 0; ii <
val.global.size(); ++ii)
1041 for (
int d = 0; d < actual_dim; ++d)
1043 result.col(d) +=
val.global[ii].val * fun(
val.global[ii].index * actual_dim + d) *
val.val;
1044 result_grad.block(0, d *
val.grad_t_m.cols(), result_grad.rows(),
val.grad_t_m.cols()) +=
val.global[ii].val * fun(
val.global[ii].index * actual_dim + d) *
val.grad_t_m;
1052 if (fun.size() <= 0)
1054 logger().error(
"Solve the problem first!");
1058 assert(fun.cols() == 1);
1060 result.resize(
vals.val.rows(), actual_dim);
1063 result_grad.resize(
vals.val.rows(), dim * actual_dim);
1064 result_grad.setZero();
1066 const int n_loc_bases = int(
vals.basis_values.size());
1068 for (
int i = 0; i < n_loc_bases; ++i)
1070 const auto &
val =
vals.basis_values[i];
1072 for (
size_t ii = 0; ii <
val.global.size(); ++ii)
1074 for (
int d = 0; d < actual_dim; ++d)
1076 result.col(d) +=
val.global[ii].val * fun(
val.global[ii].index * actual_dim + d) *
val.val;
1077 result_grad.block(0, d *
val.grad_t_m.cols(), result_grad.rows(),
val.grad_t_m.cols()) +=
val.global[ii].val * fun(
val.global[ii].index * actual_dim + d) *
val.grad_t_m;
1085 const bool is_problem_scalar,
1086 const std::vector<basis::ElementBases> &bases,
1087 const std::vector<basis::ElementBases> &gbases,
1088 const Eigen::VectorXi &disc_orders,
1089 const std::map<int, Eigen::MatrixXd> &polys,
1090 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
1093 const Eigen::MatrixXd &fun,
1095 const bool use_sampler,
1096 const bool boundary_only)
1098 if (fun.size() <= 0)
1100 logger().error(
"Solve the problem first!");
1104 assert(!is_problem_scalar);
1106 Eigen::MatrixXi vis_faces_poly, vis_edges_poly;
1108 std::vector<std::pair<std::string, Eigen::MatrixXd>> tmp_s;
1110 for (
int i = 0; i < int(bases.size()); ++i)
1117 Eigen::MatrixXd local_pts;
1128 sampler.
sample_polyhedron(polys_3d.at(i).first, polys_3d.at(i).second, local_pts, vis_faces_poly, vis_edges_poly);
1130 sampler.
sample_polygon(polys.at(i), local_pts, vis_faces_poly, vis_edges_poly);
1157 for (
const auto &s : tmp_s)
1158 if (std::isnan(s.second.norm()))
1167 const bool is_problem_scalar,
1168 const std::vector<basis::ElementBases> &bases,
1169 const std::vector<basis::ElementBases> &gbases,
1170 const Eigen::VectorXi &disc_orders,
1171 const std::map<int, Eigen::MatrixXd> &polys,
1172 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
1176 const Eigen::MatrixXd &fun,
1178 std::vector<assembler::Assembler::NamedMatrix> &result,
1179 const bool use_sampler,
1180 const bool boundary_only)
1182 if (fun.size() <= 0)
1184 logger().error(
"Solve the problem first!");
1190 assert(!is_problem_scalar);
1194 Eigen::MatrixXi vis_faces_poly, vis_edges_poly;
1195 std::vector<std::pair<std::string, Eigen::MatrixXd>> tmp_s;
1197 for (
int i = 0; i < int(bases.size()); ++i)
1204 Eigen::MatrixXd local_pts;
1215 sampler.
sample_polyhedron(polys_3d.at(i).first, polys_3d.at(i).second, local_pts, vis_faces_poly, vis_edges_poly);
1217 sampler.
sample_polygon(polys.at(i), local_pts, vis_faces_poly, vis_edges_poly);
1246 result.resize(tmp_s.size());
1247 for (
int k = 0; k < tmp_s.size(); ++k)
1249 result[k].first = tmp_s[k].first;
1250 result[k].second.resize(n_points, 1);
1254 for (
int k = 0; k < tmp_s.size(); ++k)
1256 assert(local_pts.rows() == tmp_s[k].second.rows());
1257 result[k].second.block(index, 0, tmp_s[k].second.rows(), 1) = tmp_s[k].second;
1259 index += local_pts.rows();
1265 const bool is_problem_scalar,
1266 const std::vector<basis::ElementBases> &bases,
1267 const std::vector<basis::ElementBases> &gbases,
1268 const Eigen::VectorXi &disc_orders,
1269 const std::map<int, Eigen::MatrixXd> &polys,
1270 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
1274 const Eigen::MatrixXd &fun,
1276 std::vector<assembler::Assembler::NamedMatrix> &result,
1277 const bool use_sampler,
1278 const bool boundary_only)
1280 if (fun.size() <= 0)
1282 logger().error(
"Solve the problem first!");
1288 const int actual_dim = mesh.
dimension();
1289 assert(!is_problem_scalar);
1293 Eigen::MatrixXi vis_faces_poly, vis_edges_poly;
1294 std::vector<std::pair<std::string, Eigen::MatrixXd>> tmp_t;
1296 for (
int i = 0; i < int(bases.size()); ++i)
1303 Eigen::MatrixXd local_pts;
1314 sampler.
sample_polyhedron(polys_3d.at(i).first, polys_3d.at(i).second, local_pts, vis_faces_poly, vis_edges_poly);
1316 sampler.
sample_polygon(polys.at(i), local_pts, vis_faces_poly, vis_edges_poly);
1345 result.resize(tmp_t.size());
1346 for (
int k = 0; k < tmp_t.size(); ++k)
1348 result[k].first = tmp_t[k].first;
1349 result[k].second.resize(n_points, actual_dim * actual_dim);
1353 for (
int k = 0; k < tmp_t.size(); ++k)
1355 assert(local_pts.rows() == tmp_t[k].second.rows());
1356 result[k].second.block(index, 0, tmp_t[k].second.rows(), tmp_t[k].second.cols()) = tmp_t[k].second;
1358 index += local_pts.rows();
1364 const std::shared_ptr<mesh::MeshNodes> mesh_nodes)
1366 Eigen::MatrixXd func;
1367 func.setZero(n_bases, mesh_nodes->node_position(0).size());
1369 for (
int i = 0; i < n_bases; i++)
1370 func.row(i) = mesh_nodes->node_position(i);
1377 const std::shared_ptr<mesh::MeshNodes> mesh_nodes,
1378 const Eigen::MatrixXd &grad)
1384 const std::vector<basis::ElementBases> &bases,
1385 const std::vector<basis::ElementBases> &gbases,
1386 const Eigen::MatrixXd &fun,
1388 const int actual_dim)
1390 Eigen::VectorXd result;
1391 result.setZero(actual_dim);
1392 for (
int e = 0; e < bases.size(); ++e)
1397 Eigen::MatrixXd u, grad_u;
1401 result += u.transpose() *
da;
ElementAssemblyValues vals
std::vector< Eigen::VectorXi > faces
virtual void compute_scalar_value(const OutputData &data, std::vector< NamedMatrix > &result) const
virtual void compute_tensor_value(const OutputData &data, std::vector< NamedMatrix > &result) const
stores per local bases evaluations
std::vector< basis::Local2Global > global
stores per element basis values at given quadrature points and geometric mapping
void compute(const int el_index, const bool is_volume, const Eigen::MatrixXd &pts, const basis::ElementBases &basis, const basis::ElementBases &gbasis)
computes the per element values at the local (ref el) points (pts) sets basis_values,...
Represents one basis function and its gradient.
const std::vector< Local2Global > & global() const
Stores the basis functions for a given element in a mesh (facet in 2d, cell in 3d).
void evaluate_bases(const Eigen::MatrixXd &uv, std::vector< assembler::AssemblyValues > &basis_values) const
evaluate stored bases at given points on the reference element saves results to basis_values
std::vector< Basis > bases
one basis function per node in the element
static void get_sidesets(const mesh::Mesh &mesh, Eigen::MatrixXd &pts, Eigen::MatrixXi &faces, Eigen::MatrixXd &sidesets)
returns a triangulated representation of the sideset.
static void interpolate_boundary_function_at_vertices(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::MatrixXd &pts, const Eigen::MatrixXi &faces, const Eigen::MatrixXd &fun, Eigen::MatrixXd &result)
computes integrated solution (fun) per surface face vertex.
static Eigen::MatrixXd generate_linear_field(const int n_bases, const std::shared_ptr< mesh::MeshNodes > mesh_nodes, const Eigen::MatrixXd &grad)
bool check_scalar_value(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXi &disc_orders, const std::map< int, Eigen::MatrixXd > &polys, const std::map< int, std::pair< Eigen::MatrixXd, Eigen::MatrixXi > > &polys_3d, const assembler::Assembler &assembler, const utils::RefElementSampler &sampler, const Eigen::MatrixXd &fun, const double t, const bool use_sampler, const bool boundary_only)
checks if mises are not nan
static void interpolate_at_local_vals(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const int el_index, const Eigen::MatrixXd &local_pts, const Eigen::MatrixXd &fun, Eigen::MatrixXd &result, Eigen::MatrixXd &result_grad)
interpolate solution and gradient at element (calls interpolate_at_local_vals with sol)
static void interpolate_boundary_tensor_function(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const Eigen::MatrixXi &faces, const Eigen::MatrixXd &fun, const Eigen::MatrixXd &disp, const double t, const bool compute_avg, Eigen::MatrixXd &result, Eigen::MatrixXd &stresses, Eigen::MatrixXd &mises, bool skip_orientation=false)
computes traction forces for fun (tensor * surface normal) result, stress tensor, and von mises,...
static void compute_stress_at_quadrature_points(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXi &disc_orders, const assembler::Assembler &assembler, const Eigen::MatrixXd &fun, const double t, Eigen::MatrixXd &result, Eigen::VectorXd &von_mises)
compute von mises stress at quadrature points for the function fun, also compute the interpolated fun...
static Eigen::MatrixXd get_bases_position(const int n_bases, const std::shared_ptr< mesh::MeshNodes > mesh_nodes)
static void interpolate_boundary_function(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::MatrixXd &pts, const Eigen::MatrixXi &faces, const Eigen::MatrixXd &fun, const bool compute_avg, Eigen::MatrixXd &result)
computes integrated solution (fun) per surface face.
static void interpolate_function(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const Eigen::VectorXi &disc_orders, const std::map< int, Eigen::MatrixXd > &polys, const std::map< int, std::pair< Eigen::MatrixXd, Eigen::MatrixXi > > &polys_3d, const utils::RefElementSampler &sampler, const int n_points, const Eigen::MatrixXd &fun, Eigen::MatrixXd &result, const bool use_sampler, const bool boundary_only)
interpolate the function fun.
static void compute_vertex_values(const mesh::Mesh &mesh, int actual_dim, const std::vector< basis::ElementBases > &bases, const utils::RefElementSampler &sampler, const Eigen::MatrixXd &fun, Eigen::MatrixXd &result)
evaluates the function fun at the vertices on the mesh
static void average_grad_based_function(const mesh::Mesh &mesh, const bool is_problem_scalar, const int n_bases, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXi &disc_orders, const std::map< int, Eigen::MatrixXd > &polys, const std::map< int, std::pair< Eigen::MatrixXd, Eigen::MatrixXi > > &polys_3d, const assembler::Assembler &assembler, const utils::RefElementSampler &sampler, const double t, const int n_points, const Eigen::MatrixXd &fun, std::vector< assembler::Assembler::NamedMatrix > &result_scalar, std::vector< assembler::Assembler::NamedMatrix > &result_tensor, const bool use_sampler, const bool boundary_only)
computes scalar quantity of funtion (ie von mises for elasticity and norm of velocity for fluid) the ...
static Eigen::VectorXd integrate_function(const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::MatrixXd &fun, const int dim, const int actual_dim)
static void compute_scalar_value(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXi &disc_orders, const std::map< int, Eigen::MatrixXd > &polys, const std::map< int, std::pair< Eigen::MatrixXd, Eigen::MatrixXi > > &polys_3d, const assembler::Assembler &assembler, const utils::RefElementSampler &sampler, const int n_points, const Eigen::MatrixXd &fun, const double t, std::vector< assembler::Assembler::NamedMatrix > &result, const bool use_sampler, const bool boundary_only)
computes scalar quantity of funtion (ie von mises for elasticity and norm of velocity for fluid)
static void compute_tensor_value(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXi &disc_orders, const std::map< int, Eigen::MatrixXd > &polys, const std::map< int, std::pair< Eigen::MatrixXd, Eigen::MatrixXi > > &polys_3d, const assembler::Assembler &assembler, const utils::RefElementSampler &sampler, const int n_points, const Eigen::MatrixXd &fun, const double t, std::vector< assembler::Assembler::NamedMatrix > &result, const bool use_sampler, const bool boundary_only)
compute tensor quantity (ie stress tensor or velocy)
std::array< int, 8 > get_ordered_vertices_from_hex(const int element_index) const
virtual int n_cell_faces(const int c_id) const =0
virtual int cell_face(const int c_id, const int lf_id) const =0
virtual std::array< int, 4 > get_ordered_vertices_from_tet(const int element_index) const
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
int n_elements() const
utitlity to return the number of elements, cells or faces in 3d and 2d
virtual int n_vertices() const =0
number of vertices
virtual RowVectorNd face_barycenter(const int f) const =0
face barycenter
bool is_cube(const int el_id) const
checks if element is cube compatible
virtual RowVectorNd point(const int global_index) const =0
point coordinates
virtual bool is_boundary_face(const int face_global_id) const =0
is face boundary
virtual int get_boundary_id(const int primitive) const
Get the boundary selection of an element (face in 3d, edge in 2d)
bool is_simplex(const int el_id) const
checks if element is simples compatible
virtual bool is_volume() const =0
checks if mesh is volume
virtual int edge_vertex(const int e_id, const int lv_id) const =0
id of the edge vertex
int dimension() const
utily for dimension
virtual int n_faces() const =0
number of faces
virtual int n_edges() const =0
number of edges
virtual int n_face_vertices(const int f_id) const =0
number of vertices of a face
virtual bool is_boundary_element(const int element_global_id) const =0
is cell boundary
virtual int face_vertex(const int f_id, const int lv_id) const =0
id of the face vertex
static void quadrature_for_quad_face(int index, int order, const int gid, const mesh::Mesh &mesh, Eigen::MatrixXd &uv, Eigen::MatrixXd &points, Eigen::VectorXd &weights)
static void quadrature_for_tri_face(int index, int order, const int gid, const mesh::Mesh &mesh, Eigen::MatrixXd &uv, Eigen::MatrixXd &points, Eigen::VectorXd &weights)
static void normal_for_quad_face(int index, Eigen::MatrixXd &normal)
static Eigen::MatrixXd hex_local_node_coordinates_from_face(int lf)
static void normal_for_tri_face(int index, Eigen::MatrixXd &normal)
static Eigen::MatrixXd tet_local_node_coordinates_from_face(int lf)
void sample_polygon(const Eigen::MatrixXd &poly, Eigen::MatrixXd &pts, Eigen::MatrixXi &faces, Eigen::MatrixXi &edges) const
const Eigen::MatrixXd & simplex_corners() const
const Eigen::MatrixXd & simplex_points() const
void sample_polyhedron(const Eigen::MatrixXd &vertices, const Eigen::MatrixXi &f, Eigen::MatrixXd &pts, Eigen::MatrixXi &faces, Eigen::MatrixXi &edges) const
const Eigen::MatrixXd & cube_points() const
const Eigen::MatrixXd & cube_corners() const
void q_nodes_2d(const int q, Eigen::MatrixXd &val)
void p_nodes_2d(const int p, Eigen::MatrixXd &val)
void p_nodes_3d(const int p, Eigen::MatrixXd &val)
void q_nodes_3d(const int q, Eigen::MatrixXd &val)
Eigen::VectorXd flatten(const Eigen::MatrixXd &X)
Flatten rowwises.
spdlog::logger & logger()
Retrieves the current logger.
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd