LCOV - code coverage report
Current view: top level - ttsketch - BasisFunc.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 6 6 100.0 %
Date: 2026-11-05 10:19:04 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef __PLUMED_ttsketch_BasisFunc_h
       2             : #define __PLUMED_ttsketch_BasisFunc_h
       3             : #include "tools/Matrix.h"
       4             : #include <utility>
       5             : #include <vector>
       6             : 
       7             : namespace PLMD {
       8             : namespace ttsketch {
       9             : 
      10             : // Represents a 1D basis expansion for one CV dimension, used to express the
      11             : // bias potential as a tensor train over basis function indices. Two types are
      12             : // supported:
      13             : //
      14             : //   Fourier (kernel_=false): orthonormal sinusoidal functions on [a, b].
      15             : //     phi_1(x) = 1/sqrt(2L)
      16             : //     phi_{2k}(x) = 1/sqrt(L) * cos(pi*(x-shift)*k/L)   (k = 1, 2, ...)
      17             : //     phi_{2k+1}(x) = 1/sqrt(L) * sin(pi*(x-shift)*k/L) (k = 1, 2, ...)
      18             : //
      19             : //   Kernel (kernel_=true): periodized Gaussian kernels on a uniform grid,
      20             : //     plus a constant function phi_1(x) = 1.
      21             : //
      22             : // "Conv" (convolution) mode pre-smooths basis functions by convolving with a
      23             : // Gaussian of width w_. For Fourier bases this multiplies each harmonic by
      24             : // exp(-(pi*w*k)^2 / (2L^2)); for kernel bases it widens each kernel
      25             : // analytically. This yields smooth bias forces at no extra runtime cost.
      26             : class BasisFunc {
      27             : 
      28             : private:
      29             :   std::pair<double, double> dom_; // CV domain [a, b]
      30             :   int nbasis_;                    // number of basis functions n (including constant phi_1)
      31             :   double L_;                      // domain half-length: L = (b-a)/2
      32             :   double shift_;                  // domain midpoint: shift = (a+b)/2
      33             :   double inv_L_;                  // 1/L, precomputed to avoid repeated division in Fourier evaluations
      34             :   double sqrt_inv_L_;             // 1/sqrt(L), precomputed to avoid repeated pow() in Fourier evaluations
      35             :   double inv_sqrt_2L_;            // 1/sqrt(2L), the value of phi_1(x) for the Fourier basis
      36             :   double w_;                      // smoothing width for conv mode (Fourier: sigma in x-units; kernel: Gaussian hill width)
      37             :   bool kernel_;                   // true = kernel basis, false = Fourier basis
      38             :   double dx_;                     // kernel basis function width (std dev of each periodized Gaussian)
      39             :   std::vector<double> centers_;   // centers of kernel basis functions (size nbasis-1, uniformly spaced)
      40             :   Matrix<double> ginv_;           // pseudo-inverse of the Gram matrix (kernel basis only)
      41             :   double gramCondition_;          // ratio between the largest and the smallest eigenvalue of the Gram matrix
      42             :   int gramDropped_;               // eigen-directions of the Gram matrix left out of ginv_ (see the constructor)
      43             :   Matrix<double> gram_;           // Gram matrix: gram_(i,j) = int phi_i(x)*phi_j(x) dx (kernel basis only)
      44             :   std::vector<double> damp_;      // conv mode, Fourier basis: damp_[k] = exp(-(pi*w*k/L)^2/2), k = 0..nbasis/2
      45             : 
      46             : public:
      47             :   BasisFunc();
      48             :   BasisFunc(std::pair<double, double> dom, int nbasis, double w, bool kernel, double dx);
      49             :   // Evaluate Fourier basis function phi_pos(x) (1-indexed, not convolved).
      50             :   double fourier(double x, int pos) const;
      51             :   // Evaluate kernel basis function phi_pos(x) (1-indexed, not convolved).
      52             :   // Uses periodic images (k=-1,0,1) so the function wraps smoothly across domain boundaries.
      53             :   double gaussian(double x, int pos) const;
      54             :   // Derivative of fourier(x, pos) w.r.t. x.
      55             :   double fourierd(double x, int pos) const;
      56             :   // Derivative of gaussian(x, pos) w.r.t. x.
      57             :   double gaussiand(double x, int pos) const;
      58             :   // Evaluate basis function phi_pos(x). If conv=true, applies Gaussian smoothing of width w_.
      59             :   double operator()(double x, int pos, bool conv) const;
      60             :   // Derivative of operator()(x, pos, conv) w.r.t. x.
      61             :   double grad(double x, int pos, bool conv) const;
      62             :   // Values and derivatives of all the basis functions at x:
      63             :   // phi[pos-1] = operator()(x, pos, conv) and dphi[pos-1] = grad(x, pos, conv), pos = 1..nbasis.
      64             :   // Equivalent to nbasis calls of operator() and grad(), but the Fourier harmonics are
      65             :   // obtained from a single sin/cos pair by the angle-addition recurrence.
      66             :   void evalAll(double x, bool conv, double* phi, double* dphi) const;
      67             :   int nbasis() const {
      68          92 :     return this->nbasis_;
      69             :   }
      70             :   const std::pair<double, double>& dom() const {
      71             :     return this->dom_;
      72             :   }
      73             :   double w() const {
      74             :     return this->w_;
      75             :   }
      76             :   // Integral of phi_pos over the domain: int_a^b phi_pos(x) dx.
      77             :   // Used to compute the partition function Z in covMat().
      78             :   double int0(int pos) const;
      79             :   // Integral of x*phi_pos over the domain: int_a^b x*phi_pos(x) dx.
      80             :   // Used to compute the marginal mean E[x] in covMat().
      81             :   double int1(int pos) const;
      82             :   // Integral of x^2*phi_pos over the domain: int_a^b x^2*phi_pos(x) dx.
      83             :   // Used to compute E[x^2] for the marginal variance in covMat().
      84             :   double int2(int pos) const;
      85             :   bool kernel() const {
      86        3596 :     return this->kernel_;
      87             :   }
      88             :   const Matrix<double>& ginv() const {
      89             :     return this->ginv_;
      90             :   }
      91             :   const Matrix<double>& gram() const {
      92             :     return this->gram_;
      93             :   }
      94             :   // Eigenvalues of the Gram matrix smaller than gramTolerance() times the largest one are
      95             :   // left out of ginv(): their directions are combinations of the basis functions that
      96             :   // vanish (to working precision) and whose dual coefficients would be meaningless.
      97             :   static constexpr double gramTolerance() {
      98             :     return 1e-10;
      99             :   }
     100             :   double gramCondition() const {
     101           3 :     return this->gramCondition_;
     102             :   }
     103             :   int gramDropped() const {
     104           3 :     return this->gramDropped_;
     105             :   }
     106             :   double center(int pos) const {
     107         189 :     return this->kernel_ ? this->centers_[pos - 1] : 0.0;
     108             :   }
     109             :   double dx() const {
     110         192 :     return this->dx_;
     111             :   }
     112             : };
     113             : 
     114             : }
     115             : }
     116             : 
     117             : #endif

Generated by: LCOV version 1.16