BUG: nearWallDist not updated during optimisation
Summary
When running adjointOptimisationFoam in steadyOptimisation mode, the nearWallDist
in the primal turbulence model is not updated.
A bit of background:
Up until 0f00ac2d, fvMesh::Vsc()
(used e.g. in fvc::grad()
) would return a fraction of the actual cell volume if the mesh was moving and time was sub-cycled. Both these conditions are met in shape optimisation after the first mesh update, so this would lead to a blown-up simulation if not treated. Hence, after moving the mesh in each mesh update, the mesh moving
flag is set to false in displacementMethod::update()
. This has the following unwanted side-effects
-
nearWallDist
is not updated in the turbulence model, since it is safeguarded bymesh_.changing()
. This means that the initial values are used for all geometries throughout the optimisation cycles, despite the fact that the geometry has changed. Note thatwallDist
inherits fromMeshObject
and is updated properly the moment the mesh points change, irrespective of themoving
orchanging
flags infvMesh
. -
When the mesh changes, cached fields should be cleared. This is managed in
gradScheme<Type>::grad()
by themesh_.changing()
flag, but since themoving
flag is set to false after each mesh update, this fails to delete the cached fields. As a result, the first iteration of each optimisation cycle after the first one will be slightly different if we cache gradients, leading to a slightly different optimisation convergence. This is not critical, but it creates an inconsistency that shouldn't be there.
After 0f00ac2d, fvMesh::Vsc()
is also safeguarded by fvMesh::steady()
, so fvMesh::moving()
can be left to true without blowing up the simulation. This, however, creates problems of its own
-
Since now the mesh is seen as moving, cached fields will be cleared in all iterations of the primal, after the first mesh update, loosing whatever time gain we have from there.
-
In an unsteady optimisation, it is mandatory to switch
fvMesh::moving()
to false, otherwise we will get erroneousmeshPhi
fluxes to our flow equations.
For the moment, with only steady optimisation available publicly, leaving fvMesh::moving()
to true seems the correct approach since it gives the correct nearWallDist
(accuracy first), at the cost of negating the advantages of caching gradients. I will make a merge request soon.
For the long run however, we need to address this in a more general manner. As showcased above, not everything can be addressed by just playing with fvMesh::moving()
. Ideally, we need a mechanism that performs updates when the mesh points change. This already exists in MeshObject
.
Possible solutions:
-
nearWallDist
to inherit from MeshObject; this will also create some consistency betweennearWallDist
andwallDist
. -
solution
to clear all cached fields when mesh points change. It already knows the names of the cached fields (albeit not the types; but since we are talking about gradients, this can only be vol{Vector, Tensor}Field), so it can possibly inherit from MeshObject as well?
I would be glad to hear your suggestions. If you agree with the above, I can implement them but since this touches a wider scope than just optimisation, I guess there are things I have possibly missed when considering possible solutions.