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 final :
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 GridFourier(GridFourier &&) =
default;
50 GridFourier &operator = (GridFourier &&) =
default;
52 bool isFourier()
const override{
return true; }
54 void write(std::ostream &os,
bool iomode)
const override{
if (iomode == mode_ascii) write<mode_ascii>(os);
else write<mode_binary>(os); }
56 template<
bool iomode>
void write(std::ostream &os)
const;
58 void makeGrid(
int cnum_dimensions,
int cnum_outputs,
int depth, TypeDepth type,
const std::vector<int> &anisotropic_weights,
const std::vector<int> &level_limits);
59 void updateGrid(
int depth, TypeDepth type,
const std::vector<int> &anisotropic_weights,
const std::vector<int> &level_limits);
61 void setTensors(MultiIndexSet &&tset,
int cnum_outputs);
67 void getLoadedPoints(
double *x)
const override;
68 void getNeededPoints(
double *x)
const override;
69 void getPoints(
double *x)
const override;
71 void getInterpolationWeights(
const double x[],
double weights[])
const override;
72 void getQuadratureWeights(
double weights[])
const override;
73 void getDifferentiationWeights(
const double x[],
double weights[])
const override;
75 void evaluate(
const double x[],
double y[])
const override;
76 void integrate(
double q[],
double *conformal_correction)
const override;
77 void differentiate(
const double x[],
double jacobian[])
const override;
79 void evaluateBatch(
const double x[],
int num_x,
double y[])
const override;
81 void evaluateBatchGPU(
const double gpu_x[],
int cpu_num_x,
double gpu_y[])
const override;
82 void evaluateBatchGPU(
const float gpu_x[],
int cpu_num_x,
float gpu_y[])
const override;
83 template<
typename T>
void evaluateBatchGPUtempl(
const T gpu_x[],
int cpu_num_x, T gpu_y[])
const;
84 void evaluateHierarchicalFunctionsGPU(
const double gpu_x[],
int num_x,
double gpu_y[])
const override;
85 void evaluateHierarchicalFunctionsGPU(
const float gpu_x[],
int num_x,
float gpu_y[])
const override;
87 void evaluateHierarchicalFunctionsInternalGPU(
const T gpu_x[],
int num_x, GpuVector<T> &wreal, GpuVector<T> &wimag)
const;
89 void evaluateHierarchicalFunctions(
const double x[],
int num_x,
double y[])
const override;
90 void evaluateHierarchicalFunctionsInternal(
const double x[],
int num_x, Data2D<double> &wreal, Data2D<double> &wimag)
const;
91 void setHierarchicalCoefficients(
const double c[])
override;
93 void integrateHierarchicalFunctions(
double integrals[])
const override;
95 void updateAccelerationData(AccelerationContext::ChangeType change)
const override;
97 void estimateAnisotropicCoefficients(TypeDepth type,
int output, std::vector<int> &weights)
const;
98 void setAnisotropicRefinement(TypeDepth type,
int min_growth,
int output,
const std::vector<int> &level_limits);
99 void clearRefinement()
override;
100 void mergeRefinement()
override;
102 void beginConstruction()
override;
103 void writeConstructionData(std::ostream &os,
bool)
const override;
104 void readConstructionData(std::istream &is,
bool)
override;
105 std::vector<double> getCandidateConstructionPoints(TypeDepth type,
const std::vector<int> &weights,
const std::vector<int> &level_limits);
106 std::vector<double> getCandidateConstructionPoints(TypeDepth type,
int output,
const std::vector<int> &level_limits);
107 std::vector<double> getCandidateConstructionPoints(std::function<
double(
const int *)> getTensorWeight,
const std::vector<int> &level_limits);
108 void loadConstructedPoint(
const double x[],
const std::vector<double> &y)
override;
109 void loadConstructedPoint(
const double x[],
int numx,
const double y[])
override;
110 void finishConstruction()
override;
112 const double* getFourierCoefs()
const;
115 void calculateFourierCoefficients();
117 MultiIndexSet selectTensors(
size_t dims,
int depth, TypeDepth type,
const std::vector<int> &anisotropic_weights,
118 std::vector<int>
const &level_limits)
const;
119 void proposeUpdatedTensors();
120 void acceptUpdatedTensors();
122 std::vector<std::vector<int>> generateIndexingMap()
const;
124 void loadConstructedTensors();
125 std::vector<int> getMultiIndex(
const double x[]);
127 template<
typename T,
bool interwoven>
128 void computeBasis(
const MultiIndexSet &work,
const T x[], T wreal[], T wimag[])
const{
129 int num_points = work.getNumIndexes();
131 std::vector<std::vector<std::complex<T>>> cache(num_dimensions);
132 for(
int j=0; j<num_dimensions; j++){
133 cache[j].resize(max_power[j] +1);
134 cache[j][0] = std::complex<T>(1.0, 0.0);
136 T theta = -2.0 * Maths::pi * x[j];
137 std::complex<T> step(std::cos(theta), std::sin(theta));
138 std::complex<T> pw(1.0, 0.0);
139 for(
int i=1; i<max_power[j]; i += 2){
142 cache[j][i+1] = std::conj<T>(pw);
146 for(
int i=0; i<num_points; i++){
147 const int *p = work.getIndex(i);
149 std::complex<T> v(1.0, 0.0);
150 for(
int j=0; j<num_dimensions; j++){
155 wreal[2*i] = v.real();
156 wreal[2*i+1] = v.imag();
164 void clearGpuNodes()
const;
165 void clearGpuCoefficients()
const;
168 OneDimensionalWrapper wrapper;
170 MultiIndexSet tensors;
171 MultiIndexSet active_tensors;
172 std::vector<int> active_w;
174 MultiIndexSet updated_tensors;
175 MultiIndexSet updated_active_tensors;
176 std::vector<int> updated_active_w;
178 std::vector<int> max_levels;
180 Data2D<double> fourier_coefs;
182 std::vector<int> max_power;
184 template<
typename T>
void loadGpuNodes()
const;
185 template<
typename T>
void loadGpuCoefficients()
const;
186 inline std::optional<CudaFourierData<double>>& getGpuCacheOverload(
double)
const{
return gpu_cache; }
187 inline std::optional<CudaFourierData<float>>& getGpuCacheOverload(
float)
const{
return gpu_cachef; }
188 template<
typename T>
inline std::optional<CudaFourierData<T>>& getGpuCache()
const{
189 return getGpuCacheOverload(
static_cast<T
>(0.0));
191 mutable std::optional<CudaFourierData<double>> gpu_cache;
192 mutable std::optional<CudaFourierData<float>> gpu_cachef;
194 std::unique_ptr<DynamicConstructorDataGlobal> dynamic_values;
198template<>
struct GridReaderVersion5<GridFourier>{
199 template<
typename iomode>
static void read(std::istream &is, GridFourier *grid) {
200 grid->num_dimensions = IO::readNumber<iomode, int>(is);
201 grid->num_outputs = IO::readNumber<iomode, int>(is);
203 grid->tensors = MultiIndexSet(is, iomode());
204 grid->active_tensors = MultiIndexSet(is, iomode());
205 grid->active_w = IO::readVector<iomode, int>(is, grid->active_tensors.getNumIndexes());
207 if (IO::readFlag<iomode>(is)) grid->points = MultiIndexSet(is, iomode());
208 if (IO::readFlag<iomode>(is)) grid->needed = MultiIndexSet(is, iomode());
210 grid->max_levels = IO::readVector<iomode, int>(is, grid->num_dimensions);
212 if (grid->num_outputs > 0){
213 grid->values = StorageSet(is, iomode());
214 if (IO::readFlag<iomode>(is))
215 grid->fourier_coefs = IO::readData2D<iomode, double>(is, grid->num_outputs, 2 * grid->points.getNumIndexes());
219 if (IO::readFlag<iomode>(is)){
220 grid->updated_tensors = MultiIndexSet(is, iomode());
221 oned_max_level = grid->updated_tensors.getMaxIndex();
223 grid->updated_active_tensors = MultiIndexSet(is, iomode());
225 grid->updated_active_w = IO::readVector<iomode, int>(is, grid->updated_active_tensors.getNumIndexes());
227 oned_max_level = *std::max_element(grid->max_levels.begin(), grid->max_levels.end());
230 grid->wrapper = OneDimensionalWrapper(oned_max_level, rule_fourier, 0.0, 0.0);
232 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:288
@ rule_fourier
Trigonometric basis with uniformly distributed nodes (primarily for internal use).
Definition tsgEnumerates.hpp:375
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