I’m struggling to get decent results with a Manufactured Solution for the Navier-Stokes equations, which I solve with a standard IPCS-like method, which gives good results for the Taylor-Green 2D (periodic) solution of NS, and is based on Oasis.
The fields I am solving for are taken from an article and are defined on a 2D square of side length h:
\begin{align}\mathbf{u}_{MS,0}& = -\sin(2\pi t)( y(y-h) +x)/(2\nu), \\ \mathbf{u}_{MS,1} &= -\sin(2\pi t)( x(x-h) -y)/(2\nu),\\ p &= -\sin(2\pi t) (x+y). \end{align}.
These fields are such that the viscous terms balance the pressure terms, i.e. \nu \Delta \mathbf{u} = \nabla p. There remain two terms that have to be added to the RHS of the momentum equation, since these fields do not solve NS:
\mathbf{f} = \left( \partial \mathbf{u}_{MS}/ \partial t + ( \mathbf{u}_{MS}\cdot \nabla) \mathbf{u}_{MS} \right),
where MS of course stands for manufactured solution. The boundary conditions are Dirichlet on two of the sides of the square domain, and Neumann on the others.
However, I first start from the simpler case resulting from assigning DirichletBC conditions on all of the outer boundary.
At every time step, I calculate the extra contribution to the RHS and add it to the system of equations
x = SpatialCoordinate(mesh)
u_ms = as_vector( (-sin(2.0*pi*t)/(2.0*nu)*(x[1]*(x[1]-1.0) + x[0]), -sin(2.0*pi*t)/(2.0*nu)*(x[0]*(x[0]-1.0) - x[1])) )
u_ddt_ = as_vector( (-2.0*pi*cos(2.0*pi*t)/(2.0*nu)*(x[1]*(x[1]-1.0) + x[0]),-2.0*pi*cos(2.0*pi*t)/(2.0*nu)*(x[0]*(x[0]-1.0) - x[1])) )
f_ = u_ddt_ + dot(u_ms, nabla_grad(u_ms))
then the assembly is (v is test function of the velocity discrete space):
srcv = assemble( v*f_[i]*dx )
f_tmp[ui].axpy(1.0, srcv)
where f_tmp is the RHS vector of the discrete system of the momentum equation, that is, when the tentative velocity solution is solved for. I initialize the velocity and pressure fields with the expressions above, and I calculate the L^2 error as follows:
ue = interpolate(ue, V)
uen = norm(ue.vector())
ue.vector().axpy(-1, q_[ui].vector())
error = norm(ue.vector()) / uen
where ue is one of the expressions above and V is the discrete space where the solutions are defined, the vectors of the solutions being q\_ [ui] for each component of the velocity, or pressure. If I have Neumann BCs on some boundaries, I also add an additional term to the RHS:
grdu = assemble( inner(v, dot(n,nabla_grad(u_ms[i])) )*ds )
f_tmp[ui].axpy(1.0, grdu)
that is the normal gradient of the known solution, \mathbf{u}_{MS}. Velocity and pressure spaces are P2/P1 as a starting point.
The problem is that results for this case don’t work as expected: if I assign DirichletBC everywhere on the boundary, the error stays of the order of 10^{-1} for the velocity components. This does not improve if time step is decreased, or if velocity and pressure degrees are increased to 4 and 3, respectively. So no convergence is observed.
If, on part of the boundary Neumann BCs are assigned, things get much worse, and the solution looks like garbage. I cannot understand what it is that ruins the results, since the base code works fine for the Taylor Green 2D case.
Do you have any hints on how to implement correctly Manufactured Solutions for Navier-Stokes in FEniCS (with Chorin like splitting)??