31#include "splinterRBF.H"
33splinterRBF::splinterRBF(
const Foam::word& kernelType,
bool normalize, Foam::scalar epsilon)
34: kernelType_(kernelType),
35 normalize_(normalize),
40splinterRBF::splinterRBF(
const Foam::dictionary& dict)
42 kernelType_ = dict.lookupOrDefault<Foam::word>(
"kernel",
"gaussian");
43 normalize_ = dict.lookupOrDefault<
bool>(
"normalize",
true);
44 epsilon_ = dict.lookupOrDefault<Foam::scalar>(
"epsilon", 1.0);
47splinterRBF::~splinterRBF() =
default;
49SPLINTER::RadialBasisFunctionType splinterRBF::getKernelType(
const Foam::word& kernelType)
51 if (kernelType ==
"gaussian")
53 return SPLINTER::RadialBasisFunctionType::GAUSSIAN;
55 else if (kernelType ==
"linear")
57 return SPLINTER::RadialBasisFunctionType::LINEAR;
59 else if (kernelType ==
"cubic")
61 return SPLINTER::RadialBasisFunctionType::CUBIC;
63 else if (kernelType ==
"quintic")
65 return SPLINTER::RadialBasisFunctionType::QUINTIC;
67 else if (kernelType ==
"multiquadric")
69 return SPLINTER::RadialBasisFunctionType::MULTIQUADRIC;
71 else if (kernelType ==
"inverse_multiquadric")
73 return SPLINTER::RadialBasisFunctionType::INVERSE_MULTIQUADRIC;
75 else if (kernelType ==
"inverse_quadratic")
77 return SPLINTER::RadialBasisFunctionType::INVERSE_QUADRIC;
79 else if (kernelType ==
"thin_plate_spline")
81 return SPLINTER::RadialBasisFunctionType::THIN_PLATE_SPLINE;
86 <<
"Unknown kernel type: " << kernelType
87 <<
". Valid options are: gaussian, linear, cubic, quintic, multiquadric, "
88 <<
"inverse_multiquadric, inverse_quadratic, thin_plate_spline"
89 << Foam::exit(Foam::FatalError);
90 return SPLINTER::RadialBasisFunctionType::GAUSSIAN;
94void splinterRBF::fit(
const Eigen::MatrixXd& X,
const Eigen::VectorXd& y)
96 SPLINTER::DataTable data;
101 xMean_ = X.rowwise().mean();
104 Eigen::MatrixXd centered = X.colwise() - xMean_;
105 xStd_ = (centered.array().square().rowwise().sum() / (X.cols() - 1)).sqrt();
109 xStd_ = Eigen::VectorXd::Ones(X.rows());
112 for(
int i=0; i<xStd_.size(); ++i) {
113 if(xStd_(i) < 1e-16) xStd_(i) = 1.0;
116 Eigen::MatrixXd X_norm = (X.colwise() - xMean_).array().colwise() / xStd_.array();
122 Eigen::VectorXd yCentered = y.array() - yMean_;
123 yStd_ = std::sqrt(yCentered.array().square().sum() / (y.size() - 1));
130 if(yStd_ < 1e-16) yStd_ = 1.0;
132 Eigen::VectorXd y_norm = (y.array() - yMean_) / yStd_;
134 for (
int i = 0; i < X_norm.cols(); ++i)
136 data.addSample(X_norm.col(i), y_norm(i));
141 for (
int i = 0; i < X.cols(); ++i)
143 data.addSample(X.col(i), y(i));
147 impl_ = std::make_unique<SPLINTER::RBFSpline>(data, getKernelType(kernelType_), epsilon_);
150Foam::scalar splinterRBF::predict(
const Eigen::VectorXd& x)
154 Eigen::VectorXd x_norm = (x - xMean_).array() / xStd_.array();
155 Foam::scalar y_pred_norm = impl_->eval(x_norm);
156 return y_pred_norm * yStd_ + yMean_;
158 return impl_->eval(x);
161Eigen::VectorXd splinterRBF::predict(
const Eigen::MatrixXd& X)
163 Eigen::VectorXd result(X.cols());
167 Eigen::MatrixXd X_norm = (X.colwise() - xMean_).array().colwise() / xStd_.array();
169 for (
int i = 0; i < X.cols(); ++i)
171 result(i) = impl_->eval(X_norm.col(i));
173 return result.array() * yStd_ + yMean_;
176 for (
int i = 0; i < X.cols(); ++i)
178 result(i) = impl_->eval(X.col(i));
183void splinterRBF::printInfo()
185 Foam::Info <<
"splinterRBF Model Info:" << Foam::endl;
186 Foam::Info <<
"\t Kernel Type: " << kernelType_ << Foam::endl;
187 Foam::Info <<
"\t Normalize: " << (normalize_ ?
"true" :
"false") << Foam::endl;
188 Foam::Info <<
"\t Epsilon: " << epsilon_ << Foam::endl;