You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
6.5 KiB
146 lines
6.5 KiB
2 years ago
|
#ifndef MEDUSA_BITS_APPROXIMATIONS_RBFBASIS_HPP_
|
||
|
#define MEDUSA_BITS_APPROXIMATIONS_RBFBASIS_HPP_
|
||
|
|
||
|
/**
|
||
|
* @file
|
||
|
* Implementation of RBF basis.
|
||
|
*/
|
||
|
|
||
|
#include <medusa/bits/utils/assert.hpp>
|
||
|
#include "RBFBasis_fwd.hpp"
|
||
|
|
||
|
namespace mm {
|
||
|
|
||
|
/// @cond
|
||
|
template <class vec_t, class RBFType>
|
||
|
typename RBFBasis<vec_t, RBFType>::scalar_t RBFBasis<vec_t, RBFType>::eval(
|
||
|
int index, const vector_t& point, const std::vector<vector_t>& support) const {
|
||
|
assert_msg(0 <= index && index < size_, "Basis index %d out of range [0, %d)", index, size_);
|
||
|
assert_msg(static_cast<int>(support.size()) >= size_,
|
||
|
"Not enough support points given for this basis size, got %d support points for "
|
||
|
"basis size %d.", support.size(), size_);
|
||
|
return rbf_((point-support[index]).squaredNorm());
|
||
|
}
|
||
|
|
||
|
template <class RBFType, class vec_t>
|
||
|
template <typename operator_t>
|
||
|
typename vec_t::scalar_t RBFBasis<RBFType, vec_t>::evalOp(int index, const vector_t& point,
|
||
|
operator_t op, const std::vector<vector_t>& support, scalar_t scale) const {
|
||
|
return op.apply(*this, index, point, support, scale);
|
||
|
}
|
||
|
/// @endcond
|
||
|
|
||
|
template <class RBFType, class vec_t>
|
||
|
typename vec_t::scalar_t RBFBasis<RBFType, vec_t>::evalOp(
|
||
|
int index, const vector_t& point, Lap<dim> op, const std::vector<vector_t>& support,
|
||
|
scalar_t scale) const {
|
||
|
assert_msg(0 <= index && index < size_, "Basis index %d out of range [0, %d)", index, size_);
|
||
|
assert_msg(static_cast<int>(support.size()) >= size_,
|
||
|
"Not enough support points given for this basis size, got %d support points for "
|
||
|
"basis size %d.", support.size(), size_);
|
||
|
return rbf_((point - support[index]).squaredNorm(), op)/scale/scale;
|
||
|
}
|
||
|
|
||
|
template <class RBFType, class vec_t>
|
||
|
typename vec_t::scalar_t RBFBasis<RBFType, vec_t>::evalOp(
|
||
|
int index, const vector_t& point, Der1<dim> op, const std::vector<vector_t>& support,
|
||
|
scalar_t scale) const {
|
||
|
assert_msg(0 <= index && index < size_, "Basis index %d out of range [0, %d)", index, size_);
|
||
|
assert_msg(static_cast<int>(support.size()) >= size_,
|
||
|
"Not enough support points given for this basis size, got %d support points for "
|
||
|
"basis size %d.", support.size(), size_);
|
||
|
vec_t p = point - support[index];
|
||
|
return 2*p[op.var]*rbf_(p.squaredNorm(), 1)/scale;
|
||
|
}
|
||
|
|
||
|
template <class RBFType, class vec_t>
|
||
|
typename vec_t::scalar_t RBFBasis<RBFType, vec_t>::evalOp(
|
||
|
int index, const vector_t& point, Der2<dim> op, const std::vector<vector_t>& support,
|
||
|
scalar_t scale) const {
|
||
|
assert_msg(0 <= index && index < size_, "Basis index %d out of range [0, %d)", index, size_);
|
||
|
assert_msg(static_cast<int>(support.size()) >= size_,
|
||
|
"Not enough support points given for this basis size, got %d support points for "
|
||
|
"basis size %d.", support.size(), size_);
|
||
|
vec_t p = point - support[index];
|
||
|
scalar_t r2 = p.squaredNorm();
|
||
|
double res = 4*p[op.var1]*p[op.var2]*rbf_(r2, 2);
|
||
|
if (op.var1 == op.var2) {
|
||
|
res += 2*rbf_(r2, 1);
|
||
|
}
|
||
|
return res/scale/scale;
|
||
|
}
|
||
|
|
||
|
template <class vec_t, class RBFType>
|
||
|
typename RBFBasis<vec_t, RBFType>::scalar_t RBFBasis<vec_t, RBFType>::evalAt0(
|
||
|
int index, const std::vector<vector_t>& support) const {
|
||
|
assert_msg(0 <= index && index < size_, "Basis index %d out of range [0, %d)", index, size_);
|
||
|
assert_msg(static_cast<int>(support.size()) >= size_,
|
||
|
"Not enough support points given for this basis size, got %d support points for "
|
||
|
"basis size %d.", support.size(), size_);
|
||
|
return rbf_(support[index].squaredNorm());
|
||
|
}
|
||
|
|
||
|
template <class RBFType, class vec_t>
|
||
|
typename vec_t::scalar_t
|
||
|
RBFBasis<RBFType, vec_t>::evalOpAt0(int index, const Lap<dim>& lap,
|
||
|
const std::vector<vector_t>& support, scalar_t scale) const {
|
||
|
assert_msg(0 <= index && index < size_, "Basis index %d out of range [0, %d)", index, size_);
|
||
|
assert_msg(static_cast<int>(support.size()) >= size_,
|
||
|
"Not enough support points given for this basis size, got %d support points for "
|
||
|
"basis size %d.", support.size(), size_);
|
||
|
return rbf_(support[index].squaredNorm(), lap)/scale/scale;
|
||
|
}
|
||
|
|
||
|
template <class RBFType, class vec_t>
|
||
|
typename vec_t::scalar_t RBFBasis<RBFType, vec_t>::evalOpAt0(int index, const Der1<dim>& der1,
|
||
|
const std::vector<vector_t>& support, scalar_t scale) const {
|
||
|
assert_msg(0 <= index && index < size_, "Basis index %d out of range [0, %d)", index, size_);
|
||
|
assert_msg(static_cast<int>(support.size()) >= size_,
|
||
|
"Not enough support points given for this basis size, got %d support points for "
|
||
|
"basis size %d.", support.size(), size_);
|
||
|
assert_msg(der1.var >= 0, "Index of derived variable %d should be higher or equal to 0.",
|
||
|
der1.var);
|
||
|
assert_msg(der1.var < dim, "Index of derived variable %d should be lower"
|
||
|
" than the number of dimensions %d", der1.var, dim);
|
||
|
|
||
|
const auto& s = support[index];
|
||
|
scalar_t r2 = s.squaredNorm();
|
||
|
scalar_t v = rbf_(r2, 1);
|
||
|
v *= -2*s[der1.var];
|
||
|
return v/scale;
|
||
|
}
|
||
|
|
||
|
template <class RBFType, class vec_t>
|
||
|
typename vec_t::scalar_t RBFBasis<RBFType, vec_t>::evalOpAt0(int index, const Der2<dim>& der2,
|
||
|
const std::vector<vector_t>& support, scalar_t scale) const {
|
||
|
assert_msg(0 <= index && index < size_, "Basis index %d out of range [0, %d)", index, size_);
|
||
|
assert_msg(static_cast<int>(support.size()) >= size_,
|
||
|
"Not enough support points given for this basis size, got %d support points for "
|
||
|
"basis size %d.", support.size(), size_);
|
||
|
assert_msg(der2.var1 >= 0 && der2.var2 >=0, "Indexes of derived variables %d and %d should"
|
||
|
" be both higher or equal to 0.",
|
||
|
der2.var1, der2.var2);
|
||
|
assert_msg(der2.var1 < dim && der2.var2 < dim , "Index of derived variable %d and %d should"
|
||
|
" both be lower than the number of dimensions %d", der2.var1, der2.var2, dim);
|
||
|
|
||
|
auto& s = support[index];
|
||
|
scalar_t r2 = s.squaredNorm();
|
||
|
int d1 = der2.var1;
|
||
|
int d2 = der2.var2;
|
||
|
scalar_t v = 4*s[d1]*s[d2]*rbf_(r2, 2);
|
||
|
if (d1 == d2) {
|
||
|
v += 2*rbf_(r2, 1);
|
||
|
}
|
||
|
return v/scale/scale;
|
||
|
}
|
||
|
|
||
|
/// Output basic info about given basis.
|
||
|
template <typename V, typename R>
|
||
|
std::ostream& operator<<(std::ostream& os, const RBFBasis<V, R>& m) {
|
||
|
return os << "RBF basis " << m.dim << "D, " << m.size() << "x " << m.rbf();
|
||
|
}
|
||
|
|
||
|
} // namespace mm
|
||
|
|
||
|
#endif // MEDUSA_BITS_APPROXIMATIONS_RBFBASIS_HPP_
|