31#ifndef __TASMANIAN_SPARSE_GRID_FOURIER_HPP
32#define __TASMANIAN_SPARSE_GRID_FOURIER_HPP
34#include "tsgGridCore.hpp"
38#ifndef __TASMANIAN_DOXYGEN_SKIP
39class GridFourier :
public BaseCanonicalGrid {
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);
47 ~GridFourier() =
default;
49 bool isFourier()
const override{
return true; }
51 void write(std::ostream &os,
bool iomode)
const override{
if (iomode == mode_ascii) write<mode_ascii>(os);
else write<mode_binary>(os); }
53 template<
bool iomode>
void write(std::ostream &os)
const;
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);
58 void setTensors(MultiIndexSet &&tset,
int cnum_outputs);
64 void getLoadedPoints(
double *x)
const override;
65 void getNeededPoints(
double *x)
const override;
66 void getPoints(
double *x)
const override;
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;
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;
76 void evaluateBatch(
const double x[],
int num_x,
double y[])
const override;
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;
84 void evaluateHierarchicalFunctionsInternalGPU(
const T gpu_x[],
int num_x, GpuVector<T> &wreal, GpuVector<T> &wimag)
const;
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;
90 void integrateHierarchicalFunctions(
double integrals[])
const override;
92 void updateAccelerationData(AccelerationContext::ChangeType change)
const override;
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;
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;
109 const double* getFourierCoefs()
const;
112 void calculateFourierCoefficients();
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();
119 std::vector<std::vector<int>> generateIndexingMap()
const;
121 void loadConstructedTensors();
122 std::vector<int> getMultiIndex(
const double x[]);
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();
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);
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){
139 cache[j][i+1] = std::conj<T>(pw);
143 for(
int i=0; i<num_points; i++){
144 const int *p = work.getIndex(i);
146 std::complex<T> v(1.0, 0.0);
147 for(
int j=0; j<num_dimensions; j++){
152 wreal[2*i] = v.real();
153 wreal[2*i+1] = v.imag();
161 void clearGpuNodes()
const;
162 void clearGpuCoefficients()
const;
165 OneDimensionalWrapper wrapper;
167 MultiIndexSet tensors;
168 MultiIndexSet active_tensors;
169 std::vector<int> active_w;
171 MultiIndexSet updated_tensors;
172 MultiIndexSet updated_active_tensors;
173 std::vector<int> updated_active_w;
175 std::vector<int> max_levels;
177 Data2D<double> fourier_coefs;
179 std::vector<int> max_power;
181 std::unique_ptr<DynamicConstructorDataGlobal> dynamic_values;
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));
190 mutable std::unique_ptr<CudaFourierData<double>> gpu_cache;
191 mutable std::unique_ptr<CudaFourierData<float>> gpu_cachef;
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);
199 grid->num_dimensions = IO::readNumber<iomode, int>(is);
200 grid->num_outputs = IO::readNumber<iomode, int>(is);
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());
206 if (IO::readFlag<iomode>(is)) grid->points = MultiIndexSet(is, iomode());
207 if (IO::readFlag<iomode>(is)) grid->needed = MultiIndexSet(is, iomode());
209 grid->max_levels = IO::readVector<iomode, int>(is, grid->num_dimensions);
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());
218 if (IO::readFlag<iomode>(is)){
219 grid->updated_tensors = MultiIndexSet(is, iomode());
220 oned_max_level = grid->updated_tensors.getMaxIndex();
222 grid->updated_active_tensors = MultiIndexSet(is, iomode());
224 grid->updated_active_w = IO::readVector<iomode, int>(is, grid->updated_active_tensors.getNumIndexes());
226 oned_max_level = *std::max_element(grid->max_levels.begin(), grid->max_levels.end());
229 grid->wrapper = OneDimensionalWrapper(oned_max_level, rule_fourier, 0.0, 0.0);
231 grid->max_power = MultiIndexManipulations::getMaxIndexes(((grid->points.empty()) ? grid->needed : grid->points));
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