9 const std::vector<int> &boundary_nodes,
10 const std::vector<mesh::LocalBoundary> &local_boundary,
11 const std::vector<mesh::LocalBoundary> &local_neumann_boundary,
15 const size_t obstacle_ndof,
16 const bool is_time_dependent,
19 : boundary_nodes_(boundary_nodes),
20 local_boundary_(&local_boundary),
21 local_neumann_boundary_(&local_neumann_boundary),
22 n_boundary_samples_(n_boundary_samples),
23 rhs_assembler_(&rhs_assembler),
24 is_time_dependent_(is_time_dependent),
33 const std::vector<int> &boundary_nodes,
35 const size_t obstacle_ndof,
36 const Eigen::MatrixXd &target_x)
37 : boundary_nodes_(boundary_nodes),
38 local_boundary_(nullptr),
39 local_neumann_boundary_(nullptr),
40 n_boundary_samples_({{0, 0}}),
41 rhs_assembler_(
nullptr),
42 is_time_dependent_(
false),
45 init_masked_lumped_mass(mass, obstacle_ndof);
49 igl::slice(b_, constraints_, 1, b_);
54 const size_t obstacle_ndof)
56 std::vector<Eigen::Triplet<double>> A_triplets;
64 A_triplets.emplace_back(i, bn, 1.0);
67 A_.setFromTriplets(A_triplets.begin(), A_triplets.end());
71 double min_diag = std::numeric_limits<double>::max();
73 for (
int k = 0; k < lumped.outerSize(); ++k)
75 for (StiffnessMatrix::InnerIterator it(lumped, k); it; ++it)
77 if (it.col() == it.row())
79 min_diag = std::min(min_diag, it.value());
80 max_diag = std::max(max_diag, it.value());
84 return max_diag <= 0 || min_diag <= 0 || min_diag / max_diag < 1e-16;
98 logger().warn(
"Row-sum lumped mass ill-conditioned (expected for order >= 2); using HRZ-style diagonal-scaling lumping for the BC penalty metric.");
105 if (mass.size() != 0)
107 double min_diag = std::numeric_limits<double>::max();
111 if (it.col() == it.row())
113 min_diag = std::min(min_diag, it.value());
114 diag_sum += it.value();
118 const double avg_mass = diag_sum > 0 ? diag_sum /
n_dofs_ : 1.0;
119 logger().warn(
"Lumped mass matrix has nonpositive entries; using identity scaled by the average nodal mass ({}).", avg_mass);
126 if (obstacle_ndof != 0)
128 const int n_fe_dof =
n_dofs_ - obstacle_ndof;
130 for (
int i = n_fe_dof; i <
n_dofs_; ++i)
141 std::vector<Eigen::Triplet<double>> tmp_triplets;
147 assert(it.col() == k);
148 tmp_triplets.emplace_back(it.row(), it.col(), sqrt(it.value()));
155 std::vector<bool> is_contraints(
n_dofs_,
false);
163 for (
int i = 0; i <
n_dofs_; ++i)
165 if (is_contraints[i])
168 A_triplets.emplace_back(i, index, 1.0);
174 A_proj_.setFromTriplets(A_triplets.begin(), A_triplets.end());
208 hessian.makeCompressed();
213 StiffnessMatrix::StorageIndex total_nnz = 0;
214 for (
int k = 0; k < hessian.outerSize(); ++k)
218 for (StiffnessMatrix::InnerIterator it(hessian, k); it; ++it)
230 out.reserve(total_nnz);
231 for (
int k = 0; k < hessian.outerSize(); ++k)
236 out.startVec(new_col);
237 for (StiffnessMatrix::InnerIterator it(hessian, k); it; ++it)
242 out.insertBack(new_row, new_col) = it.value();
247 hessian = std::move(out);
252 const Eigen::VectorXd dist =
A_ *
x -
b_;
278 const Eigen::VectorXd res =
A_ *
x -
b_;
279 return res.squaredNorm();
void set_bc(const std::vector< mesh::LocalBoundary > &local_boundary, const std::vector< int > &bounday_nodes, const QuadratureOrders &resolution, const std::vector< mesh::LocalBoundary > &local_neumann_boundary, Eigen::MatrixXd &rhs, const Eigen::MatrixXd &displacement=Eigen::MatrixXd(), const double t=1) const
BCLumpingMode
Lumping mode for the mass metric of the BC penalty.
@ HRZ
Hinton-Rock-Zienkiewicz diagonal-scaling lumping.
Eigen::SparseMatrix< double > lump_matrix(const Eigen::SparseMatrix< double > &M)
Lump each row of a matrix into the diagonal.
Eigen::SparseMatrix< double > lump_matrix_hrz(const Eigen::SparseMatrix< double > &M)
Lump a (mass) matrix HRZ-style: keep the diagonal, scaled by a common factor so the total (sum of all...
Eigen::SparseMatrix< double > sparse_identity(int rows, int cols)
spdlog::logger & logger()
Retrieves the current logger.
std::array< int, 2 > QuadratureOrders
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix