7#include <ipc/utils/eigen_ext.hpp>
8#include <polysolve/linear/Solver.hpp>
15 using namespace utils;
21 class LocalThreadScalarStorage
25 ElementAssemblyValues
vals;
27 LocalThreadScalarStorage()
35 const std::vector<int> &dirichlet_nodes,
const std::vector<int> &neumann_nodes,
36 const std::vector<RowVectorNd> &dirichlet_nodes_position,
const std::vector<RowVectorNd> &neumann_nodes_position,
37 const int n_basis,
const int size,
38 const std::vector<basis::ElementBases> &bases,
const std::vector<basis::ElementBases> &gbases,
const AssemblyValsCache &ass_vals_cache,
40 const std::string bc_method,
41 const json &solver_params,
42 const int fe_space_id)
43 : assembler_(assembler),
50 ass_vals_cache_(ass_vals_cache),
52 bc_method_(bc_method),
53 solver_params_(solver_params),
54 fe_space_id_(fe_space_id),
55 dirichlet_nodes_(dirichlet_nodes),
56 dirichlet_nodes_position_(dirichlet_nodes_position),
57 neumann_nodes_(neumann_nodes),
58 neumann_nodes_position_(neumann_nodes_position)
69 Eigen::MatrixXd rhs_fun;
71 const int n_elements = int(
bases_.size());
73 for (
int e = 0; e < n_elements; ++e)
86 for (
int d = 0; d <
size_; ++d)
89 for (
int q = 0; q <
quadrature.weights.size(); ++q)
92 const double rho = density(
vals.quadrature.points.row(q),
vals.val.row(q), t,
vals.element_id);
98 const int n_loc_bases_ = int(
vals.basis_values.size());
99 for (
int i = 0; i < n_loc_bases_; ++i)
103 for (
int d = 0; d <
size_; ++d)
106 const double rhs_value = (rhs_fun.col(d).array() * v.
val.array()).sum();
107 for (std::size_t ii = 0; ii < v.
global.size(); ++ii)
118 time_bc([&](
const Mesh &
mesh,
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
126 time_bc([&](
const Mesh &
mesh,
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
134 time_bc([&](
const Mesh &
mesh,
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
140 void RhsAssembler::time_bc(
const std::function<
void(
const Mesh &,
const Eigen::MatrixXi &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &fun, Eigen::MatrixXd &sol)
const
143 Eigen::MatrixXd loc_sol;
145 const int n_elements = int(
bases_.size());
151 for (
int e = 0; e < n_elements; ++e)
159 for (
long i = 0; i < bs.
bases.size(); ++i)
161 const auto &b = bs.
bases[i];
162 const auto &glob = b.global();
164 for (
size_t ii = 0; ii < glob.size(); ++ii)
166 fun(
mesh_, ids, glob[ii].node, loc_sol);
168 for (
int d = 0; d <
size_; ++d)
170 sol(glob[ii].index *
size_ + d) = loc_sol(d) * glob[ii].val;
179 for (
int e = 0; e < n_elements; ++e)
183 ids.resize(
vals.val.rows(), 1);
190 for (
int d = 0; d <
size_; ++d)
191 loc_sol.col(d) = loc_sol.col(d).array() *
vals.det.array() *
quadrature.weights.array();
193 const int n_loc_bases_ = int(
vals.basis_values.size());
194 for (
int i = 0; i < n_loc_bases_; ++i)
198 for (
int d = 0; d <
size_; ++d)
200 const double sol_value = (loc_sol.col(d).array() * v.
val.array()).sum();
201 for (std::size_t ii = 0; ii < v.
global.size(); ++ii)
207 Eigen::MatrixXd b = sol;
210 const double mmin = b.minCoeff();
211 const double mmax = b.maxCoeff();
213 if (fabs(mmin) > 1e-8 || fabs(mmax) > 1e-8)
224 logger().info(
"Solve RHS using {} linear solver", solver->name());
225 solver->analyze_pattern(mass, mass.rows());
226 solver->factorize(mass);
228 for (
long i = 0; i < b.cols(); ++i)
230 solver->solve(b.block(0, i, mass.rows(), 1), sol.block(0, i, mass.rows(), 1));
232 logger().trace(
"mass matrix error {}", (mass * sol - b).norm());
237 void RhsAssembler::lsq_bc(
const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df,
238 const std::vector<LocalBoundary> &local_boundary,
239 const std::vector<int> &bounday_nodes,
240 const int resolution,
241 Eigen::MatrixXd &rhs)
const
243 const int n_el = int(
bases_.size());
245 Eigen::MatrixXd uv, samples, gtmp, rhs_fun;
246 Eigen::VectorXi global_primitive_ids;
248 const int actual_dim =
size_;
250 Eigen::Matrix<bool, Eigen::Dynamic, 1> is_boundary(
n_basis_);
251 is_boundary.setConstant(
false);
252 int skipped_count = 0;
253 for (
int b : bounday_nodes)
255 int bindex = b / actual_dim;
257 if (bindex < is_boundary.size())
258 is_boundary[bindex] =
true;
262 assert(skipped_count <= 1);
264 for (
int d = 0; d <
size_; ++d)
267 std::vector<int> indices;
268 indices.reserve(n_el * 10);
269 std::vector<int> tags;
270 tags.reserve(n_el * 10);
274 Eigen::VectorXi global_index_to_col(
n_basis_);
275 global_index_to_col.setConstant(-1);
277 std::vector<AssemblyValues> tmp_val;
279 for (
const auto &lb : local_boundary)
281 const int e = lb.element_id();
289 const int n_local_bases = int(bs.
bases.size());
290 assert(global_primitive_ids.size() == samples.rows());
292 for (
int s = 0; s < samples.rows(); ++s)
300 for (
int j = 0; j < n_local_bases; ++j)
303 const double tmp = tmp_val[j].val(s);
305 if (fabs(tmp) < 1e-10)
308 for (std::size_t ii = 0; ii < b.global().size(); ++ii)
311 if (is_boundary[b.global()[ii].index])
313 if (global_index_to_col(b.global()[ii].index) == -1)
315 global_index_to_col(b.global()[ii].index) = index++;
316 indices.push_back(b.global()[ii].index);
318 assert(indices.size() ==
size_t(index));
326 Eigen::MatrixXd global_rhs = Eigen::MatrixXd::Zero(total_size, 1);
328 const long buffer_size = total_size * long(indices.size());
329 std::vector<Eigen::Triplet<double>>
entries, entries_t;
333 int global_counter = 0;
334 Eigen::MatrixXd mapped;
336 for (
const auto &lb : local_boundary)
338 const int e = lb.element_id();
346 const int n_local_bases = int(bs.
bases.size());
351 df(global_primitive_ids, uv, mapped, rhs_fun);
353 for (
int s = 0; s < samples.rows(); ++s)
359 for (
int j = 0; j < n_local_bases; ++j)
362 const double tmp = tmp_val[j].val(s);
364 for (std::size_t ii = 0; ii < b.global().size(); ++ii)
366 auto item = global_index_to_col(b.global()[ii].index);
369 entries.push_back(Eigen::Triplet<double>(global_counter, item, tmp * b.global()[ii].val));
370 entries_t.push_back(Eigen::Triplet<double>(item, global_counter, tmp * b.global()[ii].val));
375 global_rhs(global_counter) = rhs_fun(s, d);
380 assert(global_counter == total_size);
384 const double mmin = global_rhs.minCoeff();
385 const double mmax = global_rhs.maxCoeff();
387 if (fabs(mmin) < 1e-8 && fabs(mmax) < 1e-8)
389 for (
size_t i = 0; i < indices.size(); ++i)
391 const int tag = tags[i];
393 rhs(indices[i] *
size_ + d) = 0;
402 mat_t.setFromTriplets(entries_t.begin(), entries_t.end());
405 Eigen::VectorXd b = mat_t * global_rhs;
407 Eigen::VectorXd coeffs(b.rows(), 1);
409 logger().info(
"Solve RHS using {} linear solver", solver->name());
410 solver->analyze_pattern(A, A.rows());
411 solver->factorize(A);
413 solver->solve(b, coeffs);
415 logger().trace(
"RHS solve error {}", (A * coeffs - b).norm());
417 for (
long i = 0; i < coeffs.rows(); ++i)
419 const int tag = tags[i];
421 rhs(indices[i] *
size_ + d) = coeffs(i);
428 void RhsAssembler::sample_bc(
const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df,
429 const std::vector<LocalBoundary> &local_boundary,
const std::vector<int> &bounday_nodes, Eigen::MatrixXd &rhs)
const
431 const int n_el = int(
bases_.size());
433 Eigen::MatrixXd rhs_fun;
434 Eigen::VectorXi global_primitive_ids(1);
435 Eigen::MatrixXd nans(1, 1);
436 nans(0) = std::nan(
"");
439 Eigen::Matrix<bool, Eigen::Dynamic, 1> is_boundary(
n_basis_);
440 is_boundary.setConstant(
false);
442 const int actual_dim =
size_;
444 int skipped_count = 0;
445 for (
int b : bounday_nodes)
447 int bindex = b / actual_dim;
449 if (bindex < is_boundary.size())
450 is_boundary[bindex] =
true;
454 assert(skipped_count <= 1);
457 for (
const auto &lb : local_boundary)
459 const int e = lb.element_id();
462 for (
int i = 0; i < lb.size(); ++i)
464 global_primitive_ids(0) = lb.global_primitive_id(i);
466 assert(global_primitive_ids.size() == 1);
469 for (
long n = 0; n < nodes.size(); ++n)
471 const auto &b = bs.
bases[nodes(n)];
472 const auto &glob = b.global();
474 for (
size_t ii = 0; ii < glob.size(); ++ii)
476 assert(is_boundary[glob[ii].index]);
479 df(global_primitive_ids, nans, glob[ii].node, rhs_fun);
481 for (
int d = 0; d <
size_; ++d)
486 rhs(glob[ii].index *
size_ + d) = rhs_fun(0, d);
496 const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df,
497 const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &nf,
498 const std::vector<LocalBoundary> &local_boundary,
499 const std::vector<int> &bounday_nodes,
501 const std::vector<LocalBoundary> &local_neumann_boundary,
502 const Eigen::MatrixXd &displacement,
504 Eigen::MatrixXd &rhs)
const
507 sample_bc(df, local_boundary, bounday_nodes, rhs);
509 lsq_bc(df, local_boundary, bounday_nodes, resolution[0], rhs);
511 if (bounday_nodes.size() > 0)
513 Eigen::MatrixXd tmp_val;
521 assert(tmp_val.size() ==
size_);
523 for (
int d = 0; d <
size_; ++d)
527 const int g_index = n_id *
size_ + d;
528 rhs(g_index) = tmp_val(d);
534 Eigen::MatrixXd uv, samples, gtmp, rhs_fun, deform_mat, trafo;
535 Eigen::VectorXi global_primitive_ids;
536 Eigen::MatrixXd
points, normals;
537 Eigen::VectorXd weights;
539 ElementAssemblyValues
vals;
541 for (
const auto &lb : local_neumann_boundary)
543 const int e = lb.element_id();
544 const basis::ElementBases &gbs =
gbases_[
e];
545 const basis::ElementBases &bs =
bases_[
e];
547 for (
int i = 0; i < lb.size(); ++i)
549 const int primitive_global_id = lb.global_primitive_id(i);
551 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
555 for (
int n = 0; n <
vals.jac_it.size(); ++n)
557 trafo =
vals.jac_it[n].inverse();
559 if (displacement.size() > 0)
563 deform_mat.setZero();
564 for (
const auto &b :
vals.basis_values)
566 for (
const auto &g :
b.global)
568 for (
int d = 0; d <
size_; ++d)
570 deform_mat.row(d) += displacement(
g.index *
size_ + d) *
b.grad.row(n);
578 normals.row(n) = normals.row(n) * trafo.inverse();
579 normals.row(n).normalize();
583 nf(global_primitive_ids, uv,
vals.val, normals, rhs_fun);
587 for (
int d = 0; d <
size_; ++d)
588 rhs_fun.col(d) = rhs_fun.col(d).array() * weights.array();
590 const auto nodes = bs.local_nodes_for_primitive(primitive_global_id,
mesh_);
592 for (
long n = 0; n <
nodes.size(); ++n)
595 const AssemblyValues &v =
vals.basis_values[
nodes(n)];
596 for (
int d = 0; d <
size_; ++d)
598 const double rhs_value = (rhs_fun.col(d).array() * v.val.array()).sum();
600 for (
size_t g = 0;
g < v.global.size(); ++
g)
602 const int g_index = v.global[
g].index *
size_ + d;
603 const bool is_neumann = std::find(bounday_nodes.begin(), bounday_nodes.end(), g_index) == bounday_nodes.end();
607 rhs(g_index) += rhs_value * v.global[
g].val;
619 Eigen::MatrixXd tmp_val;
620 Eigen::MatrixXd empty_normal;
627 assert(tmp_val.size() ==
size_);
629 for (
int d = 0; d <
size_; ++d)
631 const int g_index = n_id *
size_ + d;
632 const bool is_neumann = std::find(bounday_nodes.begin(), bounday_nodes.end(), g_index) == bounday_nodes.end();
635 rhs(g_index) += tmp_val(d);
642 const std::vector<int> &bounday_nodes,
644 const std::vector<LocalBoundary> &local_neumann_boundary,
645 Eigen::MatrixXd &rhs,
646 const Eigen::MatrixXd &displacement,
647 const double t)
const
650 [&](
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &uv,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
653 [&](
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &uv,
const Eigen::MatrixXd &pts,
const Eigen::MatrixXd &normals, Eigen::MatrixXd &
val) {
656 local_boundary, bounday_nodes, resolution, local_neumann_boundary, displacement, t, rhs);
663 const std::vector<int> &bounday_nodes,
666 const std::vector<LocalBoundary> &local_neumann_boundary,
667 const Eigen::MatrixXd &final_rhs,
669 Eigen::MatrixXd &rhs)
const
680 if (rhs.size() != final_rhs.size())
682 const int prev_size = rhs.size();
683 rhs.conservativeResize(final_rhs.size(), rhs.cols());
685 rhs.block(prev_size, 0, final_rhs.size() - prev_size, rhs.cols()).setZero();
686 rhs(rhs.size() - 1) = 0;
689 assert(rhs.size() == final_rhs.size());
694 const Eigen::MatrixXd &displacement_prev,
695 const std::vector<LocalBoundary> &local_neumann_boundary,
698 const double t)
const
706 const int n_bases = int(
bases_.size());
711 Eigen::MatrixXd forces;
713 for (
int e = start; e < end; ++e)
723 assert(forces.rows() ==
da.size());
724 assert(forces.cols() ==
size_);
726 for (
long p = 0; p <
da.size(); ++p)
728 local_displacement.setZero();
730 for (
size_t i = 0; i <
vals.basis_values.size(); ++i)
732 const auto &bs =
vals.basis_values[i];
733 assert(bs.val.size() ==
da.size());
734 const double b_val = bs.val(p);
736 for (
int d = 0; d <
size_; ++d)
738 for (std::size_t ii = 0; ii < bs.global.size(); ++ii)
740 local_displacement(d) += (bs.global[ii].val * b_val) * displacement(bs.global[ii].index *
size_ + d);
745 const double rho = density(
vals.quadrature.points.row(p),
vals.val.row(p), t,
vals.element_id);
747 for (
int d = 0; d <
size_; ++d)
749 local_storage.val += forces(p, d) * local_displacement(d) *
da(p) * rho;
757 for (
const LocalThreadScalarStorage &local_storage : storage)
758 res += local_storage.val;
762 Eigen::MatrixXd forces;
766 Eigen::MatrixXd points, uv, normals, deform_mat, trafo;
767 Eigen::VectorXd weights;
768 Eigen::VectorXi global_primitive_ids;
769 for (
const auto &lb : local_neumann_boundary)
771 const int e = lb.element_id();
775 for (
int i = 0; i < lb.size(); ++i)
777 const int primitive_global_id = lb.global_primitive_id(i);
780 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
790 for (
int n = 0; n <
vals.jac_it.size(); ++n)
792 trafo =
vals.jac_it[n].inverse();
794 if (displacement_prev.size() > 0)
798 deform_mat.setZero();
799 for (
const auto &b :
vals.basis_values)
801 for (
const auto &g : b.global)
803 for (
int d = 0; d <
size_; ++d)
805 deform_mat.row(d) += displacement_prev(g.index *
size_ + d) * b.grad.row(n);
813 normals.row(n) = normals.row(n) * trafo.inverse();
814 normals.row(n).normalize();
820 for (
long p = 0; p < weights.size(); ++p)
822 local_displacement.setZero();
824 for (
size_t i = 0; i <
vals.basis_values.size(); ++i)
826 const auto &vv =
vals.basis_values[i];
827 assert(vv.val.size() == weights.size());
828 const double b_val = vv.val(p);
830 for (
int d = 0; d <
size_; ++d)
832 for (std::size_t ii = 0; ii < vv.global.size(); ++ii)
834 local_displacement(d) += (vv.global[ii].val * b_val) * displacement(vv.global[ii].index *
size_ + d);
839 for (
int d = 0; d <
size_; ++d)
840 res -= forces(p, d) * local_displacement(d) * weights(p);
849 Eigen::MatrixXd nodal_force;
850 Eigen::MatrixXd empty_normal;
857 assert(nodal_force.size() ==
size_);
859 for (
int d = 0; d <
size_; ++d)
860 res -= nodal_force(d) * displacement(n_id *
size_ + d);
868 const std::vector<int> &bounday_nodes,
870 const std::vector<mesh::LocalBoundary> &local_neumann_boundary,
871 const Eigen::MatrixXd &displacement,
873 const bool project_to_psd,
877 if (displacement.size() == 0)
880 std::vector<Eigen::Triplet<double>>
entries, entries_t;
883 Eigen::MatrixXd uv, samples, gtmp, rhs_fun, deform_mat, jac_mat, trafo;
884 Eigen::VectorXi global_primitive_ids;
885 Eigen::MatrixXd points, normals;
886 Eigen::VectorXd weights;
887 Eigen::MatrixXd local_hessian;
889 for (
const auto &lb : local_neumann_boundary)
891 const int e = lb.element_id();
895 for (
int i = 0; i < lb.size(); ++i)
897 const int primitive_global_id = lb.global_primitive_id(i);
899 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
904 Eigen::MatrixXd reference_normals = normals;
908 std::vector<std::vector<Eigen::MatrixXd>> grad_normal;
909 for (
int n = 0; n <
vals.jac_it.size(); ++n)
911 trafo =
vals.jac_it[n].inverse();
915 deform_mat.setZero();
916 jac_mat.resize(
size_,
vals.basis_values.size());
918 for (
const auto &b :
vals.basis_values)
920 jac_mat.col(b_idx++) = b.grad.row(n);
922 for (
const auto &g : b.global)
923 for (
int d = 0; d <
size_; ++d)
924 deform_mat.row(d) += displacement(g.index *
size_ + d) * b.grad.row(n);
928 trafo = trafo.inverse();
930 Eigen::VectorXd displaced_normal = normals.row(n) * trafo;
931 normals.row(n) = displaced_normal / displaced_normal.norm();
933 std::vector<Eigen::MatrixXd> grad;
935 Eigen::MatrixXd
vec = -(jac_mat.transpose() * trafo * reference_normals.row(n).transpose());
937 for (
int k = 0; k <
size_; ++k)
939 Eigen::MatrixXd grad_i(jac_mat.rows(), jac_mat.cols());
941 for (
int m = 0; m < jac_mat.rows(); ++m)
942 for (
int l = 0; l < jac_mat.cols(); ++l)
943 grad_i(m, l) = -(reference_normals.row(n) * trafo)(m) * (jac_mat.transpose() * trafo)(l, k);
944 grad.push_back(grad_i);
949 Eigen::MatrixXd normalization_chain_rule = (normals.row(n).transpose() * normals.row(n));
950 normalization_chain_rule = Eigen::MatrixXd::Identity(
size_,
size_) - normalization_chain_rule;
951 normalization_chain_rule /= displaced_normal.norm();
955 for (
const auto &b :
vals.basis_values)
957 for (
int d = 0; d <
size_; ++d)
959 for (
int k = 0; k <
size_; ++k)
960 vec(k) = grad[k](d, b_idx);
961 vec = normalization_chain_rule *
vec;
962 for (
int k = 0; k <
size_; ++k)
963 grad[k](d, b_idx) =
vec(k);
969 grad_normal.push_back(grad);
971 Eigen::MatrixXd rhs_fun;
980 local_hessian.setZero(
vals.basis_values.size() *
size_,
vals.basis_values.size() *
size_);
982 for (
long n = 0; n < nodes.size(); ++n)
986 for (
int d = 0; d <
size_; ++d)
988 for (
size_t g = 0; g < v.
global.size(); ++g)
991 const bool is_neumann = std::find(bounday_nodes.begin(), bounday_nodes.end(), g_index) == bounday_nodes.end();
995 for (
long ni = 0; ni < nodes.size(); ++ni)
998 for (
int di = 0; di <
size_; ++di)
1000 for (
size_t gi = 0; gi < vi.
global.size(); ++gi)
1002 const int gi_index = vi.
global[gi].index *
size_ + di;
1005 for (
int q = 0; q <
vals.jac_it.size(); ++q)
1007 double pressure_val = rhs_fun.row(q).dot(normals.row(q));
1010 value += grad_normal[q][d](di, nodes(ni)) * pressure_val * weights(q) * vi.
val(q);
1013 value *= v.
global[g].val;
1015 const bool is_neumann_i = std::find(bounday_nodes.begin(), bounday_nodes.end(), gi_index) == bounday_nodes.end();
1019 local_hessian(nodes(n) *
size_ + d, nodes(ni) *
size_ + di) = value;
1030 local_hessian = ipc::project_to_psd(local_hessian);
1032 for (
long n = 0; n < nodes.size(); ++n)
1035 for (
int d = 0; d <
size_; ++d)
1037 for (
size_t g = 0; g < v.
global.size(); ++g)
1039 const int g_index = v.
global[g].index *
size_ + d;
1041 for (
long ni = 0; ni < nodes.size(); ++ni)
1044 for (
int di = 0; di <
size_; ++di)
1046 for (
size_t gi = 0; gi < vi.
global.size(); ++gi)
1048 const int gi_index = vi.
global[gi].index *
size_ + di;
1049 entries.push_back(Eigen::Triplet<double>(g_index, gi_index, local_hessian(nodes(n) *
size_ + d, nodes(ni) *
size_ + di)));
ElementAssemblyValues vals
std::vector< Eigen::Triplet< double > > entries
virtual void set_size(const int size)
Caches basis evaluation and geometric mapping at every element.
bool is_initialized() const
void compute(const int el_index, const bool is_volume, const basis::ElementBases &basis, const basis::ElementBases &gbasis, ElementAssemblyValues &vals) const
retrieves cached basis evaluation and geometric for the given element if it doesn't exist,...
stores per local bases evaluations
std::vector< basis::Local2Global > global
stores per element basis values at given quadrature points and geometric mapping
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 9, 1 > assemble(const LinearAssemblerData &data) const override
computes and returns local stiffness matrix (1x1) for bases i,j (where i,j is passed in through data)...
void add_multimaterial(const int index, const json ¶ms, const Units &units, const std::string &root_path) override
inialize material parameter
virtual bool all_dimensions_dirichlet(const int fe_space_id) const
virtual void initial_velocity(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val, const int fe_space_id=-1) const
virtual bool is_dimension_dirichet(const int tag, const int dim, const int fe_space_id=-1) const
virtual void dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val, const int fe_space_id=-1) const =0
virtual void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val, const int fe_space_id=-1) const =0
virtual void dirichlet_nodal_value(const mesh::Mesh &mesh, const int node_id, const RowVectorNd &pt, const double t, Eigen::MatrixXd &val, const int fe_space_id=-1) const
virtual void initial_solution(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val, const int fe_space_id=-1) const
virtual bool is_nodal_dimension_dirichlet(const int n_id, const int tag, const int dim, const int fe_space_id=-1) const
virtual void neumann_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const Eigen::MatrixXd &normals, const double t, Eigen::MatrixXd &val, const int fe_space_id=-1) const
virtual void initial_acceleration(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val, const int fe_space_id=-1) const
virtual void neumann_nodal_value(const mesh::Mesh &mesh, const int node_id, const RowVectorNd &pt, const Eigen::MatrixXd &normal, const double t, Eigen::MatrixXd &val, const int fe_space_id=-1) const
virtual bool is_rhs_zero(const int fe_space_id=-1) const =0
virtual bool is_constant_in_time() const
virtual bool is_boundary_pressure(const int boundary_id) const
void time_bc(const std::function< void(const mesh::Mesh &, const Eigen::MatrixXi &, const Eigen::MatrixXd &, Eigen::MatrixXd &)> &fun, Eigen::MatrixXd &sol) const
void compute_energy_hess(const std::vector< int > &bounday_nodes, const QuadratureOrders &resolution, const std::vector< mesh::LocalBoundary > &local_neumann_boundary, const Eigen::MatrixXd &displacement, const double t, const bool project_to_psd, StiffnessMatrix &hess) const
const Assembler & assembler_
void set_bc(const std::vector< mesh::LocalBoundary > &local_boundary, const std::vector< int > &bounday_nodes, const QuadratureOrders &resolution, const std::vector< mesh::LocalBoundary > &local_neumann_boundary, Eigen::MatrixXd &rhs, const Eigen::MatrixXd &displacement=Eigen::MatrixXd(), const double t=1) const
RhsAssembler(const Assembler &assembler, const mesh::Mesh &mesh, const mesh::Obstacle *obstacle, const std::vector< int > &dirichlet_nodes, const std::vector< int > &neumann_nodes, const std::vector< RowVectorNd > &dirichlet_nodes_position, const std::vector< RowVectorNd > &neumann_nodes_position, const int n_basis, const int size, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &ass_vals_cache, const Problem &problem, const std::string bc_method, const json &solver_params, const int fe_space_id=-1)
const mesh::Mesh & mesh() const
const std::vector< RowVectorNd > & neumann_nodes_position_
const std::vector< basis::ElementBases > & gbases_
basis functions associated with geometric mapping
const mesh::Obstacle * obstacle_
const int size_
dimension of problem
double compute_energy(const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev, const std::vector< mesh::LocalBoundary > &local_neumann_boundary, const Density &density, const QuadratureOrders &resolution, const double t) const
const std::vector< int > & neumann_nodes_
const std::vector< RowVectorNd > & dirichlet_nodes_position_
const std::string bc_method_
const AssemblyValsCache & ass_vals_cache_
void initial_solution(Eigen::MatrixXd &sol) const
const json solver_params_
void lsq_bc(const std::function< void(const Eigen::MatrixXi &, const Eigen::MatrixXd &, const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df, const std::vector< mesh::LocalBoundary > &local_boundary, const std::vector< int > &bounday_nodes, const int resolution, Eigen::MatrixXd &rhs) const
const std::vector< basis::ElementBases > & bases_
basis functions associated with solution
void compute_energy_grad(const std::vector< mesh::LocalBoundary > &local_boundary, const std::vector< int > &bounday_nodes, const Density &density, const QuadratureOrders &resolution, const std::vector< mesh::LocalBoundary > &local_neumann_boundary, const Eigen::MatrixXd &final_rhs, const double t, Eigen::MatrixXd &rhs) const
void initial_acceleration(Eigen::MatrixXd &sol) const
void initial_velocity(Eigen::MatrixXd &sol) const
void assemble(const Density &density, Eigen::MatrixXd &rhs, const double t=1) const
const std::vector< int > & dirichlet_nodes_
void sample_bc(const std::function< void(const Eigen::MatrixXi &, const Eigen::MatrixXd &, const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df, const std::vector< mesh::LocalBoundary > &local_boundary, const std::vector< int > &bounday_nodes, Eigen::MatrixXd &rhs) const
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 eval_geom_mapping(const Eigen::MatrixXd &samples, Eigen::MatrixXd &mapped) const
Map the sample positions in the parametric domain to the object domain (if the element has no paramet...
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
Eigen::VectorXi local_nodes_for_primitive(const int local_index, const mesh::Mesh &mesh) const
std::vector< Basis > bases
one basis function per node in the element
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
virtual int get_boundary_id(const int primitive) const
Get the boundary selection of an element (face in 3d, edge in 2d)
virtual bool is_volume() const =0
checks if mesh is volume
virtual int get_node_id(const int node_id) const
Get the boundary selection of a node.
void update_displacement(const double t, Eigen::MatrixXd &sol) const
static bool sample_boundary(const mesh::LocalBoundary &local_boundary, const int n_samples, const mesh::Mesh &mesh, const bool skip_computation, Eigen::MatrixXd &uv, Eigen::MatrixXd &samples, Eigen::VectorXi &global_primitive_ids)
static bool boundary_quadrature(const mesh::LocalBoundary &local_boundary, const QuadratureOrders &order, const mesh::Mesh &mesh, const bool skip_computation, Eigen::MatrixXd &uv, Eigen::MatrixXd &points, Eigen::MatrixXd &normals, Eigen::VectorXd &weights, Eigen::VectorXi &global_primitive_ids)
auto & get_local_thread_storage(Storages &storage, int thread_id)
auto create_thread_storage(const LocalStorage &initial_local_storage)
void maybe_parallel_for(int size, const std::function< void(int, int, int)> &partial_for)
spdlog::logger & logger()
Retrieves the current logger.
std::array< int, 2 > QuadratureOrders
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > VectorNd
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix