31#ifndef __TASMANIAN_ADDONS_LOADUNSTRUCTURED_HPP
32#define __TASMANIAN_ADDONS_LOADUNSTRUCTURED_HPP
45#include "tsgLoadNeededValues.hpp"
78 and not (grid.isLocalPolynomial() and ((grid.getOrder() < 0) or (grid.getOrder() > 2)))
79 and not (grid.isWavelet() and grid.getOrder() == 3);
93template<typename scalar_type>
94void generateCoefficientsGPU(
double const data_points[],
int num_data, scalar_type model_values[],
96 AccelerationContext
const *acceleration = grid.getAccelerationContext();
97 int num_outputs = grid.getNumOutputs();
98 int num_points = grid.getNumPoints();
99 int num_equations = (tolerance > 0.0) ? num_data + num_points : num_data;
101 GpuVector<scalar_type> basis_matrix(acceleration, num_equations, num_points);
102 grid.evaluateHierarchicalFunctionsGPU(data_points, num_data,
reinterpret_cast<double*
>(basis_matrix.data()));
104 if (tolerance > 0.0){
105 double correction = std::sqrt(tolerance);
106 constexpr long long esize = (std::is_same<scalar_type, double>::value) ? 1 : 2;
107 long long num_total =
static_cast<long long>(num_points) *
static_cast<long long>(num_points) * esize;
108 TasGpu::fillDataGPU(acceleration, 0.0, num_total, 1,
109 reinterpret_cast<double*
>(basis_matrix.data() + Utils::size_mult(num_data, num_points)));
111 long long stride =
static_cast<long long>(num_points + 1) * esize;
112 TasGpu::fillDataGPU(acceleration, correction, num_points, stride,
113 reinterpret_cast<double*
>(basis_matrix.data() + Utils::size_mult(num_data, num_points)));
115 TasGpu::fillDataGPU(acceleration, 0.0, esize * num_outputs * num_points, 1,
116 reinterpret_cast<double*
>(model_values + Utils::size_mult(num_data, num_outputs)));
119 TasmanianDenseSolver::solvesLeastSquaresGPU(acceleration, num_equations, num_points,
120 basis_matrix.data(), num_outputs, model_values);
134template<
typename scalar_type>
135Data2D<scalar_type> generateCoefficients(
double const data_points[],
int num_data,
double const model_values[],
double tolerance,
TasmanianSparseGrid &grid){
136 int num_dimensions = grid.getNumDimensions();
137 int num_outputs = grid.getNumOutputs();
138 int num_points = grid.getNumPoints();
139 int num_equations = (tolerance > 0.0) ? num_data + num_points : num_data;
141 AccelerationContext
const *acceleration = grid.getAccelerationContext();
143 Data2D<scalar_type> basis_matrix(num_points, num_equations, 0.0);
144 Data2D<scalar_type> coefficients(num_outputs, num_equations, 0.0);
147 int mem_usage = 268435456 / ((std::is_same<double, scalar_type>::value) ? 1 : 2);
148 if (grid.getGPUMemory(acceleration->device) < 2048) mem_usage /= 2;
149 int num_batch = std::min(num_data, mem_usage / num_points);
150 if (num_batch < 128){
152 grid.evaluateHierarchicalFunctions(data_points, num_data,
reinterpret_cast<double*
>(basis_matrix.data()));
154 acceleration->setDevice();
155 GpuVector<double> gpu_points(acceleration, num_dimensions, num_batch);
156 GpuVector<scalar_type> gpu_matrix(acceleration, num_points, num_batch);
157 for(
int i = 0; i < num_data; i += num_batch){
158 int num_this_batch = std::min(num_batch, num_data - i);
159 gpu_points.load(acceleration, Utils::size_mult(num_this_batch, num_dimensions),
160 data_points + Utils::size_mult(i, num_dimensions));
161 grid.evaluateHierarchicalFunctionsGPU(gpu_points.data(), num_this_batch,
reinterpret_cast<double*
>(gpu_matrix.data()));
162 gpu_matrix.unload(acceleration, Utils::size_mult(num_this_batch, num_points), basis_matrix.getStrip(i));
166 grid.evaluateHierarchicalFunctions(data_points, num_data,
reinterpret_cast<double*
>(basis_matrix.data()));
169 if (tolerance > 0.0){
170 double correction = std::sqrt(tolerance);
171 for(
int i=0; i<grid.getNumPoints(); i++)
172 basis_matrix.getStrip(i + num_data)[i] = correction;
175 auto icoeff = coefficients.begin();
176 for(
size_t i=0; i<Utils::size_mult(num_data, grid.getNumOutputs()); i++)
177 *icoeff++ = model_values[i];
179 TasmanianDenseSolver::solvesLeastSquares(acceleration, num_equations, grid.getNumPoints(),
180 basis_matrix.data(), grid.getNumOutputs(), coefficients.data());
194template<
typename scalar_type>
195inline void loadUnstructuredDataL2tmpl(
double const data_points[],
int num_data,
double const model_values[],
198 if (grid.empty())
throw std::runtime_error(
"Cannot use loadUnstructuredDataL2() with an empty grid.");
199 if (grid.getNumNeeded() != 0)
200 grid.mergeRefinement();
202 AccelerationContext
const *acceleration = grid.getAccelerationContext();
204 throw std::runtime_error(
"The loadUnstructuredDataL2() method cannot be used with acceleration mode accel_none.");
206 int num_dimensions = grid.getNumDimensions();
207 int num_outputs = grid.getNumOutputs();
208 int num_points = grid.getNumPoints();
209 int num_equations = (tolerance > 0.0) ? num_data + num_points : num_data;
211 Data2D<scalar_type> coefficients =
212 [&]()->Data2D<scalar_type>{
214 acceleration->setDevice();
215 GpuVector<double> gpu_points(acceleration, num_dimensions, num_data, data_points);
216 GpuVector<scalar_type> gpu_values(acceleration, num_outputs, num_equations);
217 TasGpu::load_n(acceleration, model_values, Utils::size_mult(num_outputs, num_data), gpu_values.data());
218 generateCoefficientsGPU<scalar_type>(gpu_points.data(), num_data, gpu_values.data(), tolerance, grid);
219 return Data2D<scalar_type>(num_outputs, num_equations, gpu_values.unload(acceleration));
221 return generateCoefficients<scalar_type>(data_points, num_data, model_values, tolerance, grid);
226 if (std::is_same<scalar_type, std::complex<double>>::value){
227 std::vector<double> real_coeffs(Utils::size_mult(2 * grid.getNumOutputs(), grid.getNumPoints()));
228 auto icoeff = coefficients.begin();
229 for(
size_t i=0; i<Utils::size_mult(grid.getNumOutputs(), grid.getNumPoints()); i++)
230 real_coeffs[i] = std::real(*icoeff++);
231 icoeff = coefficients.begin();
232 for(
size_t i=Utils::size_mult(grid.getNumOutputs(), grid.getNumPoints()); i<Utils::size_mult(2 * grid.getNumOutputs(), grid.getNumPoints()); i++)
233 real_coeffs[i] = std::imag(*icoeff++);
234 grid.setHierarchicalCoefficients(real_coeffs.data());
236 grid.setHierarchicalCoefficients(
reinterpret_cast<double*
>(coefficients.data()));
285 loadUnstructuredDataL2tmpl<std::complex<double>>(data_points, num_data, model_values, tolerance, grid);
287 loadUnstructuredDataL2tmpl<double>(data_points, num_data, model_values, tolerance, grid);
301 if (grid.
empty())
throw std::runtime_error(
"Cannot use loadUnstructuredDataL2() with an empty grid.");
302 int num_data =
static_cast<int>(data_points.size() / grid.
getNumDimensions());
303 if (model_values.size() < Utils::size_mult(num_data, grid.
getNumOutputs()))
304 throw std::runtime_error(
"In loadUnstructuredDataL2(), provided more points than data.");
The master-class that represents an instance of a Tasmanian sparse grid.
Definition TasmanianSparseGrid.hpp:293
int getNumOutputs() const
Return the outputs of the grid, i.e., number of model outputs.
Definition TasmanianSparseGrid.hpp:644
bool isFourier() const
Returns true if the grid is of type Fourier, false otherwise.
Definition TasmanianSparseGrid.hpp:1089
bool empty() const
Returns true if the grid is empty (no type), false otherwise.
Definition TasmanianSparseGrid.hpp:1093
int getNumDimensions() const
Return the dimensions of the grid, i.e., number of model inputs.
Definition TasmanianSparseGrid.hpp:642
@ accel_none
Usually the slowest mode, uses only OpenMP multi-threading, but optimized for memory and could be the...
Definition tsgEnumerates.hpp:553
@ accel_gpu_magma
Same the CUDA option but uses the UTK MAGMA library for the linear algebra operations.
Definition tsgEnumerates.hpp:563
@ accel_gpu_cuda
Similar to the cuBLAS option but also uses a set of Tasmanian custom GPU kernels.
Definition tsgEnumerates.hpp:561
void loadUnstructuredDataL2(double const data_points[], int num_data, double const model_values[], double tolerance, TasmanianSparseGrid &grid)
Construct a sparse grid surrogate using a least-squares fit.
Definition tsgLoadUnstructuredPoints.hpp:282
Encapsulates the Tasmanian Sparse Grid module.
Definition TasmanianSparseGrid.hpp:68