34 #ifndef __TASMANIAN_ADDONS_EXOTICQUADRATURE_HPP
35 #define __TASMANIAN_ADDONS_EXOTICQUADRATURE_HPP
90 static int gauss_quadrature_version = 1;
100 inline double poly_eval(
const std::vector<double> &roots,
double x) {
101 double eval_value = 1.0;
102 for (
auto r : roots) eval_value *= (x - r);
117 inline double lagrange_eval(
size_t idx,
const std::vector<double> &roots,
double x) {
118 double eval_value = 1.0;
119 for (
size_t i=0; i<idx; i++) {
120 eval_value *= (x - roots[i]) / (roots[idx] - roots[i]);
122 for (
size_t i=idx+1; i<roots.size(); i++) {
123 eval_value *= (x - roots[i]) / (roots[idx] - roots[i]);
148 template <
bool is_symmetric>
149 inline void getGaussNodesAndWeights(
const int n,
const std::vector<double> &ref_points,
const std::vector<double> &ref_weights,
150 std::vector<std::vector<double>> &points_cache, std::vector<std::vector<double>> &weights_cache) {
151 #ifndef Tasmanian_ENABLE_BLAS
153 if (gauss_quadrature_version == 1) {
154 gauss_quadrature_version = 2;
158 assert(ref_points.size() == ref_weights.size());
159 assert(ref_points.size() > 0);
161 for (
auto &w : ref_weights) mu0 += w;
162 std::vector<double> poly_m1_vals(ref_points.size(), 0.0), poly_vals(ref_points.size(), 1.0);
163 std::vector<double> diag, offdiag;
164 points_cache.resize(n);
165 weights_cache.resize(n);
166 for (
int i=0; i<n; i++) {
171 double diag_numr = 0.0;
172 double diag_denm = 0.0;
173 for (
size_t j=0; j<ref_points.size(); j++) {
174 diag_numr += ref_points[j] * (poly_vals[j] * poly_vals[j]) * ref_weights[j];
175 diag_denm += (poly_vals[j] * poly_vals[j]) * ref_weights[j];
177 diag.push_back(diag_numr / diag_denm);
180 double sqr_offdiag_numr = 0.0;
181 double sqr_offdiag_denm = 0.0;
182 for (
size_t j=0; j<ref_points.size(); j++) {
183 sqr_offdiag_numr += (poly_vals[j] * poly_vals[j]) * ref_weights[j];
184 sqr_offdiag_denm += (poly_m1_vals[j] * poly_m1_vals[j]) * ref_weights[j];
186 offdiag.push_back(std::sqrt(sqr_offdiag_numr / sqr_offdiag_denm));
189 if (gauss_quadrature_version == 1) {
193 if (points_cache[i].size() % 2 == 1 && is_symmetric) {
194 points_cache[i][(points_cache[i].size() - 1) / 2] = 0.0;
196 weights_cache[i] = std::vector<double>(points_cache[i].size(), 0.0);
197 for (
size_t j=0; j<points_cache[i].size(); j++) {
199 for (
size_t k=0; k<ref_points.size(); k++) {
200 weights_cache[i][j] +=
lagrange_eval(j, points_cache[i], ref_points[k]) * ref_weights[k];
203 }
else if (gauss_quadrature_version == 2) {
205 std::vector<double> dummy_diag = diag;
206 std::vector<double> dummy_offdiag = offdiag;
209 throw std::invalid_argument(
"ERROR: gauss_quadrature_version must be a valid number!");
212 std::swap(poly_m1_vals, poly_vals);
213 std::transform(ref_points.begin(), ref_points.end(), poly_vals.begin(),
214 [&points_cache, i](
double x){return poly_eval(points_cache[i], x);});
234 const std::vector<double> &ref_points,
const char* description,
235 const bool is_symmetric =
false) {
237 assert(shifted_weights.size() == ref_points.size());
238 std::vector<std::vector<double>> points_cache, weights_cache;
240 getGaussNodesAndWeights<true>(n, ref_points, shifted_weights, points_cache, weights_cache);
242 getGaussNodesAndWeights<false>(n, ref_points, shifted_weights, points_cache, weights_cache);
247 for (
int i=0; i<n; i++) {
248 const size_t init_size = points_cache[i].size();
249 std::vector<double> correction_points, correction_weights;
251 for (
auto &w : correction_weights) w *= -shift;
252 if (correction_points.size() % 2 == 1 && is_symmetric) {
254 correction_points[(correction_points.size() - 1) / 2] = 0.0;
257 for (
size_t j=0; j<correction_points.size(); j++) {
258 long long nonunique_idx = -1;
259 for (
size_t k=0; k<init_size; k++) {
260 if (std::abs(correction_points[j] - points_cache[i][k]) <=
Maths::num_tol) {
261 nonunique_idx =
static_cast<long long>(k);
265 if (nonunique_idx == -1) {
266 points_cache[i].push_back(correction_points[j]);
267 weights_cache[i].push_back(correction_weights[j]);
269 weights_cache[i][nonunique_idx] += correction_weights[j];
276 std::vector<int> num_nodes(n), precision(n);
277 for (
int i=0; i<n; i++) {
278 num_nodes[i] =
static_cast<int>(points_cache[i].size());
279 precision[i] = 2 * (i + 1) - 1;
281 return TasGrid::CustomTabulated(std::move(num_nodes), std::move(precision), std::move(points_cache), std::move(weights_cache),
299 assert(ref_weights.size() == vals.size());
300 if (not std::all_of(vals.begin(), vals.end(), [shift](
double x){return (x+shift)>=0.0;}))
301 throw std::invalid_argument(
"ERROR: shift needs to be chosen so that weight_fn(x)+shift is nonnegative!");
302 for (
size_t k=0; k<ref_weights.size(); k++)
303 ref_weights[k] *= (vals[k] + shift);
336 const char* description,
const bool is_symmetric =
false) {
338 throw std::invalid_argument(
"ERROR: grid needs to contain a nonzero number of loaded points returned by grid.getLoadedPoints()!");
341 throw std::invalid_argument(
"ERROR: grid needs to be one dimensional!");
344 throw std::invalid_argument(
"ERROR: grid needs to have scalar outputs!");
363 const int num_ref_points,
const char* description,
const bool is_symmetric =
false) {
364 std::vector<double> shifted_weights, ref_points, weight_fn_vals(num_ref_points);
366 std::transform(ref_points.begin(), ref_points.end(), weight_fn_vals.begin(), weight_fn);
Class providing manipulation of custom tabulated rules, file I/O and structured access to the points,...
Definition: tsgCoreOneDimensional.hpp:66
The master-class that represents an instance of a Tasmanian sparse grid.
Definition: TasmanianSparseGrid.hpp:293
int getNumOutputs() const
Return the outputs of the grid, i.e., number of model outputs.
Definition: TasmanianSparseGrid.hpp:644
const double * getLoadedValues() const
Returns the model values that have been loaded in the gird.
Definition: TasmanianSparseGrid.hpp:899
int getNumLoaded() const
Return the number of points already associated with model values via loadNeededValues().
Definition: TasmanianSparseGrid.hpp:657
std::vector< double > getLoadedPoints() const
Return the points already associated with model values.
Definition: TasmanianSparseGrid.hpp:671
int getNumDimensions() const
Return the dimensions of the grid, i.e., number of model inputs.
Definition: TasmanianSparseGrid.hpp:642
std::vector< double > getQuadratureWeights() const
Returns a vector of size getNumPoints() of the quadrature weights of the grid.
Definition: TasmanianSparseGrid.hpp:747
TasGrid::CustomTabulated getExoticQuadrature(const int num_levels, const double shift, const TasGrid::TasmanianSparseGrid &grid, const char *description, const bool is_symmetric=false)
Constructs an exotic quadrature from a sparse grid object.
Definition: tsgExoticQuadrature.hpp:335
double lagrange_eval(size_t idx, const std::vector< double > &roots, double x)
Evaluates a Lagrange basis polynomial at a point x.
Definition: tsgExoticQuadrature.hpp:117
void getGaussNodesAndWeights(const int n, const std::vector< double > &ref_points, const std::vector< double > &ref_weights, std::vector< std::vector< double >> &points_cache, std::vector< std::vector< double >> &weights_cache)
Generates n levels of points and weights using orthogonal polynomials with respect to ref_points and ...
Definition: tsgExoticQuadrature.hpp:149
void shiftReferenceWeights(std::vector< double > const &vals, double shift, std::vector< double > &ref_weights)
Multiplies the reference quadrature weights by the shifted values of the weight function.
Definition: tsgExoticQuadrature.hpp:298
TasGrid::CustomTabulated getShiftedExoticQuadrature(const int n, const double shift, const std::vector< double > &shifted_weights, const std::vector< double > &ref_points, const char *description, const bool is_symmetric=false)
Generate the exotic quadrature points and weights and load them into a TasGrid::CustomTabulated objec...
Definition: tsgExoticQuadrature.hpp:233
double poly_eval(const std::vector< double > &roots, double x)
Evaluates a polynomial with roots given by roots at the point x.
Definition: tsgExoticQuadrature.hpp:100
constexpr double num_tol
Numerical tolerance for various algorithms.
Definition: tsgMathUtils.hpp:132
void getGaussLegendre(int m, std::vector< double > &w, std::vector< double > &x)
Generate Gauss-Legendre weights w and points x for (input) number of points m.
void decompose(std::vector< double > &diag, std::vector< double > &off_diag, const double mu0, std::vector< double > &nodes, std::vector< double > &weights)
Method for tridiagonal eigenvalue decomposition, used to compute nodes and weights for Gaussian rules...
std::vector< double > getSymmetricEigenvalues(int n, std::vector< double > const &diag, std::vector< double > const &offdiag)
Method for computing the eigenvalues of a symmetric matrix in place, using an LAPACK wrapper.
Encapsulates the Tasmanian Sparse Grid module.
Definition: TasmanianSparseGrid.hpp:68
Common includes and methods for all addons.