-
Notifications
You must be signed in to change notification settings - Fork 5
AdaptiveGrid
Defined in header "allscale/api/user/data/adaptive_grid.h"
template <typename T, typename CellConfig>
using AdaptiveGrid = Grid<AdaptiveGridCell<T, CellConfig>, CellConfig::dims>;
The AdaptiveGrid
data structure represents an n-dimensional array of values, with a statically fixed number of dimensions, and a size to be specified at creation.
The AdaptiveGrid
is esentially a Grid
with AdaptiveGridCell
element types. Therefore, consider also reading the Grid reference.
The AdaptiveGridCell
stores the data of different layers defined in CellConfig
and is used to switch between layers. The AdaptiveGridCell
always has a default layer that only contains a single element. The layers are numbered, where the finest layer has number 0 and is selected by default.
When going up in the layer hierarchy the size of the layer given in the CellConfig
is combined to a single element. When going down the layer hierarchy each element is split into multiple elements of the size of the next layer.
Member type | Definition |
---|---|
addr_type |
allscale::utils::Vector<int64_t, Dims> |
Member function | Description |
---|---|
AdaptiveGridCell& operator=(const T& value) |
Assign value to all elements on the selected layer |
T& operator[](const addr_type& addr) |
Read and write access to elements of the selected layer |
const T& operator[](const addr_type& addr) const |
Read access to elements of the selected layer |
allscale::utils::Vector<std::size_t, Dims> getActiveLayerSize() |
Size of the selected layer |
void setActiveLayer(unsigned level) |
Select a layer by number |
unsigned getActiveLayer() const |
Get the selected layer number |
template<unsigned Layer> auto getLayer() -> decltype(data.template getLayer<Layer>())&
|
Read and write access to layer data by the layer number |
template<unsigned Layer> auto getLayer() const -> const decltype(data.template getLayer<Layer>())&
|
Read only access to layer data by the layer number |
template<typename Op> void forAllActiveNodes(const Op& op)
|
Apply op to all elements of the selected layer |
template<typename Refiner> void refine(const Refiner& refiner)
|
Refine by a function returning a single value, copied to every refined element |
template<typename Refiner> void refineGrid(const Refiner& refiner)
|
Refine by a function returning a StaticGrid
|
template<typename Coarsener> void coarsen(const Coarsener& coarsener)
|
Coarsen by a per-element function and compute average over all elements |
template<typename Coarsener> void coarsenGrid(const Coarsener& coarsener)
|
Coarsen by a function taking a StaticGrid and returning a single element |
std::vector<T> getBoundary(Direction dir) const |
Get boundary data from Direction
|
void setBoundary(Direction dir, const std::vector<T>& boundary) |
Set boundary data at Direction
|
#include "allscale/api/user/data/adaptive_grid.h"
#include "allscale/utils/string_utils.h"
using namespace allscale::api::user::data;
// two dimensional configuration with two nested 2x2 layers and the default 1x1 layer
// even when passing an empty layers configuration (i.e. CellConfig<2, layers<>>) there will always be the implicit 1x1 layer
// the outermost 2x2 layer (consisting of 4x4 elements) is selected by default
using ThreeLayerCellConfig = CellConfig<2, layers<layer<2, 2>,layer<2, 2>>>;
// create a two-dimensional grid of integers of size 10x20
AdaptiveGrid<int, ThreeLayerCellConfig> grid({10, 20});
// set all elements on the most coarse-grained layer to 2.0
grid.forEach([](AdaptiveGridCell<int, ThreeLayerCellConfig>& cell) {
// layer 0 is selected by default
assert_eq(toString(cell.getActiveLayerSize()), "[4,4]");
//set to the default 1x1 layer
cell.setActiveLayer(2);
assert_eq(toString(cell.getActiveLayerSize()), "[1,1]");
// set all elements to 2.0
cell.forAllActiveNodes([](int& element) {
element = 2.0;
});
});
//
grid.forEach([](AdaptiveGridCell<int, ThreeLayerCellConfig>& cell) {
// refine to 2x2 layer using a user-specified function taking a single element
// and returning a grid of size of the refined layer
// Note: after refineGrid() and refine() function calls, the new, refined layer is active
cell.refineGrid([](const int& element) {
allscale::utils::StaticGrid<int, 2, 2> newGrid;
newGrid.forEach([element](auto& e) { e = element * 5; });
return newGrid;
});
// all elements on the active layer are now 10
cell.forAllActiveNodes([](const int& element) {
assert_eq(element, 10);
});
// refine to 4x4 layer using a user-specified function taking a single element
// and returning a single element (which is then copied to each refined element)
cell.refine([](const int& element) {
return element * 5;
});
// all elements on the active layer are now 50
cell.forAllActiveNodes([](const int& element) {
assert_eq(element, 50);
});
});
grid.forEach([](AdaptiveGridCell<int, ThreeLayerCellConfig>& cell) {
// Go back to the 2x2 layer by calculating the average of the current layer
// Note that this creates a single element from each 2x2 grid on this layer
cell.coarsenGrid([](const auto& grid) {
int res = 0;
grid.forEach([&](const int& element) { res += element; });
return res / (grid.size().x * grid.size().y);
});
cell.forAllActiveNodes([](const int& element) {
assert_eq(element, 50);
});
assert_eq(toString(cell.getActiveLayerSize()), "[2,2]");
// Coarsen to the 1x1 layer by calculating the average of the layer cells
cell.coarsen([](const int& element) {
return element / 5;
});
cell.forAllActiveNodes([](const int& element) {
assert_eq(element, 10);
});
assert_eq(toString(cell.getActiveLayerSize()), "[1,1]");
});
// Set active layer of AdaptiveGridCell at [0, 0] to 0
// Note: you should initialize the elements on this layer before read-accessing them
grid[{0, 0}].setActiveLayer(0);
// Set element at 3,3 of AdaptiveGridCell at [0, 0] to 2
// This is the bottom right element of the cell
grid[{0, 0}][{3, 3}] = 2;
assert_eq((grid[{0, 0}].getActiveLayer()), 0);
assert_eq(toString(grid[{0, 0}].getActiveLayerSize()), "[4,4]");
Part of the AllScale project - http://www.allscale.eu