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,
41 const std::string bc_method,
42 const json &solver_params,
43 const int fe_space_id)
44 : assembler_(assembler),
51 ass_vals_cache_(ass_vals_cache),
53 resources_(resources),
54 bc_method_(bc_method),
55 solver_params_(solver_params),
56 fe_space_id_(fe_space_id),
57 dirichlet_nodes_(dirichlet_nodes),
58 dirichlet_nodes_position_(dirichlet_nodes_position),
59 neumann_nodes_(neumann_nodes),
60 neumann_nodes_position_(neumann_nodes_position)
71 Eigen::MatrixXd rhs_fun;
73 const int n_elements = int(
bases_.size());
75 for (
int e = 0; e < n_elements; ++e)
88 for (
int d = 0; d <
size_; ++d)
91 for (
int q = 0; q <
quadrature.weights.size(); ++q)
94 const double rho = density(
vals.quadrature.points.row(q),
vals.val.row(q), t,
vals.element_id);
100 const int n_loc_bases_ = int(
vals.basis_values.size());
101 for (
int i = 0; i < n_loc_bases_; ++i)
105 for (
int d = 0; d <
size_; ++d)
108 const double rhs_value = (rhs_fun.col(d).array() * v.
val.array()).sum();
109 for (std::size_t ii = 0; ii < v.
global.size(); ++ii)
120 time_bc([&](
const Mesh &
mesh,
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
128 time_bc([&](
const Mesh &
mesh,
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
136 time_bc([&](
const Mesh &
mesh,
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
142 void RhsAssembler::time_bc(
const std::function<
void(
const Mesh &,
const Eigen::MatrixXi &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &fun, Eigen::MatrixXd &sol)
const
145 Eigen::MatrixXd loc_sol;
147 const int n_elements = int(
bases_.size());
153 for (
int e = 0; e < n_elements; ++e)
161 for (
long i = 0; i < bs.
bases.size(); ++i)
163 const auto &b = bs.
bases[i];
164 const auto &glob = b.global();
166 for (
size_t ii = 0; ii < glob.size(); ++ii)
168 fun(
mesh_, ids, glob[ii].node, loc_sol);
170 for (
int d = 0; d <
size_; ++d)
172 sol(glob[ii].index *
size_ + d) = loc_sol(d) * glob[ii].val;
181 for (
int e = 0; e < n_elements; ++e)
185 ids.resize(
vals.val.rows(), 1);
192 for (
int d = 0; d <
size_; ++d)
193 loc_sol.col(d) = loc_sol.col(d).array() *
vals.det.array() *
quadrature.weights.array();
195 const int n_loc_bases_ = int(
vals.basis_values.size());
196 for (
int i = 0; i < n_loc_bases_; ++i)
200 for (
int d = 0; d <
size_; ++d)
202 const double sol_value = (loc_sol.col(d).array() * v.
val.array()).sum();
203 for (std::size_t ii = 0; ii < v.
global.size(); ++ii)
209 Eigen::MatrixXd b = sol;
212 const double mmin = b.minCoeff();
213 const double mmax = b.maxCoeff();
215 if (fabs(mmin) > 1e-8 || fabs(mmax) > 1e-8)
226 logger().info(
"Solve RHS using {} linear solver", solver->name());
227 solver->analyze_pattern(mass, mass.rows());
228 solver->factorize(mass);
230 for (
long i = 0; i < b.cols(); ++i)
232 solver->solve(b.block(0, i, mass.rows(), 1), sol.block(0, i, mass.rows(), 1));
234 logger().trace(
"mass matrix error {}", (mass * sol - b).norm());
239 void RhsAssembler::lsq_bc(
const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df,
240 const std::vector<LocalBoundary> &local_boundary,
241 const std::vector<int> &bounday_nodes,
242 const int resolution,
243 Eigen::MatrixXd &rhs)
const
245 const int n_el = int(
bases_.size());
247 Eigen::MatrixXd uv, samples, gtmp, rhs_fun;
248 Eigen::VectorXi global_primitive_ids;
250 const int actual_dim =
size_;
252 Eigen::Matrix<bool, Eigen::Dynamic, 1> is_boundary(
n_basis_);
253 is_boundary.setConstant(
false);
254 int skipped_count = 0;
255 for (
int b : bounday_nodes)
257 int bindex = b / actual_dim;
259 if (bindex < is_boundary.size())
260 is_boundary[bindex] =
true;
264 assert(skipped_count <= 1);
266 for (
int d = 0; d <
size_; ++d)
269 std::vector<int> indices;
270 indices.reserve(n_el * 10);
271 std::vector<int> tags;
272 tags.reserve(n_el * 10);
276 Eigen::VectorXi global_index_to_col(
n_basis_);
277 global_index_to_col.setConstant(-1);
279 std::vector<AssemblyValues> tmp_val;
281 for (
const auto &lb : local_boundary)
283 const int e = lb.element_id();
291 const int n_local_bases = int(bs.
bases.size());
292 assert(global_primitive_ids.size() == samples.rows());
294 for (
int s = 0; s < samples.rows(); ++s)
302 for (
int j = 0; j < n_local_bases; ++j)
305 const double tmp = tmp_val[j].val(s);
307 if (fabs(tmp) < 1e-10)
310 for (std::size_t ii = 0; ii < b.global().size(); ++ii)
313 if (is_boundary[b.global()[ii].index])
315 if (global_index_to_col(b.global()[ii].index) == -1)
317 global_index_to_col(b.global()[ii].index) = index++;
318 indices.push_back(b.global()[ii].index);
320 assert(indices.size() ==
size_t(index));
328 Eigen::MatrixXd global_rhs = Eigen::MatrixXd::Zero(total_size, 1);
330 const long buffer_size = total_size * long(indices.size());
331 std::vector<Eigen::Triplet<double>>
entries, entries_t;
335 int global_counter = 0;
336 Eigen::MatrixXd mapped;
338 for (
const auto &lb : local_boundary)
340 const int e = lb.element_id();
348 const int n_local_bases = int(bs.
bases.size());
353 df(global_primitive_ids, uv, mapped, rhs_fun);
355 for (
int s = 0; s < samples.rows(); ++s)
361 for (
int j = 0; j < n_local_bases; ++j)
364 const double tmp = tmp_val[j].val(s);
366 for (std::size_t ii = 0; ii < b.global().size(); ++ii)
368 auto item = global_index_to_col(b.global()[ii].index);
371 entries.push_back(Eigen::Triplet<double>(global_counter, item, tmp * b.global()[ii].val));
372 entries_t.push_back(Eigen::Triplet<double>(item, global_counter, tmp * b.global()[ii].val));
377 global_rhs(global_counter) = rhs_fun(s, d);
382 assert(global_counter == total_size);
386 const double mmin = global_rhs.minCoeff();
387 const double mmax = global_rhs.maxCoeff();
389 if (fabs(mmin) < 1e-8 && fabs(mmax) < 1e-8)
391 for (
size_t i = 0; i < indices.size(); ++i)
393 const int tag = tags[i];
395 rhs(indices[i] *
size_ + d) = 0;
404 mat_t.setFromTriplets(entries_t.begin(), entries_t.end());
407 Eigen::VectorXd b = mat_t * global_rhs;
409 Eigen::VectorXd coeffs(b.rows(), 1);
411 logger().info(
"Solve RHS using {} linear solver", solver->name());
412 solver->analyze_pattern(A, A.rows());
413 solver->factorize(A);
415 solver->solve(b, coeffs);
417 logger().trace(
"RHS solve error {}", (A * coeffs - b).norm());
419 for (
long i = 0; i < coeffs.rows(); ++i)
421 const int tag = tags[i];
423 rhs(indices[i] *
size_ + d) = coeffs(i);
430 void RhsAssembler::sample_bc(
const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df,
431 const std::vector<LocalBoundary> &local_boundary,
const std::vector<int> &bounday_nodes, Eigen::MatrixXd &rhs)
const
433 const int n_el = int(
bases_.size());
435 Eigen::MatrixXd rhs_fun;
436 Eigen::VectorXi global_primitive_ids(1);
437 Eigen::MatrixXd nans(1, 1);
438 nans(0) = std::nan(
"");
441 Eigen::Matrix<bool, Eigen::Dynamic, 1> is_boundary(
n_basis_);
442 is_boundary.setConstant(
false);
444 const int actual_dim =
size_;
446 int skipped_count = 0;
447 for (
int b : bounday_nodes)
449 int bindex = b / actual_dim;
451 if (bindex < is_boundary.size())
452 is_boundary[bindex] =
true;
456 assert(skipped_count <= 1);
459 for (
const auto &lb : local_boundary)
461 const int e = lb.element_id();
464 for (
int i = 0; i < lb.size(); ++i)
466 global_primitive_ids(0) = lb.global_primitive_id(i);
468 assert(global_primitive_ids.size() == 1);
471 for (
long n = 0; n < nodes.size(); ++n)
473 const auto &b = bs.
bases[nodes(n)];
474 const auto &glob = b.global();
476 for (
size_t ii = 0; ii < glob.size(); ++ii)
478 assert(is_boundary[glob[ii].index]);
481 df(global_primitive_ids, nans, glob[ii].node, rhs_fun);
483 for (
int d = 0; d <
size_; ++d)
488 rhs(glob[ii].index *
size_ + d) = rhs_fun(0, d);
498 const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df,
499 const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &nf,
500 const std::vector<LocalBoundary> &local_boundary,
501 const std::vector<int> &bounday_nodes,
503 const std::vector<LocalBoundary> &local_neumann_boundary,
504 const Eigen::MatrixXd &displacement,
506 Eigen::MatrixXd &rhs)
const
509 sample_bc(df, local_boundary, bounday_nodes, rhs);
511 lsq_bc(df, local_boundary, bounday_nodes, resolution[0], rhs);
513 if (bounday_nodes.size() > 0)
515 Eigen::MatrixXd tmp_val;
523 assert(tmp_val.size() ==
size_);
525 for (
int d = 0; d <
size_; ++d)
529 const int g_index = n_id *
size_ + d;
530 rhs(g_index) = tmp_val(d);
536 Eigen::MatrixXd uv, samples, gtmp, rhs_fun, deform_mat, trafo;
537 Eigen::VectorXi global_primitive_ids;
538 Eigen::MatrixXd
points, normals;
541 ElementAssemblyValues
vals;
543 for (
const auto &lb : local_neumann_boundary)
545 const int e = lb.element_id();
546 const basis::ElementBases &gbs =
gbases_[
e];
547 const basis::ElementBases &bs =
bases_[
e];
549 for (
int i = 0; i < lb.size(); ++i)
551 const int primitive_global_id = lb.global_primitive_id(i);
553 global_primitive_ids.setConstant(
weights.size(), primitive_global_id);
557 for (
int n = 0; n <
vals.jac_it.size(); ++n)
559 trafo =
vals.jac_it[n].inverse();
561 if (displacement.size() > 0)
565 deform_mat.setZero();
566 for (
const auto &b :
vals.basis_values)
568 for (
const auto &g :
b.global)
570 for (
int d = 0; d <
size_; ++d)
572 deform_mat.row(d) += displacement(
g.index *
size_ + d) *
b.grad.row(n);
580 normals.row(n) = normals.row(n) * trafo.inverse();
581 normals.row(n).normalize();
585 nf(global_primitive_ids, uv,
vals.val, normals, rhs_fun);
589 for (
int d = 0; d <
size_; ++d)
590 rhs_fun.col(d) = rhs_fun.col(d).array() *
weights.array();
592 const auto nodes = bs.local_nodes_for_primitive(primitive_global_id,
mesh_);
594 for (
long n = 0; n <
nodes.size(); ++n)
597 const AssemblyValues &v =
vals.basis_values[
nodes(n)];
598 for (
int d = 0; d <
size_; ++d)
600 const double rhs_value = (rhs_fun.col(d).array() * v.val.array()).sum();
602 for (
size_t g = 0;
g < v.global.size(); ++
g)
604 const int g_index = v.global[
g].index *
size_ + d;
605 const bool is_neumann = std::find(bounday_nodes.begin(), bounday_nodes.end(), g_index) == bounday_nodes.end();
609 rhs(g_index) += rhs_value * v.global[
g].val;
621 Eigen::MatrixXd tmp_val;
622 Eigen::MatrixXd empty_normal;
629 assert(tmp_val.size() ==
size_);
631 for (
int d = 0; d <
size_; ++d)
633 const int g_index = n_id *
size_ + d;
634 const bool is_neumann = std::find(bounday_nodes.begin(), bounday_nodes.end(), g_index) == bounday_nodes.end();
637 rhs(g_index) += tmp_val(d);
644 const std::vector<int> &bounday_nodes,
646 const std::vector<LocalBoundary> &local_neumann_boundary,
647 Eigen::MatrixXd &rhs,
648 const Eigen::MatrixXd &displacement,
649 const double t)
const
652 [&](
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &uv,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
655 [&](
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &uv,
const Eigen::MatrixXd &pts,
const Eigen::MatrixXd &normals, Eigen::MatrixXd &
val) {
658 local_boundary, bounday_nodes, resolution, local_neumann_boundary, displacement, t, rhs);
665 const std::vector<int> &bounday_nodes,
668 const std::vector<LocalBoundary> &local_neumann_boundary,
669 const Eigen::MatrixXd &final_rhs,
671 Eigen::MatrixXd &rhs)
const
682 if (rhs.size() != final_rhs.size())
684 const int prev_size = rhs.size();
685 rhs.conservativeResize(final_rhs.size(), rhs.cols());
687 rhs.block(prev_size, 0, final_rhs.size() - prev_size, rhs.cols()).setZero();
688 rhs(rhs.size() - 1) = 0;
691 assert(rhs.size() == final_rhs.size());
696 const Eigen::MatrixXd &displacement_prev,
697 const std::vector<LocalBoundary> &local_neumann_boundary,
700 const double t)
const
708 const int n_bases = int(
bases_.size());
713 Eigen::MatrixXd forces;
715 for (
int e = start; e < end; ++e)
725 assert(forces.rows() ==
da.size());
726 assert(forces.cols() ==
size_);
728 for (
long p = 0; p <
da.size(); ++p)
730 local_displacement.setZero();
732 for (
size_t i = 0; i <
vals.basis_values.size(); ++i)
734 const auto &bs =
vals.basis_values[i];
735 assert(bs.val.size() ==
da.size());
736 const double b_val = bs.val(p);
738 for (
int d = 0; d <
size_; ++d)
740 for (std::size_t ii = 0; ii < bs.global.size(); ++ii)
742 local_displacement(d) += (bs.global[ii].val * b_val) * displacement(bs.global[ii].index *
size_ + d);
747 const double rho = density(
vals.quadrature.points.row(p),
vals.val.row(p), t,
vals.element_id);
749 for (
int d = 0; d <
size_; ++d)
751 local_storage.val += forces(p, d) * local_displacement(d) *
da(p) * rho;
759 for (
const LocalThreadScalarStorage &local_storage : storage)
760 res += local_storage.val;
764 Eigen::MatrixXd forces;
768 Eigen::MatrixXd points, uv, normals, deform_mat, trafo;
770 Eigen::VectorXi global_primitive_ids;
771 for (
const auto &lb : local_neumann_boundary)
773 const int e = lb.element_id();
777 for (
int i = 0; i < lb.size(); ++i)
779 const int primitive_global_id = lb.global_primitive_id(i);
782 global_primitive_ids.setConstant(
weights.size(), primitive_global_id);
792 for (
int n = 0; n <
vals.jac_it.size(); ++n)
794 trafo =
vals.jac_it[n].inverse();
796 if (displacement_prev.size() > 0)
800 deform_mat.setZero();
801 for (
const auto &b :
vals.basis_values)
803 for (
const auto &g : b.global)
805 for (
int d = 0; d <
size_; ++d)
807 deform_mat.row(d) += displacement_prev(g.index *
size_ + d) * b.grad.row(n);
815 normals.row(n) = normals.row(n) * trafo.inverse();
816 normals.row(n).normalize();
822 for (
long p = 0; p <
weights.size(); ++p)
824 local_displacement.setZero();
826 for (
size_t i = 0; i <
vals.basis_values.size(); ++i)
828 const auto &vv =
vals.basis_values[i];
829 assert(vv.val.size() ==
weights.size());
830 const double b_val = vv.val(p);
832 for (
int d = 0; d <
size_; ++d)
834 for (std::size_t ii = 0; ii < vv.global.size(); ++ii)
836 local_displacement(d) += (vv.global[ii].val * b_val) * displacement(vv.global[ii].index *
size_ + d);
841 for (
int d = 0; d <
size_; ++d)
842 res -= forces(p, d) * local_displacement(d) *
weights(p);
851 Eigen::MatrixXd nodal_force;
852 Eigen::MatrixXd empty_normal;
859 assert(nodal_force.size() ==
size_);
861 for (
int d = 0; d <
size_; ++d)
862 res -= nodal_force(d) * displacement(n_id *
size_ + d);
870 const std::vector<int> &bounday_nodes,
872 const std::vector<mesh::LocalBoundary> &local_neumann_boundary,
873 const Eigen::MatrixXd &displacement,
875 const bool project_to_psd,
879 if (displacement.size() == 0)
882 std::vector<Eigen::Triplet<double>>
entries, entries_t;
885 Eigen::MatrixXd uv, samples, gtmp, rhs_fun, deform_mat, jac_mat, trafo;
886 Eigen::VectorXi global_primitive_ids;
887 Eigen::MatrixXd points, normals;
889 Eigen::MatrixXd local_hessian;
891 for (
const auto &lb : local_neumann_boundary)
893 const int e = lb.element_id();
897 for (
int i = 0; i < lb.size(); ++i)
899 const int primitive_global_id = lb.global_primitive_id(i);
901 global_primitive_ids.setConstant(
weights.size(), primitive_global_id);
906 Eigen::MatrixXd reference_normals = normals;
910 std::vector<std::vector<Eigen::MatrixXd>> grad_normal;
911 for (
int n = 0; n <
vals.jac_it.size(); ++n)
913 trafo =
vals.jac_it[n].inverse();
917 deform_mat.setZero();
918 jac_mat.resize(
size_,
vals.basis_values.size());
920 for (
const auto &b :
vals.basis_values)
922 jac_mat.col(b_idx++) = b.grad.row(n);
924 for (
const auto &g : b.global)
925 for (
int d = 0; d <
size_; ++d)
926 deform_mat.row(d) += displacement(g.index *
size_ + d) * b.grad.row(n);
930 trafo = trafo.inverse();
932 Eigen::VectorXd displaced_normal = normals.row(n) * trafo;
933 normals.row(n) = displaced_normal / displaced_normal.norm();
935 std::vector<Eigen::MatrixXd> grad;
937 Eigen::MatrixXd
vec = -(jac_mat.transpose() * trafo * reference_normals.row(n).transpose());
939 for (
int k = 0; k <
size_; ++k)
941 Eigen::MatrixXd grad_i(jac_mat.rows(), jac_mat.cols());
943 for (
int m = 0; m < jac_mat.rows(); ++m)
944 for (
int l = 0; l < jac_mat.cols(); ++l)
945 grad_i(m, l) = -(reference_normals.row(n) * trafo)(m) * (jac_mat.transpose() * trafo)(l, k);
946 grad.push_back(grad_i);
951 Eigen::MatrixXd normalization_chain_rule = (normals.row(n).transpose() * normals.row(n));
952 normalization_chain_rule = Eigen::MatrixXd::Identity(
size_,
size_) - normalization_chain_rule;
953 normalization_chain_rule /= displaced_normal.norm();
957 for (
const auto &b :
vals.basis_values)
959 for (
int d = 0; d <
size_; ++d)
961 for (
int k = 0; k <
size_; ++k)
962 vec(k) = grad[k](d, b_idx);
963 vec = normalization_chain_rule *
vec;
964 for (
int k = 0; k <
size_; ++k)
965 grad[k](d, b_idx) =
vec(k);
971 grad_normal.push_back(grad);
973 Eigen::MatrixXd rhs_fun;
982 local_hessian.setZero(
vals.basis_values.size() *
size_,
vals.basis_values.size() *
size_);
984 for (
long n = 0; n < nodes.size(); ++n)
988 for (
int d = 0; d <
size_; ++d)
990 for (
size_t g = 0; g < v.
global.size(); ++g)
993 const bool is_neumann = std::find(bounday_nodes.begin(), bounday_nodes.end(), g_index) == bounday_nodes.end();
997 for (
long ni = 0; ni < nodes.size(); ++ni)
1000 for (
int di = 0; di <
size_; ++di)
1002 for (
size_t gi = 0; gi < vi.
global.size(); ++gi)
1004 const int gi_index = vi.
global[gi].index *
size_ + di;
1007 for (
int q = 0; q <
vals.jac_it.size(); ++q)
1009 double pressure_val = rhs_fun.row(q).dot(normals.row(q));
1012 value += grad_normal[q][d](di, nodes(ni)) * pressure_val *
weights(q) * vi.
val(q);
1015 value *= v.
global[g].val;
1017 const bool is_neumann_i = std::find(bounday_nodes.begin(), bounday_nodes.end(), gi_index) == bounday_nodes.end();
1021 local_hessian(nodes(n) *
size_ + d, nodes(ni) *
size_ + di) = value;
1032 local_hessian = ipc::project_to_psd(local_hessian);
1034 for (
long n = 0; n < nodes.size(); ++n)
1037 for (
int d = 0; d <
size_; ++d)
1039 for (
size_t g = 0; g < v.
global.size(); ++g)
1041 const int g_index = v.
global[g].index *
size_ + d;
1043 for (
long ni = 0; ni < nodes.size(); ++ni)
1046 for (
int di = 0; di <
size_; ++di)
1048 for (
size_t gi = 0; gi < vi.
global.size(); ++gi)
1050 const int gi_index = vi.
global[gi].index *
size_ + di;
1051 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
void add_multimaterial(const int index, const json ¶ms, const Units &units, const io::ResourceIO &resources) override
inialize material parameter
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)...
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_
const io::ResourceIO & resources_
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
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
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 io::ResourceIO &resources, const std::string bc_method, const json &solver_params, const int fe_space_id=-1)
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
Read-only interface to a hierarchical collection of simulation resources.
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