Test eigenvalues of vector diffusion equation in ball bases with various BCs.
(Nphi, Ntheta, Nr, radius, alpha, dtype, ell, bc)
| 202 | @pytest.mark.parametrize('ell', [1, 2, 3]) |
| 203 | @pytest.mark.parametrize('bc', ['no-slip', 'stress-free', 'potential', 'conducting', 'pseudo']) |
| 204 | def test_ball_diffusion(Nphi, Ntheta, Nr, radius, alpha, dtype, ell, bc): |
| 205 | """Test eigenvalues of vector diffusion equation in ball bases with various BCs.""" |
| 206 | # Bases |
| 207 | c = d3.SphericalCoordinates('phi', 'theta', 'r') |
| 208 | d = d3.Distributor(c, dtype=dtype) |
| 209 | b = d3.BallBasis(c, (Nphi, Ntheta, Nr), radius=radius, alpha=alpha, dtype=dtype) |
| 210 | # Fields |
| 211 | φ = d.Field(bases=b) |
| 212 | A = d.VectorField(c, bases=b) |
| 213 | tA = d.VectorField(c, bases=b.surface) |
| 214 | λ = d.Field() |
| 215 | # Problem |
| 216 | lift = lambda A: d3.Lift(A, b, -1) |
| 217 | problem = d3.EVP([φ, A, tA], λ, namespace=locals()) |
| 218 | problem.add_equation("div(A) = 0") |
| 219 | problem.add_equation("-λ*A + grad(φ) - lap(A) + lift(tA) = 0") |
| 220 | if bc == 'no-slip': |
| 221 | problem.add_equation("A(r=radius) = 0") |
| 222 | elif bc == 'stress-free': |
| 223 | problem.namespace['E'] = (d3.grad(A) + d3.grad(A).T) / 2 |
| 224 | problem.add_equation("radial(A(r=radius)) = 0") |
| 225 | problem.add_equation("angular(radial(E(r=radius))) = 0") |
| 226 | elif bc == 'potential': |
| 227 | ell_func = lambda ell: ell+1 |
| 228 | problem.namespace['ell_1'] = lambda A: d3.SphericalEllProduct(A, c, ell_func) |
| 229 | problem.add_equation("radial(grad(A)(r=radius)) + ell_1(A)(r=radius)/radius = 0") |
| 230 | elif bc == 'conducting': |
| 231 | problem.add_equation("φ(r=radius) = 0") |
| 232 | problem.add_equation("angular(A(r=radius)) = 0") |
| 233 | elif bc == 'pseudo': |
| 234 | problem.add_equation("radial(A(r=radius)) = 0") |
| 235 | problem.add_equation("angular(curl(A)(r=radius)) = 0") |
| 236 | # Solver |
| 237 | solver = problem.build_solver() |
| 238 | # TODO: clean this up with group selection interface |
| 239 | for sp in solver.subproblems: |
| 240 | if sp.group[1] == ell: |
| 241 | break |
| 242 | else: |
| 243 | raise ValueError(f"Could not find subproblem with ell = {ell}") |
| 244 | solver.solve_dense(sp) |
| 245 | # Compare eigenvalues |
| 246 | i_sort = np.argsort(solver.eigenvalues) |
| 247 | solver.eigenvalues = solver.eigenvalues[i_sort] |
| 248 | λ_analytic = analytic_eigenvalues(ell, Nr, bc, r0=radius) |
| 249 | if (bc == 'stress-free' and ell == 1): |
| 250 | # Add null space solution |
| 251 | λ_analytic = np.append(0, λ_analytic) |
| 252 | assert np.allclose(solver.eigenvalues[:Nr//4], λ_analytic[:Nr//4]) |
| 253 |
nothing calls this directly
no test coverage detected