42 reduced_mat.resize(mat.rows(), mat.cols());
44 std::vector<bool> mask(mat.rows(),
false);
48 std::vector<Eigen::Triplet<double>> coeffs;
49 for (
int k = 0; k < mat.outerSize(); ++k)
51 for (StiffnessMatrix::InnerIterator it(mat, k); it; ++it)
55 if (it.row() == it.col())
56 coeffs.emplace_back(it.row(), it.col(), 1.0);
59 coeffs.emplace_back(it.row(), it.col(), it.value());
62 reduced_mat.setFromTriplets(coeffs.begin(), coeffs.end());
65 void compute_force_jacobian(varform::DifferentiableVarForm &varform,
const Eigen::MatrixXd &sol,
const Eigen::MatrixXd &disp_grad,
StiffnessMatrix &hessian)
67 const solver::SolveData *solve_data = varform.solve_data();
68 assert(solve_data &&
"Optimization varforms must expose solve data");
70 if (varform.get_problem().is_time_dependent())
73 assert(solve_data->nl_problem &&
"Transient differentiation requires an initialized nonlinear problem");
74 solve_data->nl_problem->set_project_to_psd(
false);
75 solve_data->nl_problem->FullNLProblem::solution_changed(sol);
76 solve_data->nl_problem->FullNLProblem::hessian(sol, tmp_hess);
78 replace_rows_by_identity(hessian, tmp_hess, varform.boundary_state().boundary_nodes);
82 if (varform.primary_assembler().is_linear() && !varform.is_contact_enabled() && !varform.is_homogenization())
86 varform.build_stiffness_matrix(stiffness);
87 replace_rows_by_identity(hessian, stiffness, varform.boundary_state().boundary_nodes);
91 assert(solve_data->nl_problem &&
"Nonlinear differentiation requires an initialized nonlinear problem");
92 solve_data->nl_problem->set_project_to_psd(
false);
93 if (varform.is_homogenization())
95 Eigen::VectorXd reduced;
96 std::shared_ptr<solver::NLHomoProblem> homo_problem = std::dynamic_pointer_cast<solver::NLHomoProblem>(solve_data->nl_problem);
97 assert(homo_problem &&
"Homogenization requires NLHomoProblem solve data");
98 reduced = homo_problem->full_to_reduced(sol, disp_grad);
99 solve_data->nl_problem->solution_changed(reduced);
100 solve_data->nl_problem->hessian(reduced, hessian);
105 solve_data->nl_problem->FullNLProblem::solution_changed(sol);
106 solve_data->nl_problem->FullNLProblem::hessian(sol, tmp_hess);
108 replace_rows_by_identity(hessian, tmp_hess, varform.boundary_state().boundary_nodes);
114 StiffnessMatrix compute_basis_nodes_to_gbasis_nodes(
const varform::DifferentiableVarForm &varform)
116 auto &gbases = varform.primary_space().geometry_basis_list();
117 auto &bases = varform.primary_space().basis_list();
119 std::map<std::array<int, 2>,
double> pairs;
120 for (
int e = 0;
e < gbases.size();
e++)
122 auto &gbs = gbases[
e].bases;
123 auto &bs = bases[
e].bases;
126 Eigen::MatrixXd local_pts;
127 int order = bs.front().order();
128 if (varform.get_mesh().is_volume())
130 if (varform.get_mesh().is_simplex(e))
141 if (varform.get_mesh().is_simplex(e))
151 assembler::ElementAssemblyValues
vals;
152 vals.
compute(e, varform.get_mesh().is_volume(), local_pts, gbases[e], gbases[e]);
154 for (
int i = 0; i < bs.size(); i++)
156 for (
int j = 0; j < gbs.size(); j++)
160 std::array<int, 2> index = {{gbs[j].global()[0].index, bs[i].global()[0].index}};
167 int dim = varform.get_mesh().dimension();
168 std::vector<Eigen::Triplet<double>> coeffs;
169 coeffs.reserve(pairs.size() * dim);
170 for (
const auto &iter : pairs)
172 for (
int d = 0; d <
dim; d++)
174 coeffs.emplace_back(iter.first[0] * dim + d, iter.first[1] * dim + d, iter.second);
179 mapping.resize(varform.primary_space().geometry->n_bases * dim, varform.primary_space().n_bases * dim);
180 mapping.setFromTriplets(coeffs.begin(), coeffs.end());
190 u_.setZero(ndof, n_time_steps + 1);
191 disp_grad_.assign(n_time_steps + 1, Eigen::MatrixXd::Zero(dimension, dimension));
195 v_.setZero(ndof, n_time_steps + 1);
196 acc_.setZero(ndof, n_time_steps + 1);
208 const Eigen::MatrixXd &u,
210 const ipc::NormalCollisions &collision_set,
211 const ipc::SmoothCollisions &smooth_collision_set,
212 const ipc::TangentialCollisions &friction_constraint_set,
213 const ipc::NormalCollisions &normal_adhesion_set,
214 const ipc::TangentialCollisions &tangential_adhesion_set,
215 const Eigen::MatrixXd &disp_grad)
232 const int cur_bdf_order,
233 const Eigen::MatrixXd &u,
234 const Eigen::MatrixXd &v,
235 const Eigen::MatrixXd &acc,
238 const ipc::NormalCollisions &collision_set,
239 const ipc::SmoothCollisions &smooth_collision_set,
240 const ipc::TangentialCollisions &friction_collision_set)
244 u_.col(cur_step) =
u;
245 v_.col(cur_step) =
v;
260 const Eigen::MatrixXd &u,
262 const ipc::NormalCollisions &collision_set,
263 const ipc::SmoothCollisions &smooth_collision_set,
264 const ipc::NormalCollisions &normal_adhesion_set,
265 const Eigen::MatrixXd &disp_grad)
267 u_.col(cur_step) =
u;
282 &&
"basis_nodes_to_gbasis_nodes is empty. Expect cache_transient(step==0) to build it first.");
290 const Eigen::MatrixXd &sol,
291 const Eigen::MatrixXd *pressure)
311 ipc::NormalCollisions cur_collision_set;
312 ipc::SmoothCollisions cur_smooth_collision_set;
313 ipc::TangentialCollisions cur_friction_set;
314 ipc::NormalCollisions cur_normal_adhesion_set;
315 ipc::TangentialCollisions cur_tangential_adhesion_set;
320 const auto *solve_data = varform.
solve_data();
321 assert(solve_data &&
"Optimization varforms must expose solve data");
322 if (solve_data->contact_form)
325 cur_collision_set = barrier_contact->collision_set();
327 cur_smooth_collision_set = smooth_contact->collision_set();
329 if (solve_data->friction_form)
330 cur_friction_set = solve_data->friction_form->friction_collision_set();
331 if (solve_data->normal_adhesion_form)
332 cur_normal_adhesion_set = solve_data->normal_adhesion_form->collision_set();
333 if (solve_data->tangential_adhesion_form)
334 cur_tangential_adhesion_set = solve_data->tangential_adhesion_form->tangential_collision_set();
338 if (varform.
get_args()[
"time"][
"quasistatic"].get<
bool>())
344 Eigen::MatrixXd vel,
acc;
349 const auto bdf_integrator =
dynamic_cast<time_integrator::BDF *
>(solve_data->time_integrator.get());
355 vel = euler_integrator->
v_prev();
364 vel = solve_data->time_integrator->compute_velocity(sol);
365 acc = solve_data->time_integrator->compute_acceleration(vel);
ElementAssemblyValues vals
std::vector< StiffnessMatrix > gradu_h_
std::vector< ipc::NormalCollisions > normal_adhesion_collision_set_
std::vector< ipc::TangentialCollisions > friction_collision_set_
const ipc::NormalCollisions & collision_set(int step) const
Eigen::MatrixXd disp_grad(int step=0) const
Eigen::MatrixXd adjoint_mat_
Eigen::VectorXd v(int step) const
StiffnessMatrix basis_nodes_to_gbasis_nodes_
std::vector< Eigen::MatrixXd > disp_grad_
const ipc::TangentialCollisions & friction_collision_set(int step) const
const Eigen::MatrixXd & adjoint_mat() const
void cache_quantities_static(const Eigen::MatrixXd &u, const StiffnessMatrix &gradu_h, const ipc::NormalCollisions &collision_set, const ipc::SmoothCollisions &smooth_collision_set, const ipc::TangentialCollisions &friction_constraint_set, const ipc::NormalCollisions &normal_adhesion_set, const ipc::TangentialCollisions &tangential_adhesion_set, const Eigen::MatrixXd &disp_grad)
Eigen::VectorXd acc(int step) const
void cache_transient(int step, varform::DifferentiableVarForm &varform, const Eigen::MatrixXd &sol, const Eigen::MatrixXd *pressure)
Cache time-dependent adjoint optimization data.
std::vector< ipc::SmoothCollisions > smooth_collision_set_
std::vector< ipc::TangentialCollisions > tangential_adhesion_collision_set_
const StiffnessMatrix & basis_nodes_to_gbasis_nodes() const
Eigen::VectorXi bdf_order_
void cache_quantities_quasistatic(const int cur_step, const Eigen::MatrixXd &u, const StiffnessMatrix &gradu_h, const ipc::NormalCollisions &collision_set, const ipc::SmoothCollisions &smooth_collision_set, const ipc::NormalCollisions &normal_adhesion_set, const Eigen::MatrixXd &disp_grad)
std::vector< ipc::NormalCollisions > collision_set_
const ipc::SmoothCollisions & smooth_collision_set(int step) const
Eigen::VectorXd u(int step) const
void cache_adjoints(const Eigen::MatrixXd &adjoint_mat)
const StiffnessMatrix & gradu_h(int step) const
void init(const int dimension, const int ndof, const int n_time_steps=0)
void cache_quantities_transient(const int cur_step, const int cur_bdf_order, const Eigen::MatrixXd &u, const Eigen::MatrixXd &v, const Eigen::MatrixXd &acc, const StiffnessMatrix &gradu_h, const ipc::NormalCollisions &collision_set, const ipc::SmoothCollisions &smooth_collision_set, const ipc::TangentialCollisions &friction_collision_set)
std::vector< AssemblyValues > basis_values
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,...
virtual bool is_time_dependent() const
int dimension() const
utily for dimension
Backward Differential Formulas.
Eigen::VectorXd weighted_sum_v_prevs() const
Compute the weighted sum of the previous velocities.
Implicit Euler time integrator of a second order ODE (equivently a system of coupled first order ODEs...
const Eigen::VectorXd & v_prev() const
Get the most recent previous velocity value.
void q_nodes_2d(const int q, Eigen::MatrixXd &val)
void p_nodes_2d(const int p, Eigen::MatrixXd &val)
void p_nodes_3d(const int p, Eigen::MatrixXd &val)
void q_nodes_3d(const int q, Eigen::MatrixXd &val)
void log_and_throw_adjoint_error(const std::string &msg)
void log_and_throw_error(const std::string &msg)
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix