SplineSolver.h
Go to the documentation of this file.
1 #ifndef _SplineSolver_Spline_h_
2 #define _SplineSolver_Spline_h_
3 
4 #include <cmath>
5 #include <vector>
6 #include <boost/multi_array.hpp>
7 
8 #include <utl/EquationSolver.h>
9 
10 namespace Spline {
11 
12  typedef unsigned char dim_t;
13 
15  eNatural = 0, /* minimize total curvature */
16  ePeriodic = 1, /* for a polar coordinate */
17  eFirstDerivative = 2, /* set 1st derivatives at endpoints */
18  eSecondDerivative = 3 /* set 2nd derivatives at endpoints */
19  };
20 
22  {
24  const double vLeft = 0.0,
25  const double vRight = 0.0) :
26  fType(type), fLeft(vLeft), fRight(vRight)
27  {
28  }
29 
30  inline
31  bool
33  const
34  {
35  return fType == type;
36  }
37 
39  double fLeft;
40  double fRight;
41  };
42 
44  template<dim_t ADimension, typename AKnotVector, typename ABasisFunction>
45  class Solver
46  {
47  public:
48 
50  void
51  Configure(const dim_t idim, const AKnotVector& xs, const std::vector<ABasisFunction>& bs, const BoundaryCondition& bc)
52  {
53  fBCs[idim] = bc;
54  fSizes[idim] = bs.size();
55  if (fBuffer.size() < bs.size())
56  fBuffer.resize(bs.size());
57 
58  const size_t n = bs.size();
59  fInv[idim].resize(boost::extents[n][n]);
60  for (size_t i=0;i<n;++i)
61  for (size_t j=0;j<n;++j)
62  fInv[idim][i][j] = 0;
63 
64  for (size_t i = 0; i < n-2; ++i)
65  for (size_t k = i; k < i+3; ++k)
66  fInv[idim][i][k] = bs[k](xs[i]);
67 
68  if (bc == eFirstDerivative)
69  {
70  // set first derivative at x0 and xn
71  for (size_t der = 0; der < 2; ++der)
72  for (size_t k = 0; k < 3; ++k)
73  {
74  fInv[idim][n-2][k] = bs[k](xs[0],1);
75  fInv[idim][n-1][n-3+k] = bs[n-3+k](xs[n-3],1);
76  }
77  }
78 
79  if (bc == eNatural || bc == eSecondDerivative)
80  {
81  // second derivative zero at x0 and xn
82  for (size_t k = 0; k < 3; ++k)
83  {
84  fInv[idim][n-2][k] = bs[k](xs[0],2);
85  fInv[idim][n-1][n-3+k] = bs[n-3+k](xs[n-3],2);
86  }
87  }
88 
89  if (bc == ePeriodic)
90  {
91  // first and second derivative at x0 and xn equal
92  for (size_t der = 0; der < 2; ++der)
93  for (size_t k = 0; k < 3; ++k)
94  {
95  fInv[idim][n-2+der][k] = bs[k](xs[0],1+der);
96  fInv[idim][n-2+der][n-3+k] = -bs[n-3+k](xs[n-3],1+der);
97  }
98  }
99 
100  utl::InvertMatrix(n, fInv[idim]);
101  }
102 
103  void
104  operator()(double* cs)
105  const
106  {
107  size_t strides[ADimension];
108  strides[0] = 1;
109  for (short idim = 0; idim < short(ADimension-1); ++idim)
110  strides[idim+1] = strides[idim]*fSizes[idim];
111 
112  for (dim_t idim = 0; idim < ADimension; ++idim)
113  {
114  size_t strides2[ADimension+1];
115  strides2[0] = 1;
116  for (dim_t jdim = 0; jdim < ADimension; ++jdim)
117  {
118  const size_t n = jdim == idim ? 1 :
119  (jdim < idim ? fSizes[jdim] : fSizes[jdim]-2);
120  strides2[jdim+1] = strides2[jdim]*n;
121  }
122 
123  for (size_t i = 0; i < strides2[ADimension]; ++i)
124  {
125  size_t j = 0;
126  for (dim_t jdim = 0; jdim < ADimension; ++jdim)
127  {
128  if (idim != jdim)
129  j += ((i % strides2[jdim+1])/strides2[jdim]) * strides[jdim];
130  }
131 
132  // solve along a 1d slice in solution space
133  const size_t m = fSizes[idim];
134  for (size_t k = 0; k < m; ++k)
135  {
136  fBuffer[k] = 0;
137  for (size_t l = 0; l < m-2; ++l)
138  fBuffer[k] += fInv[idim][k][l]*cs[j + l*strides[idim]];
139  fBuffer[k] += fInv[idim][k][m-2]*fBCs[idim].fLeft;
140  fBuffer[k] += fInv[idim][k][m-1]*fBCs[idim].fRight;
141  }
142 
143  for (size_t l = 0; l < m; ++l)
144  cs[j + l*strides[idim]] = fBuffer[l];
145  }
146  }
147  }
148 
149  protected:
150  BoundaryCondition fBCs[ADimension];
151  size_t fSizes[ADimension];
152  mutable std::vector<double> fBuffer;
153  boost::multi_array<double,2> fInv[ADimension];
154  };
155 
156 } // NS Spline
157 
158 #endif
BoundaryConditionType
Definition: SplineSolver.h:14
Computes B-spline coefficients.
Definition: SplineSolver.h:45
BoundaryCondition(const BoundaryConditionType type=eNatural, const double vLeft=0.0, const double vRight=0.0)
Definition: SplineSolver.h:23
BoundaryConditionType fType
Definition: SplineSolver.h:38
void operator()(double *cs) const
Definition: SplineSolver.h:104
boost::multi_array< double, 2 > fInv[ADimension]
Definition: SplineSolver.h:153
BoundaryCondition fBCs[ADimension]
Definition: SplineSolver.h:150
std::vector< double > fBuffer
Definition: SplineSolver.h:152
bool operator==(const BoundaryConditionType type) const
Definition: SplineSolver.h:32
void InvertMatrix(const size_t n, AMatrix &a)
Invert A in place with Gauss-Jordan elimination and full pivoting.
size_t fSizes[ADimension]
Definition: SplineSolver.h:151
unsigned char dim_t
void Configure(const dim_t idim, const AKnotVector &xs, const std::vector< ABasisFunction > &bs, const BoundaryCondition &bc)
Prepare inversion matrix.
Definition: SplineSolver.h:51
constexpr double m
Definition: AugerUnits.h:121

, generated on Tue Sep 26 2023.