Skip to content

AdaptiveGrid

Philipp Gschwandtner edited this page Nov 21, 2017 · 3 revisions

allscale::api::user::data::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 types of AdaptiveGridCell

Member type Definition
addr_type allscale::utils::Vector<int64_t, Dims>

Member functions of AdaptiveGridCell

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

Examples

#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]");
Clone this wiki locally