Doxygen 1.15.0
Toolkit for Adaptive Stochastic Modeling and Non-Intrusive ApproximatioN: Tasmanian v8.2
Loading...
Searching...
No Matches
tsgGridFourier.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_FOURIER_HPP
32#define __TASMANIAN_SPARSE_GRID_FOURIER_HPP
33
34#include "tsgGridCore.hpp"
35
36namespace TasGrid{
37
38#ifndef __TASMANIAN_DOXYGEN_SKIP
39class GridFourier : public BaseCanonicalGrid {
40public:
41 GridFourier(AccelerationContext const *acc) : BaseCanonicalGrid(acc){};
42 friend struct GridReaderVersion5<GridFourier>;
43 GridFourier(AccelerationContext const *acc, const GridFourier *fourier, int ibegin, int iend);
44 GridFourier(AccelerationContext const *acc, int cnum_dimensions, int cnum_outputs, int depth, TypeDepth type, const std::vector<int> &anisotropic_weights, const std::vector<int> &level_limits) : BaseCanonicalGrid(acc) {
45 makeGrid(cnum_dimensions, cnum_outputs, depth, type, anisotropic_weights, level_limits);
46 }
47 ~GridFourier() = default;
48
49 bool isFourier() const override{ return true; }
50
51 void write(std::ostream &os, bool iomode) const override{ if (iomode == mode_ascii) write<mode_ascii>(os); else write<mode_binary>(os); }
52
53 template<bool iomode> void write(std::ostream &os) const;
54
55 void makeGrid(int cnum_dimensions, int cnum_outputs, int depth, TypeDepth type, const std::vector<int> &anisotropic_weights, const std::vector<int> &level_limits);
56 void updateGrid(int depth, TypeDepth type, const std::vector<int> &anisotropic_weights, const std::vector<int> &level_limits);
57
58 void setTensors(MultiIndexSet &&tset, int cnum_outputs);
59
60 TypeOneDRule getRule() const override{ return rule_fourier; }
61
62 void loadNeededValues(const double *vals) override;
63
64 void getLoadedPoints(double *x) const override;
65 void getNeededPoints(double *x) const override;
66 void getPoints(double *x) const override; // returns the loaded points unless no points are loaded, then returns the needed points
67
68 void getInterpolationWeights(const double x[], double weights[]) const override;
69 void getQuadratureWeights(double weights[]) const override;
70 void getDifferentiationWeights(const double x[], double weights[]) const override;
71
72 void evaluate(const double x[], double y[]) const override;
73 void integrate(double q[], double *conformal_correction) const override;
74 void differentiate(const double x[], double jacobian[]) const override;
75
76 void evaluateBatch(const double x[], int num_x, double y[]) const override;
77
78 void evaluateBatchGPU(const double gpu_x[], int cpu_num_x, double gpu_y[]) const override;
79 void evaluateBatchGPU(const float gpu_x[], int cpu_num_x, float gpu_y[]) const override;
80 template<typename T> void evaluateBatchGPUtempl(const T gpu_x[], int cpu_num_x, T gpu_y[]) const;
81 void evaluateHierarchicalFunctionsGPU(const double gpu_x[], int num_x, double gpu_y[]) const override;
82 void evaluateHierarchicalFunctionsGPU(const float gpu_x[], int num_x, float gpu_y[]) const override;
83 template<typename T>
84 void evaluateHierarchicalFunctionsInternalGPU(const T gpu_x[], int num_x, GpuVector<T> &wreal, GpuVector<T> &wimag) const;
85
86 void evaluateHierarchicalFunctions(const double x[], int num_x, double y[]) const override;
87 void evaluateHierarchicalFunctionsInternal(const double x[], int num_x, Data2D<double> &wreal, Data2D<double> &wimag) const;
88 void setHierarchicalCoefficients(const double c[]) override;
89
90 void integrateHierarchicalFunctions(double integrals[]) const override;
91
92 void updateAccelerationData(AccelerationContext::ChangeType change) const override;
93
94 void estimateAnisotropicCoefficients(TypeDepth type, int output, std::vector<int> &weights) const;
95 void setAnisotropicRefinement(TypeDepth type, int min_growth, int output, const std::vector<int> &level_limits);
96 void clearRefinement() override;
97 void mergeRefinement() override;
98
99 void beginConstruction() override;
100 void writeConstructionData(std::ostream &os, bool) const override;
101 void readConstructionData(std::istream &is, bool) override;
102 std::vector<double> getCandidateConstructionPoints(TypeDepth type, const std::vector<int> &weights, const std::vector<int> &level_limits);
103 std::vector<double> getCandidateConstructionPoints(TypeDepth type, int output, const std::vector<int> &level_limits);
104 std::vector<double> getCandidateConstructionPoints(std::function<double(const int *)> getTensorWeight, const std::vector<int> &level_limits);
105 void loadConstructedPoint(const double x[], const std::vector<double> &y) override;
106 void loadConstructedPoint(const double x[], int numx, const double y[]) override;
107 void finishConstruction() override;
108
109 const double* getFourierCoefs() const;
110
111protected:
112 void calculateFourierCoefficients();
113
114 MultiIndexSet selectTensors(size_t dims, int depth, TypeDepth type, const std::vector<int> &anisotropic_weights,
115 std::vector<int> const &level_limits) const;
116 void proposeUpdatedTensors();
117 void acceptUpdatedTensors();
118
119 std::vector<std::vector<int>> generateIndexingMap() const;
120
121 void loadConstructedTensors();
122 std::vector<int> getMultiIndex(const double x[]);
123
124 template<typename T, bool interwoven>
125 void computeBasis(const MultiIndexSet &work, const T x[], T wreal[], T wimag[]) const{
126 int num_points = work.getNumIndexes();
127
128 std::vector<std::vector<std::complex<T>>> cache(num_dimensions);
129 for(int j=0; j<num_dimensions; j++){
130 cache[j].resize(max_power[j] +1);
131 cache[j][0] = std::complex<T>(1.0, 0.0);
132
133 T theta = -2.0 * Maths::pi * x[j];
134 std::complex<T> step(std::cos(theta), std::sin(theta));
135 std::complex<T> pw(1.0, 0.0);
136 for(int i=1; i<max_power[j]; i += 2){
137 pw *= step;
138 cache[j][i] = pw;
139 cache[j][i+1] = std::conj<T>(pw);
140 }
141 }
142
143 for(int i=0; i<num_points; i++){
144 const int *p = work.getIndex(i);
145
146 std::complex<T> v(1.0, 0.0);
147 for(int j=0; j<num_dimensions; j++){
148 v *= cache[j][p[j]];
149 }
150
151 if (interwoven){
152 wreal[2*i] = v.real();
153 wreal[2*i+1] = v.imag();
154 }else{
155 wreal[i] = v.real();
156 wimag[i] = v.imag();
157 }
158 }
159 }
160
161 void clearGpuNodes() const;
162 void clearGpuCoefficients() const;
163
164private:
165 OneDimensionalWrapper wrapper;
166
167 MultiIndexSet tensors;
168 MultiIndexSet active_tensors;
169 std::vector<int> active_w;
170
171 MultiIndexSet updated_tensors;
172 MultiIndexSet updated_active_tensors;
173 std::vector<int> updated_active_w;
174
175 std::vector<int> max_levels;
176
177 Data2D<double> fourier_coefs;
178
179 std::vector<int> max_power;
180
181 std::unique_ptr<DynamicConstructorDataGlobal> dynamic_values;
182
183 template<typename T> void loadGpuNodes() const;
184 template<typename T> void loadGpuCoefficients() const;
185 inline std::unique_ptr<CudaFourierData<double>>& getGpuCacheOverload(double) const{ return gpu_cache; }
186 inline std::unique_ptr<CudaFourierData<float>>& getGpuCacheOverload(float) const{ return gpu_cachef; }
187 template<typename T> inline std::unique_ptr<CudaFourierData<T>>& getGpuCache() const{
188 return getGpuCacheOverload(static_cast<T>(0.0));
189 }
190 mutable std::unique_ptr<CudaFourierData<double>> gpu_cache;
191 mutable std::unique_ptr<CudaFourierData<float>> gpu_cachef;
192};
193
194// Old version reader
195template<> struct GridReaderVersion5<GridFourier>{
196 template<typename iomode> static std::unique_ptr<GridFourier> read(AccelerationContext const *acc, std::istream &is){
197 std::unique_ptr<GridFourier> grid = Utils::make_unique<GridFourier>(acc);
198
199 grid->num_dimensions = IO::readNumber<iomode, int>(is);
200 grid->num_outputs = IO::readNumber<iomode, int>(is);
201
202 grid->tensors = MultiIndexSet(is, iomode());
203 grid->active_tensors = MultiIndexSet(is, iomode());
204 grid->active_w = IO::readVector<iomode, int>(is, grid->active_tensors.getNumIndexes());
205
206 if (IO::readFlag<iomode>(is)) grid->points = MultiIndexSet(is, iomode());
207 if (IO::readFlag<iomode>(is)) grid->needed = MultiIndexSet(is, iomode());
208
209 grid->max_levels = IO::readVector<iomode, int>(is, grid->num_dimensions);
210
211 if (grid->num_outputs > 0){
212 grid->values = StorageSet(is, iomode());
213 if (IO::readFlag<iomode>(is))
214 grid->fourier_coefs = IO::readData2D<iomode, double>(is, grid->num_outputs, 2 * grid->points.getNumIndexes());
215 }
216
217 int oned_max_level;
218 if (IO::readFlag<iomode>(is)){
219 grid->updated_tensors = MultiIndexSet(is, iomode());
220 oned_max_level = grid->updated_tensors.getMaxIndex();
221
222 grid->updated_active_tensors = MultiIndexSet(is, iomode());
223
224 grid->updated_active_w = IO::readVector<iomode, int>(is, grid->updated_active_tensors.getNumIndexes());
225 }else{
226 oned_max_level = *std::max_element(grid->max_levels.begin(), grid->max_levels.end());
227 }
228
229 grid->wrapper = OneDimensionalWrapper(oned_max_level, rule_fourier, 0.0, 0.0);
230
231 grid->max_power = MultiIndexManipulations::getMaxIndexes(((grid->points.empty()) ? grid->needed : grid->points));
232
233 return grid;
234 }
235};
236#endif // __TASMANIAN_DOXYGEN_SKIP
237
238}
239
240#endif
TypeOneDRule
Used to specify the one dimensional family of rules that induces the sparse grid.
Definition tsgEnumerates.hpp:285
@ rule_fourier
Trigonometric basis with uniformly distributed nodes (primarily for internal use).
Definition tsgEnumerates.hpp:372
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