45 if (state.
args[
"time"][
"integrator"].is_string())
47 if (state.
args[
"time"][
"integrator"][
"type"] ==
"ImplicitEuler")
49 if (state.
args[
"time"][
"integrator"][
"type"] ==
"BDF")
50 return state.
args[
"time"][
"integrator"][
"steps"].get<
int>();
56 double dot(
const Eigen::MatrixXd &A,
const Eigen::MatrixXd &B) {
return (A.array() * B.array()).sum(); }
58 class LocalThreadScalarStorage
65 LocalThreadScalarStorage()
71 class LocalThreadVecStorage
78 LocalThreadVecStorage(
const int size)
88 T triangle_area(
const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &
V)
90 Eigen::Matrix<T, Eigen::Dynamic, 1> l1 =
V.row(1) -
V.row(0);
91 Eigen::Matrix<T, Eigen::Dynamic, 1> l2 =
V.row(2) -
V.row(0);
92 T area = 0.5 * sqrt(pow(l1(1) * l2(2) - l1(2) * l2(1), 2) + pow(l1(0) * l2(2) - l1(2) * l2(0), 2) + pow(l1(1) * l2(0) - l1(0) * l2(1), 2));
96 Eigen::MatrixXd triangle_area_grad(
const Eigen::MatrixXd &
F)
99 Eigen::Matrix<Diff, Eigen::Dynamic, Eigen::Dynamic> full_diff(
F.rows(),
F.cols());
100 for (
int i = 0; i <
F.rows(); i++)
101 for (
int j = 0; j <
F.cols(); j++)
102 full_diff(i, j) =
Diff(i + j *
F.rows(),
F(i, j));
105 Eigen::MatrixXd
grad(
F.rows(),
F.cols());
106 for (
int i = 0; i <
F.rows(); ++i)
107 for (
int j = 0; j <
F.cols(); ++j)
108 grad(i, j) = reduced_diff.getGradient()(i + j *
F.rows());
113 template <
typename T>
114 T line_length(
const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &
V)
116 Eigen::Matrix<T, Eigen::Dynamic, 1> L =
V.row(1) -
V.row(0);
121 Eigen::MatrixXd line_length_grad(
const Eigen::MatrixXd &
F)
124 Eigen::Matrix<Diff, Eigen::Dynamic, Eigen::Dynamic> full_diff(
F.rows(),
F.cols());
125 for (
int i = 0; i <
F.rows(); i++)
126 for (
int j = 0; j <
F.cols(); j++)
127 full_diff(i, j) =
Diff(i + j *
F.rows(),
F(i, j));
128 auto reduced_diff = line_length(full_diff);
130 Eigen::MatrixXd
grad(
F.rows(),
F.cols());
131 for (
int i = 0; i <
F.rows(); ++i)
132 for (
int j = 0; j <
F.cols(); ++j)
133 grad(i, j) = reduced_diff.getGradient()(i + j *
F.rows());
138 template <
typename T>
139 Eigen::Matrix<T, 2, 1> edge_normal(
const Eigen::Matrix<T, 4, 1> &
V)
141 Eigen::Matrix<T, 2, 1> v1 =
V.segment(0, 2);
142 Eigen::Matrix<T, 2, 1> v2 =
V.segment(2, 2);
143 Eigen::Matrix<T, 2, 1> normal = v1 - v2;
145 normal = normal / normal.norm();
149 template <
typename T>
150 Eigen::Matrix<T, 3, 1> face_normal(
const Eigen::Matrix<T, 9, 1> &
V)
152 Eigen::Matrix<T, 3, 1> v1 =
V.segment(0, 3);
153 Eigen::Matrix<T, 3, 1> v2 =
V.segment(3, 3);
154 Eigen::Matrix<T, 3, 1> v3 =
V.segment(6, 3);
155 Eigen::Matrix<T, 3, 1> normal = (v2 - v1).
cross(v3 - v1);
156 normal = normal / normal.norm();
160 Eigen::MatrixXd extract_lame_params(
const std::map<std::string, Assembler::ParamFunc> &lame_params,
const int e,
const int t,
const Eigen::MatrixXd &local_pts,
const Eigen::MatrixXd &pts)
162 Eigen::MatrixXd params = Eigen::MatrixXd::Zero(local_pts.rows(), 2);
164 auto search_lambda = lame_params.find(
"lambda");
165 auto search_mu = lame_params.find(
"mu");
167 if (search_lambda == lame_params.end() || search_mu == lame_params.end())
170 for (
int p = 0; p < local_pts.rows(); p++)
172 params(p, 0) = search_lambda->second(local_pts.row(p), pts.row(p), t, e);
173 params(p, 1) = search_mu->second(local_pts.row(p), pts.row(p), t, e);
183 const Eigen::MatrixXd &solution,
184 const std::set<int> &interested_ids,
188 const auto &bases = state.
bases;
191 const int dim = state.
mesh->dimension();
192 const int actual_dim = state.
problem->is_scalar() ? 1 : dim;
193 const int n_elements = int(bases.size());
194 const double t0 = state.
problem->is_time_dependent() ? state.
args[
"time"][
"t0"].get<
double>() : 0.0;
195 const double dt = state.
problem->is_time_dependent() ? state.
args[
"time"][
"dt"].get<
double>() : 0.0;
205 params.
t = dt * cur_step + t0;
206 params.
step = cur_step;
208 Eigen::MatrixXd u, grad_u;
209 Eigen::MatrixXd result;
211 for (
int e = start; e < end; ++e)
213 if (interested_ids.size() != 0 && interested_ids.find(state.
mesh->get_body_id(e)) == interested_ids.end())
229 local_storage.val += dot(result, local_storage.da);
232 for (
const LocalThreadScalarStorage &local_storage : storage)
233 integral += local_storage.val;
239 LocalThreadScalarStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
242 Eigen::MatrixXd points, normal;
243 Eigen::VectorXd weights;
245 Eigen::MatrixXd u, grad_u;
246 Eigen::MatrixXd result;
247 IntegrableFunctional::ParameterType params;
248 params.t = dt * cur_step + t0;
249 params.step = cur_step;
251 for (int lb_id = start; lb_id < end; ++lb_id)
253 const auto &lb = state.total_local_boundary[lb_id];
254 const int e = lb.element_id();
256 for (int i = 0; i < lb.size(); i++)
258 const int global_primitive_id = lb.global_primitive_id(i);
259 if (interested_ids.size() != 0 && interested_ids.find(state.mesh->get_boundary_id(global_primitive_id)) == interested_ids.end())
262 utils::BoundarySampler::boundary_quadrature(lb, state.n_boundary_samples(), *state.mesh, i, false, uv, points, normal, weights);
264 assembler::ElementAssemblyValues &vals = local_storage.vals;
265 vals.compute(e, state.mesh->is_volume(), points, bases[e], gbases[e]);
266 io::Evaluator::interpolate_at_local_vals(e, dim, actual_dim, vals, solution, u, grad_u);
268 const Eigen::MatrixXd lame_params = extract_lame_params(state.assembler->parameters(), e, params.t, points, vals.val);
271 params.body_id = state.mesh->get_body_id(e);
272 params.boundary_id = state.mesh->get_boundary_id(global_primitive_id);
273 j.evaluate(lame_params, points, vals.val, u, grad_u, normal, vals, params, result);
275 local_storage.val += dot(result, weights);
279 for (
const LocalThreadScalarStorage &local_storage : storage)
280 integral += local_storage.val;
284 std::vector<bool> traversed(state.
n_bases,
false);
286 params.
t = dt * cur_step + t0;
287 params.
step = cur_step;
288 for (
int e = 0; e < bases.size(); e++)
290 const auto &bs = bases[e];
291 for (
int i = 0; i < bs.bases.size(); i++)
293 const auto &b = bs.bases[i];
294 assert(b.global().size() == 1);
295 const auto &g = b.global()[0];
296 if (traversed[g.index])
299 const Eigen::MatrixXd lame_params = extract_lame_params(state.
assembler->parameters(), e, params.
t, Eigen::MatrixXd::Zero(1, dim) , g.node);
301 params.
node = g.index;
305 j.evaluate(lame_params, Eigen::MatrixXd::Zero(1, dim) , g.node, solution.block(g.index * dim, 0, dim, 1).transpose(), Eigen::MatrixXd::Zero(1, dim * actual_dim) , Eigen::MatrixXd::Zero(0, 0) ,
assembler::ElementAssemblyValues(), params,
val);
307 traversed[g.index] =
true;
315 void AdjointTools::compute_shape_derivative_functional_term(
317 const Eigen::MatrixXd &solution,
319 const std::set<int> &interested_ids,
321 Eigen::VectorXd &term,
322 const int cur_time_step)
325 const auto &bases = state.
bases;
326 const int dim = state.
mesh->dimension();
327 const int actual_dim = state.
problem->is_scalar() ? 1 : dim;
328 const double t0 = state.
problem->is_time_dependent() ? state.
args[
"time"][
"t0"].get<
double>() : 0.0;
329 const double dt = state.
problem->is_time_dependent() ? state.
args[
"time"][
"dt"].get<
double>() : 0.0;
331 const int n_elements = int(bases.size());
334 auto storage = utils::create_thread_storage(LocalThreadVecStorage(term.size()));
336 if (spatial_integral_type == SpatialIntegralType::Volume)
338 utils::maybe_parallel_for(n_elements, [&](
int start,
int end,
int thread_id) {
339 LocalThreadVecStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
341 Eigen::MatrixXd u, grad_u, j_val, dj_dgradu, dj_dx;
344 params.
t = cur_time_step * dt + t0;
345 params.
step = cur_time_step;
347 for (
int e = start; e < end; ++e)
349 if (interested_ids.size() != 0 && interested_ids.find(state.
mesh->get_body_id(e)) == interested_ids.end())
354 io::Evaluator::interpolate_at_local_vals(e, dim, actual_dim,
vals, solution, u, grad_u);
375 Eigen::MatrixXd tau_q, grad_u_q;
376 for (
auto &v :
gvals.basis_values)
378 for (
int q = 0; q < local_storage.da.size(); ++q)
380 local_storage.vec.block(v.global[0].index * dim, 0, dim, 1) += (j_val(q) * local_storage.da(q)) * v.grad_t_m.row(q).transpose();
383 local_storage.vec.block(v.global[0].index * dim, 0, dim, 1) += (v.val(q) * local_storage.da(q)) * dj_dx.row(q).transpose();
387 if (dim == actual_dim)
394 tau_q = dj_dgradu.row(q);
395 grad_u_q = grad_u.row(q);
397 for (
int d = 0; d < dim; d++)
398 local_storage.vec(v.global[0].index * dim + d) += -dot(tau_q, grad_u_q.col(d) * v.grad_t_m.row(q)) * local_storage.da(q);
405 else if (spatial_integral_type == SpatialIntegralType::Surface)
407 utils::maybe_parallel_for(state.
total_local_boundary.size(), [&](
int start,
int end,
int thread_id) {
408 LocalThreadVecStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
410 Eigen::MatrixXd uv, points, normal;
411 Eigen::VectorXd &weights = local_storage.da;
413 Eigen::MatrixXd u, grad_u, x, grad_x, j_val, dj_dgradu, dj_dgradx, dj_dx;
415 IntegrableFunctional::ParameterType params;
416 params.t = cur_time_step * dt + t0;
417 params.step = cur_time_step;
419 for (int lb_id = start; lb_id < end; ++lb_id)
421 const auto &lb = state.total_local_boundary[lb_id];
422 const int e = lb.element_id();
424 for (int i = 0; i < lb.size(); i++)
426 const int global_primitive_id = lb.global_primitive_id(i);
427 if (interested_ids.size() != 0 && interested_ids.find(state.mesh->get_boundary_id(global_primitive_id)) == interested_ids.end())
430 utils::BoundarySampler::boundary_quadrature(lb, state.n_boundary_samples(), *state.mesh, i, false, uv, points, normal, weights);
432 assembler::ElementAssemblyValues &vals = local_storage.vals;
433 io::Evaluator::interpolate_at_local_vals(*state.mesh, state.problem->is_scalar(), bases, gbases, e, points, solution, u, grad_u);
436 vals.compute(e, state.mesh->is_volume(), points, gbases[e], gbases[e]);
440 const int n_loc_bases_ = int(vals.basis_values.size());
442 const Eigen::MatrixXd lame_params = extract_lame_params(state.assembler->parameters(), e, params.t, points, vals.val);
445 params.body_id = state.mesh->get_body_id(e);
446 params.boundary_id = state.mesh->get_boundary_id(global_primitive_id);
448 j.evaluate(lame_params, points, vals.val, u, grad_u, normal, vals, params, j_val);
449 j_val = j_val.array().colwise() * weights.array();
451 if (j.depend_on_gradu())
453 j.dj_dgradu(lame_params, points, vals.val, u, grad_u, normal, vals, params, dj_dgradu);
454 dj_dgradu = dj_dgradu.array().colwise() * weights.array();
457 if (j.depend_on_gradx())
459 j.dj_dgradx(lame_params, points, vals.val, u, grad_u, normal, vals, params, dj_dgradx);
460 dj_dgradx = dj_dgradx.array().colwise() * weights.array();
465 j.dj_dx(lame_params, points, vals.val, u, grad_u, normal, vals, params, dj_dx);
466 dj_dx = dj_dx.array().colwise() * weights.array();
469 const auto nodes = gbases[e].local_nodes_for_primitive(lb.global_primitive_id(i), *state.mesh);
471 if (nodes.size() != dim)
472 log_and_throw_adjoint_error(
"Only linear geometry is supported in differentiable surface integral functional!");
474 Eigen::MatrixXd velocity_div_mat;
475 if (state.mesh->is_volume())
478 for (int d = 0; d < 3; d++)
479 V.row(d) = gbases[e].bases[nodes(d)].global()[0].node;
480 velocity_div_mat = face_velocity_divergence(V);
485 for (int d = 0; d < 2; d++)
486 V.row(d) = gbases[e].bases[nodes(d)].global()[0].node;
487 velocity_div_mat = edge_velocity_divergence(V);
490 Eigen::MatrixXd grad_u_q, tau_q, grad_x_q;
491 for (long n = 0; n < nodes.size(); ++n)
493 const assembler::AssemblyValues &v = vals.basis_values[nodes(n)];
495 local_storage.vec.block(v.global[0].index * dim, 0, dim, 1) += j_val.sum() * velocity_div_mat.row(n).transpose();
498 for (long n = 0; n < n_loc_bases_; ++n)
500 const assembler::AssemblyValues &v = vals.basis_values[n];
503 local_storage.vec.block(v.global[0].index * dim, 0, dim, 1) += dj_dx.transpose() * v.val;
506 if (j.depend_on_gradu())
508 for (int q = 0; q < weights.size(); ++q)
510 if (dim == actual_dim)
512 vector2matrix(grad_u.row(q), grad_u_q);
513 vector2matrix(dj_dgradu.row(q), tau_q);
517 grad_u_q = grad_u.row(q);
518 tau_q = dj_dgradu.row(q);
521 for (int d = 0; d < dim; d++)
522 local_storage.vec(v.global[0].index * dim + d) += -dot(tau_q, grad_u_q.col(d) * v.grad_t_m.row(q));
526 if (j.depend_on_gradx())
528 for (int d = 0; d < dim; d++)
530 for (int q = 0; q < weights.size(); ++q)
531 local_storage.vec(v.global[0].index * dim + d) += dot(dj_dgradx.block(q, d * dim, 1, dim), v.grad.row(q));
539 else if (spatial_integral_type == SpatialIntegralType::VertexSum)
543 for (
const LocalThreadVecStorage &local_storage : storage)
544 term += local_storage.
vec;
546 term = utils::flatten(utils::unflatten(term, dim)(state.
primitive_to_node(), Eigen::all));
315 void AdjointTools::compute_shape_derivative_functional_term( {
…}
549 void AdjointTools::dJ_shape_static_adjoint_term(
551 const Eigen::MatrixXd &sol,
552 const Eigen::MatrixXd &adjoint,
553 Eigen::VectorXd &one_form)
555 Eigen::VectorXd elasticity_term, rhs_term, pressure_term, contact_term, adhesion_term;
558 Eigen::MatrixXd adjoint_zeroed = adjoint;
567 rhs_term.setZero(one_form.size());
575 pressure_term.setZero(one_form.size());
583 contact_term.setZero(elasticity_term.size());
592 adhesion_term.setZero(elasticity_term.size());
596 one_form -= elasticity_term + rhs_term + pressure_term + contact_term + adhesion_term;
597 one_form = utils::flatten(utils::unflatten(one_form, state.
mesh->dimension())(state.
primitive_to_node(), Eigen::all));
549 void AdjointTools::dJ_shape_static_adjoint_term( {
…}
600 void AdjointTools::dJ_shape_homogenization_adjoint_term(
602 const Eigen::MatrixXd &sol,
603 const Eigen::MatrixXd &adjoint,
604 Eigen::VectorXd &one_form)
606 Eigen::VectorXd elasticity_term, contact_term, adhesion_term;
608 std::shared_ptr<NLHomoProblem> homo_problem = std::dynamic_pointer_cast<NLHomoProblem>(state.
solve_data.
nl_problem);
609 assert(homo_problem);
611 const int dim = state.
mesh->dimension();
614 const Eigen::MatrixXd affine_adjoint = homo_problem->reduced_to_disp_grad(adjoint,
true);
615 const Eigen::VectorXd full_adjoint = homo_problem->NLProblem::reduced_to_full(adjoint.topRows(homo_problem->reduced_size())) + io::Evaluator::generate_linear_field(state.
n_bases, state.
mesh_nodes, affine_adjoint);
625 contact_term.setZero(elasticity_term.size());
634 adhesion_term.setZero(elasticity_term.size());
637 one_form = -(elasticity_term + contact_term + adhesion_term);
639 Eigen::VectorXd force;
640 homo_problem->FullNLProblem::gradient(sol, force);
643 one_form = utils::flatten(utils::unflatten(one_form, dim)(state.
primitive_to_node(), Eigen::all));
600 void AdjointTools::dJ_shape_homogenization_adjoint_term( {
…}
646 void AdjointTools::dJ_periodic_shape_adjoint_term(
649 const Eigen::VectorXd &periodic_mesh_representation,
650 const Eigen::MatrixXd &sol,
651 const Eigen::MatrixXd &adjoint,
652 Eigen::VectorXd &one_form)
654 std::shared_ptr<NLHomoProblem> homo_problem = std::dynamic_pointer_cast<NLHomoProblem>(state.
solve_data.
nl_problem);
655 assert(homo_problem);
657 const Eigen::MatrixXd reduced_sol = homo_problem->full_to_reduced(sol, state.
diff_cached.
disp_grad());
658 const Eigen::VectorXd extended_sol = homo_problem->reduced_to_extended(reduced_sol);
660 const Eigen::VectorXd extended_adjoint = homo_problem->reduced_to_extended(adjoint,
true);
661 const Eigen::MatrixXd affine_adjoint = homo_problem->reduced_to_disp_grad(adjoint,
true);
662 const Eigen::VectorXd full_adjoint = homo_problem->NLProblem::reduced_to_full(adjoint.topRows(homo_problem->reduced_size())) + io::Evaluator::generate_linear_field(state.
n_bases, state.
mesh_nodes, affine_adjoint);
664 const int dim = state.
mesh->dimension();
669 homo_problem->set_project_to_psd(
false);
670 homo_problem->FullNLProblem::hessian(sol, hessian);
671 Eigen::VectorXd partial_term = full_adjoint.transpose() * hessian;
673 one_form -= utils::flatten(utils::unflatten(partial_term, dim)(state.
primitive_to_node(), Eigen::all));
675 one_form = periodic_mesh_map.
apply_jacobian(one_form, periodic_mesh_representation);
679 Eigen::VectorXd contact_term;
682 one_form -= contact_term;
646 void AdjointTools::dJ_periodic_shape_adjoint_term( {
…}
686 void AdjointTools::dJ_shape_transient_adjoint_term(
688 const Eigen::MatrixXd &adjoint_nu,
689 const Eigen::MatrixXd &adjoint_p,
690 Eigen::VectorXd &one_form)
692 const double t0 = state.
args[
"time"][
"t0"];
693 const double dt = state.
args[
"time"][
"dt"];
694 const int time_steps = state.
args[
"time"][
"time_steps"];
695 const int bdf_order = get_bdf_order(state);
697 Eigen::VectorXd elasticity_term, rhs_term, pressure_term, damping_term, mass_term, contact_term, friction_term, adhesion_term, tangential_adhesion_term;
700 Eigen::VectorXd cur_p, cur_nu;
701 for (
int i = time_steps; i > 0; --i)
703 const int real_order = std::min(bdf_order, i);
704 double beta = time_integrator::BDF::betas(real_order - 1);
705 double beta_dt = beta * dt;
706 const double t = i * dt + t0;
710 cur_p = adjoint_p.col(i);
711 cur_nu = adjoint_nu.col(i);
725 damping_term.setZero(mass_term.size());
734 contact_term.setZero(mass_term.size());
743 friction_term.setZero(mass_term.size());
752 adhesion_term.setZero(mass_term.size());
762 tangential_adhesion_term.setZero(mass_term.size());
765 one_form += beta_dt * (elasticity_term + rhs_term + pressure_term + damping_term + contact_term + friction_term + mass_term + adhesion_term + tangential_adhesion_term);
769 Eigen::VectorXd sum_alpha_p;
771 sum_alpha_p.setZero(adjoint_p.rows());
772 int num = std::min(bdf_order, time_steps);
773 for (
int j = 0; j < num; ++j)
775 int order = std::min(bdf_order - 1, j);
776 sum_alpha_p -= time_integrator::BDF::alphas(order)[j] * adjoint_p.col(j + 1);
782 one_form += mass_term;
784 one_form = utils::flatten(utils::unflatten(one_form, state.
mesh->dimension())(state.
primitive_to_node(), Eigen::all));
686 void AdjointTools::dJ_shape_transient_adjoint_term( {
…}
787 void AdjointTools::dJ_material_static_adjoint_term(
789 const Eigen::MatrixXd &sol,
790 const Eigen::MatrixXd &adjoint,
791 Eigen::VectorXd &one_form)
793 Eigen::MatrixXd adjoint_zeroed = adjoint;
787 void AdjointTools::dJ_material_static_adjoint_term( {
…}
798 void AdjointTools::dJ_material_transient_adjoint_term(
800 const Eigen::MatrixXd &adjoint_nu,
801 const Eigen::MatrixXd &adjoint_p,
802 Eigen::VectorXd &one_form)
804 const double t0 = state.
args[
"time"][
"t0"];
805 const double dt = state.
args[
"time"][
"dt"];
806 const int time_steps = state.
args[
"time"][
"time_steps"];
807 const int bdf_order = get_bdf_order(state);
809 one_form.setZero(state.
bases.size() * 2);
811 auto storage = utils::create_thread_storage(LocalThreadVecStorage(one_form.size()));
813 utils::maybe_parallel_for(time_steps, [&](
int start,
int end,
int thread_id) {
814 LocalThreadVecStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
815 Eigen::VectorXd elasticity_term;
816 for (
int i_aux = start; i_aux < end; ++i_aux)
818 const int i = time_steps - i_aux;
819 const int real_order = std::min(bdf_order, i);
820 double beta_dt = time_integrator::BDF::betas(real_order - 1) * dt;
822 Eigen::VectorXd cur_p = adjoint_p.col(i);
826 local_storage.vec += beta_dt * elasticity_term;
830 for (
const LocalThreadVecStorage &local_storage : storage)
831 one_form += local_storage.vec;
798 void AdjointTools::dJ_material_transient_adjoint_term( {
…}
834 void AdjointTools::dJ_friction_transient_adjoint_term(
836 const Eigen::MatrixXd &adjoint_nu,
837 const Eigen::MatrixXd &adjoint_p,
838 Eigen::VectorXd &one_form)
840 const double dt = state.
args[
"time"][
"dt"];
842 const int time_steps = state.
args[
"time"][
"time_steps"];
843 const int dim = state.
mesh->dimension();
844 const int bdf_order = get_bdf_order(state);
848 std::shared_ptr<time_integrator::ImplicitTimeIntegrator> time_integrator =
849 time_integrator::ImplicitTimeIntegrator::construct_time_integrator(state.
args[
"time"][
"integrator"]);
851 Eigen::MatrixXd solution, velocity, acceleration;
857 const double dt = state.
args[
"time"][
"dt"];
858 time_integrator->init(solution, velocity, acceleration, dt);
861 for (
int t = 1; t <= time_steps; ++t)
863 const int real_order = std::min(bdf_order, t);
864 double beta = time_integrator::BDF::betas(real_order - 1);
866 const Eigen::MatrixXd surface_solution_prev = state.
collision_mesh.vertices(utils::unflatten(state.
diff_cached.
u(t - 1), dim));
870 time_integrator->update_quantities(state.
diff_cached.
u(t));
877 surface_solution_prev,
883 Eigen::VectorXd cur_p = adjoint_p.col(t);
886 one_form(0) += dot(cur_p, force) * beta * dt;
834 void AdjointTools::dJ_friction_transient_adjoint_term( {
…}
890 void AdjointTools::dJ_damping_transient_adjoint_term(
892 const Eigen::MatrixXd &adjoint_nu,
893 const Eigen::MatrixXd &adjoint_p,
894 Eigen::VectorXd &one_form)
896 const double t0 = state.
args[
"time"][
"t0"];
897 const double dt = state.
args[
"time"][
"dt"];
898 const int time_steps = state.
args[
"time"][
"time_steps"];
899 const int bdf_order = get_bdf_order(state);
903 auto storage = utils::create_thread_storage(LocalThreadVecStorage(one_form.size()));
905 utils::maybe_parallel_for(time_steps, [&](
int start,
int end,
int thread_id) {
906 LocalThreadVecStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
907 Eigen::VectorXd damping_term;
908 for (
int t_aux = start; t_aux < end; ++t_aux)
910 const int t = time_steps - t_aux;
911 const int real_order = std::min(bdf_order, t);
912 const double beta = time_integrator::BDF::betas(real_order - 1);
914 Eigen::VectorXd cur_p = adjoint_p.col(t);
918 local_storage.vec += (beta * dt) * damping_term;
922 for (
const LocalThreadVecStorage &local_storage : storage)
923 one_form += local_storage.vec;
890 void AdjointTools::dJ_damping_transient_adjoint_term( {
…}
926 void AdjointTools::dJ_initial_condition_adjoint_term(
928 const Eigen::MatrixXd &adjoint_nu,
929 const Eigen::MatrixXd &adjoint_p,
930 Eigen::VectorXd &one_form)
932 const int ndof = state.
ndof();
933 one_form.setZero(ndof * 2);
936 one_form.segment(0, ndof) = -adjoint_nu.col(0);
937 one_form.segment(ndof, ndof) = -adjoint_p.col(0);
942 one_form(ndof + b) = 0;
926 void AdjointTools::dJ_initial_condition_adjoint_term( {
…}
946 void AdjointTools::dJ_dirichlet_static_adjoint_term(
948 const Eigen::MatrixXd &adjoint,
949 Eigen::VectorXd &one_form)
954 gradd_h.prune([&boundary_nodes_set](
const Eigen::Index &row,
const Eigen::Index &col,
const FullNLProblem::Scalar &value) {
957 if (boundary_nodes_set.find(row) == boundary_nodes_set.end())
961 one_form.setZero(state.
ndof());
964 one_form = utils::flatten(utils::unflatten(one_form, state.
mesh->dimension())(state.
primitive_to_node(), Eigen::all));
946 void AdjointTools::dJ_dirichlet_static_adjoint_term( {
…}
967 void AdjointTools::dJ_dirichlet_transient_adjoint_term(
969 const Eigen::MatrixXd &adjoint_nu,
970 const Eigen::MatrixXd &adjoint_p,
971 Eigen::VectorXd &one_form)
973 const double dt = state.
args[
"time"][
"dt"];
974 const int time_steps = state.
args[
"time"][
"time_steps"];
975 const int bdf_order = get_bdf_order(state);
980 one_form.setZero(time_steps * n_dirichlet_dof);
981 for (
int i = 1; i <= time_steps; ++i)
983 const int real_order = std::min(bdf_order, i);
984 const double beta_dt = time_integrator::BDF::betas(real_order - 1) * dt;
986 one_form.segment((i - 1) * n_dirichlet_dof, n_dirichlet_dof) = -(1. / beta_dt) * adjoint_p(state.
boundary_nodes, i);
967 void AdjointTools::dJ_dirichlet_transient_adjoint_term( {
…}
990 void AdjointTools::dJ_pressure_static_adjoint_term(
992 const std::vector<int> &boundary_ids,
993 const Eigen::MatrixXd &sol,
994 const Eigen::MatrixXd &adjoint,
995 Eigen::VectorXd &one_form)
997 const int n_pressure_dof = boundary_ids.size();
999 one_form.setZero(n_pressure_dof);
1001 for (
int i = 0; i < boundary_ids.size(); ++i)
1009 one_form(i) = pressure_term;
990 void AdjointTools::dJ_pressure_static_adjoint_term( {
…}
1013 void AdjointTools::dJ_pressure_transient_adjoint_term(
1015 const std::vector<int> &boundary_ids,
1016 const Eigen::MatrixXd &adjoint_nu,
1017 const Eigen::MatrixXd &adjoint_p,
1018 Eigen::VectorXd &one_form)
1020 const double t0 = state.
args[
"time"][
"t0"];
1021 const double dt = state.
args[
"time"][
"dt"];
1022 const int time_steps = state.
args[
"time"][
"time_steps"];
1023 const int bdf_order = get_bdf_order(state);
1025 const int n_pressure_dof = boundary_ids.size();
1027 one_form.setZero(time_steps * n_pressure_dof);
1028 Eigen::VectorXd cur_p, cur_nu;
1029 for (
int i = time_steps; i > 0; --i)
1031 const int real_order = std::min(bdf_order, i);
1032 double beta = time_integrator::BDF::betas(real_order - 1);
1033 double beta_dt = beta * dt;
1034 const double t = i * dt + t0;
1036 cur_p = adjoint_p.col(i);
1037 cur_nu = adjoint_nu.col(i);
1041 for (
int b = 0; b < boundary_ids.size(); ++b)
1049 one_form((i - 1) * n_pressure_dof + b) = -beta_dt * pressure_term;
1013 void AdjointTools::dJ_pressure_transient_adjoint_term( {
…}
1054 void AdjointTools::dJ_du_step(
1057 const Eigen::MatrixXd &solution,
1058 const std::set<int> &interested_ids,
1061 Eigen::VectorXd &term)
1063 const auto &bases = state.
bases;
1066 const int dim = state.
mesh->dimension();
1067 const int actual_dim = state.
problem->is_scalar() ? 1 : dim;
1068 const int n_elements = int(bases.size());
1069 const double t0 = state.
problem->is_time_dependent() ? state.
args[
"time"][
"t0"].get<
double>() : 0.0;
1070 const double dt = state.
problem->is_time_dependent() ? state.
args[
"time"][
"dt"].get<
double>() : 0.0;
1072 term = Eigen::MatrixXd::Zero(state.
n_bases * actual_dim, 1);
1077 if (spatial_integral_type == SpatialIntegralType::Volume)
1079 auto storage = utils::create_thread_storage(LocalThreadVecStorage(term.size()));
1080 utils::maybe_parallel_for(n_elements, [&](
int start,
int end,
int thread_id) {
1081 LocalThreadVecStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
1083 Eigen::MatrixXd u, grad_u;
1084 Eigen::MatrixXd lambda, mu;
1085 Eigen::MatrixXd dj_du, dj_dgradu, dj_dgradx;
1088 params.
t = dt * cur_step + t0;
1089 params.
step = cur_step;
1091 for (
int e = start; e < end; ++e)
1093 if (interested_ids.size() != 0 && interested_ids.find(state.
mesh->get_body_id(e)) == interested_ids.end())
1104 const int n_loc_bases_ = int(
vals.basis_values.size());
1106 io::Evaluator::interpolate_at_local_vals(e, dim, actual_dim,
vals, solution, u, grad_u);
1111 dj_dgradu.resize(0, 0);
1115 for (
int q = 0; q < dj_dgradu.rows(); q++)
1116 dj_dgradu.row(q) *= local_storage.da(q);
1123 for (
int q = 0; q < dj_du.rows(); q++)
1124 dj_du.row(q) *= local_storage.da(q);
1127 for (
int i = 0; i < n_loc_bases_; ++i)
1130 assert(v.
global.size() == 1);
1131 for (
int d = 0; d < actual_dim; d++)
1138 for (
int q = 0; q < local_storage.da.size(); ++q)
1139 val += dot(dj_dgradu.block(q, d * dim, 1, dim), v.
grad_t_m.row(q));
1145 for (
int q = 0; q < local_storage.da.size(); ++q)
1146 val += dj_du(q, d) * v.
val(q);
1148 local_storage.vec(v.
global[0].index * actual_dim + d) +=
val;
1153 for (
const LocalThreadVecStorage &local_storage : storage)
1154 term += local_storage.vec;
1156 else if (spatial_integral_type == SpatialIntegralType::Surface)
1158 auto storage = utils::create_thread_storage(LocalThreadVecStorage(term.size()));
1159 utils::maybe_parallel_for(state.
total_local_boundary.size(), [&](
int start,
int end,
int thread_id) {
1160 LocalThreadVecStorage &local_storage = utils::get_local_thread_storage(storage, thread_id);
1162 Eigen::MatrixXd uv, samples, gtmp;
1163 Eigen::MatrixXd points, normal;
1164 Eigen::VectorXd weights;
1166 Eigen::MatrixXd u, grad_u;
1167 Eigen::MatrixXd lambda, mu;
1168 Eigen::MatrixXd dj_du, dj_dgradu, dj_dgradu_local;
1170 IntegrableFunctional::ParameterType params;
1171 params.t = dt * cur_step + t0;
1172 params.step = cur_step;
1174 for (int lb_id = start; lb_id < end; ++lb_id)
1176 const auto &lb = state.total_local_boundary[lb_id];
1177 const int e = lb.element_id();
1179 for (int i = 0; i < lb.size(); i++)
1181 const int global_primitive_id = lb.global_primitive_id(i);
1182 if (interested_ids.size() != 0 && interested_ids.find(state.mesh->get_boundary_id(global_primitive_id)) == interested_ids.end())
1185 utils::BoundarySampler::boundary_quadrature(lb, state.n_boundary_samples(), *state.mesh, i, false, uv, points, normal, weights);
1187 assembler::ElementAssemblyValues &vals = local_storage.vals;
1188 vals.compute(e, state.mesh->is_volume(), points, bases[e], gbases[e]);
1189 io::Evaluator::interpolate_at_local_vals(e, dim, actual_dim, vals, solution, u, grad_u);
1191 const Eigen::MatrixXd lame_params = extract_lame_params(state.assembler->parameters(), e, params.t, points, vals.val);
1195 const int n_loc_bases_ = int(vals.basis_values.size());
1198 params.body_id = state.mesh->get_body_id(e);
1199 params.boundary_id = state.mesh->get_boundary_id(global_primitive_id);
1201 dj_dgradu.resize(0, 0);
1202 if (j.depend_on_gradu())
1204 j.dj_dgradu(lame_params, points, vals.val, u, grad_u, normal, vals, params, dj_dgradu);
1205 for (int q = 0; q < dj_dgradu.rows(); q++)
1206 dj_dgradu.row(q) *= weights(q);
1209 dj_dgradu_local.resize(0, 0);
1210 if (j.depend_on_gradu_local())
1212 j.dj_dgradu_local(lame_params, points, vals.val, u, grad_u, normal, vals, params, dj_dgradu_local);
1213 for (int q = 0; q < dj_dgradu_local.rows(); q++)
1214 dj_dgradu_local.row(q) *= weights(q);
1218 if (j.depend_on_u())
1220 j.dj_du(lame_params, points, vals.val, u, grad_u, normal, vals, params, dj_du);
1221 for (int q = 0; q < dj_du.rows(); q++)
1222 dj_du.row(q) *= weights(q);
1225 for (int l = 0; l < lb.size(); ++l)
1227 const auto nodes = bases[e].local_nodes_for_primitive(lb.global_primitive_id(l), *state.mesh);
1229 for (long n = 0; n < nodes.size(); ++n)
1231 const assembler::AssemblyValues &v = vals.basis_values[nodes(n)];
1232 assert(v.global.size() == 1);
1233 for (int d = 0; d < actual_dim; d++)
1238 if (j.depend_on_gradu())
1240 for (int q = 0; q < weights.size(); ++q)
1241 val += dot(dj_dgradu.block(q, d * dim, 1, dim), v.grad_t_m.row(q));
1244 if (j.depend_on_gradu_local())
1246 for (int q = 0; q < weights.size(); ++q)
1247 val += dot(dj_dgradu_local.block(q, d * dim, 1, dim), v.grad.row(q));
1250 if (j.depend_on_u())
1252 for (int q = 0; q < weights.size(); ++q)
1253 val += dj_du(q, d) * v.val(q);
1255 local_storage.vec(v.global[0].index * actual_dim + d) += val;
1262 for (
const LocalThreadVecStorage &local_storage : storage)
1263 term += local_storage.vec;
1265 else if (spatial_integral_type == SpatialIntegralType::VertexSum)
1267 std::vector<bool> traversed(state.
n_bases,
false);
1269 params.
t = dt * cur_step + t0;
1270 params.
step = cur_step;
1271 for (
int e = 0; e < bases.size(); e++)
1273 const auto &bs = bases[e];
1274 for (
int i = 0; i < bs.bases.size(); i++)
1276 const auto &b = bs.bases[i];
1277 assert(b.global().size() == 1);
1278 const auto &g = b.global()[0];
1279 if (traversed[g.index])
1282 const Eigen::MatrixXd lame_params = extract_lame_params(state.
assembler->parameters(), e, params.
t, Eigen::MatrixXd::Zero(1, dim) , g.node);
1284 params.
node = g.index;
1287 Eigen::MatrixXd
val;
1288 j.dj_du(lame_params, Eigen::MatrixXd::Zero(1, dim) , g.node, solution.block(g.index * dim, 0, dim, 1).transpose(), Eigen::MatrixXd::Zero(1, dim * actual_dim) , Eigen::MatrixXd::Zero(0, 0) ,
assembler::ElementAssemblyValues(), params,
val);
1289 term.block(g.index * actual_dim, 0, actual_dim, 1) +=
val.transpose();
1290 traversed[g.index] =
true;
1054 void AdjointTools::dJ_du_step( {
…}
1296 Eigen::VectorXd AdjointTools::map_primitive_to_node_order(
const State &state,
const Eigen::VectorXd &primitives)
1298 int dim = state.
mesh->dimension();
1299 assert(primitives.size() == (state.
n_geom_bases * dim));
1300 Eigen::VectorXd nodes(primitives.size());
1303 nodes.segment(map[v] * dim, dim) = primitives.segment(v * dim, dim);
1296 Eigen::VectorXd AdjointTools::map_primitive_to_node_order(
const State &state,
const Eigen::VectorXd &primitives) {
…}
1307 Eigen::VectorXd AdjointTools::map_node_to_primitive_order(
const State &state,
const Eigen::VectorXd &nodes)
1309 int dim = state.
mesh->dimension();
1311 Eigen::VectorXd primitives(nodes.size());
1314 primitives.segment(map[v] * dim, dim) = nodes.segment(v * dim, dim);
1307 Eigen::VectorXd AdjointTools::map_node_to_primitive_order(
const State &state,
const Eigen::VectorXd &nodes) {
…}
1318 Eigen::MatrixXd AdjointTools::edge_normal_gradient(
const Eigen::MatrixXd &
V)
1321 Eigen::Matrix<Diff, 4, 1> full_diff(4, 1);
1322 for (
int i = 0; i < 2; i++)
1323 for (
int j = 0; j < 2; j++)
1324 full_diff(i * 2 + j) =
Diff(i * 2 + j,
V(i, j));
1325 auto reduced_diff = edge_normal(full_diff);
1327 Eigen::MatrixXd grad(2, 4);
1328 for (
int i = 0; i < 2; ++i)
1329 grad.row(i) = reduced_diff[i].getGradient();
1318 Eigen::MatrixXd AdjointTools::edge_normal_gradient(
const Eigen::MatrixXd &
V) {
…}
1334 Eigen::MatrixXd AdjointTools::face_normal_gradient(
const Eigen::MatrixXd &
V)
1337 Eigen::Matrix<Diff, 9, 1> full_diff(9, 1);
1338 for (
int i = 0; i < 3; i++)
1339 for (
int j = 0; j < 3; j++)
1340 full_diff(i * 3 + j) =
Diff(i * 3 + j,
V(i, j));
1341 auto reduced_diff = face_normal(full_diff);
1343 Eigen::MatrixXd grad(3, 9);
1344 for (
int i = 0; i < 3; ++i)
1345 grad.row(i) = reduced_diff[i].getGradient();
1334 Eigen::MatrixXd AdjointTools::face_normal_gradient(
const Eigen::MatrixXd &
V) {
…}
1350 Eigen::MatrixXd AdjointTools::edge_velocity_divergence(
const Eigen::MatrixXd &
V)
1352 return line_length_grad(
V) / line_length<double>(
V);
1350 Eigen::MatrixXd AdjointTools::edge_velocity_divergence(
const Eigen::MatrixXd &
V) {
…}
1355 Eigen::MatrixXd AdjointTools::face_velocity_divergence(
const Eigen::MatrixXd &
V)
1357 return triangle_area_grad(
V) / triangle_area<double>(
V);
1355 Eigen::MatrixXd AdjointTools::face_velocity_divergence(
const Eigen::MatrixXd &
V) {
…}
1360 double AdjointTools::triangle_jacobian(
const Eigen::VectorXd &v1,
const Eigen::VectorXd &v2,
const Eigen::VectorXd &v3)
1362 Eigen::VectorXd a = v2 - v1, b = v3 - v1;
1363 return a(0) * b(1) - b(0) * a(1);
1360 double AdjointTools::triangle_jacobian(
const Eigen::VectorXd &v1,
const Eigen::VectorXd &v2,
const Eigen::VectorXd &v3) {
…}
1366 double AdjointTools::tet_determinant(
const Eigen::VectorXd &v1,
const Eigen::VectorXd &v2,
const Eigen::VectorXd &v3,
const Eigen::VectorXd &v4)
1368 Eigen::Matrix3d mat;
1369 mat.col(0) << v2 - v1;
1370 mat.col(1) << v3 - v1;
1371 mat.col(2) << v4 - v1;
1372 return mat.determinant();
1366 double AdjointTools::tet_determinant(
const Eigen::VectorXd &v1,
const Eigen::VectorXd &v2,
const Eigen::VectorXd &v3,
const Eigen::VectorXd &v4) {
…}
1375 void AdjointTools::scaled_jacobian(
const Eigen::MatrixXd &
V,
const Eigen::MatrixXi &F, Eigen::VectorXd &quality)
1377 const int dim = F.cols() - 1;
1379 quality.setZero(F.rows());
1382 for (
int i = 0; i < F.rows(); i++)
1384 Eigen::RowVector3d e0;
1386 e0.head(2) =
V.row(F(i, 2)) -
V.row(F(i, 1));
1387 Eigen::RowVector3d e1;
1389 e1.head(2) =
V.row(F(i, 0)) -
V.row(F(i, 2));
1390 Eigen::RowVector3d e2;
1392 e2.head(2) =
V.row(F(i, 1)) -
V.row(F(i, 0));
1394 double l0 = e0.norm();
1395 double l1 = e1.norm();
1396 double l2 = e2.norm();
1398 double A = 0.5 * (e0.cross(e1)).norm();
1399 double Lmax = std::max(l0 * l1, std::max(l1 * l2, l0 * l2));
1401 quality(i) = 2 * A * (2 / sqrt(3)) / Lmax;
1406 for (
int i = 0; i < F.rows(); i++)
1408 Eigen::RowVector3d e0 =
V.row(F(i, 1)) -
V.row(F(i, 0));
1409 Eigen::RowVector3d e1 =
V.row(F(i, 2)) -
V.row(F(i, 1));
1410 Eigen::RowVector3d e2 =
V.row(F(i, 0)) -
V.row(F(i, 2));
1411 Eigen::RowVector3d e3 =
V.row(F(i, 3)) -
V.row(F(i, 0));
1412 Eigen::RowVector3d e4 =
V.row(F(i, 3)) -
V.row(F(i, 1));
1413 Eigen::RowVector3d e5 =
V.row(F(i, 3)) -
V.row(F(i, 2));
1415 double l0 = e0.norm();
1416 double l1 = e1.norm();
1417 double l2 = e2.norm();
1418 double l3 = e3.norm();
1419 double l4 = e4.norm();
1420 double l5 = e5.norm();
1422 double J = std::abs((e0.cross(e3)).dot(e2));
1424 double a1 = l0 * l2 * l3;
1425 double a2 = l0 * l1 * l4;
1426 double a3 = l1 * l2 * l5;
1427 double a4 = l3 * l4 * l5;
1429 double a = std::max({a1, a2, a3, a4, J});
1430 quality(i) = J * sqrt(2) / a;
1375 void AdjointTools::scaled_jacobian(
const Eigen::MatrixXd &
V,
const Eigen::MatrixXi &F, Eigen::VectorXd &quality) {
…}
1435 bool AdjointTools::is_flipped(
const Eigen::MatrixXd &
V,
const Eigen::MatrixXi &F)
1439 for (
int i = 0; i < F.rows(); i++)
1443 else if (F.cols() == 4)
1445 for (
int i = 0; i < F.rows(); i++)
1435 bool AdjointTools::is_flipped(
const Eigen::MatrixXd &
V,
const Eigen::MatrixXi &F) {
…}
ElementAssemblyValues vals
assembler::ElementAssemblyValues gvals
bool depend_on_gradu_local() const
void dj_du(const Eigen::MatrixXd &elastic_params, const Eigen::MatrixXd &local_pts, const Eigen::MatrixXd &pts, const Eigen::MatrixXd &u, const Eigen::MatrixXd &grad_u, const Eigen::MatrixXd &reference_normals, const assembler::ElementAssemblyValues &vals, ParameterType ¶ms, Eigen::MatrixXd &val) const
bool depend_on_gradu() const
void dj_dgradu(const Eigen::MatrixXd &elastic_params, const Eigen::MatrixXd &local_pts, const Eigen::MatrixXd &pts, const Eigen::MatrixXd &u, const Eigen::MatrixXd &grad_u, const Eigen::MatrixXd &reference_normals, const assembler::ElementAssemblyValues &vals, ParameterType ¶ms, Eigen::MatrixXd &val) const
void evaluate(const Eigen::MatrixXd &elastic_params, const Eigen::MatrixXd &local_pts, const Eigen::MatrixXd &pts, const Eigen::MatrixXd &u, const Eigen::MatrixXd &grad_u, const Eigen::MatrixXd &reference_normals, const assembler::ElementAssemblyValues &vals, ParameterType ¶ms, Eigen::MatrixXd &val) const
void dj_dx(const Eigen::MatrixXd &elastic_params, const Eigen::MatrixXd &local_pts, const Eigen::MatrixXd &pts, const Eigen::MatrixXd &u, const Eigen::MatrixXd &grad_u, const Eigen::MatrixXd &reference_normals, const assembler::ElementAssemblyValues &vals, ParameterType ¶ms, Eigen::MatrixXd &val) const
main class that contains the polyfem solver and all its state
Eigen::MatrixXd initial_vel_update
int n_bases
number of bases
assembler::AssemblyValsCache ass_vals_cache
used to store assembly values for small problems
bool is_adhesion_enabled() const
does the simulation have adhesion
const std::vector< basis::ElementBases > & geom_bases() const
Get a constant reference to the geometry mapping bases.
std::shared_ptr< assembler::Assembler > assembler
assemblers
ipc::CollisionMesh collision_mesh
IPC collision mesh.
std::shared_ptr< assembler::Mass > mass_matrix_assembler
std::vector< int > primitive_to_node() const
std::unique_ptr< mesh::Mesh > mesh
current mesh, it can be a Mesh2D or Mesh3D
std::shared_ptr< polyfem::mesh::MeshNodes > mesh_nodes
Mapping from input nodes to FE nodes.
std::shared_ptr< assembler::Problem > problem
current problem, it contains rhs and bc
std::vector< int > node_to_primitive() const
json args
main input arguments containing all defaults
solver::DiffCache diff_cached
void initial_velocity(Eigen::MatrixXd &velocity) const
Load or compute the initial velocity.
void initial_acceleration(Eigen::MatrixXd &acceleration) const
Load or compute the initial acceleration.
std::vector< basis::ElementBases > bases
FE bases, the size is #elements.
int n_geom_bases
number of geometric bases
std::vector< mesh::LocalBoundary > total_local_boundary
mapping from elements to nodes for all mesh
assembler::AssemblyValsCache mass_ass_vals_cache
std::vector< int > boundary_nodes
list of boundary nodes
solver::SolveData solve_data
timedependent stuff cached
bool is_contact_enabled() const
does the simulation have contact
StiffnessMatrix basis_nodes_to_gbasis_nodes
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 compute(const int el_index, const bool is_volume, const Eigen::MatrixXd &pts, const basis::ElementBases &basis, const basis::ElementBases &gbasis)
computes the per element values at the local (ref el) points (pts) sets basis_values,...
quadrature::Quadrature quadrature
static void interpolate_at_local_vals(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const int el_index, const Eigen::MatrixXd &local_pts, const Eigen::MatrixXd &fun, Eigen::MatrixXd &result, Eigen::MatrixXd &result_grad)
interpolate solution and gradient at element (calls interpolate_at_local_vals with sol)
const ipc::NormalCollisions & collision_set(int step) const
const StiffnessMatrix & gradu_h(int step) const
const ipc::TangentialCollisions & friction_collision_set(int step) const
Eigen::MatrixXd disp_grad(int step=0) const
const ipc::TangentialCollisions & tangential_adhesion_collision_set(int step) const
const ipc::NormalCollisions & normal_adhesion_collision_set(int step) const
Eigen::VectorXd v(int step) const
Eigen::VectorXd u(int step) const
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override
std::shared_ptr< solver::FrictionForm > friction_form
std::shared_ptr< solver::InertiaForm > inertia_form
std::shared_ptr< solver::PeriodicContactForm > periodic_contact_form
std::shared_ptr< solver::PressureForm > pressure_form
std::shared_ptr< solver::BodyForm > body_form
std::shared_ptr< solver::NLProblem > nl_problem
std::shared_ptr< solver::NormalAdhesionForm > normal_adhesion_form
std::shared_ptr< solver::ContactForm > contact_form
std::shared_ptr< solver::ElasticForm > damping_form
std::shared_ptr< solver::ElasticForm > elastic_form
std::shared_ptr< solver::TangentialAdhesionForm > tangential_adhesion_form
Eigen::Matrix< double, dim, 1 > cross(const Eigen::Matrix< double, dim, 1 > &x, const Eigen::Matrix< double, dim, 1 > &y)
DScalar1< double, Eigen::Matrix< double, Eigen::Dynamic, 1 > > Diff
void vector2matrix(const Eigen::VectorXd &vec, Eigen::MatrixXd &mat)
auto & get_local_thread_storage(Storages &storage, int thread_id)
auto create_thread_storage(const LocalStorage &initial_local_storage)
double triangle_area(const Eigen::MatrixXd V)
Compute the signed area of a triangle defined by three points.
void maybe_parallel_for(int size, const std::function< void(int, int, int)> &partial_for)
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, MAX_QUAD_POINTS, 1 > QuadratureVector
void log_and_throw_adjoint_error(const std::string &msg)
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Automatic differentiation scalar with first-order derivatives.
static void setVariableCount(size_t value)
Set the independent variable count used by the automatic differentiation layer.
Parameters for the functional evaluation.