OP2/PyOP2

Understanding mixed objects

Closed this issue · 4 comments

I was wondering if someone could explain why we have mixed objects in PyOP2. Looking at DatPack and MixedDatPack it is clear that during code generation mixed objects are handled quite differently to non-mixed ones. Could someone explain what is going on here and, more importantly, why?

The data associated with a Dat is a single contiguous array. To stage from global to local in generated code we effectively do

staged[i] = dat[map[i]] # implicit Einstein notation

The data in a MixedDat is not a single contiguous array, but is a bag of Dats. Therefore to stage a mixed dat one must do:

for j, (dat, map) in enumerate(zip(dats, maps)):
    staged[j, i] = dat[map[i]] # note pseudo-code for linear unravelling of a ragged array.

To get a single contiguous array to pass to the kernel.

Historically, when assembling forms over mixed spaces we would split them into forms on the subspaces and then insert into the subfields. This is a nice interface, but it is not always possible to split the contributions like this as a separate kernels. So the codegen needs to scatter-gather into the mixed spaces (which is what mixeddatpack vs. Datpack are for).

Make sense?

This does thanks. Can I ask why we don't just have:

staged1[i] = dat1[map1[i]]
staged2[i] = dat2[map2[i]]

and pass both to the kernel?

Because we generate a kernel that acts on the whole mixed space (so the concatenation of staged1 and staged2)

Ok. Thank you for such prompt replies! I've been having a bit of a headache with this today so this has been really helpful.