lsfits.h
Go to the documentation of this file.
1 /*
2 This file is part of the Ristra wonton project.
3 Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/wonton/blob/master/LICENSE
5 */
6 
7 
8 
9 #ifndef WONTON_LS_FITS_H_
10 #define WONTON_LS_FITS_H_
11 
12 #include <algorithm>
13 #include <stdexcept>
14 #include <string>
15 #include <vector>
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <iostream>
20 
22 #include "wonton/support/Point.h"
23 #include "wonton/support/Matrix.h"
24 #include "wonton/support/svd.h"
25 
26 namespace Wonton {
27 
28 
42 template<int D, typename CoordSys = CartesianCoordinates>
44  std::vector<double> const & vals) {
45 
46  CoordSys::template verify_coordinate_system<D>();
47 
48  Point<D> coord0 = coords[0];
49 
50  double val0 = vals[0];
51 
52  // There are nvals but the first is the reference point where we
53  // are trying to compute the gradient; so the matrix sizes etc
54  // will only be nvals-1
55 
56  int nvals = vals.size();
57 
58  // Each row of A contains the components of the vector from
59  // coord0 to the candidate point being used in the Least Squares
60  // approximation (X_i-X_0).
61 
62  Matrix A(nvals-1, D);
63  for (int i = 0; i < nvals-1; ++i) {
64  for (int j = 0; j < D; ++j)
65  A[i][j] = coords[i+1][j]-coord0[j];
66  }
67 
68 
69  // A is a matrix of size nvals-1 by D (where D is the space
70  // dimension). So transpose(A)*A is D by D
71 
72  Matrix AT = A.transpose();
73 
74  Matrix ATA = AT*A;
75 
76  // Each entry/row of F contains the difference between the
77  // function value at the candidate point and the function value
78  // at the point where we are computing (f-f_0)
79 
80  std::vector<double> F(nvals-1);
81  for (int i = 0; i < nvals-1; ++i)
82  F[i] = vals[i+1]-val0;
83 
84  // F is a vector of nvals. So transpose(A)*F is vector of D
85  // (where D is the space dimension)
86 
87  Vector<D> ATF = Vector<D>(AT*F);
88 
89  // Inverse of ATA
90 
91  Matrix ATAinv = ATA.inverse();
92 
93  // Gradient of length D
94 
95  auto gradient = ATAinv*ATF;
96 
97  // Corrections for curvilinear coordinates
98 
99  CoordSys::modify_gradient(gradient, coord0);
100 
101  // Return
102 
103  return ATAinv*ATF;
104 }
105 
106 
120 template<int D>
121 // int N = D*(D+3)/2;
122 Vector<D*(D+3)/2> ls_quadfit(std::vector<Point<D>> const & coords,
123  std::vector<double> const & vals,
124  bool const boundary_element) {
125 
126  double val0 = vals[0];
127 
128  // There are nvals but the first is the reference point where we
129  // are trying to compute the quadfit; so the matrix sizes etc
130  // will only be nvals-1
131 
132  int nvals = vals.size();
133 
134  if (boundary_element) {
135  // Not enough values to do a quadratic fit - drop down to linear fit
136 
137  Vector<D> grad = ls_gradient(coords, vals);
138  Vector<D*(D+3)/2> result;
139  for (int i = 0; i < D*(D+3)/2; i++) result[i] = 0.0;
140  // Fill in the begining of the vector with gradient terms
141  for (int i = 0; i < D; i++) result[i] = grad[i];
142  return result;
143  }
144 
145 
146  // Each row of A contains the components of the vector from
147  // coord0 to the candidate point being used in the Least Squares
148  // approximation (X_i-X_0), up to quadratic order. Index j0
149  // labels the columns up to D (e.g., gradient). Index j1
150  // labels the D(D+1)/2 extra columns for the quadratic terms.
151  // Index i labels rows for data points away from the center of
152  // the point cloud (i.e., array[0]) with nvals points, contained
153  // in the array coords(nvals,D).
154 
155  Matrix A(nvals-1, D*(D+3)/2); // don't include 0th point
156  for (int i = 0; i < nvals-1; i++) {
157  int j1 = D; // index of colunns with quadrtic terms
158  for (int j0 = 0; j0 < D; ++j0) {
159  A[i][j0] = coords[i+1][j0]-coords[0][j0];
160  // Add columns with the remaining quadratic delta terms
161  // for each i, starting at D+j, reusing linear delta terms
162  for (int k=0; k <= j0; k++) {
163  A[i][j1] = A[i][k]*A[i][j0];
164  j1 += 1;
165  }
166  }
167  }
168 
169  int const ma = D*(D+3)/2;
170  std::vector<std::vector<double> > u(nvals-1, std::vector<double>(ma));
171  std::vector<std::vector<double> > v(ma, std::vector<double>(ma));
172  std::vector<double> w(ma);
173  for (int i = 0; i < nvals-1; i++) {
174  for (int j = 0; j < ma; j++) {
175  u[i][j] = A[i][j];
176  }
177  }
178 
179  svd(u,w,v);
180 
181  // "edit" the singular values (eigenvalues):
182  // (1) find wmax = largest value of w
183  // (2) select only w's between TOL*wmax <= w <= wmax
184  // -->Any other w's contribute 0 to the solution
185  double scale = 1e-5;
186  double wmax = 0.0;
187  for (int j = 0; j < ma; j++) {
188  if (w[j] > wmax) wmax=w[j];
189  }
190  double thresh = scale*wmax;
191  for (int j = 0; j < ma; j++) {
192  if (w[j] < thresh) w[j]=0.0;
193  }
194 
195  // Each entry/row of F contains the difference between the
196  // function value at the candidate point and the function value
197  // at the point where we are computing (f-f_0)
198 
199  std::vector<double> F(nvals-1);
200  for (int i = 0; i < nvals-1; ++i) {
201  F[i] = vals[i+1]-val0;
202  }
203 
204  // solve the problem for coefficients, in "result".
205  std::vector<double> result(ma);
206  svd_solve(u,w,v,F,result);
207 
208  return result;
209 }
210 
211 } // namespace Wonton
212 
213 #endif
Factorize a number N into D equal (or nearly equal) factors.
Definition: adaptive_refinement_mesh.h:31
std::vector< T > vector
Definition: wonton.h:285
int svd(std::vector< std::vector< double > > &a, std::vector< double > &w, std::vector< std::vector< double > > &v)
Definition: svd.cc:46
Vector< D > ls_gradient(std::vector< Point< D >> const &coords, std::vector< double > const &vals)
Compute least squares gradient from set of values.
Definition: lsfits.h:43
Represents a point in an N-dimensional space.
Definition: Point.h:50
void svd_solve(const std::vector< std::vector< double > > &u, const std::vector< double > &w, const std::vector< std::vector< double > > &v, std::vector< double > &b, std::vector< double > &x)
Definition: svd.cc:320
Matrix class for Wonton.
Vector< D *(D+3)/2 > ls_quadfit(std::vector< Point< D >> const &coords, std::vector< double > const &vals, bool const boundary_element)
Compute least squares quadfit from set of values.
Definition: lsfits.h:122
Represents a vector in N-dimensional space.
Definition: Vector.h:40