PolyFEM
Loading...
Searching...
No Matches
MixedAssemblerForm.cpp
Go to the documentation of this file.
2
4
5#include <algorithm>
6#include <cassert>
7#include <cmath>
8
9namespace polyfem::solver
10{
12 const int n_phi_bases,
13 const int n_psi_bases,
14 const std::vector<basis::ElementBases> &phi_bases,
15 const std::vector<basis::ElementBases> &psi_bases,
16 const std::vector<basis::ElementBases> &geom_bases,
17 const assembler::MixedNLAssembler &assembler,
20 const double t,
21 const double dt,
22 const bool is_volume)
23 : n_phi_bases_(n_phi_bases),
24 n_psi_bases_(n_psi_bases),
25 phi_bases_(phi_bases),
26 psi_bases_(psi_bases),
27 geom_bases_(geom_bases),
28 assembler_(assembler),
29 phi_cache_(phi_cache),
30 psi_cache_(psi_cache),
31 t_(t),
32 dt_(dt),
33 is_volume_(is_volume)
34 {
35 assert(n_phi_bases_ > 0);
36 assert(n_psi_bases_ > 0);
37 assert(phi_bases_.size() == psi_bases_.size());
38 assert(phi_bases_.size() == geom_bases_.size());
39 mat_cache_ = std::make_unique<utils::SparseMatrixCache>();
40 }
41
42 void MixedAssemblerForm::set_row_weights(const double phi_weight, const double psi_weight)
43 {
44 assert(std::isfinite(phi_weight));
45 assert(std::isfinite(psi_weight));
46 phi_row_weight_ = phi_weight;
47 psi_row_weight_ = psi_weight;
48 }
49
60
61 Eigen::VectorXd MixedAssemblerForm::value_per_element_unweighted(const Eigen::VectorXd &x) const
62 {
63 const Eigen::VectorXd out = assembler_.assemble_energy_per_element(
68 t_, dt_, x, x_prev_,
70 assert(std::abs(out.sum() - value_unweighted(x)) < std::max(1e-10 * std::abs(out.sum()), 1e-10));
71 return out;
72 }
73
74 void MixedAssemblerForm::first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
75 {
76 Eigen::MatrixXd grad;
82 t_, dt_, x, x_prev_,
84 grad);
85 gradv = grad;
86 gradv.head(phi_ndof()) *= phi_row_weight_;
87 gradv.tail(psi_ndof()) *= psi_row_weight_;
88 }
89
90 void MixedAssemblerForm::second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const
91 {
92 POLYFEM_SCOPED_TIMER("mixed assembler hessian");
93
94 hessian.resize(x.size(), x.size());
95 // The autodiff mixed Hessian can change its exact zero pattern between
96 // Newton iterations, so the per-element sparse pattern cache is unsafe.
97 mat_cache_ = std::make_unique<utils::SparseMatrixCache>();
104 t_, dt_, x, x_prev_,
106 *mat_cache_, hessian);
107
108 for (int k = 0; k < hessian.outerSize(); ++k)
109 {
110 for (StiffnessMatrix::InnerIterator it(hessian, k); it; ++it)
111 {
112 it.valueRef() *= it.row() < phi_ndof() ? phi_row_weight_ : psi_row_weight_;
113 }
114 }
115 }
116
118 {
119 return n_phi_bases_ * assembler_.size();
120 }
121
123 {
124 return n_psi_bases_;
125 }
126
128 {
129 return [this](const Eigen::MatrixXd &x, Eigen::MatrixXd &x_phi, Eigen::MatrixXd &x_psi) {
130 assert(x.rows() == phi_ndof() + psi_ndof());
131 assert(x.cols() == 1);
132 x_phi = x.topRows(phi_ndof());
133 x_psi = x.middleRows(phi_ndof(), psi_ndof());
134 };
135 }
136} // namespace polyfem::solver
int x
#define POLYFEM_SCOPED_TIMER(...)
Definition Timer.hpp:10
Caches basis evaluation and geometric mapping at every element.
void assemble_gradient(const bool is_volume, const int n_psi_basis, const int n_phi_basis, const std::vector< basis::ElementBases > &psi_bases, const std::vector< basis::ElementBases > &phi_bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &psi_cache, const AssemblyValsCache &phi_cache, const double t, const double dt, const Eigen::MatrixXd &x, const Eigen::MatrixXd &x_prev, const SolutionSplitter &split_solution, Eigen::MatrixXd &grad) const
void assemble_hessian(const bool is_volume, const int n_psi_basis, const int n_phi_basis, const bool project_to_psd, const std::vector< basis::ElementBases > &psi_bases, const std::vector< basis::ElementBases > &phi_bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &psi_cache, const AssemblyValsCache &phi_cache, const double t, const double dt, const Eigen::MatrixXd &x, const Eigen::MatrixXd &x_prev, const SolutionSplitter &split_solution, utils::MatrixCache &mat_cache, StiffnessMatrix &hessian) const
Eigen::VectorXd assemble_energy_per_element(const bool is_volume, const int n_psi_basis, const int n_phi_basis, const std::vector< basis::ElementBases > &psi_bases, const std::vector< basis::ElementBases > &phi_bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &psi_cache, const AssemblyValsCache &phi_cache, const double t, const double dt, const Eigen::MatrixXd &x, const Eigen::MatrixXd &x_prev, const SolutionSplitter &split_solution) const
std::function< void(const Eigen::MatrixXd &x, Eigen::MatrixXd &x_phi, Eigen::MatrixXd &x_psi)> SolutionSplitter
double assemble_energy(const bool is_volume, const int n_psi_basis, const int n_phi_basis, const std::vector< basis::ElementBases > &psi_bases, const std::vector< basis::ElementBases > &phi_bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &psi_cache, const AssemblyValsCache &phi_cache, const double t, const double dt, const Eigen::MatrixXd &x, const Eigen::MatrixXd &x_prev, const SolutionSplitter &split_solution) const
bool project_to_psd_
If true, the form's second derivative is projected to be positive semidefinite.
Definition Form.hpp:147
void set_row_weights(const double phi_weight, const double psi_weight)
void second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const override
Compute the second derivative of the value wrt x.
Eigen::VectorXd value_per_element_unweighted(const Eigen::VectorXd &x) const override
Compute the value of the form multiplied per element.
const std::vector< basis::ElementBases > & psi_bases_
const std::vector< basis::ElementBases > & phi_bases_
assembler::MixedNLAssembler::SolutionSplitter split_solution() const
assembler::AssemblyValsCache & psi_cache_
std::unique_ptr< utils::MatrixCache > mat_cache_
assembler::AssemblyValsCache & phi_cache_
const std::vector< basis::ElementBases > & geom_bases_
const assembler::MixedNLAssembler & assembler_
double value_unweighted(const Eigen::VectorXd &x) const override
Compute the value of the form.
void first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const override
Compute the first derivative of the value wrt x.
MixedAssemblerForm(const int n_phi_bases, const int n_psi_bases, const std::vector< basis::ElementBases > &phi_bases, const std::vector< basis::ElementBases > &psi_bases, const std::vector< basis::ElementBases > &geom_bases, const assembler::MixedNLAssembler &assembler, assembler::AssemblyValsCache &phi_cache, assembler::AssemblyValsCache &psi_cache, const double t, const double dt, const bool is_volume)
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24