23 void scaled_jacobian(
const Eigen::MatrixXd &
V,
const Eigen::MatrixXi &
F, Eigen::VectorXd &quality)
25 const int dim =
F.cols() - 1;
27 quality.setZero(
F.rows());
30 for (
int i = 0; i <
F.rows(); i++)
32 Eigen::RowVector3d e0;
34 e0.head(2) =
V.row(
F(i, 2)) -
V.row(
F(i, 1));
35 Eigen::RowVector3d e1;
37 e1.head(2) =
V.row(
F(i, 0)) -
V.row(
F(i, 2));
38 Eigen::RowVector3d e2;
40 e2.head(2) =
V.row(
F(i, 1)) -
V.row(
F(i, 0));
42 double l0 = e0.norm();
43 double l1 = e1.norm();
44 double l2 = e2.norm();
46 double A = 0.5 * (e0.cross(e1)).
norm();
47 double Lmax = std::max(l0 * l1, std::max(l1 * l2, l0 * l2));
49 quality(i) = 2 * A * (2 / sqrt(3)) / Lmax;
54 for (
int i = 0; i <
F.rows(); i++)
56 Eigen::RowVector3d e0 =
V.row(
F(i, 1)) -
V.row(
F(i, 0));
57 Eigen::RowVector3d e1 =
V.row(
F(i, 2)) -
V.row(
F(i, 1));
58 Eigen::RowVector3d e2 =
V.row(
F(i, 0)) -
V.row(
F(i, 2));
59 Eigen::RowVector3d e3 =
V.row(
F(i, 3)) -
V.row(
F(i, 0));
60 Eigen::RowVector3d e4 =
V.row(
F(i, 3)) -
V.row(
F(i, 1));
61 Eigen::RowVector3d e5 =
V.row(
F(i, 3)) -
V.row(
F(i, 2));
63 double l0 = e0.norm();
64 double l1 = e1.norm();
65 double l2 = e2.norm();
66 double l3 = e3.norm();
67 double l4 = e4.norm();
68 double l5 = e5.norm();
70 double J = std::abs((e0.cross(e3)).dot(e2));
72 double a1 = l0 * l2 * l3;
73 double a2 = l0 * l1 * l4;
74 double a3 = l1 * l2 * l5;
75 double a4 = l3 * l4 * l5;
77 double a = std::max({a1, a2, a3, a4,
J});
78 quality(i) =
J * sqrt(2) / a;
86 const bool is_volume =
varform_->get_mesh().is_volume();
87 double min_jacs = std::numeric_limits<double>::max();
88 for (
size_t e = 0; e <
varform_->primary_space().geometry_basis_list().size(); ++e)
90 if (
varform_->get_mesh().is_polytope(e))
93 const auto &gbasis =
varform_->primary_space().geometry_basis_list()[e];
94 const int n_local_bases = int(gbasis.bases.size());
97 gbasis.compute_quadrature(quad);
99 std::vector<assembler::AssemblyValues> tmp;
101 Eigen::MatrixXd dx = Eigen::MatrixXd::Zero(quad.
points.rows(), quad.
points.cols());
102 Eigen::MatrixXd dy = Eigen::MatrixXd::Zero(quad.
points.rows(), quad.
points.cols());
105 dz = Eigen::MatrixXd::Zero(quad.
points.rows(), quad.
points.cols());
107 gbasis.evaluate_grads(quad.
points, tmp);
109 for (
int j = 0; j < n_local_bases; ++j)
113 for (std::size_t ii = 0; ii < b.global().size(); ++ii)
115 dx += tmp[j].grad.col(0) * b.global()[ii].node * b.global()[ii].val;
116 dy += tmp[j].grad.col(1) * b.global()[ii].node * b.global()[ii].val;
118 dz += tmp[j].grad.col(2) * b.global()[ii].node * b.global()[ii].val;
122 for (
long i = 0; i < dx.rows(); ++i)
127 tmp << dx.row(i), dy.row(i), dz.row(i);
128 min_jacs = std::min(min_jacs, tmp.determinant());
133 tmp << dx.row(i), dy.row(i);
134 min_jacs = std::min(min_jacs, tmp.determinant());
149 varform_(std::move(varform))
155 use_rest[
"use_rest_pose"] =
true;
176 Eigen::MatrixXd grad;
177 amips_energy_->assemble_gradient(
varform_->get_mesh().is_volume(),
varform_->primary_space().geometry->n_bases,
init_geom_bases_,
init_geom_bases_,
init_ass_vals_cache_, 0, 0,
AdjointTools::map_primitive_to_node_order(*
varform_, X -
X_rest), Eigen::VectorXd(), grad);
static std::shared_ptr< Assembler > make_assembler(const std::string &formulation)
Represents one basis function and its gradient.
Eigen::VectorXd apply_parametrization_jacobian(ParameterType type, const varform::DifferentiableVarForm &target, const Eigen::VectorXd &x, const std::function< Eigen::VectorXd()> &grad) const
Compute parametrization jacobian for all var2sim matching parameter type and output to target varform...
bool scaled_jacobian(Mesh3DStorage &hmi, Mesh_Quality &mq)
bool is_flipped(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F)
Determine if any simplex is inverted or collapses.
Eigen::MatrixXd unflatten(const Eigen::VectorXd &x, int dim)
Unflatten rowwises, so every dim elements in x become a row.
Eigen::VectorXd flatten(const Eigen::MatrixXd &X)
Flatten rowwises.
spdlog::logger & adjoint_logger()
Retrieves the current logger for adjoint.
void log_and_throw_adjoint_error(const std::string &msg)