Loading [MathJax]/extensions/tex2jax.js
PolyFEM
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PeriodicLagrangianForm.cpp
Go to the documentation of this file.
2
4#include <igl/slice.h>
5
6namespace polyfem::solver
7{
9 const std::shared_ptr<utils::PeriodicBoundary> &periodic_bc)
10 : periodic_bc_(periodic_bc),
11 n_dofs_(ndof)
12 {
13 std::vector<Eigen::Triplet<double>> A_triplets;
14
15 const int dim = periodic_bc_->dim();
16 for (int i = 0; i < periodic_bc_->n_constraints(); ++i)
17 {
18 auto c = periodic_bc_->constraint(i);
19 for (int d = 0; d < dim; d++)
20 {
21 A_triplets.emplace_back(d + i * dim, d + dim * c[0], 1.0);
22 A_triplets.emplace_back(d + i * dim, d + dim * c[1], -1.0);
23 }
24 }
25 A_.resize(periodic_bc_->n_constraints() * dim, n_dofs_);
26 A_.setFromTriplets(A_triplets.begin(), A_triplets.end());
27 A_.makeCompressed();
28
29 b_.setZero(A_.rows(), 1);
30
31 A_triplets.clear();
32 {
33 const auto& index_map = periodic_bc_->index_map();
34 for (int i = 0; i < index_map.size(); i++)
35 for (int d = 0; d < dim; d++)
36 A_triplets.emplace_back(i * dim + d, index_map(i) * dim + d, 1.0);
37 assert(index_map.size() * dim == n_dofs_);
38 }
39
40 A_proj_.resize(n_dofs_, periodic_bc_->n_periodic_dof());
41 A_proj_.setFromTriplets(A_triplets.begin(), A_triplets.end());
42 A_proj_.makeCompressed();
43
44 b_proj_.setZero(A_proj_.rows(), 1);
45
46 lagr_mults_.resize(A_.rows());
47 lagr_mults_.setZero();
48 }
49
50 bool PeriodicLagrangianForm::can_project() const { return true; }
51
52 void PeriodicLagrangianForm::project_gradient(Eigen::VectorXd &grad) const
53 {
54 grad = periodic_bc_->full_to_periodic(grad, true);
55 }
56
58 {
59 periodic_bc_->full_to_periodic(hessian);
60 }
61
62 double PeriodicLagrangianForm::value_unweighted(const Eigen::VectorXd &x) const
63 {
64 const Eigen::VectorXd dist = A_ * x - b_;
65 const double L_penalty = -lagr_mults_.transpose() * dist;
66 const double A_penalty = 0.5 * dist.transpose() * dist;
67
68 return L_weight() * L_penalty + A_weight() * A_penalty;
69 }
70
71 void PeriodicLagrangianForm::first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
72 {
73 gradv = L_weight() * A_.transpose() * (-lagr_mults_ + A_weight() * (A_ * x - b_));
74 }
75
76 void PeriodicLagrangianForm::second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const
77 {
78 hessian = A_weight() * A_.transpose() * A_;
79 }
80
81 double PeriodicLagrangianForm::compute_error(const Eigen::VectorXd &x) const
82 {
83 // return (b_ - x).transpose() * A_ * (b_ - x);
84 const Eigen::VectorXd res = A_ * x - b_;
85 return res.squaredNorm();
86 }
87
88 void PeriodicLagrangianForm::update_lagrangian(const Eigen::VectorXd &x, const double k_al)
89 {
90 k_al_ = k_al;
91 lagr_mults_ -= k_al * (A_ * x - b_);
92 }
93}
int x
Eigen::VectorXd lagr_mults_
vector of lagrange multipliers
StiffnessMatrix A_proj_
Constraints projection matrix.
Eigen::MatrixXd b_proj_
Constraints projection value.
void update_lagrangian(const Eigen::VectorXd &x, const double k_al) override
PeriodicLagrangianForm(const int ndof, const std::shared_ptr< utils::PeriodicBoundary > &periodic_bc)
Construct a new PeriodicLagrangianForm object.
void first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const override
Compute the first derivative of the value wrt x.
virtual void project_gradient(Eigen::VectorXd &grad) const override
void second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const override
Compute the second derivative of the value wrt x.
const std::shared_ptr< utils::PeriodicBoundary > periodic_bc_
double value_unweighted(const Eigen::VectorXd &x) const override
Compute the value of the form.
double compute_error(const Eigen::VectorXd &x) const override
virtual void project_hessian(StiffnessMatrix &hessian) const override
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:22