5#include "preconditioner/domain_divider.h"
7#include "common/zip_sort.h"
22 const std::vector<index_t>& point_indices,
23 const std::vector<index_t>& grad_point_indices,
24 const std::vector<index_t>& poly_point_indices)
26 grad_points_(grad_points),
27 mixed_size_of_root_(static_cast<index_t>(point_indices.size() + grad_point_indices.size())),
28 poly_point_idcs_(poly_point_indices) {
31 root.point_indices = point_indices;
32 root.grad_point_indices = grad_point_indices;
34 root.inner_point = std::vector<bool>(point_indices.size(),
true);
35 root.inner_grad_point = std::vector<bool>(grad_point_indices.size(),
true);
37 root.bbox_ = domain_bbox(root);
38 longest_side_length_of_root_ = root.bbox_.size().maxCoeff();
40 domains_.push_back(std::move(root));
45 std::pair<std::vector<index_t>, std::vector<index_t>> domain_divider::choose_coarse_points(
47 std::vector<index_t> idcs(poly_point_idcs_);
48 std::vector<index_t> grad_idcs;
50 std::random_device rd;
51 std::mt19937 gen(rd());
53 auto n_poly_points =
static_cast<index_t
>(poly_point_idcs_.size());
54 for (
const auto& d : domains_) {
55 std::vector<mixed_point> mixed_points;
56 for (index_t i = n_poly_points; i < d.size(); i++) {
57 mixed_points.emplace_back(d.point_indices.at(i), d.inner_point.at(i),
false);
59 for (index_t i = 0; i < d.grad_size(); i++) {
60 mixed_points.emplace_back(d.grad_point_indices.at(i), d.inner_grad_point.at(i),
true);
63 std::shuffle(mixed_points.begin(), mixed_points.end(), gen);
65 auto n_inner_pts = std::count(d.inner_point.begin(), d.inner_point.end(),
true) +
66 std::count(d.inner_grad_point.begin(), d.inner_grad_point.end(),
true);
67 auto n_coarse = std::max(
69 static_cast<index_t
>(round_half_to_even(ratio *
static_cast<double>(n_inner_pts))));
71 auto count = index_t{0};
72 for (
const auto& p : mixed_points) {
73 if (count == n_coarse) {
78 (p.grad ? grad_idcs : idcs).push_back(p.index);
84 return {std::move(idcs), std::move(grad_idcs)};
87 const std::list<domain>& domain_divider::domains()
const {
return domains_; }
89 std::list<domain>&& domain_divider::into_domains() {
return std::move(domains_); }
91 void domain_divider::divide_domain(std::list<domain>::iterator it) {
94 std::vector<mixed_point> mixed_points;
95 for (index_t i = 0; i < d.size(); i++) {
96 mixed_points.emplace_back(d.point_indices.at(i), d.inner_point.at(i),
false);
98 for (index_t i = 0; i < d.grad_size(); i++) {
99 mixed_points.emplace_back(d.grad_point_indices.at(i), d.inner_grad_point.at(i),
true);
102 auto split_axis = index_t{0};
103 auto longest_side_length = d.bbox_.size().maxCoeff(&split_axis);
106 std::sort(mixed_points.begin(), mixed_points.end(),
107 [
this, split_axis](
const auto& a,
const auto& b) {
108 return (a.grad ? grad_points_ : points_)(a.index, split_axis) <
109 (b.grad ? grad_points_ : points_)(b.index, split_axis);
113 longest_side_length_of_root_ / longest_side_length *
114 std::sqrt(
static_cast<double>(max_leaf_size) /
static_cast<double>(mixed_size_of_root_)) *
116 q = std::min(0.5, q);
118 auto n_pts = d.mixed_size();
119 auto n_overlap_pts =
static_cast<index_t
>(round_half_to_even(q *
static_cast<double>(n_pts)));
120 auto n_subdomain_pts =
121 static_cast<index_t
>(std::ceil(
static_cast<double>(n_pts + n_overlap_pts) / 2.0));
122 auto left_partition = n_pts - n_subdomain_pts;
123 auto right_partition = n_subdomain_pts;
124 auto mid =
static_cast<index_t
>(
125 round_half_to_even(
static_cast<double>(left_partition + right_partition) / 2.0));
130 for (index_t i = 0; i < right_partition; i++) {
131 const auto& p = mixed_points.at(i);
132 auto inner = p.inner && i < mid;
135 left.grad_point_indices.push_back(p.index);
136 left.inner_grad_point.push_back(inner);
138 left.point_indices.push_back(p.index);
139 left.inner_point.push_back(inner);
143 for (index_t i = left_partition; i < n_pts; i++) {
144 const auto& p = mixed_points.at(i);
145 auto inner = p.inner && i >= mid;
148 right.grad_point_indices.push_back(p.index);
149 right.inner_grad_point.push_back(inner);
151 right.point_indices.push_back(p.index);
152 right.inner_point.push_back(inner);
156 left.bbox_ = domain_bbox(left);
157 right.bbox_ = domain_bbox(right);
159 domains_.push_back(std::move(left));
160 domains_.push_back(std::move(right));
163 void domain_divider::divide_domains() {
164 auto it = domains_.begin();
166 while (it != domains_.end()) {
168 if (d.mixed_size() <= max_leaf_size) {
175 it = domains_.erase(it);
178 for (
auto& d : domains_) {
179 d.merge_poly_points(poly_point_idcs_);
183 geometry::bbox3d domain_divider::domain_bbox(
const domain& domain)
const {
184 auto points = points_(domain.point_indices, Eigen::all);
185 auto grad_points = grad_points_(domain.grad_point_indices, Eigen::all);
187 return geometry::bbox3d::from_points(points).convex_hull(
188 geometry::bbox3d::from_points(grad_points));
191 double domain_divider::round_half_to_even(
double d) {
192 return std::ceil((d - 0.5) / 2.0) + std::floor((d + 0.5) / 2.0);
该命名空间下主要定义了关于krylov子空间方法的预处理相关的类和函数