Sparse Grids Example 6: adaptive surrogate modeling.
Example 5 demonstrates how to construct a surrogate by processing the samples in batches. The batch construction can facilitate parallel sampling, but the exact number of samples is hard to control since the points from the entire batch are needed at once. Furthermore, if a fixed number of computing nodes is available (e.g., processor cores or MPI ranks) it may be hard to keep all nodes loaded if the batch size does not divide evenly.
The construction procedure offers a more flexible refinement alternative. The batch size can be controlled at a much finer scale to accommodate a fixed budget and occupancy across all parallel resources can be guaranteed (unless the level limits or tolerance are about to be reached, or the initial grid is too coarse). See the documentation for TasGrid::mpiConstructSurrogate() for the MPI variant of this method that differs only in some MPI related parameters.
#endif
cout << "\n---------------------------------------------------------------------------------------------------\n";
cout << std::scientific; cout.precision(4);
cout << "Example 6: interpolate f(x,y) = exp(-x^2) * exp(y) * cos(z), using the rleja rule\n"
<< " employs adaptive construction\n";
int const num_inputs = 3;
int const num_outputs = 1;
auto model = [&](std::vector<double> const &x, std::vector<double> &y, size_t)->
void{
y.resize(num_outputs);
y[0] = std::exp(-x[0] * x[0]) * std::exp(x[1]) * std::cos(x[2]);
};
int const num_test_points = 1000;
std::vector<double> test_points(num_test_points * num_inputs);
std::minstd_rand park_miller(42);
std::uniform_real_distribution<double> domain(-1.0, 1.0);
for(auto &t : test_points) t = domain(park_miller);
std::vector<double> reference_values(num_test_points * num_outputs);
for(int i=0; i<num_test_points; i++){
std::vector<double> y(1);
model(std::vector<double>(test_points.begin() + i * num_inputs,
test_points.begin() + (i+1) * num_inputs),
y, 0);
std::copy(y.begin(), y.end(), reference_values.begin() + i * num_outputs);
}
double{
std::vector<double> result;
grid.evaluateBatch(test_points, result);
double diff = 0.0;
for(int i=0; i<num_test_points; i++)
diff = std::max(diff, std::abs(result[i] - reference_values[i]));
return diff;
};
cout << setw(10) << "points" << setw(20) << "error\n";
int budget = 25;
for(int itr=0; itr<6; itr++){
budget *= 2;
cout << setw(10) << grid.getNumPoints() << setw(20) << test_grid(grid) << "\n";
}
#ifndef __TASMANIAN_DOXYGEN_SKIP