Draft: Use less allocations on UGGrid intersection geometries
Currently, UGGrid intersection geometries do many allocations for very small objects. In simple simulations I get millions (!) of allocation calls due to this, a few orders of magnitude higher than any other allocation in a simulation. This happens because
- The geometry object is stored as a shared pointer. While this is handy when having several geometries referring to the same intersection, this is barely of any use as we mostly expect people to have one geometry and get it from the entity. An optional type is more appropriate here.
- The coordinates are a
std::vector
of field vectors that need to be created for every geometry. While is nice having a geometry that has ownership of the coordinates because it could technically outlive the grid, but in any case, this cannot be reliably exploited asUGGridEntity::UGridGeometry
does not own its coordinates either. This can be solved by generating the coordinates on-demand withstd::function
. - Every new intersection stores a
std::vector
of faces. While this is needed for the non-conforming case, it penalizes the common case where there is one or no faces neighboring the intersection. This can be solved by properly using a union type, i.e.std::variant
The current MR mitigates the first issue by using std::optional
, the second one by generating the coordinates on the fly with (WIP), and the third one by using std::function
std::variant
. All of them optimized to not allocate anything on the hot-path but still be flexible to allocate if needed.
Edited by Santiago Ospina De Los Ríos