5#include "preconditioner/coarse_grid.h"
6#include "common/macros.h"
7#include "polynomial/monomial_basis.h"
8#include "preconditioner/mat_a.h"
12 coarse_grid::coarse_grid(
const model& model, domain&& domain)
14 point_idcs_(std::move(domain.point_indices)),
15 grad_point_idcs_(std::move(domain.grad_point_indices)),
16 dim_(model.poly_dimension()),
17 l_(model.poly_basis_size()),
18 mu_(static_cast<index_t>(point_idcs_.size())),
19 sigma_(static_cast<index_t>(grad_point_idcs_.size())),
20 m_(mu_ + dim_ * sigma_) {
21 RSMESH_ASSERT(mu_ > l_);
24 void coarse_grid::clear() {
25 me_ = Eigen::MatrixXd();
26 ldlt_of_qtaq_ = Eigen::LDLT<Eigen::MatrixXd>();
28 a_top_ = Eigen::MatrixXd();
29 lu_of_p_top_ = Eigen::FullPivLU<Eigen::MatrixXd>();
32 void coarse_grid::setup(
const geometry::points3d& points_full,
33 const Eigen::MatrixXd& lagrange_pt_full) {
34 setup(points_full, geometry::points3d(0, 3), lagrange_pt_full);
37 void coarse_grid::setup(
const geometry::points3d& points_full,
38 const geometry::points3d& grad_points_full,
39 const Eigen::MatrixXd& lagrange_pt_full) {
40 auto points = points_full(point_idcs_, Eigen::all);
41 auto grad_points = grad_points_full(grad_point_idcs_, Eigen::all);
44 auto a = mat_a(model_, points, grad_points);
47 std::vector<index_t> flat_indices(point_idcs_);
48 flat_indices.reserve(mu_ + dim_ * sigma_);
49 for (
auto i : grad_point_idcs_) {
50 for (index_t j = 0; j < dim_; j++) {
51 flat_indices.push_back(mu_ + dim_ * i + j);
56 auto lagrange_pt = lagrange_pt_full(Eigen::all, flat_indices);
57 me_ = -lagrange_pt.rightCols(m_ - l_);
60 ldlt_of_qtaq_ = (me_.transpose() * a.topLeftCorner(l_, l_) * me_ +
61 me_.transpose() * a.topRightCorner(l_, m_ - l_) +
62 a.bottomLeftCorner(m_ - l_, l_) * me_ + a.bottomRightCorner(m_ - l_, m_ - l_))
66 a_top_ = a.topRows(l_);
68 polynomial::monomial_basis mono_basis(model_.poly_dimension(), model_.poly_degree());
69 auto head_points = points.topRows(l_);
70 Eigen::MatrixXd p_top = mono_basis.evaluate(head_points).transpose();
71 lu_of_p_top_ = p_top.fullPivLu();
73 ldlt_of_qtaq_ = a.ldlt();
76 mu_full_ = points_full.rows();
77 sigma_full_ = grad_points_full.rows();
80 void coarse_grid::set_solution_to(Eigen::Ref<valuesd> weights_full)
const {
81 weights_full(point_idcs_) = lambda_c_.head(mu_);
83 weights_full.segment(mu_full_, dim_ * sigma_full_)
84 .reshaped<Eigen::RowMajor>(sigma_full_, dim_)(grad_point_idcs_, Eigen::all) =
85 lambda_c_.segment(mu_, dim_ * sigma_).reshaped<Eigen::RowMajor>(sigma_, dim_);
87 weights_full.tail(l_) = lambda_c_.tail(l_);
90 void coarse_grid::solve(
const Eigen::Ref<const valuesd>& values_full) {
92 values.head(mu_) = values_full(point_idcs_);
93 values.tail(dim_ * sigma_).reshaped<Eigen::RowMajor>(sigma_, dim_) =
94 values_full.tail(dim_ * sigma_full_)
95 .reshaped<Eigen::RowMajor>(sigma_full_, dim_)(grad_point_idcs_, Eigen::all);
99 valuesd qtd = me_.transpose() * values.head(l_) + values.tail(m_ - l_);
102 valuesd gamma = ldlt_of_qtaq_.solve(qtd);
105 lambda_c_ = valuesd(m_ + l_);
106 lambda_c_.head(l_) = me_ * gamma;
107 lambda_c_.segment(l_, m_ - l_) = gamma;
110 valuesd a_top_lambda = a_top_ * lambda_c_.head(m_);
111 lambda_c_.tail(l_) = lu_of_p_top_.solve(values.head(l_) - a_top_lambda);
113 lambda_c_ = ldlt_of_qtaq_.solve(values);
该命名空间下主要定义了关于krylov子空间方法的预处理相关的类和函数