Dear all,
we currently have two supported ways of passing things into kernels,
depending on whether or not the kernel expects "flattened" arguments or
not. This is best explained with an example:
In the flattened case our kernel computes a scalar value, in the
non-flattened case it does not. The code generation takes care of
looping sufficiently over all the pieces. The flattened case is only
applicable to indirect dats accessed with an iteration-space index (or
mats, which I'll sweep under the carpet for now), so imagine we write a
par_loop accessing a dat through a map with arity 3, but the dat is
vector-valued.
void flat_kernel(double A[1], ...) {
A[0] += ...;
}
void kernel(double A[2], ...) {
A[0] += ...;
A[1] += ...;
}
In the flattened case, the inner loop does:
// loop over elements (indexed by ele)
for ( i = 0; i < 6; i++ ) {
flat_kernel(A + A_map[ele * 3 + i % 3] * 2 + i / 3, ...);
}
In the non-flattened case:
for ( i = 0; i < 3; i++ ) {
kernel(A + A_map[ele * 3 + i] * 2, ...);
}
that is in the flat case we explicitly point to every data element, in
the non-flat case we just point to the start of the block. FFC expects
the former.
Maintaining both code generation paths is becoming somewhat involved,
particularly in the extruded case (note the current issues with vector
function spaces on extruded meshes are an example of this).
Do we want to continue supporting both cases? In firedrake we currently
do rely on both. Flattened for all ffc-generated kernels, non-flattened
in, at least, interpolation.
Lawrence