24#include <igl/per_face_normals.h>
31 using namespace assembler;
32 using namespace basis;
36 void flattened_tensor_coeffs(
const Eigen::MatrixXd &S, Eigen::MatrixXd &X)
40 X.resize(S.rows(), 3);
45 else if (S.cols() == 9)
48 X.resize(S.rows(), 6);
58 logger().error(
"Invalid tensor dimensions.");
62 void avoid_pyramid_apex(Eigen::MatrixXd &points)
64 assert(points.cols() == 3);
65 constexpr double eps = 1e-8;
66 for (
int i = 0; i < points.rows(); ++i)
68 if (std::abs(points(i, 2) - 1.0) < eps)
69 points(i, 2) = 1.0 - eps;
73 void pyramid_nodes_for_output(
const int order, Eigen::MatrixXd &points)
76 avoid_pyramid_apex(points);
82 const bool is_problem_scalar,
83 const std::vector<basis::ElementBases> &bases,
84 const std::vector<basis::ElementBases> &gbases,
85 const Eigen::MatrixXd &pts,
86 const Eigen::MatrixXi &
faces,
87 const Eigen::MatrixXd &fun,
88 const bool compute_avg,
89 Eigen::MatrixXd &result)
93 logger().error(
"Solve the problem first!");
98 const Mesh3D &mesh3d =
dynamic_cast<const Mesh3D &
>(mesh);
100 Eigen::MatrixXd points, uv;
104 if (!is_problem_scalar)
107 igl::AABB<Eigen::MatrixXd, 3> tree;
108 tree.init(pts,
faces);
110 result.resize(
faces.rows(), actual_dim);
111 result.setConstant(std::numeric_limits<double>::quiet_NaN());
122 const int face_id = mesh3d.
cell_face(e, lf);
147 for (
size_t j = 0; j < bs.
bases.size(); ++j)
152 for (
int d = 0; d < actual_dim; ++d)
154 for (
size_t g = 0; g < v.
global.size(); ++g)
156 loc_val(d) += (v.
global[g].val * v.
val.array() * fun(v.
global[g].index * actual_dim + d) *
weights.array()).sum();
162 Eigen::RowVector3d C;
165 const double dist = tree.squared_distance(pts,
faces, bary, I, C);
166 assert(dist < 1e-16);
168 assert(std::isnan(result(I, 0)));
170 result.row(I) = loc_val /
weights.sum();
172 result.row(I) = loc_val;
177 assert(counter == result.rows());
182 const bool is_problem_scalar,
184 const std::vector<basis::ElementBases> &bases,
185 const std::vector<basis::ElementBases> &gbases,
186 const Eigen::VectorXi &disc_orders,
187 const Eigen::VectorXi &disc_ordersq,
188 const std::map<int, Eigen::MatrixXd> &polys,
189 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
194 const Eigen::MatrixXd &fun,
195 std::vector<assembler::Assembler::NamedMatrix> &result_scalar,
196 std::vector<assembler::Assembler::NamedMatrix> &result_tensor,
197 const bool use_sampler,
198 const bool boundary_only)
200 result_scalar.clear();
201 result_tensor.clear();
205 logger().error(
"Solve the problem first!");
208 if (is_problem_scalar)
210 logger().error(
"Define a tensor problem!");
214 assert(!is_problem_scalar);
217 std::vector<Eigen::MatrixXd> avg_scalar, avg_tensor;
219 Eigen::MatrixXd areas(n_bases, 1);
222 std::vector<std::pair<std::string, Eigen::MatrixXd>> tmp_s, tmp_t;
223 Eigen::MatrixXd local_val;
226 for (
int i = 0; i < int(bases.size()); ++i)
230 Eigen::MatrixXd local_pts;
249 int max_order = std::max(disc_orders(i), disc_ordersq(i));
255 pyramid_nodes_for_output(disc_orders(i), local_pts);
263 vals.compute(i, actual_dim == 3, bases[i], gbases[i]);
265 const double area = (
vals.det.array() *
quadrature.weights.array()).sum();
270 for (
size_t j = 0; j < bs.
bases.size(); ++j)
273 if (b.global().size() > 1)
276 auto &global = b.global().front();
277 areas(global.index) += area;
280 if (avg_scalar.empty())
282 avg_scalar.resize(tmp_s.size());
283 for (
auto &m : avg_scalar)
285 m.resize(n_bases, 1);
290 if (avg_tensor.empty())
292 avg_tensor.resize(tmp_t.size());
293 for (
auto &m : avg_tensor)
295 m.resize(n_bases, actual_dim * actual_dim);
300 for (
int k = 0; k < tmp_s.size(); ++k)
302 local_val = tmp_s[k].second;
304 for (
size_t j = 0; j < bs.
bases.size(); ++j)
307 if (b.global().size() > 1)
310 auto &global = b.global().front();
311 avg_scalar[k](global.index) += local_val(j) * area;
315 for (
int k = 0; k < tmp_t.size(); ++k)
317 local_val = tmp_t[k].second;
319 for (
size_t j = 0; j < bs.
bases.size(); ++j)
322 if (b.global().size() > 1)
325 auto &global = b.global().front();
326 avg_tensor[k].row(global.index) += local_val.row(j) * area;
331 for (
auto &m : avg_scalar)
333 m.array() /= areas.array();
336 for (
auto &m : avg_tensor)
338 for (
int i = 0; i < m.rows(); ++i)
340 m.row(i).array() /= areas(i);
344 result_scalar.resize(tmp_s.size());
345 for (
int k = 0; k < tmp_s.size(); ++k)
347 result_scalar[k].first = tmp_s[k].first;
348 interpolate_function(mesh, 1, bases, disc_orders, disc_ordersq, polys, polys_3d, sampler, n_points,
349 avg_scalar[k], result_scalar[k].second, use_sampler, boundary_only);
352 result_tensor.resize(tmp_t.size());
353 for (
int k = 0; k < tmp_t.size(); ++k)
355 result_tensor[k].first = tmp_t[k].first;
356 interpolate_function(mesh, actual_dim * actual_dim, bases, disc_orders, disc_ordersq, polys, polys_3d, sampler, n_points,
357 utils::flatten(avg_tensor[k]), result_tensor[k].second, use_sampler, boundary_only);
363 const bool is_problem_scalar,
364 const std::vector<basis::ElementBases> &bases,
365 const std::vector<basis::ElementBases> &gbases,
366 const Eigen::VectorXi &disc_orders,
367 const Eigen::VectorXi &disc_ordersq,
369 const Eigen::MatrixXd &fun,
371 Eigen::MatrixXd &result,
372 Eigen::VectorXd &von_mises)
381 logger().error(
"Solve the problem first!");
384 if (is_problem_scalar)
386 logger().error(
"Define a tensor problem!");
391 assert(!is_problem_scalar);
393 Eigen::MatrixXd local_val, local_stress, local_mises;
395 int num_quadr_pts = 0;
396 result.resize(disc_orders.sum(), actual_dim == 2 ? 3 : 6);
398 von_mises.resize(disc_orders.sum(), 1);
409 f.get_quadrature(disc_orders(e), quadr);
414 f.get_quadrature(disc_orders(e), quadr);
422 f.get_quadrature(disc_orders(e), quadr);
427 f.get_quadrature(disc_orders(e), quadr);
435 f.get_quadrature(disc_orders(e), disc_ordersq(e), quadr);
442 f.get_quadrature(disc_orders(e), quadr);
449 std::vector<std::pair<std::string, Eigen::MatrixXd>> tmp_s, tmp_t;
454 local_mises = tmp_s[0].second;
455 local_val = tmp_t[0].second;
457 if (num_quadr_pts + local_val.rows() >= result.rows())
459 result.conservativeResize(
460 std::max(num_quadr_pts + local_val.rows() + 1, 2 * result.rows()),
462 von_mises.conservativeResize(result.rows(), von_mises.cols());
464 flattened_tensor_coeffs(local_val, local_stress);
465 result.block(num_quadr_pts, 0, local_stress.rows(), local_stress.cols()) = local_stress;
466 von_mises.block(num_quadr_pts, 0, local_mises.rows(), local_mises.cols()) = local_mises;
467 num_quadr_pts += local_val.rows();
469 result.conservativeResize(num_quadr_pts, result.cols());
470 von_mises.conservativeResize(num_quadr_pts, von_mises.cols());
475 const bool is_problem_scalar,
476 const std::vector<basis::ElementBases> &bases,
477 const Eigen::VectorXi &disc_orders,
478 const Eigen::VectorXi &disc_ordersq,
479 const std::map<int, Eigen::MatrixXd> &polys,
480 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
483 const Eigen::MatrixXd &fun,
484 Eigen::MatrixXd &result,
485 const bool use_sampler,
486 const bool boundary_only)
489 if (!is_problem_scalar)
492 polys, polys_3d, sampler, n_points,
493 fun, result, use_sampler, boundary_only);
498 const std::vector<basis::ElementBases> &gbasis,
499 const std::vector<basis::ElementBases> &basis,
500 const Eigen::VectorXi &disc_orders,
501 const Eigen::VectorXi &disc_ordersq,
502 const std::map<int, Eigen::MatrixXd> &polys,
503 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
506 const Eigen::MatrixXd &fun,
507 Eigen::Vector<bool, -1> &result,
508 const bool use_sampler,
509 const bool boundary_only)
513 logger().error(
"Solve the problem first!");
517 result.setZero(n_points);
521 Eigen::MatrixXi vis_faces_poly, vis_edges_poly;
525 for (
int i = 0; i < int(basis.size()); ++i)
528 Eigen::MatrixXd local_pts;
546 sampler.
sample_polyhedron(polys_3d.at(i).first, polys_3d.at(i).second, local_pts, vis_faces_poly, vis_edges_poly);
548 sampler.
sample_polygon(polys.at(i), local_pts, vis_faces_poly, vis_edges_poly);
561 int max_order = std::max(disc_orders(i), disc_ordersq(i));
578 if (std::find(invalidList.begin(), invalidList.end(), i) != invalidList.end())
579 result.segment(index, local_pts.rows()).array() =
true;
580 index += local_pts.rows();
586 const int actual_dim,
587 const std::vector<basis::ElementBases> &basis,
588 const Eigen::VectorXi &disc_orders,
589 const Eigen::VectorXi &disc_ordersq,
590 const std::map<int, Eigen::MatrixXd> &polys,
591 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
594 const Eigen::MatrixXd &fun,
595 Eigen::MatrixXd &result,
596 const bool use_sampler,
597 const bool boundary_only)
601 logger().error(
"Solve the problem first!");
604 assert(fun.cols() == 1);
606 std::vector<AssemblyValues> tmp;
608 result.resize(n_points, actual_dim);
612 Eigen::MatrixXi vis_faces_poly, vis_edges_poly;
614 for (
int i = 0; i < int(basis.size()); ++i)
617 Eigen::MatrixXd local_pts;
635 sampler.
sample_polyhedron(polys_3d.at(i).first, polys_3d.at(i).second, local_pts, vis_faces_poly, vis_edges_poly);
637 sampler.
sample_polygon(polys.at(i), local_pts, vis_faces_poly, vis_edges_poly);
650 int max_order = std::max(disc_orders(i), disc_ordersq(i));
655 pyramid_nodes_for_output(disc_orders(i), local_pts);
671 Eigen::MatrixXd local_res = Eigen::MatrixXd::Zero(local_pts.rows(), actual_dim);
673 for (
size_t j = 0; j < bs.
bases.size(); ++j)
677 for (
int d = 0; d < actual_dim; ++d)
679 for (
size_t ii = 0; ii < b.global().size(); ++ii)
680 local_res.col(d) += b.global()[ii].val * tmp[j].val * fun(b.global()[ii].index * actual_dim + d);
684 result.block(index, 0, local_res.rows(), actual_dim) = local_res;
685 index += local_res.rows();
691 const bool is_problem_scalar,
692 const std::vector<basis::ElementBases> &bases,
693 const std::vector<basis::ElementBases> &gbases,
695 const Eigen::MatrixXd &local_pts,
696 const Eigen::MatrixXd &fun,
697 Eigen::MatrixXd &result,
698 Eigen::MatrixXd &result_grad)
701 if (!is_problem_scalar)
704 local_pts, fun, result, result_grad);
709 const int actual_dim,
710 const std::vector<basis::ElementBases> &bases,
711 const std::vector<basis::ElementBases> &gbases,
713 const Eigen::MatrixXd &local_pts,
714 const Eigen::MatrixXd &fun,
715 Eigen::MatrixXd &result,
716 Eigen::MatrixXd &result_grad)
720 logger().error(
"Solve the problem first!");
724 assert(local_pts.cols() == mesh.
dimension());
725 assert(fun.cols() == 1);
733 result.resize(
vals.val.rows(), actual_dim);
736 result_grad.resize(
vals.val.rows(), mesh.
dimension() * actual_dim);
737 result_grad.setZero();
739 const int n_loc_bases = int(
vals.basis_values.size());
741 for (
int i = 0; i < n_loc_bases; ++i)
743 const auto &
val =
vals.basis_values[i];
745 for (
size_t ii = 0; ii <
val.global.size(); ++ii)
747 for (
int d = 0; d < actual_dim; ++d)
749 result.col(d) +=
val.global[ii].val * fun(
val.global[ii].index * actual_dim + d) *
val.val;
750 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;
760 logger().error(
"Solve the problem first!");
764 assert(fun.cols() == 1);
766 result.resize(
vals.val.rows(), actual_dim);
769 result_grad.resize(
vals.val.rows(), dim * actual_dim);
770 result_grad.setZero();
772 const int n_loc_bases = int(
vals.basis_values.size());
774 for (
int i = 0; i < n_loc_bases; ++i)
776 const auto &
val =
vals.basis_values[i];
778 for (
size_t ii = 0; ii <
val.global.size(); ++ii)
780 for (
int d = 0; d < actual_dim; ++d)
782 result.col(d) +=
val.global[ii].val * fun(
val.global[ii].index * actual_dim + d) *
val.val;
783 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;
791 const bool is_problem_scalar,
792 const std::vector<basis::ElementBases> &bases,
793 const std::vector<basis::ElementBases> &gbases,
794 const Eigen::VectorXi &disc_orders,
795 const Eigen::VectorXi &disc_ordersq,
796 const std::map<int, Eigen::MatrixXd> &polys,
797 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
800 const Eigen::MatrixXd &fun,
802 const bool use_sampler,
803 const bool boundary_only)
807 logger().error(
"Solve the problem first!");
811 assert(!is_problem_scalar);
813 Eigen::MatrixXi vis_faces_poly, vis_edges_poly;
815 std::vector<std::pair<std::string, Eigen::MatrixXd>> tmp_s;
817 for (
int i = 0; i < int(bases.size()); ++i)
824 Eigen::MatrixXd local_pts;
839 sampler.
sample_polyhedron(polys_3d.at(i).first, polys_3d.at(i).second, local_pts, vis_faces_poly, vis_edges_poly);
841 sampler.
sample_polygon(polys.at(i), local_pts, vis_faces_poly, vis_edges_poly);
854 int max_order = std::max(disc_orders(i), disc_ordersq(i));
859 pyramid_nodes_for_output(disc_orders(i), local_pts);
877 for (
const auto &s : tmp_s)
878 if (std::isnan(s.second.norm()))
887 const bool is_problem_scalar,
888 const std::vector<basis::ElementBases> &bases,
889 const std::vector<basis::ElementBases> &gbases,
890 const Eigen::VectorXi &disc_orders,
891 const Eigen::VectorXi &disc_ordersq,
892 const std::map<int, Eigen::MatrixXd> &polys,
893 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
897 const Eigen::MatrixXd &fun,
899 std::vector<assembler::Assembler::NamedMatrix> &result,
900 const bool use_sampler,
901 const bool boundary_only)
905 logger().error(
"Solve the problem first!");
911 assert(!is_problem_scalar);
915 Eigen::MatrixXi vis_faces_poly, vis_edges_poly;
916 std::vector<std::pair<std::string, Eigen::MatrixXd>> tmp_s;
918 for (
int i = 0; i < int(bases.size()); ++i)
925 Eigen::MatrixXd local_pts;
940 sampler.
sample_polyhedron(polys_3d.at(i).first, polys_3d.at(i).second, local_pts, vis_faces_poly, vis_edges_poly);
942 sampler.
sample_polygon(polys.at(i), local_pts, vis_faces_poly, vis_edges_poly);
955 int max_order = std::max(disc_orders(i), disc_ordersq(i));
960 pyramid_nodes_for_output(disc_orders(i), local_pts);
980 result.resize(tmp_s.size());
981 for (
int k = 0; k < tmp_s.size(); ++k)
983 result[k].first = tmp_s[k].first;
984 result[k].second.resize(n_points, 1);
988 for (
int k = 0; k < tmp_s.size(); ++k)
990 assert(local_pts.rows() == tmp_s[k].second.rows());
991 result[k].second.block(index, 0, tmp_s[k].second.rows(), 1) = tmp_s[k].second;
993 index += local_pts.rows();
999 const bool is_problem_scalar,
1000 const std::vector<basis::ElementBases> &bases,
1001 const std::vector<basis::ElementBases> &gbases,
1002 const Eigen::VectorXi &disc_orders,
1003 const Eigen::VectorXi &disc_ordersq,
1004 const std::map<int, Eigen::MatrixXd> &polys,
1005 const std::map<
int, std::pair<Eigen::MatrixXd, Eigen::MatrixXi>> &polys_3d,
1009 const Eigen::MatrixXd &fun,
1011 std::vector<assembler::Assembler::NamedMatrix> &result,
1012 const bool use_sampler,
1013 const bool boundary_only)
1015 if (fun.size() <= 0)
1017 logger().error(
"Solve the problem first!");
1023 const int actual_dim = mesh.
dimension();
1024 assert(!is_problem_scalar);
1028 Eigen::MatrixXi vis_faces_poly, vis_edges_poly;
1029 std::vector<std::pair<std::string, Eigen::MatrixXd>> tmp_t;
1031 for (
int i = 0; i < int(bases.size()); ++i)
1038 Eigen::MatrixXd local_pts;
1053 sampler.
sample_polyhedron(polys_3d.at(i).first, polys_3d.at(i).second, local_pts, vis_faces_poly, vis_edges_poly);
1055 sampler.
sample_polygon(polys.at(i), local_pts, vis_faces_poly, vis_edges_poly);
1068 int max_order = std::max(disc_orders(i), disc_ordersq(i));
1073 pyramid_nodes_for_output(disc_orders(i), local_pts);
1093 result.resize(tmp_t.size());
1094 for (
int k = 0; k < tmp_t.size(); ++k)
1096 result[k].first = tmp_t[k].first;
1097 result[k].second.resize(n_points, actual_dim * actual_dim);
1101 for (
int k = 0; k < tmp_t.size(); ++k)
1103 assert(local_pts.rows() == tmp_t[k].second.rows());
1104 result[k].second.block(index, 0, tmp_t[k].second.rows(), tmp_t[k].second.cols()) = tmp_t[k].second;
1106 index += local_pts.rows();
1112 const std::shared_ptr<mesh::MeshNodes> mesh_nodes)
1114 Eigen::MatrixXd func;
1115 func.setZero(n_bases, mesh_nodes->node_position(0).size());
1117 for (
int i = 0; i < n_bases; i++)
1118 func.row(i) = mesh_nodes->node_position(i);
1125 const std::shared_ptr<mesh::MeshNodes> mesh_nodes,
1126 const Eigen::MatrixXd &grad)
1132 const std::vector<basis::ElementBases> &bases,
1133 const std::vector<basis::ElementBases> &gbases,
1134 const Eigen::MatrixXd &fun,
1136 const int actual_dim)
1138 Eigen::VectorXd result;
1139 result.setZero(actual_dim);
1140 for (
int e = 0; e < bases.size(); ++e)
1145 Eigen::MatrixXd u, grad_u;
1149 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.
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 Eigen::MatrixXd generate_linear_field(const int n_bases, const std::shared_ptr< mesh::MeshNodes > mesh_nodes, const Eigen::MatrixXd &grad)
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 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 Eigen::VectorXi &disc_ordersq, 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)
calls compute_scalar_value (i.e von mises for elasticity and norm of velocity for fluid) and compute_...
static Eigen::MatrixXd get_bases_position(const int n_bases, const std::shared_ptr< mesh::MeshNodes > mesh_nodes)
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 Eigen::VectorXi &disc_ordersq, 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 Eigen::VectorXi &disc_ordersq, 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 velocity)
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 Eigen::VectorXi &disc_ordersq, 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_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 Eigen::VectorXi &disc_ordersq, 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_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 Eigen::VectorXi &disc_ordersq, 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 void mark_flipped_cells(const mesh::Mesh &mesh, const std::vector< basis::ElementBases > &gbasis, const std::vector< basis::ElementBases > &basis, const Eigen::VectorXi &disc_orders, const Eigen::VectorXi &disc_ordersq, 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::Vector< bool, -1 > &result, const bool use_sampler, const bool boundary_only)
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)
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
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 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 bool is_boundary_face(const int face_global_id) const =0
is face boundary
bool is_simplex(const int el_id) const
checks if element is simplex
bool is_prism(const int el_id) const
checks if element is a prism
virtual bool is_volume() const =0
checks if mesh is volume
int dimension() const
utily for dimension
bool is_pyramid(const int el_id) const
checks if element is a pyramid
virtual bool is_boundary_element(const int element_global_id) const =0
is cell boundary
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 quadrature_for_prism_face(int index, int orderp, int orderq, const int gid, const mesh::Mesh &mesh, Eigen::MatrixXd &uv, Eigen::MatrixXd &points, Eigen::VectorXd &weights)
static void quadrature_for_pyramid_face(int index, int orderp, const int gid, const mesh::Mesh &mesh, Eigen::MatrixXd &uv, Eigen::MatrixXd &points, Eigen::VectorXd &weights)
const Eigen::MatrixXd & prism_points() const
void sample_polygon(const Eigen::MatrixXd &poly, Eigen::MatrixXd &pts, Eigen::MatrixXi &faces, Eigen::MatrixXi &edges) 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 & pyramid_points() const
void q_nodes_2d(const int q, Eigen::MatrixXd &val)
void pyramid_nodes_3d(const int pyramid, Eigen::MatrixXd &val)
void prism_nodes_3d(const int p, 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)
std::vector< int > count_invalid(const int dim, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXd &u, const unsigned max_iter)
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