144 vals.
basis_values[star_index + 0].grad = Eigen::MatrixXd(pts.rows(), pts.cols());
150 vals.
basis_values[star_index + 1].grad = Eigen::MatrixXd(pts.rows(), pts.cols());
155 vals.
basis_values[star_index + 2].val = pts.col(0).array() * pts.col(1).array();
156 vals.
basis_values[star_index + 2].grad = Eigen::MatrixXd(pts.rows(), pts.cols());
161 vals.
basis_values[star_index + 3].val = pts.col(0).array() * pts.col(0).array();
162 vals.
basis_values[star_index + 3].grad = Eigen::MatrixXd(pts.rows(), pts.cols());
167 vals.
basis_values[star_index + 4].val = pts.col(1).array() * pts.col(1).array();
168 vals.
basis_values[star_index + 4].grad = Eigen::MatrixXd(pts.rows(), pts.cols());
172 for (
size_t i = star_index; i < star_index + 5; ++i)
386 const int num_kernels =
centers_.rows();
389 A.resize(samples.rows(), num_kernels + 1 + dim + dim * (dim + 1) / 2);
390 for (
int j = 0; j < num_kernels; ++j)
392 A.col(j) = (samples.rowwise() -
centers_.row(j)).rowwise().norm().unaryExpr([
this](
double x) {
return kernel(
is_volume(),
x); });
394 A.col(num_kernels).setOnes();
395 A.middleCols(num_kernels + 1, dim) = samples;
398 A.middleCols(num_kernels + dim + 1, 1) = samples.rowwise().prod();
402 A.middleCols(num_kernels + dim + 1, 3) = samples;
403 A.middleCols(num_kernels + dim + 1 + 0, 1).array() *= samples.col(1).array();
404 A.middleCols(num_kernels + dim + 1 + 1, 1).array() *= samples.col(2).array();
405 A.middleCols(num_kernels + dim + 1 + 2, 1).array() *= samples.col(0).array();
407 A.rightCols(dim) = samples.array().square();
415 const Eigen::MatrixXd &local_basis_integral,
417 Eigen::MatrixXd &t)
const
419 const int num_kernels =
centers_.rows();
427 Eigen::VectorXd K_cst = Eigen::VectorXd::Zero(num_kernels);
428 Eigen::MatrixXd K_lin = Eigen::MatrixXd::Zero(num_kernels, dim);
429 Eigen::MatrixXd K_mix = Eigen::MatrixXd::Zero(num_kernels, dim);
430 Eigen::MatrixXd K_sqr = Eigen::MatrixXd::Zero(num_kernels, dim);
431 for (
int j = 0; j < num_kernels; ++j)
438 for (
int q = 0; q < quadr.
points.rows(); ++q)
441 const double r = p.norm();
444 K_lin.row(j) += gradPhi;
445 K_mix(j, 0) += quadr.
points(q, 1) * gradPhi(0);
446 K_mix(j, 1) += quadr.
points(q, 0) * gradPhi(1);
447 K_sqr.row(j) += (quadr.
points.row(q).array() * gradPhi.array()).matrix();
454 Eigen::RowVectorXd I_lin = (quadr.
points.array().colwise() * quadr.
weights.array()).colwise().sum();
455 Eigen::RowVectorXd I_mix = (quadr.
points.rowwise().prod().array() * quadr.
weights.array()).colwise().sum();
456 Eigen::RowVectorXd I_sqr = (quadr.
points.array().square().colwise() * quadr.
weights.array()).colwise().sum();
457 double volume = quadr.
weights.sum();
464 Eigen::Matrix<double, 5, 5> M;
465 M << volume, 0, I_lin(1), 2 * I_lin(0), 0,
466 0, volume, I_lin(0), 0, 2 * I_lin(1),
467 I_lin(1), I_lin(0), I_sqr(0) + I_sqr(1), 2 * I_mix(0), 2 * I_mix(0),
468 4 * I_lin(0), 2 * I_lin(1), 4 * I_mix(0), 6 * I_sqr(0), 2 * I_sqr(1),
469 2 * I_lin(0), 4 * I_lin(1), 4 * I_mix(0), 2 * I_sqr(0), 6 * I_sqr(1);
470 Eigen::FullPivLU<Eigen::Matrix<double, 5, 5>> lu(M);
471 assert(lu.isInvertible());
476 L.resize(num_kernels + 1 + dim + dim * (dim + 1) / 2, num_kernels + 1);
478 L.diagonal().setOnes();
480 L.block(num_kernels + 1, 0, dim, num_kernels) = -K_lin.transpose();
481 L.block(num_kernels + 1 + dim, 0, 1, num_kernels) = -K_mix.transpose().colwise().sum();
482 L.block(num_kernels + 1 + dim + 1, 0, dim, num_kernels) = -2.0 * (K_sqr.colwise() + K_cst).transpose();
483 L.bottomRightCorner(dim, 1).setConstant(-2.0 * volume);
493 L.block(num_kernels + 1, 0, 5, num_kernels + 1) = lu.solve(L.block(num_kernels + 1, 0, 5, num_kernels + 1));
497 t.resize(L.rows(), num_bases);
499 t.bottomRows(5) = local_basis_integral.transpose();
500 t.bottomRows(5) = lu.solve(
weights_.bottomRows(5));
507 const Eigen::MatrixXd &local_basis_integral,
509 Eigen::MatrixXd &t)
const
512 const double time = 0;
513 const int num_kernels =
centers_.rows();
514 const int space_dim =
centers_.cols();
515 const int assembler_dim = assembler.
is_tensor() ? 2 : 1;
516 assert(space_dim == 2);
518 std::array<Eigen::MatrixXd, 5> strong;
530 for (
int j = 0; j < num_kernels; ++j)
535 for (
int q = 0; q < quadr.
points.rows(); ++q)
538 const double r = p.norm();
545 for (
size_t i = 5; i < ass_val.
basis_values.size(); ++i)
550 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 10, 10> M(5 * assembler_dim, 5 * assembler_dim);
551 for (
int i = 0; i < 5; ++i)
553 for (
int j = 0; j < 5; ++j)
557 for (
int d1 = 0; d1 < assembler_dim; ++d1)
559 for (
int d2 = 0; d2 < assembler_dim; ++d2)
561 const int loc_index = d1 * assembler_dim + d2;
562 M(i * assembler_dim + d1, j * assembler_dim + d2) = tmp(loc_index) + (strong[i].row(loc_index).transpose().array() * ass_val.
basis_values[j].val.array()).sum();
568 Eigen::FullPivLU<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 10, 10>> lu(M);
569 assert(lu.isInvertible());
572 L.resize((num_kernels + 1 + space_dim + space_dim * (space_dim + 1) / 2) * assembler_dim, (num_kernels + 1) * assembler_dim);
574 L.diagonal().setOnes();
576 for (
int i = 0; i < 5; ++i)
578 for (
int j = 0; j < num_kernels; ++j)
581 for (
int d1 = 0; d1 < assembler_dim; ++d1)
583 for (
int d2 = 0; d2 < assembler_dim; ++d2)
585 const int loc_index = d1 * assembler_dim + d2;
586 L((num_kernels + 1 + i) * assembler_dim + d1, j * assembler_dim + d2) = -tmp(loc_index) - (strong[i].row(loc_index).transpose().array() * ass_val.
basis_values[5 + j].val.array()).sum();
591 for (
int d1 = 0; d1 < assembler_dim; ++d1)
593 for (
int d2 = 0; d2 < assembler_dim; ++d2)
595 const int loc_index = d1 * assembler_dim + d2;
596 L(num_kernels + 1 + i * assembler_dim + d1, assembler_dim * num_kernels + d2) = -strong[i].row(loc_index).sum();
603 L.block((num_kernels + 1) * assembler_dim, 0, 5 * assembler_dim, (num_kernels + 1) * assembler_dim) = lu.solve(L.block((num_kernels + 1) * assembler_dim, 0, 5 * assembler_dim, (num_kernels + 1) * assembler_dim));
607 t.resize(L.rows(), num_bases * assembler_dim);
609 t.bottomRows(5 * assembler_dim) = lu.solve(local_basis_integral.transpose());
618 const Eigen::MatrixXd &local_basis_integral,
620 Eigen::MatrixXd &t)
const
622 const int num_kernels =
centers_.rows();
625 assert(local_basis_integral.cols() == 9);
631 Eigen::VectorXd K_cst = Eigen::VectorXd::Zero(num_kernels);
632 Eigen::MatrixXd K_lin = Eigen::MatrixXd::Zero(num_kernels, dim);
633 Eigen::MatrixXd K_mix = Eigen::MatrixXd::Zero(num_kernels, dim);
634 Eigen::MatrixXd K_sqr = Eigen::MatrixXd::Zero(num_kernels, dim);
635 for (
int j = 0; j < num_kernels; ++j)
642 for (
int q = 0; q < quadr.
points.rows(); ++q)
645 const double r = p.norm();
648 K_lin.row(j) += gradPhi;
649 for (
int d = 0; d < dim; ++d)
651 K_mix(j, d) += quadr.
points(q, (d + 1) % dim) * gradPhi(d) + quadr.
points(q, d) * gradPhi((d + 1) % dim);
653 K_sqr.row(j) += (quadr.
points.row(q).array() * gradPhi.array()).matrix();
660 Eigen::RowVectorXd I_lin = (quadr.
points.array().colwise() * quadr.
weights.array()).colwise().sum();
661 Eigen::RowVectorXd I_sqr = (quadr.
points.array().square().colwise() * quadr.
weights.array()).colwise().sum();
662 Eigen::RowVectorXd I_mix(3);
663 I_mix(0) = (quadr.
points.col(0).array() * quadr.
points.col(1).array() * quadr.
weights.array()).sum();
664 I_mix(1) = (quadr.
points.col(1).array() * quadr.
points.col(2).array() * quadr.
weights.array()).sum();
665 I_mix(2) = (quadr.
points.col(2).array() * quadr.
points.col(0).array() * quadr.
weights.array()).sum();
666 double volume = quadr.
weights.sum();
673 Eigen::Matrix<double, 9, 9> M;
674 M << volume, 0, 0, I_lin(1), 0, I_lin(2), 2 * I_lin(0), 0, 0,
675 0, volume, 0, I_lin(0), I_lin(2), 0, 0, 2 * I_lin(1), 0,
676 0, 0, volume, 0, I_lin(1), I_lin(0), 0, 0, 2 * I_lin(2),
677 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,
678 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),
679 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),
680 2 * I_lin(0), 0, 0, 2 * I_mix(0), 0, 2 * I_mix(2), 4 * I_sqr(0), 0, 0,
681 0, 2 * I_lin(1), 0, 2 * I_mix(0), 2 * I_mix(1), 0, 0, 4 * I_sqr(1), 0,
682 0, 0, 2 * I_lin(2), 0, 2 * I_mix(1), 2 * I_mix(2), 0, 0, 4 * I_sqr(2);
683 Eigen::Matrix<double, 1, 9> M_rhs;
684 M_rhs.segment<3>(0) = I_lin;
685 M_rhs.segment<3>(3) = I_mix;
686 M_rhs.segment<3>(6) = I_sqr;
688 M.bottomRows(dim).rowwise() += 2.0 * M_rhs;
689 Eigen::FullPivLU<Eigen::Matrix<double, 9, 9>> lu(M);
690 assert(lu.isInvertible());
695 L.resize(num_kernels + 1 + dim + dim * (dim + 1) / 2, num_kernels + 1);
697 L.diagonal().setOnes();
698 L.block(num_kernels + 1, 0, dim, num_kernels) = -K_lin.transpose();
699 L.block(num_kernels + 1 + dim, 0, dim, num_kernels) = -K_mix.transpose();
700 L.block(num_kernels + 1 + dim + dim, 0, dim, num_kernels) = -2.0 * (K_sqr.colwise() + K_cst).transpose();
701 L.bottomRightCorner(dim, 1).setConstant(-2.0 * volume);
702 L.block(num_kernels + 1, 0, 9, num_kernels + 1) = lu.solve(L.block(num_kernels + 1, 0, 9, num_kernels + 1));
706 t.resize(L.rows(), num_bases);
708 t.bottomRows(9) = local_basis_integral.transpose();
709 t.bottomRows(9) = lu.solve(
weights_.bottomRows(9));
715 const Eigen::MatrixXd &local_basis_integral,
const Quadrature &quadr,
716 Eigen::MatrixXd &rhs,
bool with_constraints)
720 logger().trace(
"#collocation points: {}", samples.rows());
721 logger().trace(
"#quadrature points: {}", quadr.
weights.size());
722 logger().trace(
"#non-vanishing bases: {}", rhs.cols());
725 if (!with_constraints)
732 const int num_kernels =
centers_.rows();
733 logger().trace(
"-- Solving system of size {}x{}", num_kernels, num_kernels);
734 weights_ = (A.transpose() * A).ldlt().solve(A.transpose() * rhs);
735 logger().trace(
"-- Solved!");
740 const int num_bases = rhs.cols();
759 Eigen::MatrixXd b = rhs - A *
weights_;
763 logger().trace(
"-- Solving system of size {}x{}", L.cols(), L.cols());
765 auto ldlt = (L.transpose() * A.transpose() * A * L).ldlt();
766 if (ldlt.info() == Eigen::NumericalIssue)
768 logger().error(
"-- WARNING: Numerical issues when solving the harmonic least square.");
770 weights_ += L * ldlt.solve(L.transpose() * A.transpose() * b);
772 logger().trace(
"-- Solved!");
776 logger().trace(
"-- Mean residual: {}", (A *
weights_ - rhs).array().abs().colwise().maxCoeff().mean());
780 Eigen::MatrixXd MM,
x, dx,
val;
784 for (
int d = 0; d < dim; ++d) {
790 std::cout << (MM.col(d).array() * quadr.
weights.array()).sum() - local_basis_integral(0, d) << std::endl;
792 MM.col((d+1)%dim).array() * quadr.
points.col(d).array()
793 + MM.col(d).array() * quadr.
points.col((d+1)%dim).array()
794 ) * quadr.
weights.array()).sum() - local_basis_integral(0, (dim == 2 ? 2 : (dim+d) )) << std::endl;
796 (quadr.
points.col(d).array() * MM.col(d).array()
799 ).sum() - local_basis_integral(0, (dim == 2 ? (3 + d) : (dim+dim+d))) << std::endl;