Create DIS/DISV/DISU derived classes for mf6 packages

It has become somewhat clear through the Lake Package (!166 (closed)), Well, etc. that we could use both a "high level" package interface next to a "low level" one, which (mostly) matches the mf6 input one-to-one.

The high level classes would contain to_dis, to_disv, to_disu methods; the low level classes would contain to_grid (or more general name, wells would be turned into points or something). I'd like to avoid creating quadruple classes for every package. Python is plenty dynamic, so we can dynamically create classes (only once, at import imod). However, those classes should ideally also be importable.

Python is very dynamic, so it seems this can be done relatively easily: https://stackoverflow.com/questions/13624603/python-how-to-register-dynamic-class-in-module

This would replace the "to_recarr" functions and "to_sparse" method (which is a bit of a misnomer on my part anyway). Benefit is that users can completely inspect the intermediate objects, rather than having to debug the files.

Easiest way to do this is by having the long list exist in the imod.mf6.__init__ module.

DisRiver = River.create_dis_class()
DisvRiver = River.create_disv_class()
DisuRiver = River.create_disu_class()

The list is quite long, but it seems like the most straightforward way that doesn't require hacks.

I'd hope we can easily setup the create_..._class on the base classes. These will have to vary a little per class (e.g. Drainage, River are a grid -> cell_id conversion; Wells are x, y, top, bottom -> cell_id conversion, etc.).

Edited by Huite Bootsma