Doxygen 1.17.0
Toolkit for Adaptive Stochastic Modeling and Non-Intrusive ApproximatioN: Tasmanian v8.3
Loading...
Searching...
No Matches
tsgGridLocalPolynomial.hpp
1/*
2 * Copyright (c) 2017, Miroslav Stoyanov
3 *
4 * This file is part of
5 * Toolkit for Adaptive Stochastic Modeling And Non-Intrusive ApproximatioN: TASMANIAN
6 *
7 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
12 * and the following disclaimer in the documentation and/or other materials provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
20 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
21 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * UT-BATTELLE, LLC AND THE UNITED STATES GOVERNMENT MAKE NO REPRESENTATIONS AND DISCLAIM ALL WARRANTIES, BOTH EXPRESSED AND IMPLIED.
25 * THERE ARE NO EXPRESS OR IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY PATENT,
26 * COPYRIGHT, TRADEMARK, OR OTHER PROPRIETARY RIGHTS, OR THAT THE SOFTWARE WILL ACCOMPLISH THE INTENDED RESULTS OR THAT THE SOFTWARE OR ITS USE WILL NOT RESULT IN INJURY OR DAMAGE.
27 * THE USER ASSUMES RESPONSIBILITY FOR ALL LIABILITIES, PENALTIES, FINES, CLAIMS, CAUSES OF ACTION, AND COSTS AND EXPENSES, CAUSED BY, RESULTING FROM OR ARISING OUT OF,
28 * IN WHOLE OR IN PART THE USE, STORAGE OR DISPOSAL OF THE SOFTWARE.
29 */
30
31#ifndef __TASMANIAN_SPARSE_GRID_LPOLY_HPP
32#define __TASMANIAN_SPARSE_GRID_LPOLY_HPP
33
34#include "tsgGridCore.hpp"
35
36namespace TasGrid{
37
38#ifndef __TASMANIAN_DOXYGEN_SKIP
39class GridLocalPolynomial final : public BaseCanonicalGrid{
40public:
41 GridLocalPolynomial(AccelerationContext const *acc) : BaseCanonicalGrid(acc), order(1), top_level(0){}
42 friend struct GridReaderVersion5<GridLocalPolynomial>;
43 GridLocalPolynomial(AccelerationContext const *acc, const GridLocalPolynomial *pwpoly, int ibegin, int iend);
44 GridLocalPolynomial(AccelerationContext const *acc, int cnum_dimensions, int cnum_outputs, int depth, int corder, TypeOneDRule crule, const std::vector<int> &level_limits);
45 ~GridLocalPolynomial() = default;
46
47 GridLocalPolynomial(GridLocalPolynomial &&) = default;
48 GridLocalPolynomial &operator = (GridLocalPolynomial &&) = default;
49
50 bool isLocalPolynomial() const override{ return true; }
51
52 void write(std::ostream &os, bool iomode) const override{ if (iomode == mode_ascii) write<mode_ascii>(os); else write<mode_binary>(os); }
53
54 template<bool iomode> void write(std::ostream &os) const;
55
56 TypeOneDRule getRule() const override{ return RuleLocal::getRule(effective_rule); }
57 int getOrder() const{ return order; }
58
59 template<RuleLocal::erule, typename points_mode>
60 void getPoints(double *x) const;
61 void getLoadedPoints(double *x) const override;
62 void getNeededPoints(double *x) const override;
63 void getPoints(double *x) const override; // returns the loaded points unless no points are loaded, then returns the needed points
64
65 template<RuleLocal::erule effrule>
66 void getQuadratureWeights(double weights[]) const;
67 void getQuadratureWeights(double weights[]) const override;
68 void getInterpolationWeights(const double x[], double weights[]) const override;
69 void getDifferentiationWeights(const double x[], double weights[]) const override;
70
71 void loadNeededValues(const double *vals) override;
72
73 void evaluate(const double x[], double y[]) const override;
74 void integrate(double q[], double *conformal_correction) const override;
75 void differentiate(const double x[], double jacobian[]) const override;
76
77 void evaluateBatchOpenMP(const double x[], int num_x, double y[]) const;
78 void evaluateBatch(const double x[], int num_x, double y[]) const override;
79
80 void loadNeededValuesGPU(const double *vals);
81 void evaluateGpuMixed(const double x[], int num_x, double y[]) const;
82 void evaluateBatchGPU(const double gpu_x[], int cpu_num_x, double gpu_y[]) const override;
83 void evaluateBatchGPU(const float gpu_x[], int cpu_num_x, float gpu_y[]) const override;
84 template<typename T> void evaluateBatchGPUtempl(const T gpu_x[], int cpu_num_x, T gpu_y[]) const;
85 void evaluateHierarchicalFunctionsGPU(const double gpu_x[], int cpu_num_x, double *gpu_y) const override;
86 void buildSparseBasisMatrixGPU(const double gpu_x[], int cpu_num_x, GpuVector<int> &gpu_spntr, GpuVector<int> &gpu_sindx, GpuVector<double> &gpu_svals) const;
87 void evaluateHierarchicalFunctionsGPU(const float gpu_x[], int cpu_num_x, float *gpu_y) const override;
88 void buildSparseBasisMatrixGPU(const float gpu_x[], int cpu_num_x, GpuVector<int> &gpu_spntr, GpuVector<int> &gpu_sindx, GpuVector<float> &gpu_svals) const;
89
90 void setSurplusRefinement(double tolerance, TypeRefinement criteria, int output, const std::vector<int> &level_limits, const double *scale_correction);
91 void clearRefinement() override;
92 void mergeRefinement() override;
99 std::vector<double> getScaledCoefficients(int output, const double *scale_correction);
100 int removePointsByHierarchicalCoefficient(double tolerance, int output, const double *scale_correction); // returns the number of points kept
101 void removePointsByHierarchicalCoefficient(int new_num_points, int output, const double *scale_correction);
107 int removeMappedPoints(std::vector<bool> const &pmap);
108
109 void beginConstruction() override;
110 void writeConstructionData(std::ostream &os, bool) const override;
111 void readConstructionData(std::istream &is, bool) override;
112 template<RuleLocal::erule effrule>
113 std::vector<double> getCandidateConstructionPoints(double tolerance, TypeRefinement criteria, int output, std::vector<int> const &level_limits, double const *scale_correction);
114 std::vector<double> getCandidateConstructionPoints(double tolerance, TypeRefinement criteria, int output, std::vector<int> const &level_limits, double const *scale_correction);
115 template<RuleLocal::erule effrule>
116 void loadConstructedPoint(const double x[], const std::vector<double> &y);
117 void loadConstructedPoint(const double x[], const std::vector<double> &y) override;
118 template<RuleLocal::erule effrule>
119 void loadConstructedPoint(const double x[], int numx, const double y[]);
120 void loadConstructedPoint(const double x[], int numx, const double y[]) override;
121 void finishConstruction() override;
122
123 void evaluateHierarchicalFunctions(const double x[], int num_x, double y[]) const override;
124 std::vector<double> getSupport() const override final;
125 void setHierarchicalCoefficients(const double c[]) override;
126 void integrateHierarchicalFunctions(double integrals[]) const override;
127
128 void updateAccelerationData(AccelerationContext::ChangeType change) const override;
129
130 const double* getSurpluses() const;
131 const int* getNeededIndexes() const;
132
133 void buildSpareBasisMatrix(const double x[], int num_x, int num_chunk, std::vector<int> &spntr, std::vector<int> &sindx, std::vector<double> &svals) const;
134 void buildSpareBasisMatrixStatic(const double x[], int num_x, int num_chunk, int *spntr, int *sindx, double *svals) const;
135 int getSpareBasisMatrixNZ(const double x[], int num_x) const;
136
137protected:
139 GridLocalPolynomial(AccelerationContext const *acc, int cnum_dimensions, int cnum_outputs, int corder, TypeOneDRule crule, std::vector<int> &&pnts, std::vector<double> &&vals, std::vector<double> &&surps);
140
142 void updateValues(double const *vals);
143
144 void buildTree();
145
147 template<RuleLocal::erule effrule>
148 std::vector<int> getSubGraph(std::vector<int> const &point) const;
149
151 template<RuleLocal::erule effrule>
152 void expandGrid(std::vector<int> const &point, std::vector<double> const &value);
153
155 template<RuleLocal::erule effrule>
156 std::vector<int> getMultiIndex(const double x[]);
157
159 template<RuleLocal::erule effrule>
160 void loadConstructedPoints();
161
163 template<RuleLocal::erule effrule>
164 void recomputeSurpluses();
165
166 void recomputeSurpluses();
167
183 template<RuleLocal::erule effrule>
184 void updateSurpluses(MultiIndexSet const &work, int max_level, std::vector<int> const &level, Data2D<int> const &dagUp);
185
186 // Same idea as in GridSequence::applyTransformationTransposed().
190 enum class TranspMode {
192 value,
194 derivative
195 };
196
197 template<TranspMode mode>
198 void applyTransformationTransposed(double weights[], const MultiIndexSet &work, const std::vector<int> &active_points) const;
199 template<TranspMode mode, RuleLocal::erule effrule>
200 void applyTransformationTransposed(double weights[], const MultiIndexSet &work, const std::vector<int> &active_points) const;
201
202 void buildSparseMatrixBlockForm(const double x[], int num_x, int num_chunk, std::vector<int> &numnz,
203 std::vector<std::vector<int>> &tindx, std::vector<std::vector<double>> &tvals) const;
204
205 template<RuleLocal::erule eff_rule>
206 double evalBasisSupported(const int point[], const double x[], bool &isSupported) const{
207 double f = RuleLocal::evalSupport<eff_rule>(order, point[0], x[0], isSupported);
208 if (!isSupported) return 0.0;
209 for(int j=1; j<num_dimensions; j++){
210 f *= RuleLocal::evalSupport<eff_rule>(order, point[j], x[j], isSupported);
211 if (!isSupported) return 0.0;
212 }
213 return f;
214 }
215 template<RuleLocal::erule effrule>
216 void diffBasisSupported(const int point[], const double x[], double diff_values[], bool &isSupported) const{
217 // The isSupported uses only the logic provided by the evalSupport()
218 // If any 1D function has no support, then the derivative has no support
219 // If all 1D function have support, the derivative could be theoretically 0, but probably not
220 std::fill_n(diff_values, num_dimensions, 1);
221 for(int k=0; k<num_dimensions; k++) {
222 bool constexpr use_edge_support = true;
223 double fval = RuleLocal::evalSupport<effrule, use_edge_support>(order, point[k], x[k], isSupported);
224 if (not isSupported) {
225 std::fill_n(diff_values, num_dimensions, 0);
226 isSupported = false;
227 return;
228 }
229 // when num_dimension == 1, these two loops do nothing
230 // however, the call evalSupport() above is still needed for isSupported
231 for(int j=0; j<k; j++) diff_values[j] *= fval;
232 for(int j=k+1; j<num_dimensions; j++) diff_values[j] *= fval;
233 }
234 for (int k=0; k<num_dimensions; k++) {
235 diff_values[k] *= RuleLocal::diffSupport<effrule>(order, point[k], x[k]);
236 }
237 // no early termination in the first for-loop, must be supported
238 isSupported = true;
239 }
240
246 enum class WalkerMode {
248 increment,
250 fill_entries,
252 fill_sorted,
254 increment_diff,
256 fill_entries_diff
257 };
258
269 template<WalkerMode mode, RuleLocal::erule effrule>
270 void walkTree(const MultiIndexSet &work, const double x[], std::vector<int> &sindx, std::vector<double> &svals, double *y) const{
271 std::vector<int> monkey_count(top_level+1); // traverse the tree, counts the branches of the current node
272 std::vector<int> monkey_tail(top_level+1); // traverse the tree, keeps track of the previous node (history)
273
274 bool isSupported;
275 double basis_value;
276 std::vector<double> basis_derivative(num_dimensions);
277
278 for(const auto &r : roots){
279 if constexpr (mode == WalkerMode::increment_diff or mode == WalkerMode::fill_entries_diff) {
280 diffBasisSupported<effrule>(work.getIndex(r), x, basis_derivative.data(), isSupported);
281 } else {
282 basis_value = evalBasisSupported<effrule>(work.getIndex(r), x, isSupported);
283 }
284
285 if (isSupported){
286 if constexpr (mode == WalkerMode::increment){
287 double const *s = surpluses.getStrip(r);
288 for(int k=0; k<num_outputs; k++)
289 y[k] += basis_value * s[k];
290 }else if constexpr (mode == WalkerMode::fill_entries or mode == WalkerMode::fill_sorted){
291 sindx.push_back(r);
292 svals.push_back(basis_value);
293 }else if constexpr (mode == WalkerMode::increment_diff){
294 double const *s = surpluses.getStrip(r);
295 for(int k=0; k<num_outputs; k++)
296 for (int d=0; d<num_dimensions; d++)
297 y[k * num_dimensions + d] += basis_derivative[d] * s[k];
298 }else{
299 sindx.push_back(r);
300 for (auto dx : basis_derivative)
301 svals.push_back(dx);
302 }
303
304 int current = 0;
305 monkey_tail[0] = r;
306 monkey_count[0] = pntr[r];
307
308 while(monkey_count[0] < pntr[monkey_tail[0]+1]){
309 if (monkey_count[current] < pntr[monkey_tail[current]+1]){
310 int p = indx[monkey_count[current]];
311 if constexpr (mode == WalkerMode::increment_diff or mode == WalkerMode::fill_entries_diff){
312 diffBasisSupported<effrule>(work.getIndex(p), x, basis_derivative.data(), isSupported);
313 }else{
314 basis_value = evalBasisSupported<effrule>(work.getIndex(p), x, isSupported);
315 }
316 if (isSupported){
317 if constexpr (mode == WalkerMode::increment){
318 double const *s = surpluses.getStrip(p);
319 for(int k=0; k<num_outputs; k++)
320 y[k] += basis_value * s[k];
321 }else if constexpr (mode == WalkerMode::fill_entries or mode == WalkerMode::fill_sorted){
322 sindx.push_back(p);
323 svals.push_back(basis_value);
324 }else if constexpr (mode == WalkerMode::increment_diff){
325 double const *s = surpluses.getStrip(p);
326 for(int k=0; k<num_outputs; k++)
327 for (int d=0; d<num_dimensions; d++)
328 y[k * num_dimensions + d] += basis_derivative[d] * s[k];
329 }else{
330 sindx.push_back(p);
331 for (auto dx : basis_derivative)
332 svals.push_back(dx);
333 }
334 monkey_tail[++current] = p;
335 monkey_count[current] = pntr[p];
336 }else{
337 monkey_count[current]++;
338 }
339 }else{
340 monkey_count[--current]++;
341 }
342 }
343 }
344 }
345
346 // according to https://docs.nvidia.com/cuda/cusparse/index.html#sparse-format
347 // "... it is assumed that the indices are provided in increasing order and that each index appears only once."
348 // This may not be a requirement for cusparseDgemvi(), but it may be that I have not tested it sufficiently
349 // Also, see AccelerationDataGPUFull::cusparseMatveci() for inaccuracies in Nvidia documentation
350 if constexpr (mode == WalkerMode::fill_sorted){
351 std::vector<int> map(sindx);
352 std::iota(map.begin(), map.end(), 0);
353 std::sort(map.begin(), map.end(), [&](int a, int b)->bool{ return (sindx[a] < sindx[b]); });
354
355 std::vector<int> idx = sindx;
356 std::vector<double> vls = svals;
357 std::transform(map.begin(), map.end(), sindx.begin(), [&](int i)->int{ return idx[i]; });
358 std::transform(map.begin(), map.end(), svals.begin(), [&](int i)->double{ return vls[i]; });
359 }
360 }
361 // Explicitly instantiates based on the effective_rule
362 template<WalkerMode mode>
363 void walkTree(const MultiIndexSet &work, const double x[], std::vector<int> &sindx, std::vector<double> &svals, double *y) const{
364 switch(effective_rule) {
365 case RuleLocal::erule::pwc:
366 walkTree<mode, RuleLocal::erule::pwc>(work,x, sindx, svals, y);
367 break;
368 case RuleLocal::erule::localp:
369 walkTree<mode, RuleLocal::erule::localp>(work,x, sindx, svals, y);
370 break;
371 case RuleLocal::erule::semilocalp:
372 walkTree<mode, RuleLocal::erule::semilocalp>(work,x, sindx, svals, y);
373 break;
374 case RuleLocal::erule::localp0:
375 walkTree<mode, RuleLocal::erule::localp0>(work,x, sindx, svals, y);
376 break;
377 default: // case RuleLocal::erule::localpb:
378 walkTree<mode, RuleLocal::erule::localpb>(work,x, sindx, svals, y);
379 break;
380 };
381 }
382
383 template<RuleLocal::erule effrule>
384 double evalBasisRaw(const int point[], const double x[]) const {
385 double f = RuleLocal::evalRaw<effrule>(order, point[0], x[0]);
386 for(int j=1; j<num_dimensions; j++) f *= RuleLocal::evalRaw<effrule>(order, point[j], x[j]);
387 return f;
388 }
389
390 std::vector<double> getNormalization() const;
391
392 template<RuleLocal::erule effrule>
393 Data2D<int> buildUpdateMap(double tolerance, TypeRefinement criteria, int output, const double *scale_correction) const;
394 template<RuleLocal::erule effrule>
395 MultiIndexSet getRefinementCanidates(double tolerance, TypeRefinement criteria, int output, const std::vector<int> &level_limits, const double *scale_correction) const;
396
397 template<RuleLocal::erule effrule>
398 bool addParent(const int point[], int direction, const MultiIndexSet &exclude, Data2D<int> &destination) const;
399 template<RuleLocal::erule effrule>
400 void addChild(const int point[], int direction, const MultiIndexSet &exclude, Data2D<int> &destination) const;
401 template<RuleLocal::erule effrule>
402 void addChildLimited(const int point[], int direction, const MultiIndexSet &exclude, const std::vector<int> &level_limits, Data2D<int> &destination) const;
403
404 void clearGpuSurpluses();
405 void clearGpuBasisHierarchy();
406
407private:
408 int order, top_level;
409
410 Data2D<double> surpluses;
411
412 Data2D<int> parents;
413
414 // tree for evaluation
415 std::vector<int> roots;
416 std::vector<int> pntr;
417 std::vector<int> indx;
418
419 RuleLocal::erule effective_rule;
420
421 // synchronize with tasgpu_devalpwpoly_feval
422 template<int ord, TypeOneDRule crule, typename T>
423 Data2D<T> encodeSupportForGPU(const MultiIndexSet &work) const{
424 Data2D<T> cpu_support(num_dimensions, work.getNumIndexes());
425 for(int i=0; i<work.getNumIndexes(); i++){
426 const int* p = work.getIndex(i);
427 T *s = cpu_support.getStrip(i);
428 for(int j=0; j<num_dimensions; j++){
429 if (ord == 0){
430 s[j] = static_cast<T>(RuleLocal::getSupport<RuleLocal::erule::pwc>(p[j]));
431 } else {
432 switch(crule) {
433 case rule_localp:
434 s[j] = static_cast<T>(RuleLocal::getSupport<RuleLocal::erule::localp>(p[j]));
435 break;
436 case rule_semilocalp:
437 s[j] = static_cast<T>(RuleLocal::getSupport<RuleLocal::erule::semilocalp>(p[j]));
438 break;
439 case rule_localp0:
440 s[j] = static_cast<T>(RuleLocal::getSupport<RuleLocal::erule::localp0>(p[j]));
441 break;
442 case rule_localpb:
443 s[j] = static_cast<T>(RuleLocal::getSupport<RuleLocal::erule::localpb>(p[j]));
444 break;
445 };
446 if (ord == 2) s[j] *= s[j];
447 if ((crule == rule_localp) || (crule == rule_semilocalp)) if (p[j] == 0) s[j] = static_cast<T>(-1.0); // constant function
448 if ((crule == rule_localp) && (ord == 2)){
449 if (p[j] == 1) s[j] = static_cast<T>(-2.0);
450 else if (p[j] == 2) s[j] = static_cast<T>(-3.0);
451 }
452 if ((crule == rule_semilocalp) && (ord == 2)){
453 if (p[j] == 1) s[j] = static_cast<T>(-4.0);
454 else if (p[j] == 2) s[j] = static_cast<T>(-5.0);
455 }
456 if ((crule == rule_localpb) && (ord == 2)){
457 if (p[j] < 2) s[j] = static_cast<T>(-2.0); // linear functions on level 0
458 }
459 }
460 }
461 }
462 return cpu_support;
463 }
464 std::optional<CudaLocalPolynomialData<double>>& getGpuCacheOverload(double) const{ return gpu_cache; }
465 std::optional<CudaLocalPolynomialData<float>>& getGpuCacheOverload(float) const{ return gpu_cachef; }
466 template<typename T> std::optional<CudaLocalPolynomialData<T>>& getGpuCache() const{
467 return getGpuCacheOverload(static_cast<T>(0.0));
468 }
469 template<typename T> void loadGpuBasis() const;
470 template<typename T> void loadGpuHierarchy() const;
471 template<typename T> void loadGpuSurpluses() const;
472 mutable std::optional<CudaLocalPolynomialData<double>> gpu_cache;
473 mutable std::optional<CudaLocalPolynomialData<float>> gpu_cachef;
474
475 std::unique_ptr<SimpleConstructData> dynamic_values;
476};
477
478// Old version reader
479template<> struct GridReaderVersion5<GridLocalPolynomial>{
480 template<typename iomode> static void read(std::istream &is, GridLocalPolynomial *grid) {
481 grid->num_dimensions = IO::readNumber<iomode, int>(is);
482 grid->num_outputs = IO::readNumber<iomode, int>(is);
483 grid->order = IO::readNumber<iomode, int>(is);
484 grid->top_level = IO::readNumber<iomode, int>(is);
485 TypeOneDRule rule = IO::readRule<iomode>(is);
486 grid->effective_rule = RuleLocal::getEffectiveRule(grid->order, rule);
487
488 if (IO::readFlag<iomode>(is)) grid->points = MultiIndexSet(is, iomode());
489 if (std::is_same<iomode, IO::mode_ascii_type>::value){ // backwards compatible: surpluses and needed, or needed and surpluses
490 if (IO::readFlag<iomode>(is))
491 grid->surpluses = IO::readData2D<iomode, double>(is, grid->num_outputs, grid->points.getNumIndexes());
492 if (IO::readFlag<iomode>(is)) grid->needed = MultiIndexSet(is, iomode());
493 }else{
494 if (IO::readFlag<iomode>(is)) grid->needed = MultiIndexSet(is, iomode());
495 if (IO::readFlag<iomode>(is))
496 grid->surpluses = IO::readData2D<iomode, double>(is, grid->num_outputs, grid->points.getNumIndexes());
497 }
498 int max_parents = [&]()->int {
499 switch(grid->effective_rule) {
500 case RuleLocal::erule::pwc: return RuleLocal::getMaxNumParents<RuleLocal::erule::pwc>();
501 case RuleLocal::erule::localp: return RuleLocal::getMaxNumParents<RuleLocal::erule::localp>();
502 case RuleLocal::erule::semilocalp: return RuleLocal::getMaxNumParents<RuleLocal::erule::semilocalp>();
503 case RuleLocal::erule::localp0: return RuleLocal::getMaxNumParents<RuleLocal::erule::localp0>();
504 default: // case RuleLocal::erule::localpb:
505 return RuleLocal::getMaxNumParents<RuleLocal::erule::localpb>();
506 };
507 }();
508
509 if (IO::readFlag<iomode>(is))
510 grid->parents = IO::readData2D<iomode, int>(is, max_parents * grid->num_dimensions, grid->points.getNumIndexes());
511
512 size_t num_points = (size_t) ((grid->points.empty()) ? grid->needed.getNumIndexes() : grid->points.getNumIndexes());
513 grid->roots = std::vector<int>((size_t) IO::readNumber<iomode, int>(is));
514 if (grid->roots.size() > 0){
515 IO::readVector<iomode>(is, grid->roots);
516 grid->pntr = IO::readVector<iomode, int>(is, num_points + 1);
517 if (grid->pntr[num_points] > 0){
518 grid->indx = IO::readVector<iomode, int>(is, grid->pntr[num_points]);
519 }else{
520 grid->indx = IO::readVector<iomode, int>(is, 1);
521 }
522 }
523
524 if (grid->num_outputs > 0) grid->values = StorageSet(is, iomode());
525 }
526};
527#endif // __TASMANIAN_DOXYGEN_SKIP
528}
529
530#endif
TypeOneDRule
Used to specify the one dimensional family of rules that induces the sparse grid.
Definition tsgEnumerates.hpp:288
@ rule_localp
Nested rule with a hierarchy of uniformly distributed nodes and functions with compact support.
Definition tsgEnumerates.hpp:365
@ rule_localpb
Variation of rule_localp focusing nodes on the boundary instead of the interior.
Definition tsgEnumerates.hpp:371
@ rule_localp0
Variation of rule_localp assuming the model is zero at the domain boundary.
Definition tsgEnumerates.hpp:367
@ rule_semilocalp
Variation of rule_localp using increased support in exchange for higher order basis (better for smoot...
Definition tsgEnumerates.hpp:369
void loadNeededValues(std::function< void(double const x[], double y[], size_t thread_id)> model, TasmanianSparseGrid &grid, size_t num_threads)
Loads the current grid with model values, does not perform any refinement.
Definition tsgLoadNeededValues.hpp:104
Encapsulates the Tasmanian Sparse Grid module.
Definition TasmanianSparseGrid.hpp:68