20 Eigen::Matrix<T, Eigen::Dynamic, 1, 0, 3, 1> compute_displaced_normal(
const Eigen::MatrixXd &reference_normal,
const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> &grad_x,
const Eigen::MatrixXd &grad_u_local)
22 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> trafo = grad_x;
23 for (
int i = 0; i < grad_x.rows(); ++i)
24 for (
int j = 0; j < grad_x.cols(); ++j)
25 trafo(i, j) = trafo(i, j) + grad_u_local(i, j);
27 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> trafo_inv =
inverse(trafo);
29 Eigen::Matrix<T, Eigen::Dynamic, 1, 0, 3, 1> n(reference_normal.cols(), 1);
30 for (
int d = 0; d < n.size(); ++d)
33 for (
int i = 0; i < n.size(); ++i)
34 for (
int j = 0; j < n.size(); ++j)
35 n(j) = n(j) + (reference_normal(i) * trafo_inv(i, j));
41 class QuadraticBarrier :
public ipc::Barrier
44 QuadraticBarrier(
const double weight = 1) :
weight_(weight) {}
46 double operator()(
const double d,
const double dhat)
const override
51 return weight_ * (d - dhat) * (d - dhat);
53 double first_derivative(
const double d,
const double dhat)
const override
58 return 2 *
weight_ * (d - dhat);
60 double second_derivative(
const double d,
const double dhat)
const override
72 void compute_collision_mesh_quantities(
74 const std::set<int> &boundary_ids,
75 const ipc::CollisionMesh &collision_mesh,
76 Eigen::MatrixXd &node_positions,
77 Eigen::MatrixXi &boundary_edges,
78 Eigen::MatrixXi &boundary_triangles,
79 Eigen::SparseMatrix<double> &displacement_map,
80 std::vector<bool> &is_on_surface,
81 Eigen::MatrixXi &can_collide_cache)
83 std::vector<Eigen::Triplet<double>> displacement_map_entries;
85 node_positions, boundary_edges, boundary_triangles, displacement_map_entries);
87 is_on_surface.resize(node_positions.rows(),
false);
89 std::map<int, std::set<int>> boundary_ids_to_dof;
91 Eigen::MatrixXd
points, uv, normals;
92 Eigen::VectorXd weights;
93 Eigen::VectorXi global_primitive_ids;
96 const int e = lb.element_id();
107 for (
int i = 0; i < lb.size(); ++i)
109 const int primitive_global_id = lb.global_primitive_id(i);
111 const int boundary_id = state.
mesh->get_boundary_id(primitive_global_id);
113 if (!std::count(boundary_ids.begin(), boundary_ids.end(), boundary_id))
116 for (
long n = 0; n <
nodes.size(); ++n)
119 is_on_surface[v.
global[0].index] =
true;
120 if (v.
global[0].index >= node_positions.rows())
122 boundary_ids_to_dof[boundary_id].insert(v.
global[0].index);
127 if (!displacement_map_entries.empty())
129 displacement_map.resize(node_positions.rows(), state.
n_bases);
130 displacement_map.setFromTriplets(displacement_map_entries.begin(), displacement_map_entries.end());
134 Eigen::MatrixXi boundary_edges_alt(0, 2), boundary_triangles_alt(0, 3);
136 for (
int i = 0; i < boundary_edges.rows(); ++i)
138 bool on_surface =
true;
139 for (
int j = 0; j < boundary_edges.cols(); ++j)
140 on_surface &= is_on_surface[boundary_edges(i, j)];
143 boundary_edges_alt.conservativeResize(boundary_edges_alt.rows() + 1, 2);
144 boundary_edges_alt.row(boundary_edges_alt.rows() - 1) = boundary_edges.row(i);
148 if (state.
mesh->is_volume())
150 for (
int i = 0; i < boundary_triangles.rows(); ++i)
152 bool on_surface =
true;
153 for (
int j = 0; j < boundary_triangles.cols(); ++j)
154 on_surface &= is_on_surface[boundary_triangles(i, j)];
157 boundary_triangles_alt.conservativeResize(boundary_triangles_alt.rows() + 1, 3);
158 boundary_triangles_alt.row(boundary_triangles_alt.rows() - 1) = boundary_triangles.row(i);
163 boundary_triangles_alt.resize(0, 0);
165 boundary_edges = boundary_edges_alt;
166 boundary_triangles = boundary_triangles_alt;
168 can_collide_cache.resize(0, 0);
169 can_collide_cache.resize(collision_mesh.num_vertices(), collision_mesh.num_vertices());
170 for (
int i = 0; i < can_collide_cache.rows(); ++i)
172 int dof_idx_i = collision_mesh.to_full_vertex_id(i);
173 if (!is_on_surface[dof_idx_i])
175 for (
int j = 0; j < can_collide_cache.cols(); ++j)
177 int dof_idx_j = collision_mesh.to_full_vertex_id(j);
178 if (!is_on_surface[dof_idx_j])
181 bool collision_allowed =
true;
182 for (
const auto &
id : boundary_ids)
183 if (boundary_ids_to_dof[id].count(dof_idx_i) && boundary_ids_to_dof[id].count(dof_idx_j))
184 collision_allowed = false;
185 can_collide_cache(i, j) = collision_allowed;
190 double compute_quantity(
191 const Eigen::MatrixXd &node_positions,
192 const Eigen::MatrixXi &boundary_edges,
193 const Eigen::MatrixXi &boundary_triangles,
194 const Eigen::SparseMatrix<double> &displacement_map,
195 const std::vector<bool> &is_on_surface,
196 const Eigen::MatrixXi &can_collide_cache,
199 std::function<ipc::Collisions(
const Eigen::MatrixXd &)> cs_func,
200 const Eigen::MatrixXd &u,
201 const ipc::BarrierPotential &barrier_potential)
204 static int count = 0;
205 std::cout <<
"computing " << ((double)count / 2) / u.size() * 100. << std::endl;
207 ipc::CollisionMesh collision_mesh = ipc::CollisionMesh(is_on_surface,
213 collision_mesh.can_collide = [&can_collide_cache](
size_t vi,
size_t vj) {
215 return (
bool)can_collide_cache(vi, vj);
218 collision_mesh.init_area_jacobians();
220 Eigen::MatrixXd displaced_surface = collision_mesh.displace_vertices(
utils::unflatten(u, collision_mesh.dim()));
222 ipc::Collisions cs_ = cs_func(displaced_surface);
223 cs_.build(collision_mesh, displaced_surface, dhat, dmin, ipc::BroadPhaseMethod::HASH_GRID);
225 Eigen::MatrixXd forces = collision_mesh.to_full_dof(barrier_potential.gradient(cs_, collision_mesh, displaced_surface));
227 double sum = (forces.array() * forces.array()).sum();
790 const bool quadratic_potential,
796 barrier_potential_(dhat)
798 auto tmp_ids = args[
"surface_selection"].get<std::vector<int>>();
805 if (state.
problem->is_time_dependent())
807 int time_steps = state.
args[
"time"][
"time_steps"].get<
int>() + 1;
809 for (
int i = 0; i < time_steps + 1; ++i)
824 if (quadratic_potential)
835 Eigen::MatrixXi boundary_edges, boundary_triangles;
836 std::vector<Eigen::Triplet<double>> displacement_map_entries;
838 node_positions_, boundary_edges, boundary_triangles, displacement_map_entries);
840 std::vector<bool> is_on_surface;
844 Eigen::MatrixXd points, uv, normals;
845 Eigen::VectorXd weights;
846 Eigen::VectorXi global_primitive_ids;
849 const int e = lb.element_id();
860 for (
int i = 0; i < lb.size(); ++i)
862 const int primitive_global_id = lb.global_primitive_id(i);
864 const int boundary_id =
state_.
mesh->get_boundary_id(primitive_global_id);
869 for (
long n = 0; n < nodes.size(); ++n)
872 is_on_surface[v.
global[0].index] =
true;
880 Eigen::SparseMatrix<double> displacement_map;
881 if (!displacement_map_entries.empty())
884 displacement_map.setFromTriplets(displacement_map_entries.begin(), displacement_map_entries.end());
888 Eigen::MatrixXi boundary_edges_alt(0, 2), boundary_triangles_alt(0, 3);
890 for (
int i = 0; i < boundary_edges.rows(); ++i)
892 bool on_surface =
true;
893 for (
int j = 0; j < boundary_edges.cols(); ++j)
894 on_surface &= is_on_surface[boundary_edges(i, j)];
897 boundary_edges_alt.conservativeResize(boundary_edges_alt.rows() + 1, 2);
898 boundary_edges_alt.row(boundary_edges_alt.rows() - 1) = boundary_edges.row(i);
904 for (
int i = 0; i < boundary_triangles.rows(); ++i)
906 bool on_surface =
true;
907 for (
int j = 0; j < boundary_triangles.cols(); ++j)
908 on_surface &= is_on_surface[boundary_triangles(i, j)];
911 boundary_triangles_alt.conservativeResize(boundary_triangles_alt.rows() + 1, 3);
912 boundary_triangles_alt.row(boundary_triangles_alt.rows() - 1) = boundary_triangles.row(i);
917 boundary_triangles_alt.resize(0, 0);
923 boundary_triangles_alt,
930 if (!is_on_surface[dof_idx_i])
935 if (!is_on_surface[dof_idx_j])
938 bool collision_allowed =
true;
941 collision_allowed =
false;
975 double sum = (forces.array() * forces.array()).sum();
991 Eigen::VectorXd gradu = 2 * hessian.transpose() * forces;
1030 Eigen::VectorXd grads = 2 * shape_derivative.transpose() * forces;
ElementAssemblyValues vals
main class that contains the polyfem solver and all its state
int n_bases
number of bases
int n_boundary_samples() const
quadrature used for projecting boundary conditions
const std::vector< basis::ElementBases > & geom_bases() const
Get a constant reference to the geometry mapping bases.
std::unique_ptr< mesh::Mesh > mesh
current mesh, it can be a Mesh2D or Mesh3D
std::shared_ptr< assembler::Problem > problem
current problem, it contains rhs and bc
json args
main input arguments containing all defaults
solver::DiffCache diff_cached
std::vector< basis::ElementBases > bases
FE bases, the size is #elements.
std::vector< mesh::LocalBoundary > total_local_boundary
mapping from elements to nodes for all mesh
solver::SolveData solve_data
timedependent stuff cached
StiffnessMatrix basis_nodes_to_gbasis_nodes
stores per local bases evaluations
std::vector< basis::Local2Global > global
stores per element basis values at given quadrature points and geometric mapping
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,...
Stores the basis functions for a given element in a mesh (facet in 2d, cell in 3d).
Eigen::VectorXi local_nodes_for_primitive(const int local_index, const mesh::Mesh &mesh) const
static void extract_boundary_mesh(const mesh::Mesh &mesh, const int n_bases, const std::vector< basis::ElementBases > &bases, const std::vector< mesh::LocalBoundary > &total_local_boundary, Eigen::MatrixXd &node_positions, Eigen::MatrixXi &boundary_edges, Eigen::MatrixXi &boundary_triangles, std::vector< Eigen::Triplet< double > > &displacement_map_entries)
extracts the boundary mesh
Eigen::VectorXd u(int step) const
std::shared_ptr< solver::ContactForm > contact_form
std::shared_ptr< time_integrator::ImplicitTimeIntegrator > time_integrator
A collection of VariableToSimulation.
virtual Eigen::VectorXd apply_parametrization_jacobian(const ParameterType type, const State *state_ptr, const Eigen::VectorXd &x, const std::function< Eigen::VectorXd()> &grad) const
Maps the partial gradient wrt.
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)
DScalar1< double, Eigen::Matrix< double, Eigen::Dynamic, 1 > > Diff
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > inverse(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > &mat)
Eigen::MatrixXd unflatten(const Eigen::VectorXd &x, int dim)
Unflatten rowwises, so every dim elements in x become a row.
void log_and_throw_adjoint_error(const std::string &msg)
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Automatic differentiation scalar with first-order derivatives.