18 double triangle_jacobian(
const Eigen::VectorXd &v1,
const Eigen::VectorXd &v2,
const Eigen::VectorXd &v3)
20 Eigen::VectorXd a = v2 - v1, b = v3 - v1;
21 return a(0) * b(1) - b(0) * a(1);
24 double tet_determinant(
const Eigen::VectorXd &v1,
const Eigen::VectorXd &v2,
const Eigen::VectorXd &v3,
const Eigen::VectorXd &v4)
27 mat.col(0) << v2 - v1;
28 mat.col(1) << v3 - v1;
29 mat.col(2) << v4 - v1;
30 return mat.determinant();
33 void scaled_jacobian(
const Eigen::MatrixXd &
V,
const Eigen::MatrixXi &
F, Eigen::VectorXd &quality)
35 const int dim =
F.cols() - 1;
37 quality.setZero(
F.rows());
40 for (
int i = 0; i <
F.rows(); i++)
42 Eigen::RowVector3d e0;
44 e0.head(2) =
V.row(
F(i, 2)) -
V.row(
F(i, 1));
45 Eigen::RowVector3d e1;
47 e1.head(2) =
V.row(
F(i, 0)) -
V.row(
F(i, 2));
48 Eigen::RowVector3d e2;
50 e2.head(2) =
V.row(
F(i, 1)) -
V.row(
F(i, 0));
52 double l0 = e0.norm();
53 double l1 = e1.norm();
54 double l2 = e2.norm();
56 double A = 0.5 * (e0.cross(e1)).
norm();
57 double Lmax = std::max(l0 * l1, std::max(l1 * l2, l0 * l2));
59 quality(i) = 2 * A * (2 / sqrt(3)) / Lmax;
64 for (
int i = 0; i <
F.rows(); i++)
66 Eigen::RowVector3d e0 =
V.row(
F(i, 1)) -
V.row(
F(i, 0));
67 Eigen::RowVector3d e1 =
V.row(
F(i, 2)) -
V.row(
F(i, 1));
68 Eigen::RowVector3d e2 =
V.row(
F(i, 0)) -
V.row(
F(i, 2));
69 Eigen::RowVector3d e3 =
V.row(
F(i, 3)) -
V.row(
F(i, 0));
70 Eigen::RowVector3d e4 =
V.row(
F(i, 3)) -
V.row(
F(i, 1));
71 Eigen::RowVector3d e5 =
V.row(
F(i, 3)) -
V.row(
F(i, 2));
73 double l0 = e0.norm();
74 double l1 = e1.norm();
75 double l2 = e2.norm();
76 double l3 = e3.norm();
77 double l4 = e4.norm();
78 double l5 = e5.norm();
80 double J = std::abs((e0.cross(e3)).dot(e2));
82 double a1 = l0 * l2 * l3;
83 double a2 = l0 * l1 * l4;
84 double a3 = l1 * l2 * l5;
85 double a4 = l3 * l4 * l5;
87 double a = std::max({a1, a2, a3, a4, J});
88 quality(i) = J * sqrt(2) / a;
93 bool is_flipped(
const Eigen::MatrixXd &
V,
const Eigen::MatrixXi &
F)
97 for (
int i = 0; i <
F.rows(); i++)
101 else if (
F.cols() == 4)
103 for (
int i = 0; i <
F.rows(); i++)
118 const bool is_volume =
state_.
mesh->is_volume();
119 double min_jacs = std::numeric_limits<double>::max();
126 const int n_local_bases = int(gbasis.bases.size());
129 gbasis.compute_quadrature(quad);
131 std::vector<assembler::AssemblyValues> tmp;
133 Eigen::MatrixXd dx = Eigen::MatrixXd::Zero(quad.
points.rows(), quad.
points.cols());
134 Eigen::MatrixXd dy = Eigen::MatrixXd::Zero(quad.
points.rows(), quad.
points.cols());
137 dz = Eigen::MatrixXd::Zero(quad.
points.rows(), quad.
points.cols());
139 gbasis.evaluate_grads(quad.
points, tmp);
141 for (
int j = 0; j < n_local_bases; ++j)
145 for (std::size_t ii = 0; ii < b.
global().size(); ++ii)
147 dx += tmp[j].grad.col(0) * b.
global()[ii].node * b.
global()[ii].val;
148 dy += tmp[j].grad.col(1) * b.
global()[ii].node * b.
global()[ii].val;
150 dz += tmp[j].grad.col(2) * b.
global()[ii].node * b.
global()[ii].val;
154 for (
long i = 0; i < dx.rows(); ++i)
159 tmp << dx.row(i), dy.row(i), dz.row(i);
160 min_jacs = std::min(min_jacs, tmp.determinant());
165 tmp << dx.row(i), dy.row(i);
166 min_jacs = std::min(min_jacs, tmp.determinant());
186 json transform_params = {};
187 transform_params[
"canonical_transformation"] = json::array();
188 if (!state.
mesh->is_volume())
190 Eigen::MatrixXd regular_tri(3, 3);
191 regular_tri << 0, 0, 1,
193 1. / 2., std::sqrt(3) / 2., 1;
194 regular_tri.transposeInPlace();
195 Eigen::MatrixXd regular_tri_inv = regular_tri.inverse();
198 for (
int e = 0; e < state.
mesh->n_elements(); e++)
200 Eigen::MatrixXd transform;
202 transform_params[
"canonical_transformation"].push_back(
json({
216 Eigen::MatrixXd regular_tet(4, 4);
217 regular_tet << 0, 0, 0, 1,
219 1. / 2., std::sqrt(3) / 2., 0, 1,
220 1. / 2., 1. / 2. / std::sqrt(3), std::sqrt(3) / 2., 1;
221 regular_tet.transposeInPlace();
222 Eigen::MatrixXd regular_tet_inv = regular_tet.inverse();
225 for (
int e = 0; e < state.
mesh->n_elements(); e++)
227 Eigen::MatrixXd transform;
229 transform_params[
"canonical_transformation"].push_back(
json({
248 transform_params[
"solve_displacement"] =
true;
269 Eigen::MatrixXd grad;
270 amips_energy_->assemble_gradient(
state_.
mesh->is_volume(),
state_.
n_geom_bases,
init_geom_bases_,
init_geom_bases_,
init_ass_vals_cache_, 0, 0,
AdjointTools::map_primitive_to_node_order(
state_, X -
X_rest), Eigen::VectorXd(), grad);
279 bool flipped = is_flipped(
V1,
F);
main class that contains the polyfem solver and all its state
void get_vertices(Eigen::MatrixXd &vertices) const
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
void get_elements(Eigen::MatrixXi &elements) const
int n_geom_bases
number of geometric bases
static std::shared_ptr< Assembler > make_assembler(const std::string &formulation)
Represents one basis function and its gradient.
const std::vector< Local2Global > & global() const
void compute_face_jacobian(const int el_id, const Eigen::MatrixXd &reference_map, Eigen::MatrixXd &jacobian) const
void compute_cell_jacobian(const int el_id, const Eigen::MatrixXd &reference_map, Eigen::MatrixXd &jacobian) const
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.
bool scaled_jacobian(Mesh3DStorage &hmi, Mesh_Quality &mq)
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)