In our implementation of boundary conditions we prescribe the "outer"
state and use that to compute a flux on the boundary.
For Neumann boundary conditions it is not so obvious, which value to
use for this outer state.
The default approach is to simply use the solution in the domain
at the boundary also for the "outer" state.
However, this does not really imply any gradient as actually required
for the Neumann boundaries.
To get a better approximation for the boundary condition, we need to
take the gradient normal to the boundary into account.
This can be activated for individual boundary conditions via the
enforce_zero_grad
option.
For example like this:
boundary_condition = {
{
label = 'west',
kind = 'outflow',
enforce_zero_grad = true,
pressure = p
}
}
When a boundary is set to enforce a zero gradient, we compute the gradient at the side and instead of using the original value at the boundary we use the one that we get when changing the last mode to obtain a zero gradient.
For increased stability it might be desirable to cut off even more
modes for the extrapolation.
This can be controlled by the neumann_mode_fraction
setting.
The fraction defines how many modes of the original polynomial
in boundary normal direction should be used for the extrapolation:
A setting of neumann_mode_fraction = 0
results in just the integral
mean value being used for the boundary value.
The default of neumann_mode_fraction = 1
results in the value from
changing just the last Legendre mode of the original polynomial to meet
the zero gradient constraint at the boundary.
To find the suitable extrapolation value for the boundary, taking the gradient into account, we exploit some properties of the Legendre polynomials. All Legendre polynomials are 1 at the right end of the interval: They are symmetric (even modes) or antisymmetric (odd modes): Thus, we get at the left end of the interval:
With the Legendre series of the form we therefore, obtain at the element boundaries: and
The derivative of a Legendre polynomial can be expressed recursively by: and the first two are: As can be seen from this recursion, the derivative only consists of even Legendre modes for odd Legendre modes to derive and vice-versa. The derivative at the right end of the interval is given by: And due to the symmetry property for the derivatives, on the left end the value is accordingly given by:
For a polynomial series we now can also compute the derivative at the two end points: and
For Neumann boundaries we assume a zero gradient at the boundary, and we prescribe the value that we get when we use a polynomial, for which this condition or is met. We can find this polynomial with minimal modifications by changing the last mode of the polynomial. Thus, we compute a new polynomial , which has all the lower modes from the original polynomial but the last mode taken such, that the gradient at the boundary is . For this we introduce a correcting term:
For the newly computed polynomial , we want to ensure or Here, is the last mode that is computed according to this constraint if the zero gradient should be at the left side and if should be on the right side. From this we get: and
Finally the value of this new, corrected polynomial at the boundary can be computed by plugging this into the series evaluation: and on the left side:
To use the same code for left and right, we introduce a factor to take the side (left or right) into account. This sidefactor is for right and for left. With this we get:
and resulting in the end in:
Note that the factor of two within the sum cancels out with the final multiplication and can be left out completely.