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 : assembler_(assembler),
49 ass_vals_cache_(ass_vals_cache),
51 bc_method_(bc_method),
52 solver_params_(solver_params),
53 dirichlet_nodes_(dirichlet_nodes),
54 dirichlet_nodes_position_(dirichlet_nodes_position),
55 neumann_nodes_(neumann_nodes),
56 neumann_nodes_position_(neumann_nodes_position)
67 Eigen::MatrixXd rhs_fun;
69 const int n_elements = int(
bases_.size());
71 for (
int e = 0; e < n_elements; ++e)
84 for (
int d = 0; d <
size_; ++d)
87 for (
int q = 0; q <
quadrature.weights.size(); ++q)
90 const double rho = density(
vals.quadrature.points.row(q),
vals.val.row(q), t,
vals.element_id);
96 const int n_loc_bases_ = int(
vals.basis_values.size());
97 for (
int i = 0; i < n_loc_bases_; ++i)
101 for (
int d = 0; d <
size_; ++d)
104 const double rhs_value = (rhs_fun.col(d).array() * v.
val.array()).sum();
105 for (std::size_t ii = 0; ii < v.
global.size(); ++ii)
116 time_bc([&](
const Mesh &
mesh,
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
124 time_bc([&](
const Mesh &
mesh,
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
132 time_bc([&](
const Mesh &
mesh,
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
138 void RhsAssembler::time_bc(
const std::function<
void(
const Mesh &,
const Eigen::MatrixXi &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &fun, Eigen::MatrixXd &sol)
const
141 Eigen::MatrixXd loc_sol;
143 const int n_elements = int(
bases_.size());
149 for (
int e = 0; e < n_elements; ++e)
157 for (
long i = 0; i < bs.
bases.size(); ++i)
159 const auto &b = bs.
bases[i];
160 const auto &glob = b.global();
162 for (
size_t ii = 0; ii < glob.size(); ++ii)
164 fun(
mesh_, ids, glob[ii].node, loc_sol);
166 for (
int d = 0; d <
size_; ++d)
168 sol(glob[ii].index *
size_ + d) = loc_sol(d) * glob[ii].val;
177 for (
int e = 0; e < n_elements; ++e)
181 ids.resize(
vals.val.rows(), 1);
188 for (
int d = 0; d <
size_; ++d)
189 loc_sol.col(d) = loc_sol.col(d).array() *
vals.det.array() *
quadrature.weights.array();
191 const int n_loc_bases_ = int(
vals.basis_values.size());
192 for (
int i = 0; i < n_loc_bases_; ++i)
196 for (
int d = 0; d <
size_; ++d)
198 const double sol_value = (loc_sol.col(d).array() * v.
val.array()).sum();
199 for (std::size_t ii = 0; ii < v.
global.size(); ++ii)
205 Eigen::MatrixXd b = sol;
208 const double mmin = b.minCoeff();
209 const double mmax = b.maxCoeff();
211 if (fabs(mmin) > 1e-8 || fabs(mmax) > 1e-8)
222 logger().info(
"Solve RHS using {} linear solver", solver->name());
223 solver->analyze_pattern(mass, mass.rows());
224 solver->factorize(mass);
226 for (
long i = 0; i < b.cols(); ++i)
228 solver->solve(b.block(0, i, mass.rows(), 1), sol.block(0, i, mass.rows(), 1));
230 logger().trace(
"mass matrix error {}", (mass * sol - b).norm());
235 void RhsAssembler::lsq_bc(
const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df,
236 const std::vector<LocalBoundary> &local_boundary,
237 const std::vector<int> &bounday_nodes,
238 const int resolution,
239 Eigen::MatrixXd &rhs)
const
241 const int n_el = int(
bases_.size());
243 Eigen::MatrixXd uv, samples, gtmp, rhs_fun;
244 Eigen::VectorXi global_primitive_ids;
248 Eigen::Matrix<bool, Eigen::Dynamic, 1> is_boundary(
n_basis_);
249 is_boundary.setConstant(
false);
250 int skipped_count = 0;
251 for (
int b : bounday_nodes)
253 int bindex = b / actual_dim;
255 if (bindex < is_boundary.size())
256 is_boundary[bindex] =
true;
260 assert(skipped_count <= 1);
262 for (
int d = 0; d <
size_; ++d)
265 std::vector<int> indices;
266 indices.reserve(n_el * 10);
267 std::vector<int> tags;
268 tags.reserve(n_el * 10);
272 Eigen::VectorXi global_index_to_col(
n_basis_);
273 global_index_to_col.setConstant(-1);
275 std::vector<AssemblyValues> tmp_val;
277 for (
const auto &lb : local_boundary)
279 const int e = lb.element_id();
287 const int n_local_bases = int(bs.
bases.size());
288 assert(global_primitive_ids.size() == samples.rows());
290 for (
int s = 0; s < samples.rows(); ++s)
298 for (
int j = 0; j < n_local_bases; ++j)
301 const double tmp = tmp_val[j].val(s);
303 if (fabs(tmp) < 1e-10)
306 for (std::size_t ii = 0; ii < b.
global().size(); ++ii)
309 if (is_boundary[b.
global()[ii].index])
311 if (global_index_to_col(b.
global()[ii].index) == -1)
313 global_index_to_col(b.
global()[ii].index) = index++;
314 indices.push_back(b.
global()[ii].index);
316 assert(indices.size() ==
size_t(index));
324 Eigen::MatrixXd global_rhs = Eigen::MatrixXd::Zero(total_size, 1);
326 const long buffer_size = total_size * long(indices.size());
327 std::vector<Eigen::Triplet<double>>
entries, entries_t;
331 int global_counter = 0;
332 Eigen::MatrixXd mapped;
334 for (
const auto &lb : local_boundary)
336 const int e = lb.element_id();
344 const int n_local_bases = int(bs.
bases.size());
349 df(global_primitive_ids, uv, mapped, rhs_fun);
351 for (
int s = 0; s < samples.rows(); ++s)
357 for (
int j = 0; j < n_local_bases; ++j)
360 const double tmp = tmp_val[j].val(s);
362 for (std::size_t ii = 0; ii < b.
global().size(); ++ii)
364 auto item = global_index_to_col(b.
global()[ii].index);
367 entries.push_back(Eigen::Triplet<double>(global_counter, item, tmp * b.
global()[ii].val));
368 entries_t.push_back(Eigen::Triplet<double>(item, global_counter, tmp * b.
global()[ii].val));
373 global_rhs(global_counter) = rhs_fun(s, d);
378 assert(global_counter == total_size);
382 const double mmin = global_rhs.minCoeff();
383 const double mmax = global_rhs.maxCoeff();
385 if (fabs(mmin) < 1e-8 && fabs(mmax) < 1e-8)
387 for (
size_t i = 0; i < indices.size(); ++i)
389 const int tag = tags[i];
391 rhs(indices[i] *
size_ + d) = 0;
400 mat_t.setFromTriplets(entries_t.begin(), entries_t.end());
403 Eigen::VectorXd b = mat_t * global_rhs;
405 Eigen::VectorXd coeffs(b.rows(), 1);
407 logger().info(
"Solve RHS using {} linear solver", solver->name());
408 solver->analyze_pattern(A, A.rows());
409 solver->factorize(A);
411 solver->solve(b, coeffs);
413 logger().trace(
"RHS solve error {}", (A * coeffs - b).norm());
415 for (
long i = 0; i < coeffs.rows(); ++i)
417 const int tag = tags[i];
419 rhs(indices[i] *
size_ + d) = coeffs(i);
426 void RhsAssembler::sample_bc(
const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df,
427 const std::vector<LocalBoundary> &local_boundary,
const std::vector<int> &bounday_nodes, Eigen::MatrixXd &rhs)
const
429 const int n_el = int(
bases_.size());
431 Eigen::MatrixXd rhs_fun;
432 Eigen::VectorXi global_primitive_ids(1);
433 Eigen::MatrixXd nans(1, 1);
434 nans(0) = std::nan(
"");
437 Eigen::Matrix<bool, Eigen::Dynamic, 1> is_boundary(
n_basis_);
438 is_boundary.setConstant(
false);
442 int skipped_count = 0;
443 for (
int b : bounday_nodes)
445 int bindex = b / actual_dim;
447 if (bindex < is_boundary.size())
448 is_boundary[bindex] =
true;
452 assert(skipped_count <= 1);
455 for (
const auto &lb : local_boundary)
457 const int e = lb.element_id();
460 for (
int i = 0; i < lb.size(); ++i)
462 global_primitive_ids(0) = lb.global_primitive_id(i);
464 assert(global_primitive_ids.size() == 1);
467 for (
long n = 0; n < nodes.size(); ++n)
469 const auto &b = bs.
bases[nodes(n)];
470 const auto &glob = b.global();
472 for (
size_t ii = 0; ii < glob.size(); ++ii)
474 assert(is_boundary[glob[ii].index]);
477 df(global_primitive_ids, nans, glob[ii].node, rhs_fun);
479 for (
int d = 0; d <
size_; ++d)
484 rhs(glob[ii].index *
size_ + d) = rhs_fun(0, d);
494 const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df,
495 const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &nf,
496 const std::vector<LocalBoundary> &local_boundary,
497 const std::vector<int> &bounday_nodes,
499 const std::vector<LocalBoundary> &local_neumann_boundary,
500 const Eigen::MatrixXd &displacement,
502 Eigen::MatrixXd &rhs)
const
505 sample_bc(df, local_boundary, bounday_nodes, rhs);
507 lsq_bc(df, local_boundary, bounday_nodes, resolution[0], rhs);
509 if (bounday_nodes.size() > 0)
511 Eigen::MatrixXd tmp_val;
519 assert(tmp_val.size() ==
size_);
521 for (
int d = 0; d <
size_; ++d)
525 const int g_index = n_id *
size_ + d;
526 rhs(g_index) = tmp_val(d);
532 Eigen::MatrixXd uv, samples, gtmp, rhs_fun, deform_mat, trafo;
533 Eigen::VectorXi global_primitive_ids;
534 Eigen::MatrixXd
points, normals;
535 Eigen::VectorXd weights;
537 ElementAssemblyValues
vals;
539 for (
const auto &lb : local_neumann_boundary)
541 const int e = lb.element_id();
542 const basis::ElementBases &gbs =
gbases_[
e];
543 const basis::ElementBases &bs =
bases_[
e];
545 for (
int i = 0; i < lb.size(); ++i)
547 const int primitive_global_id = lb.global_primitive_id(i);
549 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
553 for (
int n = 0; n <
vals.jac_it.size(); ++n)
555 trafo =
vals.jac_it[n].inverse();
557 if (displacement.size() > 0)
561 deform_mat.setZero();
562 for (
const auto &b :
vals.basis_values)
564 for (
const auto &g : b.global)
566 for (
int d = 0; d <
size_; ++d)
568 deform_mat.row(d) += displacement(
g.index *
size_ + d) * b.grad.row(n);
576 normals.row(n) = normals.row(n) * trafo.inverse();
577 normals.row(n).normalize();
581 nf(global_primitive_ids, uv,
vals.val, normals, rhs_fun);
585 for (
int d = 0; d <
size_; ++d)
586 rhs_fun.col(d) = rhs_fun.col(d).array() * weights.array();
588 const auto nodes = bs.local_nodes_for_primitive(primitive_global_id,
mesh_);
590 for (
long n = 0; n <
nodes.size(); ++n)
593 const AssemblyValues &v =
vals.basis_values[
nodes(n)];
594 for (
int d = 0; d <
size_; ++d)
596 const double rhs_value = (rhs_fun.col(d).array() * v.val.array()).sum();
598 for (
size_t g = 0;
g < v.global.size(); ++
g)
600 const int g_index = v.global[
g].index *
size_ + d;
601 const bool is_neumann = std::find(bounday_nodes.begin(), bounday_nodes.end(), g_index) == bounday_nodes.end();
605 rhs(g_index) += rhs_value * v.global[
g].val;
617 const std::vector<int> &bounday_nodes,
619 const std::vector<LocalBoundary> &local_neumann_boundary,
620 Eigen::MatrixXd &rhs,
621 const Eigen::MatrixXd &displacement,
622 const double t)
const
625 [&](
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &uv,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
628 [&](
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &uv,
const Eigen::MatrixXd &pts,
const Eigen::MatrixXd &normals, Eigen::MatrixXd &
val) {
631 local_boundary, bounday_nodes, resolution, local_neumann_boundary, displacement, t, rhs);
637 const std::vector<int> &bounday_nodes,
640 const std::vector<LocalBoundary> &local_neumann_boundary,
641 const Eigen::MatrixXd &final_rhs,
643 Eigen::MatrixXd &rhs)
const
654 if (rhs.size() != final_rhs.size())
656 const int prev_size = rhs.size();
657 rhs.conservativeResize(final_rhs.size(), rhs.cols());
659 rhs.block(prev_size, 0, final_rhs.size() - prev_size, rhs.cols()).setZero();
660 rhs(rhs.size() - 1) = 0;
663 assert(rhs.size() == final_rhs.size());
668 const Eigen::MatrixXd &displacement_prev,
669 const std::vector<LocalBoundary> &local_neumann_boundary,
672 const double t)
const
680 const int n_bases = int(
bases_.size());
685 Eigen::MatrixXd forces;
687 for (
int e = start; e < end; ++e)
697 assert(forces.rows() ==
da.size());
698 assert(forces.cols() ==
size_);
700 for (
long p = 0; p <
da.size(); ++p)
702 local_displacement.setZero();
704 for (
size_t i = 0; i <
vals.basis_values.size(); ++i)
706 const auto &bs =
vals.basis_values[i];
707 assert(bs.val.size() ==
da.size());
708 const double b_val = bs.val(p);
710 for (
int d = 0; d <
size_; ++d)
712 for (std::size_t ii = 0; ii < bs.global.size(); ++ii)
714 local_displacement(d) += (bs.global[ii].val * b_val) * displacement(bs.global[ii].index *
size_ + d);
719 const double rho = density(
vals.quadrature.points.row(p),
vals.val.row(p), t,
vals.element_id);
721 for (
int d = 0; d <
size_; ++d)
723 local_storage.val += forces(p, d) * local_displacement(d) *
da(p) * rho;
731 for (
const LocalThreadScalarStorage &local_storage : storage)
732 res += local_storage.val;
736 Eigen::MatrixXd forces;
740 Eigen::MatrixXd points, uv, normals, deform_mat, trafo;
741 Eigen::VectorXd weights;
742 Eigen::VectorXi global_primitive_ids;
743 for (
const auto &lb : local_neumann_boundary)
745 const int e = lb.element_id();
749 for (
int i = 0; i < lb.size(); ++i)
751 const int primitive_global_id = lb.global_primitive_id(i);
754 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
764 for (
int n = 0; n <
vals.jac_it.size(); ++n)
766 trafo =
vals.jac_it[n].inverse();
768 if (displacement_prev.size() > 0)
772 deform_mat.setZero();
773 for (
const auto &b :
vals.basis_values)
775 for (
const auto &g : b.global)
777 for (
int d = 0; d <
size_; ++d)
779 deform_mat.row(d) += displacement_prev(g.index *
size_ + d) * b.grad.row(n);
787 normals.row(n) = normals.row(n) * trafo.inverse();
788 normals.row(n).normalize();
794 for (
long p = 0; p < weights.size(); ++p)
796 local_displacement.setZero();
798 for (
size_t i = 0; i <
vals.basis_values.size(); ++i)
800 const auto &vv =
vals.basis_values[i];
801 assert(vv.val.size() == weights.size());
802 const double b_val = vv.val(p);
804 for (
int d = 0; d <
size_; ++d)
806 for (std::size_t ii = 0; ii < vv.global.size(); ++ii)
808 local_displacement(d) += (vv.global[ii].val * b_val) * displacement(vv.global[ii].index *
size_ + d);
813 for (
int d = 0; d <
size_; ++d)
814 res -= forces(p, d) * local_displacement(d) * weights(p);
823 const std::vector<int> &bounday_nodes,
825 const std::vector<mesh::LocalBoundary> &local_neumann_boundary,
826 const Eigen::MatrixXd &displacement,
828 const bool project_to_psd,
832 if (displacement.size() == 0)
835 std::vector<Eigen::Triplet<double>>
entries, entries_t;
838 Eigen::MatrixXd uv, samples, gtmp, rhs_fun, deform_mat, jac_mat, trafo;
839 Eigen::VectorXi global_primitive_ids;
840 Eigen::MatrixXd points, normals;
841 Eigen::VectorXd weights;
842 Eigen::MatrixXd local_hessian;
844 for (
const auto &lb : local_neumann_boundary)
846 const int e = lb.element_id();
850 for (
int i = 0; i < lb.size(); ++i)
852 const int primitive_global_id = lb.global_primitive_id(i);
854 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
859 Eigen::MatrixXd reference_normals = normals;
863 std::vector<std::vector<Eigen::MatrixXd>> grad_normal;
864 for (
int n = 0; n <
vals.jac_it.size(); ++n)
866 trafo =
vals.jac_it[n].inverse();
870 deform_mat.setZero();
871 jac_mat.resize(
size_,
vals.basis_values.size());
873 for (
const auto &b :
vals.basis_values)
875 jac_mat.col(b_idx++) = b.grad.row(n);
877 for (
const auto &g : b.global)
878 for (
int d = 0; d <
size_; ++d)
879 deform_mat.row(d) += displacement(g.index *
size_ + d) * b.grad.row(n);
883 trafo = trafo.inverse();
885 Eigen::VectorXd displaced_normal = normals.row(n) * trafo;
886 normals.row(n) = displaced_normal / displaced_normal.norm();
888 std::vector<Eigen::MatrixXd> grad;
890 Eigen::MatrixXd
vec = -(jac_mat.transpose() * trafo * reference_normals.row(n).transpose());
892 for (
int k = 0; k <
size_; ++k)
894 Eigen::MatrixXd grad_i(jac_mat.rows(), jac_mat.cols());
896 for (
int m = 0; m < jac_mat.rows(); ++m)
897 for (
int l = 0; l < jac_mat.cols(); ++l)
898 grad_i(m, l) = -(reference_normals.row(n) * trafo)(m) * (jac_mat.transpose() * trafo)(l, k);
899 grad.push_back(grad_i);
904 Eigen::MatrixXd normalization_chain_rule = (normals.row(n).transpose() * normals.row(n));
905 normalization_chain_rule = Eigen::MatrixXd::Identity(
size_,
size_) - normalization_chain_rule;
906 normalization_chain_rule /= displaced_normal.norm();
910 for (
const auto &b :
vals.basis_values)
912 for (
int d = 0; d <
size_; ++d)
914 for (
int k = 0; k <
size_; ++k)
915 vec(k) = grad[k](d, b_idx);
916 vec = normalization_chain_rule *
vec;
917 for (
int k = 0; k <
size_; ++k)
918 grad[k](d, b_idx) =
vec(k);
924 grad_normal.push_back(grad);
926 Eigen::MatrixXd rhs_fun;
935 local_hessian.setZero(
vals.basis_values.size() *
size_,
vals.basis_values.size() *
size_);
937 for (
long n = 0; n < nodes.size(); ++n)
941 for (
int d = 0; d <
size_; ++d)
943 for (
size_t g = 0; g < v.
global.size(); ++g)
946 const bool is_neumann = std::find(bounday_nodes.begin(), bounday_nodes.end(), g_index) == bounday_nodes.end();
950 for (
long ni = 0; ni < nodes.size(); ++ni)
953 for (
int di = 0; di <
size_; ++di)
955 for (
size_t gi = 0; gi < vi.
global.size(); ++gi)
957 const int gi_index = vi.
global[gi].index *
size_ + di;
960 for (
int q = 0; q <
vals.jac_it.size(); ++q)
962 double pressure_val = rhs_fun.row(q).dot(normals.row(q));
965 value += grad_normal[q][d](di, nodes(ni)) * pressure_val * weights(q) * vi.
val(q);
970 const bool is_neumann_i = std::find(bounday_nodes.begin(), bounday_nodes.end(), gi_index) == bounday_nodes.end();
974 local_hessian(nodes(n) *
size_ + d, nodes(ni) *
size_ + di) = value;
985 local_hessian = ipc::project_to_psd(local_hessian);
987 for (
long n = 0; n < nodes.size(); ++n)
990 for (
int d = 0; d <
size_; ++d)
992 for (
size_t g = 0; g < v.
global.size(); ++g)
996 for (
long ni = 0; ni < nodes.size(); ++ni)
999 for (
int di = 0; di <
size_; ++di)
1001 for (
size_t gi = 0; gi < vi.
global.size(); ++gi)
1003 const int gi_index = vi.
global[gi].index *
size_ + di;
1004 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) 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 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
virtual bool is_rhs_zero() const =0
virtual bool is_dimension_dirichet(const int tag, const int dim) const
virtual bool all_dimensions_dirichlet() const
virtual void initial_acceleration(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const
virtual bool is_scalar() const =0
virtual void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) 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
virtual void initial_velocity(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const
virtual bool is_constant_in_time() const
virtual bool is_nodal_dimension_dirichlet(const int n_id, const int tag, const int dim) const
virtual bool is_boundary_pressure(const int boundary_id) const
virtual void initial_solution(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) 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 =0
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
const mesh::Mesh & mesh() const
const std::vector< basis::ElementBases > & gbases_
basis functions associated with geometric mapping
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< RowVectorNd > & dirichlet_nodes_position_
const std::string bc_method_
const AssemblyValsCache & ass_vals_cache_
void initial_solution(Eigen::MatrixXd &sol) const
const mesh::Obstacle & obstacle_
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_
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)
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.
const std::vector< Local2Global > & global() const
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
int dimension() const
utily for dimension
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::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix