A shape enumeration is a complete, ordered list of all lattice nodes that are part of the basis shape.
More...
template<dim_t D, class MultiIndex>
class waveblocks::wavepackets::shapes::ShapeEnum< D, MultiIndex >
A shape enumeration is a complete, ordered list of all lattice nodes that are part of the basis shape.
Definition
A \( D \)-dimensional shape enumeration \( \mathfrak{K} \) is a set of ordered D-dimensional integer-tuples (aka node).
Rationale
A basis shape description just tells, whether it contains a specific node. But we need to associate coefficients \(c_{\underline{k}}\) and basis functions \(\phi_{\underline{k}}\) with shape nodes \(\underline{k}\). We can use a hashtable to map \(\underline{k}\) to \(c_{\underline{k}}\), \(\phi_{\underline{k}}\). But it is simpler to enumerate all nodes in a shape. This means, if a multi-index \(\underline{k}\) maps to ordinal \(i\), we find \(\phi_{\underline{k}}\) at the position \(i\) on the array \(\{\phi\}\). This way, we can keep coefficients and basis function values in an array, ordered according to the shape enumeration.
Slicing
Many algorithms, notable evaluation of a hagedorn wavepacket, use recursive formulas in the form \( \phi_{\underline{k}} = f(\phi_{\underline{k}-\underline{e}^1}, \ldots, \phi_{\underline{k}-\underline{e}^D}) \), where \( \phi_{\underline{k}} \) is a value associated with the node \( \underline{k} \) and where \( \underline{e}^d \) is the unit vector in direction \( d \). Thus, it is beneficial to organize a shape into slices. The \( s \)-th slice of a shape \( \mathfrak{K} \) contains all nodes \( \underline{k} \in \mathfrak{K} \) that satisfy \( \sum_{d=1}^{D} k_d = s \).
The \( s \)-th slice contains all multi-indices \( \boldsymbol{k} \in \mathfrak{K} \) that satisfy \( \displaystyle\sum_{d=1}^{D} k_d = s \).
To determine, to which slice a multi-index belongs, use:
#include <numeric>
int islice = std::accumulate(index.begin(), index.end(), int(0));
Nodes in the same slice are ordered lexically. This ordering enables simple and efficient union and intersect operations on shape enumerations.
Usage
#include "waveblocks/shape_commons.hpp"
#include "waveblocks/tiny_multi_index.hpp"
#include "waveblocks/shape_enumerator.hpp"
#include "waveblocks/shape_enum.hpp"
Create a shape description (see AbstractShape).
LimitedHyperbolicCutShape<D> shape(7.0, {2,2,4,4,4});
Select an appropriate data type to represent an integer tuple.
typedef TinyMultiIndex<std::size_t,D> MultiIndex;
Pass the shape description to the ShapeEnumerator and you get a ShapeEnum:
ShapeEnumerator<D, MultiIndex> enumerator;
std::shared_ptr< ShapeEnum<D, MultiIndex> > enumeration = enumerator.enumerate(shape);
Select a slice:
const ShapeSlice<D, MultiIndex>&
slice = enumeration->slice(slice_index);
Get the \( i \)-th node of the slice:
MultiIndex index = slice[i];
Get ordinal of a node \( \underline{k} \):
std::size_t ordinal = slice.offset() + slice.find(
k);
If you aren't sure, whether the slice contains a node, use:
std::size_t ordinal;
if (slice.try_find(
k, ordinal)) {
ordinal += slice.offset();
}