Derived terms and associated equations for the Stokes system.
All terms are considered as if they were on the right-hand side of the equation, leading
to the following UFL expression returned by the residual method:
This sign convention ensures compatibility with Thetis's time integrators. In general,
however, we like to think about the terms as they are on the left-hand side. Therefore,
in the residual methods below, we first sum the terms in the variable F as if they
were on the left-hand side, i.e.
and then return -F.
viscosity_term(eq,trial)
Viscosity term in the momentum equation.
Using the symmetric interior penalty method (Epshteyn & Rivière, 2007), the weak
form becomes
where σ is a penalty parameter.
Epshteyn, Y., & Rivière, B. (2007).
Estimation of penalty parameters for symmetric interior penalty Galerkin methods.
Journal of Computational and Applied Mathematics, 206(2), 843-872.
Source code in g-adopt/gadopt/momentum_equation.py
defviscosity_term(eq:Equation,trial:Argument|ufl.indexed.Indexed|Function)->Form:r"""Viscosity term $-nabla * (mu nabla u)$ in the momentum equation. Using the symmetric interior penalty method (Epshteyn & Rivière, 2007), the weak form becomes $$ {:( -int_Omega nabla * (mu grad u) phi dx , = , int_Omega mu (grad phi) * (grad u) dx ), ( , - , int_(cc"I" uu cc"I"_v) "jump"(phi bb n) * "avg"(mu grad u) dS - int_(cc"I" uu cc"I"_v) "jump"(u bb n) * "avg"(mu grad phi) dS ), ( , + , int_(cc"I" uu cc"I"_v) sigma "avg"(mu) "jump"(u bb n) * "jump"(phi bb n) dS ) :} $$ where σ is a penalty parameter. Epshteyn, Y., & Rivière, B. (2007). Estimation of penalty parameters for symmetric interior penalty Galerkin methods. Journal of Computational and Applied Mathematics, 206(2), 843-872. """dim=eq.mesh.geometric_dimension()identity=Identity(dim)compressible_stress=eq.approximation.compressiblemu=eq.approximation.mustress=eq.stressF=inner(nabla_grad(eq.test),stress)*eq.dxsigma=interior_penalty_factor(eq)sigma*=FacetArea(eq.mesh)/avg(CellVolume(eq.mesh))ifnotis_continuous(eq.trial_space):trial_tensor_jump=tensor_jump(eq.n,trial)+tensor_jump(trial,eq.n)ifcompressible_stress:trial_tensor_jump-=2/3*identity*jump(trial,eq.n)F+=(sigma*inner(tensor_jump(eq.n,eq.test),avg(mu)*trial_tensor_jump)*eq.dS)F-=inner(avg(mu*nabla_grad(eq.test)),trial_tensor_jump)*eq.dSF-=inner(tensor_jump(eq.n,eq.test),avg(stress))*eq.dS# NOTE: Unspecified boundaries result in free stress (i.e. free in all directions).# NOTE: "un" can be combined with "stress" provided the stress component is# tangential (e.g. no normal flow with wind)forbc_id,bcineq.bcs.items():if"u"inbcandany(bc_typeinbcforbc_typein["stress","un"]):raiseValueError('"stress" or "un" cannot be specified if "u" is already given.')if"normal_stress"inbcandany(bc_typeinbcforbc_typein["u","un"]):raiseValueError('"u" or "un" cannot be specified if "normal_stress" is already given.')if"u"inbc:trial_tensor_jump=outer(eq.n,trial-bc["u"])ifcompressible_stress:trial_tensor_jump-=(2/3*identity*(dot(eq.n,trial)-dot(eq.n,bc["u"])))trial_tensor_jump+=transpose(trial_tensor_jump)# Terms below are similar to the above terms for the DG dS integrals.F+=(2*sigma*inner(outer(eq.n,eq.test),mu*trial_tensor_jump)*eq.ds(bc_id))F-=inner(mu*nabla_grad(eq.test),trial_tensor_jump)*eq.ds(bc_id)F-=inner(outer(eq.n,eq.test),stress)*eq.ds(bc_id)if"un"inbc:trial_tensor_jump=outer(eq.n,eq.n)*(dot(eq.n,trial)-bc["un"])ifcompressible_stress:trial_tensor_jump-=2/3*identity*(dot(eq.n,trial)-bc["un"])trial_tensor_jump+=transpose(trial_tensor_jump)# Terms below are similar to the above terms for the DG dS integrals.F+=(2*sigma*inner(outer(eq.n,eq.test),mu*trial_tensor_jump)*eq.ds(bc_id))F-=inner(mu*nabla_grad(eq.test),trial_tensor_jump)*eq.ds(bc_id)# We only keep the normal part of stress; the tangential part is assumed to# be zero stress (i.e. free slip) or prescribed via "stress".F-=dot(eq.n,eq.test)*dot(eq.n,dot(stress,eq.n))*eq.ds(bc_id)if"stress"inbc:# a momentum flux, a.k.a. "force"# Here we need only the third term because we assume jump_u = 0# (u_ext = trial) and stress = n . (mu . stress_tensor).F-=dot(eq.test,bc["stress"])*eq.ds(bc_id)if"normal_stress"inbc:F+=dot(eq.test,bc["normal_stress"]*eq.n)*eq.ds(bc_id)return-F