132 const int num_kernels =
centers_.rows();
136 Eigen::MatrixXd A_prime(samples.rows(), num_kernels + 1 + dim + dim * (dim + 1) / 2);
139 for (
int j = 0; j < num_kernels; ++j)
141 A_prime.col(j) = (samples.rowwise() -
centers_.row(j)).rowwise().norm().unaryExpr([
this](
double x) {
return kernel_prime(
is_volume(),
x) /
x; });
142 A_prime.col(j) = (samples.col(axis).array() -
centers_(j, axis)) * A_prime.col(j).array();
145 A_prime.middleCols(num_kernels + 1 + axis, 1).setOnes();
149 A_prime.col(num_kernels + 1 + dim) = samples.col(1 - axis);
153 A_prime.col(num_kernels + 1 + dim + axis) = samples.col((axis + 1) % dim);
154 A_prime.col(num_kernels + 1 + dim + (axis + 2) % dim) = samples.col((axis + 2) % dim);
157 A_prime.rightCols(dim).col(axis) = 2.0 * samples.col(axis);
168 const int num_kernels =
centers_.rows();
171 A.resize(samples.rows(), num_kernels + 1 + dim + dim * (dim + 1) / 2);
172 for (
int j = 0; j < num_kernels; ++j)
174 A.col(j) = (samples.rowwise() -
centers_.row(j)).rowwise().norm().unaryExpr([
this](
double x) {
return kernel(
is_volume(),
x); });
176 A.col(num_kernels).setOnes();
177 A.middleCols(num_kernels + 1, dim) = samples;
180 A.middleCols(num_kernels + dim + 1, 1) = samples.rowwise().prod();
184 A.middleCols(num_kernels + dim + 1, 3) = samples;
185 A.middleCols(num_kernels + dim + 1 + 0, 1).array() *= samples.col(1).array();
186 A.middleCols(num_kernels + dim + 1 + 1, 1).array() *= samples.col(2).array();
187 A.middleCols(num_kernels + dim + 1 + 2, 1).array() *= samples.col(0).array();
189 A.rightCols(dim) = samples.array().square();
195 const int num_bases,
const Quadrature &quadr, Eigen::MatrixXd &C)
const
197 const int num_kernels =
centers_.rows();
205 Eigen::VectorXd K_cst = Eigen::VectorXd::Zero(num_kernels);
206 Eigen::MatrixXd K_lin = Eigen::MatrixXd::Zero(num_kernels, dim);
207 Eigen::MatrixXd K_mix = Eigen::MatrixXd::Zero(num_kernels, dim);
208 Eigen::MatrixXd K_sqr = Eigen::MatrixXd::Zero(num_kernels, dim);
209 for (
int j = 0; j < num_kernels; ++j)
216 for (
int q = 0; q < quadr.
points.rows(); ++q)
219 const double r = p.norm();
222 K_lin.row(j) += gradPhi;
223 K_mix(j, 0) += quadr.
points(q, 1) * gradPhi(0);
224 K_mix(j, 1) += quadr.
points(q, 0) * gradPhi(1);
225 K_sqr.row(j) += (quadr.
points.row(q).array() * gradPhi.array()).matrix();
232 Eigen::RowVectorXd I_lin = (quadr.
points.array().colwise() * quadr.
weights.array()).colwise().sum();
233 Eigen::RowVectorXd I_mix = (quadr.
points.rowwise().prod().array() * quadr.
weights.array()).colwise().sum();
234 Eigen::RowVectorXd I_sqr = (quadr.
points.array().square().colwise() * quadr.
weights.array()).colwise().sum();
235 double volume = quadr.
weights.sum();
243 Eigen::Matrix<double, 5, 5> M;
244 M << volume, 0, I_lin(1), 2 * I_lin(0), 0,
245 0, volume, I_lin(0), 0, 2 * I_lin(1),
246 I_lin(1), I_lin(0), I_sqr(0) + I_sqr(1), 2 * I_mix(0), 2 * I_mix(0),
247 4 * I_lin(0), 2 * I_lin(1), 4 * I_mix(0), 6 * I_sqr(0), 2 * I_sqr(1),
248 2 * I_lin(0), 4 * I_lin(1), 4 * I_mix(0), 2 * I_sqr(0), 6 * I_sqr(1);
249 Eigen::FullPivLU<Eigen::Matrix<double, 5, 5>> lu(M);
254 C.resize(5, num_kernels + 1 + dim + dim * (dim + 1) / 2);
256 C.block(0, 0, dim, num_kernels) = K_lin.transpose();
257 C.block(dim, 0, 1, num_kernels) = K_mix.transpose().colwise().sum();
258 C.block(dim + 1, 0, dim, num_kernels) = 2.0 * (K_sqr.colwise() + K_cst).transpose();
259 C.block(dim + 1, num_kernels, dim, 1).setConstant(2.0 * volume);
260 C.bottomRightCorner(5, 5) = M;
265 const int num_bases,
const Quadrature &quadr, Eigen::MatrixXd &C)
const
269 const int num_kernels =
centers_.rows();
270 const int space_dim =
centers_.cols();
271 const int assembler_dim = assembler.
is_tensor() ? 2 : 1;
272 assert(space_dim == 2);
274 std::array<Eigen::MatrixXd, 5> strong;
286 for (
int j = 0; j < num_kernels; ++j)
291 for (
int q = 0; q < quadr.
points.rows(); ++q)
294 const double r = p.norm();
301 for (
size_t i = 5; i < ass_val.
basis_values.size(); ++i)
310 for (
int d = 0; d < 5; ++d)
313 for (
int i = 0; i < num_kernels; ++i)
316 for (
int alpha = 0; alpha < assembler_dim; ++alpha)
318 for (
int beta = 0; beta < assembler_dim; ++beta)
320 const int loc_index = alpha * assembler_dim + beta;
327 for (
int i = 0; i < 5; ++i)
330 for (
int alpha = 0; alpha < assembler_dim; ++alpha)
332 for (
int beta = 0; beta < assembler_dim; ++beta)
334 const int loc_index = alpha * assembler_dim + beta;
341 for (
int alpha = 0; alpha < assembler_dim; ++alpha)
343 for (
int beta = 0; beta < assembler_dim; ++beta)
346 const int loc_index = alpha * assembler_dim + beta;
372 const int num_bases,
const Quadrature &quadr, Eigen::MatrixXd &C)
const
374 const int num_kernels =
centers_.rows();
382 Eigen::VectorXd K_cst = Eigen::VectorXd::Zero(num_kernels);
383 Eigen::MatrixXd K_lin = Eigen::MatrixXd::Zero(num_kernels, dim);
384 Eigen::MatrixXd K_mix = Eigen::MatrixXd::Zero(num_kernels, dim);
385 Eigen::MatrixXd K_sqr = Eigen::MatrixXd::Zero(num_kernels, dim);
386 for (
int j = 0; j < num_kernels; ++j)
393 for (
int q = 0; q < quadr.
points.rows(); ++q)
396 const double r = p.norm();
399 K_lin.row(j) += gradPhi;
400 for (
int d = 0; d < dim; ++d)
402 K_mix(j, d) += quadr.
points(q, (d + 1) % dim) * gradPhi(d) + quadr.
points(q, d) * gradPhi((d + 1) % dim);
404 K_sqr.row(j) += (quadr.
points.row(q).array() * gradPhi.array()).matrix();
411 Eigen::RowVectorXd I_lin = (quadr.
points.array().colwise() * quadr.
weights.array()).colwise().sum();
412 Eigen::RowVectorXd I_sqr = (quadr.
points.array().square().colwise() * quadr.
weights.array()).colwise().sum();
413 Eigen::RowVectorXd I_mix(3);
414 I_mix(0) = (quadr.
points.col(0).array() * quadr.
points.col(1).array() * quadr.
weights.array()).sum();
415 I_mix(1) = (quadr.
points.col(1).array() * quadr.
points.col(2).array() * quadr.
weights.array()).sum();
416 I_mix(2) = (quadr.
points.col(2).array() * quadr.
points.col(0).array() * quadr.
weights.array()).sum();
417 double volume = quadr.
weights.sum();
424 Eigen::Matrix<double, 9, 9> M;
425 M << volume, 0, 0, I_lin(1), 0, I_lin(2), 2 * I_lin(0), 0, 0,
426 0, volume, 0, I_lin(0), I_lin(2), 0, 0, 2 * I_lin(1), 0,
427 0, 0, volume, 0, I_lin(1), I_lin(0), 0, 0, 2 * I_lin(2),
428 I_lin(1), I_lin(0), 0, I_sqr(0) + I_sqr(1), I_mix(2), I_mix(1), 2 * I_mix(0), 2 * I_mix(0), 0,
429 0, I_lin(2), I_lin(1), I_mix(2), I_sqr(1) + I_sqr(2), I_mix(0), 0, 2 * I_mix(1), 2 * I_mix(1),
430 I_lin(2), 0, I_lin(0), I_mix(1), I_mix(0), I_sqr(2) + I_sqr(0), 2 * I_mix(2), 0, 2 * I_mix(2),
431 2 * I_lin(0), 0, 0, 2 * I_mix(0), 0, 2 * I_mix(2), 4 * I_sqr(0), 0, 0,
432 0, 2 * I_lin(1), 0, 2 * I_mix(0), 2 * I_mix(1), 0, 0, 4 * I_sqr(1), 0,
433 0, 0, 2 * I_lin(2), 0, 2 * I_mix(1), 2 * I_mix(2), 0, 0, 4 * I_sqr(2);
434 Eigen::Matrix<double, 1, 9> M_rhs;
435 M_rhs.segment<3>(0) = I_lin;
436 M_rhs.segment<3>(3) = I_mix;
437 M_rhs.segment<3>(6) = I_sqr;
439 M.bottomRows(dim).rowwise() += 2.0 * M_rhs;
446 C.resize(9, num_kernels + 1 + dim + dim * (dim + 1) / 2);
448 C.block(0, 0, dim, num_kernels) = K_lin.transpose();
449 C.block(dim, 0, dim, num_kernels) = K_mix.transpose();
450 C.block(dim + dim, 0, dim, num_kernels) = 2.0 * (K_sqr.colwise() + K_cst).transpose();
451 C.block(dim + dim, num_kernels, dim, 1).setConstant(2.0 * volume);
452 C.bottomRightCorner(9, 9) = M;
459 const Eigen::MatrixXd &local_basis_integral,
const Quadrature &quadr,
460 Eigen::MatrixXd &b,
bool with_constraints)
463 logger().trace(
"#collocation points: {}", samples.rows());
464 logger().trace(
"#quadrature points: {}", quadr.
weights.size());
465 logger().trace(
"#non-vanishing bases: {}", b.cols());
466 logger().trace(
"#constraints: {}", b.cols());
472 if (!with_constraints)
475 const int num_kernels =
centers_.rows();
476 logger().trace(
"-- Solving system of size {}x{}", num_kernels, num_kernels);
477 weights_ = (A.transpose() * A).ldlt().solve(A.transpose() * b);
478 logger().trace(
"-- Solved!");
483 const int num_bases = b.cols();
485 const Eigen::MatrixXd At = A.transpose();
499 assert(
centers_.rows() + 1 + dim + dim * (dim + 1) / 2 > C.rows());
500 logger().trace(
"#constraints: {}", C.rows());
503 assert(local_basis_integral.cols() == C.rows());
504 assert(local_basis_integral.rows() == b.cols());
505 assert(A.rows() == b.rows());
506 Eigen::MatrixXd rhs(A.cols() + local_basis_integral.cols(), b.cols());
507 rhs.topRows(A.cols()) = At * b;
508 rhs.bottomRows(local_basis_integral.cols()) = local_basis_integral.transpose();
511 assert(C.cols() == A.cols());
512 assert(A.rows() == b.rows());
513 Eigen::MatrixXd M(A.cols() + C.rows(), A.cols() + C.rows());
514 M.topLeftCorner(A.cols(), A.cols()) = At * A;
515 M.topRightCorner(A.cols(), C.rows()) = C.transpose();
516 M.bottomLeftCorner(C.rows(), A.cols()) = C;
517 M.bottomRightCorner(C.rows(), C.rows()).setZero();
522 logger().trace(
"-- Solving system of size {}x{}", M.rows(), M.cols());
523 auto ldlt = M.ldlt();
524 if (ldlt.info() == Eigen::NumericalIssue)
526 logger().error(
"-- WARNING: Numerical issues when solving the harmonic least square.");
528 const auto tmp = ldlt.solve(rhs);
530 logger().trace(
"-- Solved!");
531 logger().trace(
"-- Mean residual: {}", (A *
weights_ - b).array().abs().colwise().maxCoeff().mean());
532 logger().trace(
"-- Max constraints error: {}", (C *
weights_ - local_basis_integral.transpose()).array().abs().maxCoeff());
566 assert(local_basis_integral.cols() == C.rows());
567 assert(local_basis_integral.rows() == b.cols());
568 assert(A.rows() == b.rows());
569 Eigen::MatrixXd rhs(A.cols() + local_basis_integral.cols(), b.cols());
570 rhs.topRows(A.cols()) = At * b;
571 rhs.bottomRows(local_basis_integral.cols()) = local_basis_integral.transpose();
574 assert(C.cols() == A.cols());
575 assert(A.rows() == b.rows());
576 Eigen::MatrixXd M(A.cols() + C.rows(), A.cols() + C.rows());
577 M.topLeftCorner(A.cols(), A.cols()) = At * A;
578 M.topRightCorner(A.cols(), C.rows()) = C.transpose();
579 M.bottomLeftCorner(C.rows(), A.cols()) = C;
580 M.bottomRightCorner(C.rows(), C.rows()).setZero();
585 logger().trace(
"-- Solving system of size {}x{}", M.rows(), M.cols());
586 auto ldlt = M.ldlt();
587 if (ldlt.info() == Eigen::NumericalIssue) {
588 logger().error(
"-- WARNING: Numerical issues when solving the harmonic least square.");
590 weights_ = ldlt.solve(rhs).topRows(A.cols());
591 logger().trace(
"-- Solved!");
592 logger().trace(
"-- Mean residual: {}", (A *
weights_ - b).array().abs().colwise().maxCoeff().mean());
595 Eigen::MatrixXd MM,
x, dx,
val;
599 for (
int d = 0; d < dim; ++d) {
605 std::cout << (MM.col(d).array() * quadr.
weights.array()).sum() - local_basis_integral(0, d) << std::endl;
607 MM.col((d+1)%dim).array() * quadr.
points.col(d).array()
608 + MM.col(d).array() * quadr.
points.col((d+1)%dim).array()
609 ) * quadr.
weights.array()).sum() - local_basis_integral(0, (dim == 2 ? 2 : (dim+d) )) << std::endl;
611 (quadr.
points.col(d).array() * MM.col(d).array()
614 ).sum() - local_basis_integral(0, (dim == 2 ? (3 + d) : (dim+dim+d))) << std::endl;