1 /* _______________________________________________________________________
2
3 PECOS: Parallel Environment for Creation Of Stochastics
4 Copyright (c) 2011, Sandia National Laboratories.
5 This software is distributed under the GNU Lesser General Public License.
6 For more information, see the README file in the top Pecos directory.
7 _______________________________________________________________________ */
8
9 //- Class: SparseGridDriver
10 //- Description: Implementation code for SparseGridDriver class
11 //- Owner: Mike Eldred
12 //- Revised by:
13 //- Version:
14
15 #include "SparseGridDriver.hpp"
16 #include "PolynomialApproximation.hpp"
17 #include "sandia_sgmga.hpp"
18 #include "sandia_sgmgg.hpp"
19 #include "pecos_stat_util.hpp"
20 #include "MultivariateDistribution.hpp"
21
22 static const char rcsId[]="@(#) $Id: SparseGridDriver.C,v 1.57 2004/06/21 19:57:32 mseldre Exp $";
23
24 //#define DEBUG
25
26 namespace Pecos {
27
28
dimension_preference(const RealVector & dim_pref)29 void SparseGridDriver::dimension_preference(const RealVector& dim_pref)
30 {
31 RealVector aniso_wts;
32 if (!dim_pref.empty()) {
33 size_t num_pref = dim_pref.length();
34 aniso_wts.sizeUninitialized(num_pref);
35 webbur::sandia_sgmga_importance_to_aniso(num_pref, dim_pref.values(),
36 aniso_wts.values());
37 #ifdef DEBUG
38 PCout << "dimension preference:\n" << dim_pref << "anisotropic weights "
39 << "after sandia_sgmga_importance_to_aniso():\n" << aniso_wts;
40 #endif
41 }
42 anisotropic_weights(aniso_wts);
43 }
44
45
anisotropic_weights(const RealVector & aniso_wts)46 void SparseGridDriver::anisotropic_weights(const RealVector& aniso_wts)
47 {
48 RealVector& curr_aniso_wts = anisoWtsIter->second;
49 if (aniso_wts.empty()) {
50 if (!curr_aniso_wts.empty()) { // change from current
51 curr_aniso_wts.sizeUninitialized(0);
52 clear_size(); // clear state to mandate a grid / grid size update
53 }
54 }
55 else {
56 if (aniso_wts.length() != numVars) {
57 PCerr << "Error: length of sparse grid anisotropic weights specification "
58 << "is inconsistent with\n number of variables in SparseGrid"
59 << "Driver::anisotropic_weights()." << std::endl;
60 abort_handler(-1);
61 }
62
63 // detect anisotropy
64 bool dim_iso = true; size_t i;
65 const Real& wt0 = aniso_wts[0];
66 for (i=1; i<numVars; ++i)
67 if (std::abs(aniso_wts[i] - wt0) > DBL_EPSILON)
68 { dim_iso = false; break; }
69 // update active anisoLevelWts and grid update indicator
70 if (dim_iso) {
71 if (!curr_aniso_wts.empty()) {
72 curr_aniso_wts.sizeUninitialized(0);
73 clear_size(); // clear state to mandate a grid / grid size update
74 }
75 }
76 else {
77 RealVector prev_aniso_wts = curr_aniso_wts; // for update indicator
78 // truncate any negative values
79 curr_aniso_wts.resize(numVars);
80 for (i=0; i<numVars; ++i)
81 curr_aniso_wts[i] = std::max(aniso_wts[i], 0.);
82 // normalize and enforce axis lower bounds/weight upper bounds
83 int option = 1; // weights scaled so that minimum nonzero entry is 1
84 webbur::sandia_sgmga_aniso_normalize(option, numVars,
85 curr_aniso_wts.values());
86 #ifdef DEBUG
87 PCout << "anisoLevelWts after sandia_sgmga_aniso_normalize():\n"
88 << curr_aniso_wts;
89 #endif
90 // enforce axis lower bounds, if present, for current ssgLevel. An axis
91 // lower bound defines a weight upper bound based on the current ssgLevel:
92 // LB_i = level*wt_min/wt_i --> wt_i = level*wt_min/LB_i and wt_min=1.
93 // Catch special case of dim_pref_i = 0 --> wt_i = LB_i = 0.
94 const RealVector& axis_l_bnds
95 = axisLowerBounds[activeKey];//axisLBndsIter->second;
96 if (!axis_l_bnds.empty()) {
97 Real ssg_lev = (Real)(ssgLevIter->second);
98 for (i=0; i<numVars; ++i)
99 if (axis_l_bnds[i] > SMALL_NUMBER) { // nonzero LB
100 Real wt_u_bnd = ssg_lev / axis_l_bnds[i];
101 curr_aniso_wts[i] = (curr_aniso_wts[i] > SMALL_NUMBER) // nonzero wt
102 ? std::min(wt_u_bnd, curr_aniso_wts[i]) : wt_u_bnd;
103 }
104 #ifdef DEBUG
105 PCout << "anisoLevelWts after axisLowerBounds enforcement:\n"
106 << curr_aniso_wts;
107 #endif
108 }
109 // indicate need for numCollocPts update
110 if (curr_aniso_wts != prev_aniso_wts)
111 clear_size(); // clear state to mandate a grid / grid size update
112 }
113 }
114 }
115
116
update_axis_lower_bounds()117 void SparseGridDriver::update_axis_lower_bounds()
118 {
119 const RealVector& aniso_wts = anisoWtsIter->second;
120 RealVector& axis_l_bnds = axisLowerBounds[activeKey];//axisLBndsIter->second;
121 if (axis_l_bnds.empty())
122 axis_l_bnds.sizeUninitialized(numVars);
123 // An axis lower bound is the maximum index coverage achieved on a coordinate
124 // axis (when all other indices are zero); it defines a constraint for
125 // minimum coordinate coverage in future refinements. The linear index set
126 // constraint is level*wt_min-|wt| < j.wt <= level*wt_min, which becomes
127 // level-|wt| < j_i w_i <= level for wt_min=1 and all other indices=0.
128 // The max feasible j_i is then level/w_i (except for special case w_i=0).
129 Real ssg_lev = (Real)(ssgLevIter->second);
130 if (aniso_wts.empty())
131 axis_l_bnds = ssg_lev; // all weights = 1
132 else // min nonzero weight scaled to 1 --> just catch special case w_i=0
133 for (size_t i=0; i<numVars; ++i)
134 axis_l_bnds[i] = (aniso_wts[i] > SMALL_NUMBER) ? // nonzero wt
135 ssg_lev / aniso_wts[i] : 0.;
136 }
137
138
139 void SparseGridDriver::
initialize_grid(unsigned short ssg_level,const RealVector & dim_pref,const MultivariateDistribution & u_dist,const ExpansionConfigOptions & ec_options,BasisConfigOptions & bc_options,short growth_rate)140 initialize_grid(unsigned short ssg_level, const RealVector& dim_pref,
141 const MultivariateDistribution& u_dist,
142 const ExpansionConfigOptions& ec_options,
143 BasisConfigOptions& bc_options, short growth_rate)
144 {
145 growthRate = growth_rate;
146 //refineType = ec_options.refineType;
147 refineControl = ec_options.refineControl;
148
149 // For unrestricted exponential growth, use of nested rules is restricted
150 // to uniform/normal in order to enforce similar growth rates:
151 if (bc_options.nestedRules && growthRate == UNRESTRICTED_GROWTH) {
152 const ShortArray& u_types = u_dist.random_variable_types();
153 const BitArray& active_vars = u_dist.active_variables();
154 size_t i, num_u_types = u_types.size(); // numVars not yet defined
155 bool no_mask = active_vars.empty();
156 for (i=0; i<num_u_types; ++i)
157 if ( ( no_mask || active_vars[i] ) &&
158 u_types[i] != STD_UNIFORM && u_types[i] != STD_NORMAL )
159 { bc_options.nestedRules = false; break; }
160 }
161 // For MODERATE and SLOW restricted exponential growth, nested rules
162 // can be used heterogeneously and synchronized with STANDARD and SLOW
163 // linear growth, respectively.
164
165 IntegrationDriver::initialize_grid(u_dist, ec_options, bc_options);
166
167 level(ssg_level);
168 dimension_preference(dim_pref);
169 }
170
171
172 void SparseGridDriver::
initialize_grid_parameters(const MultivariateDistribution & mv_dist)173 initialize_grid_parameters(const MultivariateDistribution& mv_dist)
174 {
175 IntegrationDriver::initialize_grid_parameters(mv_dist);
176 if (basisParamUpdates.any()) clear_size(); // clear number of colloc points
177
178 // assign is unnecessary as reset/update are sufficiently robust
179 //if (collocPts1D.empty())
180 // assign_1d_collocation_points_weights();
181 //else {
182 reset_1d_collocation_points_weights(); // replace invalidated pt/wt sets
183 update_1d_collocation_points_weights(); // augment 1-D pt/wt sets
184 //}
185 }
186
187
precompute_rules()188 void SparseGridDriver::precompute_rules()
189 {
190 unsigned short l, m, ssg_lev = ssgLevIter->second;
191 if (isotropic())
192 for (size_t i=0; i<numVars; ++i) {
193 level_to_order(i, ssg_lev, m); // max order is full level in this dim
194 polynomialBasis[i].precompute_rules(m);
195 }
196 else {
197 const RealVector& aniso_wts = anisoWtsIter->second;
198 Real wt_i;
199 for (size_t i=0; i<numVars; ++i) {
200 wt_i = aniso_wts[i];
201 l = (wt_i > 0.) ? (unsigned short)((Real)ssg_lev / wt_i) : 0;
202 level_to_order(i, l, m); // max order is full aniso level[dim]
203 polynomialBasis[i].precompute_rules(m);
204 }
205 }
206 }
207
208
resize_1d_collocation_points_weights()209 void SparseGridDriver::resize_1d_collocation_points_weights()
210 {
211 // resize arrays in a one-sided manner (don't prune 1D points)
212
213 unsigned short ssg_lev = ssgLevIter->second;
214 size_t i, num_levels = ssg_lev + 1, curr_lev;
215 curr_lev = collocPts1D.size();
216 if (num_levels > curr_lev) {
217 collocPts1D.resize(num_levels);
218 for (i=curr_lev; i<num_levels; ++i)
219 collocPts1D[i].resize(numVars);
220 }
221 curr_lev = type1CollocWts1D.size();
222 if (num_levels > curr_lev) {
223 type1CollocWts1D.resize(num_levels);
224 for (i=curr_lev; i<num_levels; ++i)
225 type1CollocWts1D[i].resize(numVars);
226 }
227 curr_lev = type2CollocWts1D.size();
228 if (computeType2Weights && num_levels > curr_lev) {
229 type2CollocWts1D.resize(num_levels);
230 for (i=curr_lev; i<num_levels; ++i)
231 type2CollocWts1D[i].resize(numVars);
232 }
233 }
234
235
236 /*
237 void SparseGridDriver::assign_1d_collocation_points_weights()
238 {
239 resize_1d_collocation_points_weights();
240
241 // level_index (j indexing) range is 0:w, level (i indexing) range is 1:w+1
242 unsigned short l_index, q_order, num_levels = ssgLevIter->second + 1;
243 for (size_t i=0; i<numVars; i++)
244 for (l_index=0; l_index<num_levels; ++l_index) {
245 level_to_order(i, l_index, q_order);
246 IntegrationDriver::
247 assign_1d_collocation_points_weights(i, q_order, l_index);
248 }
249 }
250 */
251
252
update_1d_collocation_points_weights()253 void SparseGridDriver::update_1d_collocation_points_weights()
254 {
255 unsigned short curr_levels = collocPts1D.size();
256 resize_1d_collocation_points_weights();
257
258 // level_index (j indexing) range is 0:w, level (i indexing) range is 1:w+1
259 unsigned short l_index, q_order, num_levels = ssgLevIter->second + 1;
260 for (l_index=curr_levels; l_index<num_levels; ++l_index)
261 for (size_t i=0; i<numVars; i++) {
262 level_to_order(i, l_index, q_order);
263 IntegrationDriver::
264 assign_1d_collocation_points_weights(i, q_order, l_index);
265 }
266 }
267
268
reset_1d_collocation_points_weights()269 void SparseGridDriver::reset_1d_collocation_points_weights()
270 {
271 // re-assign 1D pts/wts per variable, if indicated by basisParamUpdates
272 size_t v, num_v = basisParamUpdates.size();
273 for (v=0; v<num_v; ++v)
274 if (basisParamUpdates[v])
275 reset_1d_collocation_points_weights(v);
276 }
277
278
reset_1d_collocation_points_weights(size_t i)279 void SparseGridDriver::reset_1d_collocation_points_weights(size_t i)
280 {
281 // replaces only the existing pts/wts (no resizing)
282
283 unsigned short lev, order; size_t num_lev = collocPts1D.size();
284 BasisPolynomial& poly_i = polynomialBasis[i];
285 for (lev=0; lev<num_lev; ++lev) {
286 level_to_order(i, lev, order);
287 collocPts1D[lev][i] = poly_i.collocation_points(order);
288 type1CollocWts1D[lev][i] = poly_i.type1_collocation_weights(order);
289 if (computeType2Weights)
290 type2CollocWts1D[lev][i] = poly_i.type2_collocation_weights(order);
291 }
292 }
293
294
initialize_sets()295 void SparseGridDriver::initialize_sets()
296 {
297 PCerr << "Error: no default implementation for SparseGridDriver::"
298 << "initialize_sets()." << std::endl;
299 abort_handler(-1);
300 }
301
302
increment_smolyak_multi_index(const UShortArray & set)303 void SparseGridDriver::increment_smolyak_multi_index(const UShortArray& set)
304 {
305 PCerr << "Error: no default implementation for SparseGridDriver::"
306 << "increment_smolyak_multi_index()." << std::endl;
307 abort_handler(-1);
308 }
309
310
311 bool SparseGridDriver::
push_trial_available(const UShortArray & key,const UShortArray & tr_set)312 push_trial_available(const UShortArray& key, const UShortArray& tr_set)
313 { return false; }
314
315
push_trial_available(const UShortArray & key)316 bool SparseGridDriver::push_trial_available(const UShortArray& key)
317 { return false; }
318
319
push_trial_available()320 bool SparseGridDriver::push_trial_available()
321 { return false; }
322
323
324 size_t SparseGridDriver::
push_trial_index(const UShortArray & key,const UShortArray & tr_set)325 push_trial_index(const UShortArray& key, const UShortArray& tr_set)
326 { return _NPOS; }
327
328
push_trial_index(const UShortArray & key)329 size_t SparseGridDriver::push_trial_index(const UShortArray& key)
330 { return _NPOS; }
331
332
push_trial_index()333 size_t SparseGridDriver::push_trial_index()
334 { return _NPOS; }
335
336
push_index(const UShortArray & key) const337 size_t SparseGridDriver::push_index(const UShortArray& key) const
338 { return _NPOS; }
339
340
restore_index(const UShortArray & key) const341 size_t SparseGridDriver::restore_index(const UShortArray& key) const
342 { return push_index(key); } // default for identity mapping (flat to flat)
343
344
finalize_index(size_t i,const UShortArray & key) const345 size_t SparseGridDriver::finalize_index(size_t i, const UShortArray& key) const
346 { return i; } // default is an identity mapping
347
348
push_set()349 void SparseGridDriver::push_set()
350 {
351 PCerr << "Error: no default implementation for SparseGridDriver::push_set()."
352 << std::endl;
353 abort_handler(-1);
354 }
355
356
pop_set()357 void SparseGridDriver::pop_set()
358 {
359 PCerr << "Error: no default implementation for SparseGridDriver::pop_set()."
360 << std::endl;
361 abort_handler(-1);
362 }
363
364
365 void SparseGridDriver::
finalize_sets(bool output_sets,bool converged_within_tol,bool reverted)366 finalize_sets(bool output_sets, bool converged_within_tol, bool reverted)
367 {
368 PCerr << "Error: no default implementation for SparseGridDriver::"
369 << "finalize_sets()." << std::endl;
370 abort_handler(-1);
371 }
372
373
update_reference()374 void SparseGridDriver::update_reference()
375 {
376 // Not needed for HierarchSparseGridDriver, so use no-op as default
377
378 /*
379 PCerr << "Error: no default implementation for SparseGridDriver::"
380 << "update_reference()." << std::endl;
381 abort_handler(-1);
382 */
383 }
384
385
compute_trial_grid(RealMatrix & var_sets)386 void SparseGridDriver::compute_trial_grid(RealMatrix& var_sets)
387 {
388 PCerr << "Error: no default implementation for SparseGridDriver::"
389 << "compute_trial_grid()." << std::endl;
390 abort_handler(-1);
391 }
392
393
compute_increment(RealMatrix & var_sets)394 void SparseGridDriver::compute_increment(RealMatrix& var_sets)
395 {
396 PCerr << "Error: no default implementation for SparseGridDriver::"
397 << "compute_increment()." << std::endl;
398 abort_handler(-1);
399 }
400
401
push_increment()402 void SparseGridDriver::push_increment()
403 {
404 PCerr << "Error: no default implementation for SparseGridDriver::"
405 << "push_increment()." << std::endl;
406 abort_handler(-1);
407 }
408
409
pop_increment()410 void SparseGridDriver::pop_increment()
411 {
412 PCerr << "Error: no default implementation for SparseGridDriver::"
413 << "pop_increment()." << std::endl;
414 abort_handler(-1);
415 }
416
417
merge_unique()418 void SparseGridDriver::merge_unique()
419 { } // not needed for HierarchSparseGridDriver, so use no-op as default
420
421
trial_set(const UShortArray & key) const422 const UShortArray& SparseGridDriver::trial_set(const UShortArray& key) const
423 {
424 PCerr << "Error: no default implementation for SparseGridDriver::trial_set()."
425 << std::endl;
426 abort_handler(-1);
427 return key; // dummy UShortArray
428 }
429
430
trial_set() const431 const UShortArray& SparseGridDriver::trial_set() const
432 { return trial_set(activeKey); } // default implementation
433
434
unique_trial_points() const435 int SparseGridDriver::unique_trial_points() const
436 {
437 PCerr << "Error: no default implementation for SparseGridDriver::"
438 << "unique_trial_points()." << std::endl;
439 abort_handler(-1);
440 return 0;
441 }
442
443
update_smolyak_arrays()444 void SparseGridDriver::update_smolyak_arrays()
445 {
446 PCerr << "Error: no default implementation for SparseGridDriver::"
447 << "update_smolyak_arrays()." << std::endl;
448 abort_handler(-1);
449 }
450
451
update_sets(const UShortArray & set_star)452 void SparseGridDriver::update_sets(const UShortArray& set_star)
453 {
454 // set_star is passed as *cit_star from the best entry in activeMultiIndex.
455 // Therefore, we must use caution in updates to activeMultiIndex that can
456 // invalidate cit_star.
457
458 // update smolyakMultiIndex (permanently, will not be popped)
459 increment_smolyak_multi_index(set_star);
460 push_set(); // calls increment_unique() --> INC2
461 merge_unique(); // promotes increment to new ref --> INC3
462
463 // use trial set rather than incoming set_star due to iterator invalidation
464 const UShortArray& tr_set = trial_set();
465 UShortArrayDeque& pop_trials = poppedTrialSets[activeKey];
466 UShortArraySet& active_mi = activeMultiIndex[activeKey];
467 UShortArraySet& old_mi = oldMultiIndex[activeKey];
468
469 // update set O by adding the trial set to oldMultiIndex:
470 old_mi.insert(tr_set);
471 // remove the trial set from set A by erasing from activeMultiIndex:
472 active_mi.erase(tr_set); // invalidates cit_star -> set_star
473 // update subset of A that have been evaluated as trial sets but not selected
474 UShortArrayDeque::iterator tr_it
475 = std::find(pop_trials.begin(), pop_trials.end(), tr_set);
476 if (tr_it != pop_trials.end()) pop_trials.erase(tr_it);
477
478 // update set A (activeMultiIndex) based on neighbors of trial set
479 add_active_neighbors(tr_set, false);//, isotropic());
480
481 // Note: pruning irrelevant sets that have Coeff = 0 would be tricky,
482 // since a 0 close to the frontier can become nonzero
483
484 #ifdef DEBUG
485 PCout << "Sets updated: (Smolyak,Old,Active,Trial) = (" << smolyak_size()
486 << ',' << old_mi.size() << ',' << active_mi.size() << ','
487 << pop_trials.size() << ')' << std::endl;
488 #endif // DEBUG
489 }
490
491
492 void SparseGridDriver::
add_active_neighbors(const UShortArray & set,bool frontier)493 add_active_neighbors(const UShortArray& set, bool frontier)
494 {
495 UShortArray trial_set = set;
496 UShortArraySet& old_mi = oldMultiIndex[activeKey];
497 UShortArraySet& active_mi = activeMultiIndex[activeKey];
498 UShortArraySet::const_iterator cit;
499 size_t i, j, num_v = set.size();
500 for (i=0; i<num_v; ++i) {
501 // i^{th} candidate for set A (active) computed from forward neighbor:
502 // increment by 1 in dimension i
503 unsigned short& trial_set_i = trial_set[i];
504 ++trial_set_i;
505 // if !frontier, then candidates could exist in oldMultiIndex
506 if (frontier || old_mi.find(trial_set) == old_mi.end()) {
507 // test all backwards neighbors for membership in set O (old)
508 bool backward_old = true;
509 for (j=0; j<num_v; ++j) {
510 unsigned short& trial_set_j = trial_set[j];
511 if (trial_set_j) { // if 0, then admissible by default
512 --trial_set_j;
513 cit = old_mi.find(trial_set);
514 ++trial_set_j; // restore
515 if (cit == old_mi.end())
516 { backward_old = false; break; }
517 }
518 }
519 if (backward_old) // std::set<> will discard any active duplicates
520 active_mi.insert(trial_set);
521 }
522 --trial_set_i; // restore
523 }
524 }
525
526
clear_inactive()527 void SparseGridDriver::clear_inactive()
528 {
529 // These are always defined in update_active_iterators()
530 std::map<UShortArray, unsigned short>::iterator sg_it = ssgLevel.begin();
531 std::map<UShortArray, RealVector>::iterator aw_it = anisoLevelWts.begin();
532 std::map<UShortArray, int>::iterator cp_it = numCollocPts.begin();
533 while (sg_it != ssgLevel.end())
534 if (sg_it == ssgLevIter) // preserve active
535 { ++sg_it; ++aw_it; ++cp_it; }
536 else { // clear inactive: postfix increments manage iterator invalidations
537 ssgLevel.erase(sg_it++);
538 anisoLevelWts.erase(aw_it++);
539 numCollocPts.erase(cp_it++);
540 }
541
542 // Generalized sparse grid sets may be active
543 if (!oldMultiIndex.empty()) {
544 std::map<UShortArray, UShortArraySet>::iterator
545 om_it = oldMultiIndex.begin(), om_act_it = oldMultiIndex.find(activeKey);
546 std::map<UShortArray, UShortArraySet>::iterator am_it
547 = activeMultiIndex.begin();
548 std::map<UShortArray, UShortArrayDeque>::iterator pt_it
549 = poppedTrialSets.begin();
550 while (om_it != oldMultiIndex.end())
551 if (om_it == om_act_it) // preserve active
552 { ++om_it; ++am_it; ++pt_it; }
553 else { // clear inactive: postfix increments manage iterator invalidations
554 oldMultiIndex.erase(om_it++);
555 activeMultiIndex.erase(am_it++);
556 poppedTrialSets.erase(pt_it++);
557 }
558 }
559
560 // Anisotropic refinement bounds may be active
561 if (!axisLowerBounds.empty()) {
562 std::map<UShortArray, RealVector>::iterator ab_it = axisLowerBounds.begin(),
563 ab_act_it = axisLowerBounds.find(activeKey);
564 while (ab_it != axisLowerBounds.end())
565 if (ab_it == ab_act_it) // preserve active
566 ++ab_it;
567 else // clear inactive: postfix increments manage iterator invalidations
568 axisLowerBounds.erase(ab_it++);
569 }
570 }
571
572
level_to_order_exp_hgk_interp(int level,int growth)573 int SparseGridDriver::level_to_order_exp_hgk_interp(int level, int growth)
574 {
575 if (level == 0) return 1;
576
577 switch (growth) {
578 case SLOW_RESTRICTED_GROWTH: {
579 unsigned short level = 0, max_level = 5;
580 int m = 1, m_goal = level + 1;
581 while (level <= max_level && m < m_goal)
582 { ++level; m = orderGenzKeister[level]; }
583 return m; break;
584 }
585 case MODERATE_RESTRICTED_GROWTH: {
586 unsigned short level = 0, max_level = 5;
587 int m = 1, m_goal = 2 * level + 1;
588 while (level <= max_level && m < m_goal)
589 { ++level; m = orderGenzKeister[level]; }
590 return m; break;
591 }
592 case UNRESTRICTED_GROWTH:
593 return orderGenzKeister[std::min(level, 5)]; break;
594 }
595 }
596
597
level_to_order_exp_closed_interp(int level,int growth)598 int SparseGridDriver::level_to_order_exp_closed_interp(int level, int growth)
599 {
600 if (level == 0) return 1;
601
602 switch (growth) {
603 case SLOW_RESTRICTED_GROWTH: {
604 int m = 1, lev_pow = 1, m_goal = level + 1;
605 while (m < m_goal)
606 { lev_pow *= 2; m = lev_pow + 1; } //std::pow(2.,level) + 1;
607 return m; break;
608 }
609 case MODERATE_RESTRICTED_GROWTH: {
610 int m = 1, lev_pow = 1, m_goal = 2 * level + 1;
611 while (m < m_goal)
612 { lev_pow *= 2; m = lev_pow + 1; } //std::pow(2.,level) + 1;
613 return m; break;
614 }
615 case UNRESTRICTED_GROWTH:
616 return (int)std::pow(2., level) + 1; break;
617 }
618 }
619
620
level_to_order_exp_open_interp(int level,int growth)621 int SparseGridDriver::level_to_order_exp_open_interp(int level, int growth)
622 {
623 if (level == 0) return 1;
624
625 switch (growth) {
626 case SLOW_RESTRICTED_GROWTH: {
627 int m = 1, lev_pow = 2, m_goal = level + 1;
628 while (m < m_goal)
629 { lev_pow *= 2; m = lev_pow - 1; } //std::pow(2.,level+1) - 1;
630 return m; break;
631 }
632 case MODERATE_RESTRICTED_GROWTH: {
633 int m = 1, lev_pow = 2, m_goal = 2 * level + 1;
634 while (m < m_goal)
635 { lev_pow *= 2; m = lev_pow - 1; } //std::pow(2.,level+1) - 1;
636 return m; break;
637 }
638 case UNRESTRICTED_GROWTH:
639 return (int)std::pow(2., level+1) - 1; break;
640 }
641 }
642
643 } // namespace Pecos
644