What this MR does / why does DuMux need it:
Introduces a new
GridGeometry for cell-centered finite volume schemes with a modified interface of local views. The new implementation uses significantly less memory while (at least for one considered performance test) being equally fast with caching, but over 3 times faster without caching (while still requiring less memory). The new implementation does not contain a
ConnectivityMap, as the new local view interface should be enough to construct connectivity information. The new local view interface could be useful in the new assembly...
I added a header in
geometry/normal, that, given a geometry and the index of a codim-1 entity computes the outer unit normal vector. In case we keep this, this should be done properly...
we should probably add support for injecting custom stencils (currently we have that extended source stencil somewhere...)
extraction/reusage of the
BaseGeometry, which is currently possible on master
we may think of making grid geometries "observable" to design our depending classes such that they can automatically update in adaptive simulations (probably best to postpone once it actually becomes relevant during development)
Notes for the reviewer
The new implementation has the following key differences:
- It introduces the concept of a
Face, which is basically the geometric part of our current scvfs (center, area). The scvfs internally reuse a face and additionally expose the outer normal vector. This way, one only has to compute/store the geometric information on scvfs once for all branches meeting at the face. This reduces the memory overhead, but comes with the downside that now scvfs are no longer self-contained objects. Internally, they currently store a pointer to a
Face, so the lifetime is bound to the lifetime of
Face. The intended usage is solely with a previously bound local view (which we currently do and promote anyway).
- The only things (currently) configurable in new implementation are related to optimizing memory - the number of maximum neighbors per face, etc. We had this before, I just renamed the variables to (hopefully) make it a bit more clear what exactly can be customized, and I chose those variation points such that internally we can optimize memory usage. In the old implementation, one could inject the type of
LocalViewto be used as well as the type of
SubControlVolumeFace. I didn't really see the use case for the latter two, because the grid geometry constructs these objects (at least in case of caching), so the constructor is fixed, but since these only store/expose the information given in the ctor (basically), I didn't see why I would want to use different types. I figured that if I want different behaviour, I may simply wrap the existing GG and local views and expose some new interface. It also seemed to me that this would be the easiest way in case I want a different local view... Besides this, to really use a custom
LocalViewis probably pretty difficult, as you need to know quite something on the internal wires of the grid geometry... But I am happy to hear examples on where I would need this.
- Related to 2: While one can inject less things into the GG, I think it is now also easier to just implement a custom grid geometry. I extracted the connectivity determination step into a reusable class, such that in the case of caching, the only thing the grid geometry does is to use that info and construct the grid geometries. In this case the local view basically just forwards calls to the grid geometry. In the case of no caching, the grid geometry class is pretty much empty, and the local view contains the logic of constructing the locally (in the stencil) required geometries. So I don't really see what should be injected where and why (over just wrapping), besides that the GG and local view are highly cohesive...
- In the case of no caching, the local view does not store the dof indices anymore, finding the local index of scvs by searching in that local container. I went for a different approach, wrapping the Scvs and Scvfs in something that additionally carries an
id, which is private and can only be accessed by the local view itself. Thus, the local view actually returns not
SubControlVolume, but a wrapped sub-control volume with the same public interface. I don't mind this, though.
- Related to 2: Internally, we currently use
Dune::ReservedVectorto store things, and the maximum expected container size can be configured via the traits. I added a class
DefaultStorage, which uses
Dune::ReservedVectorwhen an integer value is given for the desired size, but I also introduced a class
Size::Dynamic, and if that one is set, it uses
Dynamiccan be used in arithmetic operations to compute sizes, with the result always being
Dynamic. This allows for users to configure the grid geometry such that it uses purely dynamic containers for everything. This could be useful especially on network grids where you may have a few vertices with many branches while the majority of the network only has one branch. In this case
Dynamicshould avoid unnecessary memory overhead.
Before you request a review from someone, make sure to revise the following points:
does the new code follow the style guide?
do the test pipelines pass? (see guide on how to run pipelines for a merge request)
is the code you changed and/or the new code you wrote covered in the test suite? (if not, extend the existing tests or write new ones)
does your change affect public interfaces or behavior, or, does it introduce a new feature? If so, document the change in
is the list of the header includes complete? ("include what you use")
all files have to end with a
\ncharacter. Make sure there is no
\ No newline at end of filecomment in "Changes" of this MR.
(if not applicable remove) are newly introduced or modified physical values/functions backed up with a scientific reference (including doi) in the docs?
(if not applicable remove) if the examples are modified, is the documentation regenerated (using