RSMesh 1.0.0
一个曲面重构的系统,输入为点云,输出为obj,stl等主流格式的网格文件,使用的方法为径向基函数插值,采取了并行优化、Intel-MKL等优化措施,支持百万级别的点云
载入中...
搜索中...
未找到
coarse_grid.cpp
1//
2// Created by RainSure on 2024/2/18.
3//
4
5#include "preconditioner/coarse_grid.h"
6#include "common/macros.h"
7#include "polynomial/monomial_basis.h"
8#include "preconditioner/mat_a.h"
9#include <utility>
10
11namespace rsmesh::preconditioner {
12 coarse_grid::coarse_grid(const model& model, domain&& domain)
13 : model_(model),
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_);
22 }
23
24 void coarse_grid::clear() {
25 me_ = Eigen::MatrixXd();
26 ldlt_of_qtaq_ = Eigen::LDLT<Eigen::MatrixXd>();
27
28 a_top_ = Eigen::MatrixXd();
29 lu_of_p_top_ = Eigen::FullPivLU<Eigen::MatrixXd>();
30 }
31
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);
35 }
36
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);
42
43 // Compute A.
44 auto a = mat_a(model_, points, grad_points);
45
46 if (l_ > 0) {
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);
52 }
53 }
54
55 // Compute -E.
56 auto lagrange_pt = lagrange_pt_full(Eigen::all, flat_indices);
57 me_ = -lagrange_pt.rightCols(m_ - l_);
58
59 // Compute decomposition of Q^T A Q.
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_))
63 .ldlt();
64
65 // Compute matrices used for solving polynomial part.
66 a_top_ = a.topRows(l_);
67
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();
72 } else {
73 ldlt_of_qtaq_ = a.ldlt();
74 }
75
76 mu_full_ = points_full.rows();
77 sigma_full_ = grad_points_full.rows();
78 }
79
80 void coarse_grid::set_solution_to(Eigen::Ref<valuesd> weights_full) const {
81 weights_full(point_idcs_) = lambda_c_.head(mu_);
82
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_);
86
87 weights_full.tail(l_) = lambda_c_.tail(l_);
88 }
89
90 void coarse_grid::solve(const Eigen::Ref<const valuesd>& values_full) {
91 valuesd values(m_);
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);
96
97 if (l_ > 0) {
98 // Compute Q^T d.
99 valuesd qtd = me_.transpose() * values.head(l_) + values.tail(m_ - l_);
100
101 // Solve Q^T A Q gamma = Q^T d for gamma.
102 valuesd gamma = ldlt_of_qtaq_.solve(qtd);
103
104 // Compute lambda = Q gamma.
105 lambda_c_ = valuesd(m_ + l_);
106 lambda_c_.head(l_) = me_ * gamma;
107 lambda_c_.segment(l_, m_ - l_) = gamma;
108
109 // Solve P c = d - A lambda for c at poly_points.
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);
112 } else {
113 lambda_c_ = ldlt_of_qtaq_.solve(values);
114 }
115 }
116}
该命名空间下主要定义了关于krylov子空间方法的预处理相关的类和函数