r"""This module contains functions that compute the coefficients in analytical
solution to the Stokes equations in cylindrical and spherical shell domains
with a smooth RHS forcing term, which in the 2D cylindrical shell domain takes
the form:

.. math::

  f = -g (r/Rp)^k cos(n\varphi) \hat{r}

where r is the radius (distance from origin), :math:`\varphi` is the angle with
the x-axis, Rp and Rm are the outer and inner radius of the shell domain, and
:math:`\hat{r}` is the outward pointing radial unit vector. The magnitude g,
degree l and wave number n can be chosen arbitrarily. Similarly in a 3D
spherical domain we consider the forcing term

.. math::

  f = -g (r/Rp)^k Y_{lm}(\theta,\varphi) \hat{r}

where :math:`\theta` and :math:`\varphi` are the co-latitude and longitude
respectively, and :math:`Y_{lm}` is Laplace's spherical harmonic function of
degree l and order m.

We consider the following cases:

  cylinder_smooth_fs: cylindrical, with free-slip boundary condition at r=Rm and r=Rp
  cylinder_smooth_ns: cylindrical, with zero-slip boundary conditions at r=Rm and r=Rp
  sphere_smooth_fs:   spherical, with free-slip boundary condition at r=Rm and r=Rp
  sphere_smooth_ns:    spherical, with zero-slip boundary condition at r=Rm and r=Rp

The functions below take the following parameters:

   :param Rp:   outer radius
   :param Rm:   inner radius
   :param k:    polynomial degree of forcing term
   :param n:    wave number (2D cylindrical only)
   :param l:    spherical degree (3D only)
   :param g:    scalar magnitude of forcing
   :param nu:   viscosity

and return the five coefficients A, B, C, D, and E used in the analytical solution.

This module has been automatically generated by extracting the solutions from the
latex source of the associated paper.
"""


def coefficients_cylinder_smooth_fs(Rp, Rm, k, n, g, nu):
    alpha = Rm/Rp
    A = -0.25*(alpha**2 - alpha**(k + n + 3))*Rp**(-n + 3)*g/((alpha + alpha**n)*(alpha**n - alpha)*(k + n + 1)*(k - n + 3)*nu)
    B = 0.25*Rp**(n + 3)*(alpha**(k + n + 3) - alpha**(2*n + 2))*g/((alpha**(n + 1) + 1)*(alpha**(n + 1) - 1)*(k + n + 3)*(k - n + 1)*nu)
    C = -0.25*Rp**(-n + 1)*(alpha**(k + n + 3) - 1)*g/((alpha**(n + 1) + 1)*(alpha**(n + 1) - 1)*(k + n + 3)*(k - n + 1)*nu)
    D = -0.25*Rp**(n + 1)*(alpha**(k + n + 3) - alpha**(2*n))*g/((alpha + alpha**n)*(alpha**n - alpha)*(k + n + 1)*(k - n + 3)*nu)
    E = g*n/(((k + 3)**2 - n**2)*((k + 1)**2 - n**2)*Rp**k*nu)
    return A, B, C, D, E


def coefficients_cylinder_smooth_ns(Rp, Rm, k, n, g, nu):
    alpha = Rm/Rp
    A = 0.5*((alpha**(k + n + 3) + alpha**(2*n))*(k + n + 1)*(n + 1) - (alpha**(k + n + 1) + alpha**(2*n + 2))*(k + n + 3)*n - (alpha**(k + 3*n + 3) + 1)*(k - n + 1))*Rp**(-n + 3)*g*n/(((alpha**(n + 1) - alpha**(n - 1))**2*n**2 - (alpha**(2*n) - 1)**2)*((k + 3)**2 - n**2)*((k + 1)**2 - n**2)*nu)
    B = -0.5*((alpha**(k + 3*n + 3) + alpha**(2*n))*(k - n + 1)*(n - 1) - (alpha**(k + 3*n + 1) + alpha**(2*n + 2))*(k - n + 3)*n + (alpha**(k + n + 3) + alpha**(4*n))*(k + n + 1))*Rp**(n + 3)*g*n/(((alpha**(n + 1) - alpha**(n - 1))**2*n**2 - (alpha**(2*n) - 1)**2)*((k + 3)**2 - n**2)*((k + 1)**2 - n**2)*nu)
    C = 0.5*((alpha**(k + n + 1) + alpha**(2*n))*(k + n + 3)*(n - 1) - (alpha**(k + n + 3) + alpha**(2*n - 2))*(k + n + 1)*n + (alpha**(k + 3*n + 1) + 1)*(k - n + 3))*Rp**(-n + 1)*g*n/(((alpha**(n + 1) - alpha**(n - 1))**2*n**2 - (alpha**(2*n) - 1)**2)*((k + 3)**2 - n**2)*((k + 1)**2 - n**2)*nu)
    D = -0.5*((alpha**(k + 3*n + 1) + alpha**(2*n))*(k - n + 3)*(n + 1) - (alpha**(k + 3*n + 3) + alpha**(2*n - 2))*(k - n + 1)*n - (alpha**(k + n + 1) + alpha**(4*n))*(k + n + 3))*Rp**(n + 1)*g*n/(((alpha**(n + 1) - alpha**(n - 1))**2*n**2 - (alpha**(2*n) - 1)**2)*((k + 3)**2 - n**2)*((k + 1)**2 - n**2)*nu)
    E = g*n/(((k + 3)**2 - n**2)*((k + 1)**2 - n**2)*Rp**k*nu)
    return A, B, C, D, E


def coefficients_sphere_smooth_fs(Rp, Rm, k, l, g, nu):
    alpha = Rm/Rp
    A = 0.5*Rp**(-l + 3)*(alpha**(k + 3) - alpha**(-l + 1))*g/((alpha**l - alpha**(-l + 1))*(k + l + 2)*(k - l + 3)*(2*l + 1)*nu)
    B = 0.5*Rp**(l + 4)*(alpha**(k + 4) - alpha**(l + 3))*g/((alpha**(l + 3) - 1/alpha**l)*(k + l + 4)*(k - l + 1)*(2*l + 1)*nu)
    C = -0.5*Rp**(-l + 1)*(alpha**(k + 4) - 1/alpha**l)*g/((alpha**(l + 3) - 1/alpha**l)*(k + l + 4)*(k - l + 1)*(2*l + 1)*nu)
    D = -0.5*Rp**(l + 2)*(alpha**(k + 3) - alpha**l)*g/((alpha**l - alpha**(-l + 1))*(k + l + 2)*(k - l + 3)*(2*l + 1)*nu)
    E = g/(Rp**k*(k + l + 4)*(k + l + 2)*(k - l + 3)*(k - l + 1)*nu)
    return A, B, C, D, E


def coefficients_sphere_smooth_ns(Rp, Rm, k, l, g, nu):
    alpha = Rm/Rp
    Gamma = ((alpha**(l + 1) + alpha**(l - 3))*(2*l + 1)**2 - 2*alpha**(l - 1)*(2*l + 3)*(2*l - 1) - 4*alpha**(3*l) - 4*alpha**(-l - 2))*(k + l + 4)*(k + l + 2)*(k - l + 3)*(k - l + 1)
    A = ((alpha**(k + 2) + alpha**(l - 1))*(k + l + 2)*(2*l + 3) - (alpha**k + alpha**(l + 1))*(k + l + 4)*(2*l + 1) - 2*(alpha**(k + 2*l + 3) + alpha**(-l - 2))*(k - l + 1))*Rp**(-l + 3)*g/(Gamma*nu)
    B = ((alpha**(k + 2*l + 1) + alpha**(l + 1))*(k - l + 3)*(2*l + 1) - (alpha**(k + 2*l + 3) + alpha**(l - 1))*(k - l + 1)*(2*l - 1) - 2*(alpha**(k + 2) + alpha**(3*l))*(k + l + 2))*Rp**(l + 4)*g/(Gamma*nu)
    C = -((alpha**(k + 2) + alpha**(l - 3))*(k + l + 2)*(2*l + 1) - (alpha**k + alpha**(l - 1))*(k + l + 4)*(2*l - 1) - 2*(alpha**(k + 2*l + 1) + alpha**(-l - 2))*(k - l + 3))*Rp**(-l + 1)*g/(Gamma*nu)
    D = -((alpha**(k + 2*l + 1) + alpha**(l - 1))*(k - l + 3)*(2*l + 3) - (alpha**(k + 2*l + 3) + alpha**(l - 3))*(k - l + 1)*(2*l + 1) - 2*(alpha**k + alpha**(3*l))*(k + l + 4))*Rp**(l + 2)*g/(Gamma*nu)
    E = g/(Rp**k*(k + l + 4)*(k + l + 2)*(k - l + 3)*(k - l + 1)*nu)
    return A, B, C, D, E
