Test eigenfunctions of Bessel equation in ball bases.
(Nphi, Ntheta, Nr, radius, alpha, dtype, ell)
| 151 | @pytest.mark.parametrize('dtype', [np.complex128]) |
| 152 | @pytest.mark.parametrize('ell', [0, 1, 2, 3]) |
| 153 | def test_ball_bessel_eigenfunction(Nphi, Ntheta, Nr, radius, alpha, dtype, ell): |
| 154 | """Test eigenfunctions of Bessel equation in ball bases.""" |
| 155 | # Bases |
| 156 | c = d3.SphericalCoordinates('phi', 'theta', 'r') |
| 157 | d = d3.Distributor(c, dtype=dtype) |
| 158 | b = d3.BallBasis(c, (Nphi, Ntheta, Nr), radius=radius, alpha=alpha, dtype=dtype) |
| 159 | phi, theta, r = d.local_grids(b, scales=(1, 1, 1)) |
| 160 | # Fields |
| 161 | u = d.Field(bases=b) |
| 162 | tau = d.Field(bases=b.surface) |
| 163 | s = d.Field() |
| 164 | # Problem |
| 165 | lift = lambda A: d3.Lift(A, b, -1) |
| 166 | problem = d3.EVP([u, tau], s, namespace=locals()) |
| 167 | problem.add_equation("s*u + lap(u) + lift(tau) = 0") |
| 168 | problem.add_equation("u(r=radius) = 0") |
| 169 | # Solver |
| 170 | solver = problem.build_solver() |
| 171 | # TODO: clean this up with group selection interface |
| 172 | for sp in solver.subproblems: |
| 173 | if sp.group[1] == ell: |
| 174 | break |
| 175 | else: |
| 176 | raise ValueError(f"Could not find subproblem with ell = {ell}") |
| 177 | solver.solve_dense(sp) |
| 178 | # Compare eigenfunction |
| 179 | i_sort = np.argsort(solver.eigenvalues) |
| 180 | solver.eigenvalues = solver.eigenvalues[i_sort] |
| 181 | solver.eigenvectors = solver.eigenvectors[:,i_sort] |
| 182 | for Neig in [0, 1, 5, 10]: |
| 183 | solver.set_state(Neig, sp.subsystems[0]) # m = 0 mode |
| 184 | u.change_layout(d.layouts[1]) |
| 185 | local_m, local_ell, local_n = u.layout.local_group_arrays(u.domain, u.scales) |
| 186 | radial_eigenfunction = u.data[(local_m == 0)*(local_ell == ell)] |
| 187 | i_max = np.argmax(np.abs(radial_eigenfunction)) |
| 188 | radial_eigenfunction /= radial_eigenfunction[i_max] |
| 189 | k = np.sqrt(solver.eigenvalues[Neig]) |
| 190 | sol = spec.jv(ell+1/2, k*r) / np.sqrt(k*r) |
| 191 | sol = sol.ravel() |
| 192 | sol /= sol[i_max] |
| 193 | assert np.allclose(radial_eigenfunction, sol) |
| 194 | |
| 195 | |
| 196 | @pytest.mark.parametrize('Nphi', [8]) |
nothing calls this directly
no test coverage detected