29#include "bitpit_private_lapacke.hpp"
31#include "bitpit_common.hpp"
32#include "bitpit_operators.hpp"
65 : m_supportRadii(1, 1.)
88 : m_fields(other.m_fields), m_mode(other.m_mode),
89 m_supportRadii(other.m_supportRadii), m_typef(other.m_typef),
90 m_fPtr(other.m_fPtr), m_error(other.m_error), m_value(other.m_value),
91 m_weight(other.m_weight), m_activeNodes(other.m_activeNodes),
92 m_maxFields(other.m_maxFields), m_nodes(other.m_nodes),
93 m_polyEnabled(other.m_polyEnabled), m_polyActiveBasis(other.m_polyActiveBasis),
94 m_polynomial(other.m_polynomial)
105 std::swap(m_fields, other.m_fields);
106 std::swap(m_mode, other.m_mode);
107 std::swap(m_supportRadii, other.m_supportRadii);
108 std::swap(m_typef, other.m_typef);
109 std::swap(m_fPtr, other.m_fPtr);
110 std::swap(m_error, other.m_error);
111 std::swap(m_value, other.m_value);
112 std::swap(m_weight, other.m_weight);
113 std::swap(m_activeNodes, other.m_activeNodes);
114 std::swap(m_maxFields, other.m_maxFields);
115 std::swap(m_nodes, other.m_nodes);
116 std::swap(m_polyEnabled, other.m_polyEnabled);
117 std::swap(m_polyActiveBasis, other.m_polyActiveBasis);
118 std::swap(m_polynomial, other.m_polynomial);
250 nActive += (
int) active;
262 std::vector<int> activeSet;
268 activeSet.push_back(i);
316 for(
int index : list) {
357 for(
int index : list) {
377 m_supportRadii.resize(1);
378 m_supportRadii[0] = radius;
387 m_supportRadii = radius;
399 return m_supportRadii[0];
411 bool variableSupportRadius = (m_supportRadii.size() != 1);
412 if (!variableSupportRadius) {
413 return m_supportRadii[0];
416 return m_supportRadii[i];
446 if(id<0 || id >= m_fields) {
450 if((
int)(value.size()) != m_fields) {
451 log::cout() <<
"Mismatch dimension between value vector size and number of data attached to rbf.";
452 log::cout() <<
"This may lead to nasty errors. Check it with getDataCount()!" << std::endl;
453 log::cout() <<
"Data could not be set" << std::endl;
459 for( i=0; i<m_fields; ++i ) {
463 for( i=0; i<m_fields; ++i ) {
478 if(id<0 || id >= m_fields) {
484 if((
int)(value.size()) != size) {
485 log::cout() <<
"Mismatch dimension between data vector and current data container. One or both does not match RBFKernel nodes count.";
486 log::cout() <<
"This may lead to nasty errors. Use fitDataToNodes to reshape container or fit your data vector first!" << std::endl;
487 log::cout() <<
"Data could not be set" << std::endl;
507 log::cout() <<
"Maximum number of data set reached" << std::endl;
528 log::cout() <<
"Maximum number of data set reached" << std::endl;
545 if(id<0 || id >=m_fields) {
567 std::sort(list.begin(), list.end(), std::greater<int>());
575 return ((nInitialFields - nFinalFields) ==
static_cast<int>(list.size()));
599 std::vector<double> values(m_fields, 0.);
608 for( j=0; j<m_fields; ++j) {
609 values[j] += basis *
m_weight[j][i];
616 for (j = 0; j < m_fields; ++j) {
618 std::vector<double> basis = evalPolynomialBasis(point);
621 values[j] += polynomialCoefficients[iactive] * basis[z];
640 std::vector<double> values(m_fields, 0.);
644 if(jnode<0 || jnode>=
m_nodes ) {
653 for( j=0; j<m_fields; ++j) {
654 values[j] += basis *
m_weight[j][i];
661 for (j = 0; j < m_fields; ++j) {
663 std::vector<double> basis = evalPolynomialBasis(jnode);
666 values[j] += polynomialCoefficients[iactive] * basis[z];
690 initializePolynomial();
694 initializePolynomialActiveBasis();
700 int nActive = activeSet.size();
703 int nS = nActive + nPoly;
710 std::vector<int> ipiv(nS);
713 std::vector<double> A(lda * nS);
714 std::vector<double> b(ldb * nrhs);
716 for (
int j = 0; j < nrhs; ++j) {
717 for (
const auto &i : activeSet) {
724 for (
const auto &i : activeSet) {
725 for (
const auto &j : activeSet) {
727 int row = k % nActive;
728 int col = k / nActive;
737 for (
int i = 0; i < nActive; ++i) {
738 std::vector<double> polynomialTerms = evalPolynomialBasis(activeSet[i]);
740 for (
const double &val : polynomialTerms) {
741 A[(j + nActive) * nS + i] = val;
742 A[i * nS + (j + nActive)] = val;
748 info = LAPACKE_dgesv(LAPACK_COL_MAJOR, nS, nrhs, A.data(), lda, ipiv.data(), b.data(), ldb);
751 printf(
"The diagonal element of the triangular factor of the linear system matrix \n" );
752 printf(
"U(%i,%i) is zero, so that matrix is singular;\n", info, info );
753 printf(
"the solution could not be computed.\n" );
759 for (
int j = 0; j < nrhs; ++j) {
762 for (
const auto &i : activeSet) {
769 for (
int j = 0; j < nrhs; ++j) {
773 polynomialCoefficients[iactive] = b[j * ldb + nActive + i];
794 std::vector<double> local(m_fields);
802 for( j=0; j<m_fields; ++j) {
806 m_error[i] =
norm2(local);
809 std::ios::fmtflags streamFlags(
log::cout().flags());
812 while( error > tolerance) {
858 for (
int i=0;i<m_fields; ++i) {
886 return (*m_fPtr)(dist);
919 for(
auto error : m_error ){
923 if( error > maxError ) {
948 double maxError(0), relError, realValue;
949 std::vector<double> reconValues;
951 for(
int iX=0; iX<
m_nodes; ++iX ) {
956 for(
auto &val : reconValues ) {
958 relError += std::pow( (val - realValue), 2 );
963 relError = sqrt(relError);
964 m_error[i] = relError;
966 if( relError > maxError ) {
990 initializePolynomial();
994 initializePolynomialActiveBasis();
1000 int nActive = activeSet.size();
1003 int nS = nActive + nPoly;
1007 int n ,m, lda, ldb, info, rank;
1008 double rcond = -1.0;
1016 std::vector<double> A(lda * n);
1017 std::vector<double> b(ldb * nrhs, 0.0);
1018 std::vector<double> s(m);
1020 for (
int j = 0; j < nrhs; ++j) {
1021 for (
int i = 0; i < m; ++i) {
1022 int k = j * ldb + i;
1028 for (
const auto &i : activeSet) {
1029 for (
int j = 0; j < nP; ++j) {
1041 for (
int i = 0; i < nActive; ++i) {
1042 std::vector<double> polynomialTerms = evalPolynomialBasis(activeSet[i]);
1044 for (
const double &val : polynomialTerms) {
1045 A[lda * i + (nP + j)] = val;
1054 for (
int i = 0; i < nP; ++i) {
1055 std::vector<double> polynomialTerms = evalPolynomialBasis(i);
1057 for (
const double &val : polynomialTerms) {
1058 A[(lda * (nActive + j) + i)] = val;
1064 info = LAPACKE_dgelsd(LAPACK_COL_MAJOR, lda, nS, nrhs, A.data(), lda, b.data(), ldb, s.data(), rcond, &rank);
1072 for (
int j = 0; j < nrhs; ++j) {
1077 for(
const auto &i : activeSet ) {
1084 for (
int j = 0; j < nrhs; ++j) {
1088 polynomialCoefficients[iactive] = b[j * ldb + nActive + i];
1118RBFKernel::LinearPolynomial::LinearPolynomial()
1128void RBFKernel::LinearPolynomial::clear()
1143void RBFKernel::LinearPolynomial::initialize()
1145 std::array<double, 3> m_origin;
1148 double *coeffs = getCoefficients();
1149 for (
auto i = 0; i < getCoefficientCount(); i++) {
1158void RBFKernel::LinearPolynomial::setDimension(
int dim)
1160 m_dim = (dim > 0) ? (dim < 4 ? dim : 3) : 0;
1167void RBFKernel::LinearPolynomial::setDataCount(
int fields)
1169 m_fields = std::max(0, fields);
1177void RBFKernel::LinearPolynomial::evalBasis(
const double *x,
double *basis)
1183 for (
int i = 0; i < m_dim; ++i) {
1184 basis[i + 1] = x[i];
1230 m_node(other.m_node)
1253 std::swap(m_node, other.m_node);
1286std::vector<int>
RBF::addNode(
const std::vector<std::array<double,3>> &node )
1289 std::vector<int> ids;
1291 ids.resize( node.size() );
1293 for(
auto &
id:ids ) {
1298 m_node.insert(
m_node.end(), node.begin(), node.end() );
1333 std::sort(list.begin(), list.end(), std::greater<int>());
1336 for(
int id : list) {
1341 return ((nInitialNodes - nFinalNodes) ==
static_cast<int>(list.size()));
1359double RBF::calcDist(
int i,
int j)
1369double RBF::calcDist(
const std::array<double,3>& point,
int j)
1380void RBF::initializePolynomialActiveBasis()
1389 std::array<double, 3> coord(
m_node[0]);
1394 for (
int d = 0; d < 2; ++d) {
1395 for (
const auto &i : activeSet) {
1396 const std::array<double, 3> &point =
m_node[i];
1397 if (!utils::DoubleFloatingEqual()(coord[d], point[d])) {
1408void RBF::initializePolynomial()
1421std::vector<double> RBF::evalPolynomialBasis(
int i)
1424 std::vector<double> result(nPoly);
1429 const std::array<double, 3> &point =
m_node[i];
1432 m_polynomial.evalBasis(point.data(), completeBasis.data());
1436 result[k] = completeBasis[j];
1448std::vector<double> RBF::evalPolynomialBasis(
const std::array<double,3> &point)
1451 std::vector<double> result(nPoly);
1457 m_polynomial.evalBasis(point.data(), completeBasis.data());
1461 result[k] = completeBasis[j];
1480 return std::pow(1.-dist,4)*(4.*dist+1.);
1505 double eps = std::pow(-1.0*std::log(0.1),0.5);
1507 return std::exp(-1.0*std::pow(dist*eps,2));
1517 double eps = std::pow(-1.0*std::log(0.05),0.5);
1519 return std::exp(-1.0*std::pow(dist*eps,2));
1529 double eps = std::pow(-1.0*std::log(0.01),0.5);
1531 return std::exp(-1.0*std::pow(dist*eps,2));
1545 return (1.0-std::pow(dist,2));
1560 return (1.0-std::pow(dist,3));
1575 return (1.0- 2.0*dist + std::pow(dist,2));
1590 return (1.0-3.0*std::pow(dist,2)+2.0*std::pow(dist,3));
1605 return (1.0- 4.0*std::pow(dist,3) + 3.0*std::pow(dist,4));
1620 return (1.0 -3.0*dist +3.0*std::pow(dist,2) - std::pow(dist,3));
1635 return (1.0 -6.0*std::pow(dist,2) + 8.0*std::pow(dist,3) - 3.0*std::pow(dist,4));
1650 return (1.0 -10.0*std::pow(dist,3) +15.0*std::pow(dist,4) -6.0*std::pow(dist,5));
1665 return 0.5 + 0.5 * std::cos(dist*BITPIT_PI);
1677 return dist * dist * std::log(dist);
Base class to handle Radial Basis Function with a large set of nodes.
std::vector< std::vector< double > > m_weight
void enablePolynomial(bool enable=true)
void setMode(RBFMode mode)
std::vector< std::vector< double > > m_value
void swap(RBFKernel &x) noexcept
double getSupportRadius()
void setSupportRadius(double)
void setFunction(RBFBasisFunction)
const std::vector< std::vector< double > > & getWeights() const
RBFBasisFunction getFunctionType()
std::vector< double > evalRBF(const std::array< double, 3 > &)
std::vector< int > m_polyActiveBasis
double evalBasisPair(int i, int j)
std::vector< int > getActiveSet()
void setDataToNode(int, const std::vector< double > &)
std::vector< bool > m_activeNodes
void setDataToAllNodes(int, const std::vector< double > &)
LinearPolynomial m_polynomial
void deactivateAllNodes()
int getPolynomialWeightsCount()
Class to handle Radial Basis Function with a large set of 3D points as nodes.
void swap(RBF &x) noexcept
int addNode(const std::array< double, 3 > &)
std::vector< std::array< double, 3 > > m_node
RBF(RBFBasisFunction=RBFBasisFunction::WENDLANDC2)
RBF & operator=(RBF other)
uint16_t getCoefficientCount() const
void clear(bool release=true)
void initialize(uint8_t degree, uint8_t dimensions, const std::array< double, 3 > &origin, int nFields=1, bool release=true)
const double * getCoefficients() const
double norm2(const std::array< T, d > &x)
RBFBasisFunction
Enum class defining types of RBF kernel functions that could be used in bitpit::RBF class.
RBFMode
Enum class defining behaviour of the bitpit::RBF class.
Logger & cout(log::Level defaultSeverity, log::Visibility defaultVisibility)
double wendlandc2(double)