91 const Eigen::MatrixXd &displacement,
92 const std::vector<mesh::LocalBoundary> &local_boundary,
95 const bool multiply_pressure)
const
102 LocalThreadScalarStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
104 Eigen::MatrixXd pressure_vals, g_3;
105 ElementAssemblyValues vals;
106 Eigen::MatrixXd points, uv, normals, deform_mat, trafo;
107 Eigen::VectorXd weights;
108 Eigen::VectorXi global_primitive_ids;
109 for (int lb_id = start; lb_id < end; ++lb_id)
111 const auto &lb = local_boundary[lb_id];
112 const int e = lb.element_id();
113 const basis::ElementBases &gbs = gbases_[e];
114 const basis::ElementBases &bs = bases_[e];
116 for (int i = 0; i < lb.size(); ++i)
118 const int primitive_global_id = lb.global_primitive_id(i);
119 const auto nodes = bs.local_nodes_for_primitive(primitive_global_id, mesh_);
121 bool has_samples = utils::BoundarySampler::boundary_quadrature(lb, resolution, mesh_, i, false, uv, points, normals, weights);
122 if (mesh_.is_volume())
123 weights /= 2 * mesh_.tri_area(primitive_global_id);
125 weights /= mesh_.edge_length(primitive_global_id);
126 g_3.setZero(normals.rows(), normals.cols());
131 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
133 vals.compute(e, mesh_.is_volume(), points, bs, gbs);
135 for (int n = 0; n < vals.jac_it.size(); ++n)
137 trafo = vals.jac_it[n].inverse();
139 if (displacement.size() > 0)
141 assert(size_ == 2 || size_ == 3);
142 deform_mat.resize(size_, size_);
143 deform_mat.setZero();
144 for (const auto &b : vals.basis_values)
146 for (const auto &g : b.global)
148 for (int d = 0; d < size_; ++d)
150 deform_mat.row(d) += displacement(g.index * size_ + d) * b.grad.row(n);
158 normals.row(n) = normals.row(n) * trafo.inverse();
159 normals.row(n).normalize();
161 if (mesh_.is_volume())
163 Eigen::Vector3d g1, g2, g3;
164 auto endpoints = utils::BoundarySampler::tet_local_node_coordinates_from_face(lb[i]);
165 g1 = trafo * (endpoints.row(0) - endpoints.row(1)).transpose();
166 g2 = trafo * (endpoints.row(0) - endpoints.row(2)).transpose();
170 g_3.row(n) = g3.transpose();
174 Eigen::Vector2d g1, g3;
175 auto endpoints = utils::BoundarySampler::tri_local_node_coordinates_from_edge(lb[i]);
176 g1 = trafo * (endpoints.row(0) - endpoints.row(1)).transpose();
179 g_3.row(n) = g3.transpose();
183 if (multiply_pressure)
184 problem_.pressure_bc(mesh_, global_primitive_ids, uv, vals.val, normals, t, pressure_vals);
186 pressure_vals = Eigen::MatrixXd::Ones(weights.size(), 1);
188 Eigen::MatrixXd u, grad_u;
189 if (displacement.size() > 0)
190 io::Evaluator::interpolate_at_local_vals(mesh_, problem_.is_scalar(), bases_, gbases_, e, points, displacement, u, grad_u);
192 u.setZero(weights.size(), size_);
195 for (long p = 0; p < weights.size(); ++p)
196 for (int d = 0; d < size_; ++d)
197 local_storage.val += pressure_vals(p) * g_3(p, d) * u(p, d) * weights(p);
202 for (
const LocalThreadScalarStorage &local_storage : storage)
203 res += local_storage.
val;
211 const Eigen::MatrixXd &displacement,
212 const std::vector<mesh::LocalBoundary> &local_boundary,
213 const std::vector<int> &dirichlet_nodes,
214 const int resolution,
215 Eigen::VectorXd &grad,
217 const bool multiply_pressure)
const
224 LocalThreadVecStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
226 Eigen::MatrixXd pressure_vals, g_3;
227 ElementAssemblyValues vals;
228 Eigen::MatrixXd points, uv, normals, deform_mat, trafo;
229 Eigen::VectorXd weights;
230 Eigen::VectorXi global_primitive_ids;
231 for (int lb_id = start; lb_id < end; ++lb_id)
233 const auto &lb = local_boundary[lb_id];
234 const int e = lb.element_id();
235 const basis::ElementBases &gbs = gbases_[e];
236 const basis::ElementBases &bs = bases_[e];
238 for (int i = 0; i < lb.size(); ++i)
240 const int primitive_global_id = lb.global_primitive_id(i);
241 const auto nodes = bs.local_nodes_for_primitive(primitive_global_id, mesh_);
243 bool has_samples = utils::BoundarySampler::boundary_quadrature(lb, resolution, mesh_, i, false, uv, points, normals, weights);
244 if (mesh_.is_volume())
245 weights /= 2 * mesh_.tri_area(primitive_global_id);
247 weights /= mesh_.edge_length(primitive_global_id);
248 g_3.setZero(normals.rows(), normals.cols());
253 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
255 vals.compute(e, mesh_.is_volume(), points, bs, gbs);
256 for (int n = 0; n < vals.jac_it.size(); ++n)
258 trafo = vals.jac_it[n].inverse();
260 if (displacement.size() > 0)
262 assert(size_ == 2 || size_ == 3);
263 deform_mat.resize(size_, size_);
264 deform_mat.setZero();
265 for (const auto &b : vals.basis_values)
267 for (const auto &g : b.global)
269 for (int d = 0; d < size_; ++d)
271 deform_mat.row(d) += displacement(g.index * size_ + d) * b.grad.row(n);
279 normals.row(n) = normals.row(n) * trafo.inverse();
280 normals.row(n).normalize();
282 if (mesh_.is_volume())
284 Eigen::Vector3d g1, g2, g3;
285 auto endpoints = utils::BoundarySampler::tet_local_node_coordinates_from_face(lb[i]);
286 g1 = trafo * (endpoints.row(0) - endpoints.row(1)).transpose();
287 g2 = trafo * (endpoints.row(0) - endpoints.row(2)).transpose();
291 g_3.row(n) = g3.transpose();
295 Eigen::Vector2d g1, g3;
296 auto endpoints = utils::BoundarySampler::tri_local_node_coordinates_from_edge(lb[i]);
297 g1 = trafo * (endpoints.row(0) - endpoints.row(1)).transpose();
300 g_3.row(n) = g3.transpose();
304 if (multiply_pressure)
305 problem_.pressure_bc(mesh_, global_primitive_ids, uv, vals.val, normals, t, pressure_vals);
307 pressure_vals = Eigen::MatrixXd::Ones(weights.size(), 1);
309 for (long n = 0; n < nodes.size(); ++n)
311 const AssemblyValues &v = vals.basis_values[nodes(n)];
312 for (int d = 0; d < size_; ++d)
314 for (size_t g = 0; g < v.global.size(); ++g)
316 const int g_index = v.global[g].index * size_ + d;
317 const bool is_dof_dirichlet = std::find(dirichlet_nodes.begin(), dirichlet_nodes.end(), g_index) != dirichlet_nodes.end();
318 if (is_dof_dirichlet)
321 for (long p = 0; p < weights.size(); ++p)
323 local_storage.vec(g_index) += pressure_vals(p) * g_3(p, d) * v.val(p) * weights(p);
331 for (
const LocalThreadVecStorage &local_storage : storage)
332 grad += local_storage.
vec;
336 const Eigen::MatrixXd &displacement,
337 const int boundary_id,
338 const std::vector<mesh::LocalBoundary> &local_boundary,
339 const std::vector<int> &dirichlet_nodes,
340 const int resolution,
341 Eigen::VectorXd &grad,
343 const bool multiply_pressure)
const
350 LocalThreadVecStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
352 Eigen::MatrixXd pressure_vals, g_3;
353 ElementAssemblyValues vals;
354 Eigen::MatrixXd points, uv, normals, deform_mat, trafo;
355 Eigen::VectorXd weights;
356 Eigen::VectorXi global_primitive_ids;
357 for (int lb_id = start; lb_id < end; ++lb_id)
359 const auto &lb = local_boundary[lb_id];
360 const int e = lb.element_id();
361 const basis::ElementBases &gbs = gbases_[e];
362 const basis::ElementBases &bs = bases_[e];
364 for (int i = 0; i < lb.size(); ++i)
366 const int primitive_global_id = lb.global_primitive_id(i);
367 const auto nodes = bs.local_nodes_for_primitive(primitive_global_id, mesh_);
368 const int curr_boundary_id = mesh_.get_boundary_id(primitive_global_id);
370 if (curr_boundary_id != boundary_id)
373 bool has_samples = utils::BoundarySampler::boundary_quadrature(lb, resolution, mesh_, i, false, uv, points, normals, weights);
374 if (mesh_.is_volume())
375 weights /= 2 * mesh_.tri_area(primitive_global_id);
377 weights /= mesh_.edge_length(primitive_global_id);
378 g_3.setZero(normals.rows(), normals.cols());
383 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
385 vals.compute(e, mesh_.is_volume(), points, bs, gbs);
386 for (int n = 0; n < vals.jac_it.size(); ++n)
388 trafo = vals.jac_it[n].inverse();
390 if (displacement.size() > 0)
392 assert(size_ == 2 || size_ == 3);
393 deform_mat.resize(size_, size_);
394 deform_mat.setZero();
395 for (const auto &b : vals.basis_values)
397 for (const auto &g : b.global)
399 for (int d = 0; d < size_; ++d)
401 deform_mat.row(d) += displacement(g.index * size_ + d) * b.grad.row(n);
409 normals.row(n) = normals.row(n) * trafo.inverse();
410 normals.row(n).normalize();
412 if (mesh_.is_volume())
414 Eigen::Vector3d g1, g2, g3;
415 auto endpoints = utils::BoundarySampler::tet_local_node_coordinates_from_face(lb[i]);
416 g1 = trafo * (endpoints.row(0) - endpoints.row(1)).transpose();
417 g2 = trafo * (endpoints.row(0) - endpoints.row(2)).transpose();
421 g_3.row(n) = g3.transpose();
425 Eigen::Vector2d g1, g3;
426 auto endpoints = utils::BoundarySampler::tri_local_node_coordinates_from_edge(lb[i]);
427 g1 = trafo * (endpoints.row(0) - endpoints.row(1)).transpose();
430 g_3.row(n) = g3.transpose();
434 if (multiply_pressure)
435 problem_.pressure_bc(mesh_, global_primitive_ids, uv, vals.val, normals, t, pressure_vals);
437 pressure_vals = Eigen::MatrixXd::Ones(weights.size(), 1);
439 for (long n = 0; n < nodes.size(); ++n)
441 const AssemblyValues &v = vals.basis_values[nodes(n)];
442 for (int d = 0; d < size_; ++d)
444 for (size_t g = 0; g < v.global.size(); ++g)
446 const int g_index = v.global[g].index * size_ + d;
447 const bool is_dof_dirichlet = std::find(dirichlet_nodes.begin(), dirichlet_nodes.end(), g_index) != dirichlet_nodes.end();
448 if (is_dof_dirichlet)
451 for (long p = 0; p < weights.size(); ++p)
453 local_storage.vec(g_index) += pressure_vals(p) * g_3(p, d) * v.val(p) * weights(p);
461 for (
const LocalThreadVecStorage &local_storage : storage)
462 grad += local_storage.
vec;
466 const Eigen::MatrixXd &displacement,
467 const std::vector<mesh::LocalBoundary> &local_boundary,
468 const std::vector<int> &dirichlet_nodes,
469 const int resolution,
472 const bool multiply_pressure)
const
479 LocalThreadMatStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
481 Eigen::MatrixXd pressure_vals, g_1, g_2, g_3, local_hessian;
482 ElementAssemblyValues vals;
483 Eigen::MatrixXd points, uv, normals, deform_mat, trafo;
484 Eigen::VectorXd weights;
485 Eigen::VectorXi global_primitive_ids;
486 for (int lb_id = start; lb_id < end; ++lb_id)
488 const auto &lb = local_boundary[lb_id];
489 const int e = lb.element_id();
490 const basis::ElementBases &gbs = gbases_[e];
491 const basis::ElementBases &bs = bases_[e];
493 for (int i = 0; i < lb.size(); ++i)
495 const int primitive_global_id = lb.global_primitive_id(i);
496 const auto nodes = bs.local_nodes_for_primitive(primitive_global_id, mesh_);
498 bool has_samples = utils::BoundarySampler::boundary_quadrature(lb, resolution, mesh_, i, false, uv, points, normals, weights);
499 std::vector<Eigen::VectorXd> param_chain_rule;
500 if (mesh_.is_volume())
502 weights /= 2 * mesh_.tri_area(primitive_global_id);
503 g_1.setZero(normals.rows(), normals.cols());
504 g_2.setZero(normals.rows(), normals.cols());
505 g_3.setZero(normals.rows(), normals.cols());
507 auto endpoints = utils::BoundarySampler::tet_local_node_coordinates_from_face(lb[i]);
508 param_chain_rule = {(endpoints.row(0) - endpoints.row(1)).transpose(), (endpoints.row(0) - endpoints.row(2)).transpose()};
510 param_chain_rule[0] *= -1;
518 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
520 vals.compute(e, mesh_.is_volume(), points, bs, gbs);
521 for (int n = 0; n < vals.jac_it.size(); ++n)
523 trafo = vals.jac_it[n].inverse();
525 if (displacement.size() > 0)
528 deform_mat.resize(size_, size_);
529 deform_mat.setZero();
530 for (const auto &b : vals.basis_values)
532 for (const auto &g : b.global)
534 for (int d = 0; d < size_; ++d)
536 deform_mat.row(d) += displacement(g.index * size_ + d) * b.grad.row(n);
544 normals.row(n) = normals.row(n) * trafo.inverse();
545 normals.row(n).normalize();
547 if (mesh_.is_volume())
549 Eigen::Vector3d g1, g2, g3;
550 auto endpoints = utils::BoundarySampler::tet_local_node_coordinates_from_face(lb[i]);
551 g1 = trafo * (endpoints.row(0) - endpoints.row(1)).transpose();
552 g2 = trafo * (endpoints.row(0) - endpoints.row(2)).transpose();
557 g_1.row(n) = g1.transpose();
558 g_2.row(n) = g2.transpose();
559 g_3.row(n) = g3.transpose();
565 if (multiply_pressure)
566 problem_.pressure_bc(mesh_, global_primitive_ids, uv, vals.val, normals, t, pressure_vals);
568 pressure_vals = Eigen::MatrixXd::Ones(weights.size(), 1);
570 local_hessian.setZero(vals.basis_values.size() * size_, vals.basis_values.size() * size_);
572 for (long p = 0; p < weights.size(); ++p)
574 Eigen::Vector3d g_up_1, g_up_2;
575 g_dual(g_1.row(p).transpose(), g_2.row(p).transpose(), g_up_1, g_up_2);
576 std::vector<Eigen::MatrixXd> g_3_wedge_g_up = {wedge_product(g_3.row(p), g_up_1), wedge_product(g_3.row(p), g_up_2)};
578 for (long ni = 0; ni < nodes.size(); ++ni)
580 const AssemblyValues &vi = vals.basis_values[nodes(ni)];
581 for (int di = 0; di < size_; ++di)
583 const int gi_index = vi.global[0].index * size_ + di;
584 const bool is_dof_i_dirichlet = std::find(dirichlet_nodes.begin(), dirichlet_nodes.end(), gi_index) != dirichlet_nodes.end();
585 if (is_dof_i_dirichlet)
588 Eigen::MatrixXd grad_phi_i;
589 grad_phi_i.setZero(3, 3);
590 grad_phi_i.row(di) = vi.grad.row(p);
592 for (long nj = 0; nj < nodes.size(); ++nj)
594 const AssemblyValues &vj = vals.basis_values[nodes(nj)];
595 for (int dj = 0; dj < size_; ++dj)
597 const int gj_index = vj.global[0].index * size_ + dj;
598 const bool is_dof_j_dirichlet = std::find(dirichlet_nodes.begin(), dirichlet_nodes.end(), gj_index) != dirichlet_nodes.end();
599 if (is_dof_j_dirichlet)
602 Eigen::MatrixXd grad_phi_j;
603 grad_phi_j.setZero(3, 3);
604 grad_phi_j.row(dj) = vj.grad.row(p);
607 for (int alpha = 0; alpha < size_ - 1; ++alpha)
609 auto a = vj.val(p) * g_3_wedge_g_up[alpha].row(di) * (grad_phi_i * param_chain_rule[alpha]);
610 auto b = (g_3_wedge_g_up[alpha] * (grad_phi_j * param_chain_rule[alpha])).row(di) * vi.val(p);
611 value += pressure_vals(p) * (a(0) + b(0)) * weights(p);
613 local_hessian(nodes(ni) * size_ + di, nodes(nj) * size_ + dj) += value;
620 for (long ni = 0; ni < nodes.size(); ++ni)
622 const AssemblyValues &vi = vals.basis_values[nodes(ni)];
623 for (int di = 0; di < size_; ++di)
625 const int gi_index = vi.global[0].index * size_ + di;
626 for (long nj = 0; nj < nodes.size(); ++nj)
628 const AssemblyValues &vj = vals.basis_values[nodes(nj)];
629 for (int dj = 0; dj < size_; ++dj)
631 const int gj_index = vj.global[0].index * size_ + dj;
633 local_storage.entries.push_back(Eigen::Triplet<double>(gi_index, gj_index, local_hessian(nodes(ni) * size_ + di, nodes(nj) * size_ + dj)));
642 std::vector<Eigen::Triplet<double>> all_entries;
644 for (LocalThreadMatStorage &local_storage : storage)
646 all_entries.insert(all_entries.end(), local_storage.entries.begin(), local_storage.entries.end());
649 hess.setFromTriplets(all_entries.begin(), all_entries.end());
653 const Eigen::MatrixXd &displacement,
654 const std::vector<mesh::LocalBoundary> &local_boundary,
655 const std::vector<int> &dirichlet_nodes,
656 const int resolution,
659 const bool multiply_pressure)
const
666 LocalThreadMatStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
668 Eigen::MatrixXd pressure_vals, g_3_grad, local_hessian;
669 ElementAssemblyValues vals;
670 Eigen::MatrixXd points, uv, normals, deform_mat, trafo;
671 Eigen::VectorXd weights;
672 Eigen::VectorXi global_primitive_ids;
673 for (int lb_id = start; lb_id < end; ++lb_id)
675 const auto &lb = local_boundary[lb_id];
676 const int e = lb.element_id();
677 const basis::ElementBases &gbs = gbases_[e];
678 const basis::ElementBases &bs = bases_[e];
680 for (int i = 0; i < lb.size(); ++i)
682 const int primitive_global_id = lb.global_primitive_id(i);
683 const auto nodes = bs.local_nodes_for_primitive(primitive_global_id, mesh_);
685 bool has_samples = utils::BoundarySampler::boundary_quadrature(lb, resolution, mesh_, i, false, uv, points, normals, weights);
686 std::vector<Eigen::VectorXd> param_chain_rule;
691 if (mesh_.is_volume())
694 weights /= mesh_.edge_length(primitive_global_id);
696 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
698 vals.compute(e, mesh_.is_volume(), points, bs, gbs);
699 g_3_grad.setZero(normals.rows(), size_ * vals.basis_values.size() * size_);
701 for (int n = 0; n < vals.jac_it.size(); ++n)
703 trafo = vals.jac_it[n].inverse();
705 if (displacement.size() > 0)
708 deform_mat.resize(size_, size_);
709 deform_mat.setZero();
710 for (const auto &b : vals.basis_values)
712 for (const auto &g : b.global)
714 for (int d = 0; d < size_; ++d)
716 deform_mat.row(d) += displacement(g.index * size_ + d) * b.grad.row(n);
724 normals.row(n) = normals.row(n) * trafo.inverse();
725 normals.row(n).normalize();
727 if (mesh_.is_volume())
731 Eigen::MatrixXd g_3_grad_local(size_, vals.basis_values.size() * size_);
732 g_3_grad_local.setZero();
733 auto endpoints = utils::BoundarySampler::tri_local_node_coordinates_from_edge(lb[i]);
734 Eigen::VectorXd reference_normal = (endpoints.row(0) - endpoints.row(1)).transpose();
736 for (const auto &b : vals.basis_values)
738 for (const auto &g : b.global)
739 for (int d = 0; d < size_; ++d)
740 for (int k = 0; k < size_; ++k)
741 g_3_grad_local(1 - d, b_count * size_ + d) += b.grad(n, k) * reference_normal(k);
744 g_3_grad_local.row(0) *= -1;
746 for (int k = 0; k < size_; ++k)
747 for (int l = 0; l < vals.basis_values.size() * size_; ++l)
748 g_3_grad(n, k * (vals.basis_values.size() * size_) + l) = g_3_grad_local(k, l);
752 if (multiply_pressure)
753 problem_.pressure_bc(mesh_, global_primitive_ids, uv, vals.val, normals, t, pressure_vals);
755 pressure_vals = Eigen::MatrixXd::Ones(weights.size(), 1);
757 local_hessian.setZero(vals.basis_values.size() * size_, vals.basis_values.size() * size_);
759 for (long p = 0; p < weights.size(); ++p)
761 for (long ni = 0; ni < nodes.size(); ++ni)
763 const AssemblyValues &vi = vals.basis_values[nodes(ni)];
764 for (int di = 0; di < size_; ++di)
766 const int gi_index = vi.global[0].index * size_ + di;
767 const bool is_dof_i_dirichlet = std::find(dirichlet_nodes.begin(), dirichlet_nodes.end(), gi_index) != dirichlet_nodes.end();
768 if (is_dof_i_dirichlet)
771 for (long nj = 0; nj < nodes.size(); ++nj)
773 const AssemblyValues &vj = vals.basis_values[nodes(nj)];
774 for (int dj = 0; dj < size_; ++dj)
776 const int gj_index = vj.global[0].index * size_ + dj;
777 const bool is_dof_j_dirichlet = std::find(dirichlet_nodes.begin(), dirichlet_nodes.end(), gj_index) != dirichlet_nodes.end();
778 if (is_dof_j_dirichlet)
781 double value = pressure_vals(p) * g_3_grad(p, (di * vals.basis_values.size() * size_) + nodes(nj) * size_ + dj) * vi.val(p) * weights(p);
782 local_hessian(nodes(ni) * size_ + di, nodes(nj) * size_ + dj) += value;
789 for (long ni = 0; ni < nodes.size(); ++ni)
791 const AssemblyValues &vi = vals.basis_values[nodes(ni)];
792 for (int di = 0; di < size_; ++di)
794 const int gi_index = vi.global[0].index * size_ + di;
795 for (long nj = 0; nj < nodes.size(); ++nj)
797 const AssemblyValues &vj = vals.basis_values[nodes(nj)];
798 for (int dj = 0; dj < size_; ++dj)
800 const int gj_index = vj.global[0].index * size_ + dj;
802 local_storage.entries.push_back(Eigen::Triplet<double>(gi_index, gj_index, local_hessian(nodes(ni) * size_ + di, nodes(nj) * size_ + dj)));
811 std::vector<Eigen::Triplet<double>> all_entries;
813 for (LocalThreadMatStorage &local_storage : storage)
815 all_entries.insert(all_entries.end(), local_storage.entries.begin(), local_storage.entries.end());
818 hess.setFromTriplets(all_entries.begin(), all_entries.end());
822 const std::vector<mesh::LocalBoundary> &local_boundary,
823 const std::vector<int> &dirichlet_nodes)
const
825 if (local_boundary.size() == 0)
831 LocalThreadPrimitiveStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
833 ElementAssemblyValues vals;
834 Eigen::MatrixXd points, uv, normals, deform_mat, trafo;
835 Eigen::VectorXd weights;
836 Eigen::VectorXi global_primitive_ids;
837 for (int lb_id = start; lb_id < end; ++lb_id)
839 const auto &lb = local_boundary[lb_id];
840 const int e = lb.element_id();
841 const basis::ElementBases &bs = bases_[e];
842 const basis::ElementBases &gbs = gbases_[e];
844 for (int i = 0; i < lb.size(); ++i)
846 const int primitive_global_id = lb.global_primitive_id(i);
847 const auto nodes = bs.local_nodes_for_primitive(primitive_global_id, mesh_);
849 points.resize(0, size_);
850 vals.compute(e, mesh_.is_volume(), points, bs, gbs);
852 if (!((lb.type() == BoundaryType::TRI_LINE) || (lb.type() == BoundaryType::TRI)))
854 logger().warn(
"Detected element not triangle or tet, cannot check if pressure boundary is closed");
858 Eigen::VectorXi face(size_);
860 for (int n = 0; n < size_; ++n)
862 const AssemblyValues &v = vals.basis_values[nodes(n)];
863 assert(v.global.size() == 1);
864 face(n) = v.global[0].index;
866 local_storage.faces.push_back(face);
871 Eigen::MatrixXi
F(0, size_);
873 for (
const LocalThreadPrimitiveStorage &local_storage : storage)
875 for (
int i = 0; i < local_storage.faces.size(); ++i)
877 F.conservativeResize(count + 1, size_);
878 F.row(count) = local_storage.faces[i];
885 boundary_loop_2d(
F, L);
887 igl::boundary_loop(
F, L);
889 for (
const int &l : L)
890 if (std::
find(dirichlet_nodes.begin(), dirichlet_nodes.end(), l * size_) == dirichlet_nodes.end())
974 const Eigen::MatrixXd &displacement,
975 const std::unordered_map<
int, std::vector<mesh::LocalBoundary>> &local_pressure_cavity,
976 const std::vector<int> &dirichlet_nodes,
977 const int resolution,
979 const bool project_to_psd,
982 if (project_to_psd && (local_pressure_cavity.size() > 0))
987 hess.resize(displacement.size(), displacement.size());
988 for (
const auto &v : local_pressure_cavity)
992 double curr_volume =
compute_volume(displacement, v.second, resolution, t,
false);
1003 -start_pressure, -start_volume, -curr_volume);
1005 -start_pressure, -start_volume, -curr_volume);
1008 hess += dp_dv * (g * g.transpose()).sparseView();