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,
const std::vector<int> &bounday_nodes,
const int resolution, Eigen::MatrixXd &rhs)
const
238 const int n_el = int(
bases_.size());
240 Eigen::MatrixXd uv, samples, gtmp, rhs_fun;
241 Eigen::VectorXi global_primitive_ids;
245 Eigen::Matrix<bool, Eigen::Dynamic, 1> is_boundary(
n_basis_);
246 is_boundary.setConstant(
false);
247 int skipped_count = 0;
248 for (
int b : bounday_nodes)
250 int bindex = b / actual_dim;
252 if (bindex < is_boundary.size())
253 is_boundary[bindex] =
true;
257 assert(skipped_count <= 1);
259 for (
int d = 0; d <
size_; ++d)
262 std::vector<int> indices;
263 indices.reserve(n_el * 10);
264 std::vector<int> tags;
265 tags.reserve(n_el * 10);
269 Eigen::VectorXi global_index_to_col(
n_basis_);
270 global_index_to_col.setConstant(-1);
272 std::vector<AssemblyValues> tmp_val;
274 for (
const auto &lb : local_boundary)
276 const int e = lb.element_id();
284 const int n_local_bases = int(bs.
bases.size());
285 assert(global_primitive_ids.size() == samples.rows());
287 for (
int s = 0; s < samples.rows(); ++s)
295 for (
int j = 0; j < n_local_bases; ++j)
298 const double tmp = tmp_val[j].val(s);
300 if (fabs(tmp) < 1e-10)
303 for (std::size_t ii = 0; ii < b.
global().size(); ++ii)
306 if (is_boundary[b.
global()[ii].index])
308 if (global_index_to_col(b.
global()[ii].index) == -1)
310 global_index_to_col(b.
global()[ii].index) = index++;
311 indices.push_back(b.
global()[ii].index);
313 assert(indices.size() ==
size_t(index));
321 Eigen::MatrixXd global_rhs = Eigen::MatrixXd::Zero(total_size, 1);
323 const long buffer_size = total_size * long(indices.size());
324 std::vector<Eigen::Triplet<double>>
entries, entries_t;
328 int global_counter = 0;
329 Eigen::MatrixXd mapped;
331 for (
const auto &lb : local_boundary)
333 const int e = lb.element_id();
341 const int n_local_bases = int(bs.
bases.size());
346 df(global_primitive_ids, uv, mapped, rhs_fun);
348 for (
int s = 0; s < samples.rows(); ++s)
354 for (
int j = 0; j < n_local_bases; ++j)
357 const double tmp = tmp_val[j].val(s);
359 for (std::size_t ii = 0; ii < b.
global().size(); ++ii)
361 auto item = global_index_to_col(b.
global()[ii].index);
364 entries.push_back(Eigen::Triplet<double>(global_counter, item, tmp * b.
global()[ii].val));
365 entries_t.push_back(Eigen::Triplet<double>(item, global_counter, tmp * b.
global()[ii].val));
370 global_rhs(global_counter) = rhs_fun(s, d);
375 assert(global_counter == total_size);
379 const double mmin = global_rhs.minCoeff();
380 const double mmax = global_rhs.maxCoeff();
382 if (fabs(mmin) < 1e-8 && fabs(mmax) < 1e-8)
384 for (
size_t i = 0; i < indices.size(); ++i)
386 const int tag = tags[i];
388 rhs(indices[i] *
size_ + d) = 0;
397 mat_t.setFromTriplets(entries_t.begin(), entries_t.end());
400 Eigen::VectorXd b = mat_t * global_rhs;
402 Eigen::VectorXd coeffs(b.rows(), 1);
404 logger().info(
"Solve RHS using {} linear solver", solver->name());
405 solver->analyze_pattern(A, A.rows());
406 solver->factorize(A);
408 solver->solve(b, coeffs);
410 logger().trace(
"RHS solve error {}", (A * coeffs - b).norm());
412 for (
long i = 0; i < coeffs.rows(); ++i)
414 const int tag = tags[i];
416 rhs(indices[i] *
size_ + d) = coeffs(i);
423 void RhsAssembler::sample_bc(
const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df,
424 const std::vector<LocalBoundary> &local_boundary,
const std::vector<int> &bounday_nodes, Eigen::MatrixXd &rhs)
const
426 const int n_el = int(
bases_.size());
428 Eigen::MatrixXd rhs_fun;
429 Eigen::VectorXi global_primitive_ids(1);
430 Eigen::MatrixXd nans(1, 1);
431 nans(0) = std::nan(
"");
434 Eigen::Matrix<bool, Eigen::Dynamic, 1> is_boundary(
n_basis_);
435 is_boundary.setConstant(
false);
439 int skipped_count = 0;
440 for (
int b : bounday_nodes)
442 int bindex = b / actual_dim;
444 if (bindex < is_boundary.size())
445 is_boundary[bindex] =
true;
449 assert(skipped_count <= 1);
452 for (
const auto &lb : local_boundary)
454 const int e = lb.element_id();
457 for (
int i = 0; i < lb.size(); ++i)
459 global_primitive_ids(0) = lb.global_primitive_id(i);
461 assert(global_primitive_ids.size() == 1);
464 for (
long n = 0; n < nodes.size(); ++n)
466 const auto &b = bs.
bases[nodes(n)];
467 const auto &glob = b.global();
469 for (
size_t ii = 0; ii < glob.size(); ++ii)
471 assert(is_boundary[glob[ii].index]);
474 df(global_primitive_ids, nans, glob[ii].node, rhs_fun);
476 for (
int d = 0; d <
size_; ++d)
481 rhs(glob[ii].index *
size_ + d) = rhs_fun(0, d);
491 const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &df,
492 const std::function<
void(
const Eigen::MatrixXi &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &,
const Eigen::MatrixXd &, Eigen::MatrixXd &)> &nf,
493 const std::vector<LocalBoundary> &local_boundary,
const std::vector<int> &bounday_nodes,
494 const int resolution,
const std::vector<LocalBoundary> &local_neumann_boundary,
495 const Eigen::MatrixXd &displacement,
const double t,
496 Eigen::MatrixXd &rhs)
const
499 sample_bc(df, local_boundary, bounday_nodes, rhs);
501 lsq_bc(df, local_boundary, bounday_nodes, resolution, rhs);
503 if (bounday_nodes.size() > 0)
505 Eigen::MatrixXd tmp_val;
513 assert(tmp_val.size() ==
size_);
515 for (
int d = 0; d <
size_; ++d)
519 const int g_index = n_id *
size_ + d;
520 rhs(g_index) = tmp_val(d);
526 Eigen::MatrixXd uv, samples, gtmp, rhs_fun, deform_mat, trafo;
527 Eigen::VectorXi global_primitive_ids;
528 Eigen::MatrixXd
points, normals;
529 Eigen::VectorXd weights;
531 ElementAssemblyValues
vals;
533 for (
const auto &lb : local_neumann_boundary)
535 const int e = lb.element_id();
536 const basis::ElementBases &gbs =
gbases_[
e];
537 const basis::ElementBases &bs =
bases_[
e];
539 for (
int i = 0; i < lb.size(); ++i)
541 const int primitive_global_id = lb.global_primitive_id(i);
544 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
548 for (
int n = 0; n <
vals.jac_it.size(); ++n)
550 trafo =
vals.jac_it[n].inverse();
552 if (displacement.size() > 0)
556 deform_mat.setZero();
557 for (
const auto &b :
vals.basis_values)
559 for (
const auto &g : b.global)
561 for (
int d = 0; d <
size_; ++d)
563 deform_mat.row(d) += displacement(
g.index *
size_ + d) * b.grad.row(n);
571 normals.row(n) = normals.row(n) * trafo.inverse();
572 normals.row(n).normalize();
576 nf(global_primitive_ids, uv,
vals.val, normals, rhs_fun);
580 for (
int d = 0; d <
size_; ++d)
581 rhs_fun.col(d) = rhs_fun.col(d).array() * weights.array();
583 const auto nodes = bs.local_nodes_for_primitive(primitive_global_id,
mesh_);
585 for (
long n = 0; n <
nodes.size(); ++n)
588 const AssemblyValues &v =
vals.basis_values[
nodes(n)];
589 for (
int d = 0; d <
size_; ++d)
591 const double rhs_value = (rhs_fun.col(d).array() * v.val.array()).sum();
593 for (
size_t g = 0;
g < v.global.size(); ++
g)
595 const int g_index = v.global[
g].index *
size_ + d;
596 const bool is_neumann = std::find(bounday_nodes.begin(), bounday_nodes.end(), g_index) == bounday_nodes.end();
600 rhs(g_index) += rhs_value * v.global[
g].val;
611 void RhsAssembler::set_bc(
const std::vector<LocalBoundary> &local_boundary,
const std::vector<int> &bounday_nodes,
const int resolution,
const std::vector<LocalBoundary> &local_neumann_boundary, Eigen::MatrixXd &rhs,
const Eigen::MatrixXd &displacement,
const double t)
const
614 [&](
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &uv,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &
val) {
617 [&](
const Eigen::MatrixXi &global_ids,
const Eigen::MatrixXd &uv,
const Eigen::MatrixXd &pts,
const Eigen::MatrixXd &normals, Eigen::MatrixXd &
val) {
620 local_boundary, bounday_nodes, resolution, local_neumann_boundary, displacement, t, rhs);
625 void RhsAssembler::compute_energy_grad(
const std::vector<LocalBoundary> &local_boundary,
const std::vector<int> &bounday_nodes,
const Density &density,
const int resolution,
const std::vector<LocalBoundary> &local_neumann_boundary,
const Eigen::MatrixXd &final_rhs,
const double t, Eigen::MatrixXd &rhs)
const
636 if (rhs.size() != final_rhs.size())
638 const int prev_size = rhs.size();
639 rhs.conservativeResize(final_rhs.size(), rhs.cols());
641 rhs.block(prev_size, 0, final_rhs.size() - prev_size, rhs.cols()).setZero();
642 rhs(rhs.size() - 1) = 0;
645 assert(rhs.size() == final_rhs.size());
650 const Eigen::MatrixXd &displacement_prev,
651 const std::vector<LocalBoundary> &local_neumann_boundary,
653 const int resolution,
654 const double t)
const
662 const int n_bases = int(
bases_.size());
667 Eigen::MatrixXd forces;
669 for (
int e = start; e < end; ++e)
679 assert(forces.rows() ==
da.size());
680 assert(forces.cols() ==
size_);
682 for (
long p = 0; p <
da.size(); ++p)
684 local_displacement.setZero();
686 for (
size_t i = 0; i <
vals.basis_values.size(); ++i)
688 const auto &bs =
vals.basis_values[i];
689 assert(bs.val.size() ==
da.size());
690 const double b_val = bs.val(p);
692 for (
int d = 0; d <
size_; ++d)
694 for (std::size_t ii = 0; ii < bs.global.size(); ++ii)
696 local_displacement(d) += (bs.global[ii].val * b_val) * displacement(bs.global[ii].index *
size_ + d);
701 const double rho = density(
vals.quadrature.points.row(p),
vals.val.row(p), t,
vals.element_id);
703 for (
int d = 0; d <
size_; ++d)
705 local_storage.val += forces(p, d) * local_displacement(d) *
da(p) * rho;
713 for (
const LocalThreadScalarStorage &local_storage : storage)
714 res += local_storage.val;
718 Eigen::MatrixXd forces;
722 Eigen::MatrixXd points, uv, normals, deform_mat, trafo;
723 Eigen::VectorXd weights;
724 Eigen::VectorXi global_primitive_ids;
725 for (
const auto &lb : local_neumann_boundary)
727 const int e = lb.element_id();
731 for (
int i = 0; i < lb.size(); ++i)
733 const int primitive_global_id = lb.global_primitive_id(i);
736 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
746 for (
int n = 0; n <
vals.jac_it.size(); ++n)
748 trafo =
vals.jac_it[n].inverse();
750 if (displacement_prev.size() > 0)
754 deform_mat.setZero();
755 for (
const auto &b :
vals.basis_values)
757 for (
const auto &g : b.global)
759 for (
int d = 0; d <
size_; ++d)
761 deform_mat.row(d) += displacement_prev(g.index *
size_ + d) * b.grad.row(n);
769 normals.row(n) = normals.row(n) * trafo.inverse();
770 normals.row(n).normalize();
776 for (
long p = 0; p < weights.size(); ++p)
778 local_displacement.setZero();
780 for (
size_t i = 0; i <
vals.basis_values.size(); ++i)
782 const auto &vv =
vals.basis_values[i];
783 assert(vv.val.size() == weights.size());
784 const double b_val = vv.val(p);
786 for (
int d = 0; d <
size_; ++d)
788 for (std::size_t ii = 0; ii < vv.global.size(); ++ii)
790 local_displacement(d) += (vv.global[ii].val * b_val) * displacement(vv.global[ii].index *
size_ + d);
795 for (
int d = 0; d <
size_; ++d)
796 res -= forces(p, d) * local_displacement(d) * weights(p);
805 const std::vector<int> &bounday_nodes,
806 const int resolution,
807 const std::vector<mesh::LocalBoundary> &local_neumann_boundary,
808 const Eigen::MatrixXd &displacement,
810 const bool project_to_psd,
814 if (displacement.size() == 0)
817 std::vector<Eigen::Triplet<double>>
entries, entries_t;
820 Eigen::MatrixXd uv, samples, gtmp, rhs_fun, deform_mat, jac_mat, trafo;
821 Eigen::VectorXi global_primitive_ids;
822 Eigen::MatrixXd points, normals;
823 Eigen::VectorXd weights;
824 Eigen::MatrixXd local_hessian;
826 for (
const auto &lb : local_neumann_boundary)
828 const int e = lb.element_id();
832 for (
int i = 0; i < lb.size(); ++i)
834 const int primitive_global_id = lb.global_primitive_id(i);
837 global_primitive_ids.setConstant(weights.size(), primitive_global_id);
842 Eigen::MatrixXd reference_normals = normals;
846 std::vector<std::vector<Eigen::MatrixXd>> grad_normal;
847 for (
int n = 0; n <
vals.jac_it.size(); ++n)
849 trafo =
vals.jac_it[n].inverse();
853 deform_mat.setZero();
854 jac_mat.resize(
size_,
vals.basis_values.size());
856 for (
const auto &b :
vals.basis_values)
858 jac_mat.col(b_idx++) = b.grad.row(n);
860 for (
const auto &g : b.global)
861 for (
int d = 0; d <
size_; ++d)
862 deform_mat.row(d) += displacement(g.index *
size_ + d) * b.grad.row(n);
866 trafo = trafo.inverse();
868 Eigen::VectorXd displaced_normal = normals.row(n) * trafo;
869 normals.row(n) = displaced_normal / displaced_normal.norm();
871 std::vector<Eigen::MatrixXd> grad;
873 Eigen::MatrixXd
vec = -(jac_mat.transpose() * trafo * reference_normals.row(n).transpose());
875 for (
int k = 0; k <
size_; ++k)
877 Eigen::MatrixXd grad_i(jac_mat.rows(), jac_mat.cols());
879 for (
int m = 0; m < jac_mat.rows(); ++m)
880 for (
int l = 0; l < jac_mat.cols(); ++l)
881 grad_i(m, l) = -(reference_normals.row(n) * trafo)(m) * (jac_mat.transpose() * trafo)(l, k);
882 grad.push_back(grad_i);
887 Eigen::MatrixXd normalization_chain_rule = (normals.row(n).transpose() * normals.row(n));
888 normalization_chain_rule = Eigen::MatrixXd::Identity(
size_,
size_) - normalization_chain_rule;
889 normalization_chain_rule /= displaced_normal.norm();
893 for (
const auto &b :
vals.basis_values)
895 for (
int d = 0; d <
size_; ++d)
897 for (
int k = 0; k <
size_; ++k)
898 vec(k) = grad[k](d, b_idx);
899 vec = normalization_chain_rule *
vec;
900 for (
int k = 0; k <
size_; ++k)
901 grad[k](d, b_idx) =
vec(k);
907 grad_normal.push_back(grad);
909 Eigen::MatrixXd rhs_fun;
918 local_hessian.setZero(
vals.basis_values.size() *
size_,
vals.basis_values.size() *
size_);
920 for (
long n = 0; n < nodes.size(); ++n)
924 for (
int d = 0; d <
size_; ++d)
926 for (
size_t g = 0; g < v.
global.size(); ++g)
929 const bool is_neumann = std::find(bounday_nodes.begin(), bounday_nodes.end(), g_index) == bounday_nodes.end();
933 for (
long ni = 0; ni < nodes.size(); ++ni)
936 for (
int di = 0; di <
size_; ++di)
938 for (
size_t gi = 0; gi < vi.
global.size(); ++gi)
940 const int gi_index = vi.
global[gi].index *
size_ + di;
943 for (
int q = 0; q <
vals.jac_it.size(); ++q)
945 double pressure_val = rhs_fun.row(q).dot(normals.row(q));
948 value += grad_normal[q][d](di, nodes(ni)) * pressure_val * weights(q) * vi.
val(q);
953 const bool is_neumann_i = std::find(bounday_nodes.begin(), bounday_nodes.end(), gi_index) == bounday_nodes.end();
957 local_hessian(nodes(n) *
size_ + d, nodes(ni) *
size_ + di) = value;
968 local_hessian = ipc::project_to_psd(local_hessian);
970 for (
long n = 0; n < nodes.size(); ++n)
973 for (
int d = 0; d <
size_; ++d)
975 for (
size_t g = 0; g < v.
global.size(); ++g)
979 for (
long ni = 0; ni < nodes.size(); ++ni)
982 for (
int di = 0; di <
size_; ++di)
984 for (
size_t gi = 0; gi < vi.
global.size(); ++gi)
986 const int gi_index = vi.
global[gi].index *
size_ + di;
987 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.
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 set_bc(const std::vector< mesh::LocalBoundary > &local_boundary, const std::vector< int > &bounday_nodes, const int resolution, const std::vector< mesh::LocalBoundary > &local_neumann_boundary, Eigen::MatrixXd &rhs, const Eigen::MatrixXd &displacement=Eigen::MatrixXd(), const double t=1) const
void time_bc(const std::function< void(const mesh::Mesh &, const Eigen::MatrixXi &, const Eigen::MatrixXd &, Eigen::MatrixXd &)> &fun, Eigen::MatrixXd &sol) const
const Assembler & assembler_
const mesh::Mesh & mesh() const
const std::vector< basis::ElementBases > & gbases_
basis functions associated with geometric mapping
const int size_
dimension of problem
void compute_energy_grad(const std::vector< mesh::LocalBoundary > &local_boundary, const std::vector< int > &bounday_nodes, const Density &density, const int resolution, const std::vector< mesh::LocalBoundary > &local_neumann_boundary, const Eigen::MatrixXd &final_rhs, const double t, Eigen::MatrixXd &rhs) const
const std::vector< RowVectorNd > & dirichlet_nodes_position_
double compute_energy(const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev, const std::vector< mesh::LocalBoundary > &local_neumann_boundary, const Density &density, const int resolution, const double t) const
const std::string bc_method_
void compute_energy_hess(const std::vector< int > &bounday_nodes, const int 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 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 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 int 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.
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > VectorNd
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix