31#ifndef __TSG_ONE_DIMENSIONAL_WRAPPER_HPP
32#define __TSG_ONE_DIMENSIONAL_WRAPPER_HPP
34#include "tsgHardCodedTabulatedRules.hpp"
53class OneDimensionalWrapper{
56 OneDimensionalWrapper() : isNonNested(false), num_levels(0), rule(
rule_none){}
58 ~OneDimensionalWrapper() =
default;
68 OneDimensionalWrapper(
const CustomTabulated &custom,
int max_level,
TypeOneDRule crule,
double alpha,
double beta) :
69 isNonNested(OneDimensionalMeta::isNonNested(crule)),
70 num_levels(max_level + 1),
72 num_points(num_levels),
73 pntr(num_levels + 1, 0),
79 if (max_level + 1 > custom.getNumLevels()){
80 std::string message =
"ERROR: custom-tabulated rule needed with levels ";
81 message += std::to_string(num_levels);
82 message +=
", but only ";
83 message += std::to_string(custom.getNumLevels());
84 message +=
" are provided.";
85 throw std::runtime_error(message);
90 for(
int l=0; l<num_levels; l++){
91 num_points[l] = OneDimensionalMeta::getNumPoints(l, rule);
92 pntr[l+1] = pntr[l] + num_points[l];
95 for(
int l=0; l<num_levels; l++){
96 num_points[l] = custom.getNumPoints(l);
97 pntr[l+1] = pntr[l] + num_points[l];
100 int num_total = pntr[num_levels];
103 indx.reserve(num_total);
104 unique.reserve(num_total);
106 for(
int l=0; l<num_levels; l++){
107 int n = num_points[l];
109 OneDimensionalNodes::getChebyshev(n, weights[l], nodes[l]);
111 OneDimensionalNodes::getGaussLegendre(n, weights[l], nodes[l]);
113 OneDimensionalNodes::getGaussChebyshev1(n, weights[l], nodes[l]);
115 OneDimensionalNodes::getGaussChebyshev2(n, weights[l], nodes[l]);
117 OneDimensionalNodes::getGaussJacobi(n, weights[l], nodes[l], alpha, alpha);
119 OneDimensionalNodes::getGaussHermite(n, weights[l], nodes[l], alpha);
121 OneDimensionalNodes::getGaussJacobi(n, weights[l], nodes[l], alpha, beta);
123 OneDimensionalNodes::getGaussLaguerre(n, weights[l], nodes[l], alpha);
125 custom.getWeightsNodes(l, weights[l], nodes[l]);
128 for(
auto x : nodes[l]){
130 for(
int j=0; j<(int) unique.size(); j++){
131 if (std::abs(x - unique[j]) < Maths::num_tol){
138 point = (int) (unique.size() - 1);
140 indx.push_back(point);
144 unique.shrink_to_fit();
147 for(
int l=0; l<num_levels; l++){
148 int n = num_points[l];
150 double *x = nodes[l].data();
151 for(
int i=0; i<n; i++){
153 for(
int j=0; j<i; j++){
156 for(
int j=i+1; j<n; j++){
164 unique = OneDimensionalNodes::getClenshawCurtisNodes(max_level);
166 unique = OneDimensionalNodes::getClenshawCurtisNodesZero(max_level);
168 unique = OneDimensionalNodes::getFejer2Nodes(max_level);
170 TableGaussPatterson gp;
171 if (num_levels > gp.getNumLevels()){
172 std::string message =
"ERROR: gauss-patterson rule needed with level ";
173 message += std::to_string(max_level);
174 message +=
", but only ";
175 message += std::to_string(gp.getNumLevels());
176 message +=
" are hardcoded.";
177 throw std::runtime_error(message);
179 unique = gp.getNodes(max_level);
182 for(
int l=0; l<num_levels; l++){
183 weights[l].resize(num_points[l]);
184 for(
int i=0; i<num_points[l]; i++){
185 weights[l][i] = gp.getWeight(l, i);
189 unique = OneDimensionalNodes::getRLeja(OneDimensionalMeta::getNumPoints(max_level,rule));
191 unique = OneDimensionalNodes::getRLejaCentered(OneDimensionalMeta::getNumPoints(max_level,rule));
193 unique = OneDimensionalNodes::getRLejaShifted(OneDimensionalMeta::getNumPoints(max_level,rule));
195 unique = Optimizer::getGreedyNodes<rule_leja>(OneDimensionalMeta::getNumPoints(max_level, rule));
197 unique = Optimizer::getGreedyNodes<rule_maxlebesgue>(OneDimensionalMeta::getNumPoints(max_level, rule));
199 unique = Optimizer::getGreedyNodes<rule_minlebesgue>(OneDimensionalMeta::getNumPoints(max_level, rule));
201 unique = Optimizer::getGreedyNodes<rule_mindelta>(OneDimensionalMeta::getNumPoints(max_level, rule));
203 unique = OneDimensionalNodes::getFourierNodes(max_level);
206 for(
int l=0; l<num_levels; l++){
207 int n = num_points[l];
208 weights[l].resize(n);
210 for(
int i=0; i<n; i++){
212 for(
int j=0; j<i; j++){
213 c /= (unique[i] - unique[j]);
215 for(
int j=i+1; j<n; j++){
216 c /= (unique[i] - unique[j]);
219 c /= (unique[i] - 1.0) * (unique[i] + 1.0);
226 for(
int l=0; l<num_levels; l++){
227 for(
int i=0; i<num_points[l]; i++){
228 weights[l][i] = OneDimensionalNodes::getClenshawCurtisWeight(l, i);
232 for(
int l=0; l<num_levels; l++){
233 for(
int i=0; i<num_points[l]; i++){
234 weights[l][i] = OneDimensionalNodes::getClenshawCurtisWeightZero(l, i);
238 for(
int l=0; l<num_levels; l++){
239 for(
int i=0; i<num_points[l]; i++){
240 weights[l][i] = OneDimensionalNodes::getFejer2Weight(l, i);
247 int n = 1 + num_points[max_level] / 2;
248 std::vector<double> lag_x, lag_w;
249 OneDimensionalNodes::getGaussLegendre(n, lag_w, lag_x);
250 for(
int l=0; l<num_levels; l++){
251 std::fill(weights[l].begin(), weights[l].end(), 0.0);
252 int npl = num_points[l];
253 std::vector<double> v(npl);
254 for(
int i=0; i<n; i++){
256 for(
int j=0; j<npl-1; j++){
257 v[j+1] = (lag_x[i] - unique[j]) * v[j];
259 v[npl-1] *= coeff[l][npl-1];
261 for(
int j=npl-2; j>=0; j--){
262 s *= (lag_x[i] - unique[j+1]);
263 v[j] *= s * coeff[l][j];
265 for(
int j=0; j<npl; j++){
266 weights[l][j] += lag_w[i] * v[j];
275 OneDimensionalWrapper(
int max_level,
TypeOneDRule crule,
double alpha,
double beta) :
276 OneDimensionalWrapper(CustomTabulated(), max_level, crule, alpha, beta){}
279 int getNumPoints(
int level)
const{
return num_points[level]; }
281 int getPointIndex(
int level,
int j)
const{
return indx[pntr[level] + j]; }
283 int getLevel(
int point) {
286 while(point >= num_points[l]) l++;
289 std::vector<int> getLevels(std::vector<int>
const &point){
290 std::vector<int> result(point.size());
291 for(
size_t i=0; i<point.size(); i++) result[i] = getLevel(point[i]);
296 int getNumNodes()
const{
return (
int) unique.size(); }
298 double getNode(
int j)
const{
return unique[j]; }
300 double getWeight(
int level,
int j)
const{
return weights[level][j]; }
303 const double* getNodes(
int level)
const{
return (isNonNested) ? nodes[level].data() : unique.data(); }
305 const double* getCoefficients(
int level)
const{
return coeff[level].data(); }
308 const std::vector<int>& getPointsCount()
const{
return pntr; }
313 int getNumLevels()
const{
return num_levels; }
316 const std::vector<double>& getUnique()
const{
return unique; }
318 std::vector<double> getAllNodes()
const{
return Utils::mergeVectors(nodes); }
320 std::vector<double> getAllCoeff()
const{
return Utils::mergeVectors(coeff); }
322 const std::vector<int>& getNumNodesPerLevel()
const{
return num_points; }
324 std::vector<int> getOffsetNodesPerLevel()
const{
325 std::vector<int> offsets(num_points.size());
327 for(
size_t i=1; i<num_points.size(); i++)
328 offsets[i] = offsets[i-1] + num_points[i-1];
337 std::vector<int> num_points;
338 std::vector<int> pntr;
339 std::vector<int> indx;
341 std::vector<std::vector<double>> weights;
342 std::vector<std::vector<double>> nodes;
343 std::vector<double> unique;
345 std::vector<std::vector<double>> coeff;
TypeOneDRule
Used to specify the one dimensional family of rules that induces the sparse grid.
Definition tsgEnumerates.hpp:285
@ rule_minlebesgue
A greedy sequence rule with nodes added to minimize the Lebesgue constant.
Definition tsgEnumerates.hpp:321
@ rule_gaussgegenbauer
Non-nested rule optimized for integral of the form .
Definition tsgEnumerates.hpp:343
@ rule_gausshermite
Non-nested rule optimized for integral of the form .
Definition tsgEnumerates.hpp:355
@ rule_gausslegendre
Non-nested rule but optimized for integration.
Definition tsgEnumerates.hpp:329
@ rule_fejer2
Similar to rule_clenshawcurtis but with nodes strictly in the interior.
Definition tsgEnumerates.hpp:293
@ rule_leja
Classic sequence rule, moderate Lebesgue constant growth (empirical result only).
Definition tsgEnumerates.hpp:299
@ rule_rlejashifteddouble
Same as rule_rlejashifted but doubling the number of nodes per level, which reduced the Lebesgue cons...
Definition tsgEnumerates.hpp:315
@ rule_gausslaguerreodd
Same as rule_gausslaguerre but using only odd levels, partially mitigates the non-nested issues.
Definition tsgEnumerates.hpp:353
@ rule_chebyshevodd
Same as rule_chebyshev but using only odd levels, partially mitigates the non-nested issues.
Definition tsgEnumerates.hpp:297
@ rule_minlebesgueodd
Same as rule_minlebesgue but using only odd levels, quadrature is more stable.
Definition tsgEnumerates.hpp:323
@ rule_gausslegendreodd
Same as rule_gausslegendre but using only odd levels, partially mitigates the non-nested issues.
Definition tsgEnumerates.hpp:331
@ rule_gausschebyshev1
Non-nested rule optimized for integral of the form .
Definition tsgEnumerates.hpp:335
@ rule_gausslaguerre
Non-nested rule optimized for integral of the form .
Definition tsgEnumerates.hpp:351
@ rule_mindelta
A greedy sequence rule with nodes added to minimize the norm of the surplus operator.
Definition tsgEnumerates.hpp:325
@ rule_gaussgegenbauerodd
Same as rule_gaussgegenbauer but using only odd levels, partially mitigates the non-nested issues.
Definition tsgEnumerates.hpp:345
@ rule_customtabulated
User provided rule, nodes and weights must be provided with a separate file.
Definition tsgEnumerates.hpp:359
@ rule_gausshermiteodd
Same as rule_gausshermite but using only odd levels, partially mitigates the non-nested issues.
Definition tsgEnumerates.hpp:357
@ rule_clenshawcurtis
Classic nested rule using Chebyshev nodes with very low Lebesgue constant.
Definition tsgEnumerates.hpp:289
@ rule_gausschebyshev2odd
Same as rule_gausschebyshev2 but using only odd levels, partially mitigates the non-nested issues.
Definition tsgEnumerates.hpp:341
@ rule_maxlebesgueodd
Same as rule_maxlebesgue but using only odd levels, quadrature is more stable.
Definition tsgEnumerates.hpp:319
@ rule_maxlebesgue
A greedy sequence rule with nodes placed at the maximum of the Lebesgue function.
Definition tsgEnumerates.hpp:317
@ rule_clenshawcurtis0
Same as rule_clenshawcurtis but with modified basis that assumes the model is zero at the boundary.
Definition tsgEnumerates.hpp:291
@ rule_none
Null rule, should never be used as input (default rule for an empty grid).
Definition tsgEnumerates.hpp:287
@ rule_chebyshev
Using Chebyshev nodes with very low Lebesgue constant and slow node growth, but non-nested.
Definition tsgEnumerates.hpp:295
@ rule_gausschebyshev1odd
Same as rule_gausschebyshev1 but using only odd levels, partially mitigates the non-nested issues.
Definition tsgEnumerates.hpp:337
@ rule_rlejashifted
Similar sequence to rule_rleja but with nodes strictly in the interior.
Definition tsgEnumerates.hpp:311
@ rule_gausschebyshev2
Non-nested rule optimized for integral of the form .
Definition tsgEnumerates.hpp:339
@ rule_mindeltaodd
Same as rule_mindelta but using only odd levels, quadrature is more stable.
Definition tsgEnumerates.hpp:327
@ rule_rlejadouble4
Using rule_rleja nodes but doubling the nodes every 4 levels, reduces the Lebesgue constant.
Definition tsgEnumerates.hpp:307
@ rule_gaussjacobiodd
Same as rule_gaussjacobi but using only odd levels, partially mitigates the non-nested issues.
Definition tsgEnumerates.hpp:349
@ rule_lejaodd
Same as rule_leja but using only odd levels, quadrature is more stable.
Definition tsgEnumerates.hpp:301
@ rule_rlejaodd
Same as rule_rleja but using only odd levels, quadrature is more stable.
Definition tsgEnumerates.hpp:309
@ rule_rlejadouble2
Using rule_rleja nodes but doubling the nodes every 2 levels, reduces the Lebesgue constant.
Definition tsgEnumerates.hpp:305
@ rule_rlejashiftedeven
Same as rule_rlejashifted but using only even levels, quadrature is more stable.
Definition tsgEnumerates.hpp:313
@ rule_gausspatterson
Nested rule that is optimized for integration, probably the best integration rule in more than 2 dime...
Definition tsgEnumerates.hpp:333
@ rule_rleja
Classic sequence rule based on complex analysis, moderate Lebesgue constant growth (theoretically pro...
Definition tsgEnumerates.hpp:303
@ rule_gaussjacobi
Non-nested rule optimized for integral of the form .
Definition tsgEnumerates.hpp:347
Encapsulates the Tasmanian Sparse Grid module.
Definition TasmanianSparseGrid.hpp:68