def test_vector_heat_disk_dirichlet(Nr, Nphi, dtype): # Bases dealias = 1 c, d, b, phi, r, x, y = build_disk(Nphi, Nr, dealias=dealias, dtype=dtype) # Fields u = field.Field(name='u', dist=d, bases=(b, ), tensorsig=(c, ), dtype=dtype) τu = field.Field(name='u', dist=d, bases=(b.S1_basis(), ), tensorsig=(c, ), dtype=dtype) v = field.Field(name='u', dist=d, bases=(b, ), tensorsig=(c, ), dtype=dtype) ex = np.array([-np.sin(phi), np.cos(phi)]) ey = np.array([np.cos(phi), np.sin(phi)]) v['g'] = (x + 4 * y) * ex vr = operators.RadialComponent(v(r=radius_disk)) vph = operators.AzimuthalComponent(v(r=radius_disk)) # Problem Lap = lambda A: operators.Laplacian(A, c) Lift = lambda A: operators.Lift(A, b, -1) problem = problems.LBVP([u, τu]) problem.add_equation((Lap(u) + Lift(τu), 0)) problem.add_equation((u(r=radius_disk), v(r=radius_disk))) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() assert np.allclose(u['g'], v['g'])
def test_heat_shell(Nmax, Lmax, dtype): # Bases dealias = 1 c, d, b, phi, theta, r, x, y, z = build_shell(2 * (Lmax + 1), Lmax + 1, Nmax + 1, dealias=dealias, dtype=dtype) r0, r1 = b.radial_basis.radii # Fields u = field.Field(name='u', dist=d, bases=(b, ), dtype=dtype) τu1 = field.Field(name='τu1', dist=d, bases=(b.S2_basis(), ), dtype=dtype) τu2 = field.Field(name='τu2', dist=d, bases=(b.S2_basis(), ), dtype=dtype) F = field.Field(name='a', dist=d, bases=(b, ), dtype=dtype) F['g'] = 6 # Problem Lap = lambda A: operators.Laplacian(A, c) Lift = lambda A, n: operators.Lift(A, b, n) problem = problems.LBVP([u, τu1, τu2]) problem.add_equation((Lap(u) + Lift(τu1, -1) + Lift(τu2, -2), F)) problem.add_equation((u(r=r0), 0)) problem.add_equation((u(r=r1), 0)) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() # Check solution u_true = r**2 + 6 / r - 7 assert np.allclose(u['g'], u_true)
def test_heat_ball_cart(Nmax, Lmax, dtype): # Bases dealias = 1 c, d, b, phi, theta, r, x, y, z = build_ball(2 * (Lmax + 1), Lmax + 1, Nmax + 1, dealias=dealias, dtype=dtype) xr = radius_ball * np.cos(phi) * np.sin(theta) yr = radius_ball * np.sin(phi) * np.sin(theta) zr = radius_ball * np.cos(theta) # Fields u = field.Field(name='u', dist=d, bases=(b, ), dtype=dtype) τu = field.Field(name='u', dist=d, bases=(b.S2_basis(), ), dtype=dtype) f = field.Field(name='a', dist=d, bases=(b, ), dtype=dtype) f['g'] = 12 * x**2 - 6 * y + 2 g = field.Field(name='a', dist=d, bases=(b.S2_basis(), ), dtype=dtype) g['g'] = xr**4 - yr**3 + zr**2 # Problem Lap = lambda A: operators.Laplacian(A, c) Lift = lambda A: operators.Lift(A, b, -1) problem = problems.LBVP([u, τu]) problem.add_equation((Lap(u) + Lift(τu), f)) problem.add_equation((u(r=radius_ball), g)) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() # Check solution u_true = x**4 - y**3 + z**2 assert np.allclose(u['g'], u_true)
def test_scalar_prod_vector(Nphi, Nr, basis, ncc_first, dealias, dtype): c, d, b, phi, r, x, y = basis(Nphi, Nr, dealias=dealias, dtype=dtype) f = field.Field(dist=d, bases=(b.radial_basis, ), dtype=dtype) g = field.Field(dist=d, bases=(b, ), dtype=dtype) f['g'] = r**2 g['g'] = 3 * x**2 + 2 * y u = operators.Gradient(g, c).evaluate() vars = [u] if ncc_first: w0 = f * u else: w0 = u * f w1 = w0.reinitialize(ncc=True, ncc_vars=vars) problem = problems.LBVP(vars) problem.add_equation((w1, 0)) solver = solvers.LinearBoundaryValueSolver( problem, matsolver='SuperluNaturalSpsolve', matrix_coupling=[False, True]) w1.store_ncc_matrices(vars, solver.subproblems) w0 = w0.evaluate() w0.change_scales(1) w1 = w1.evaluate_as_ncc() assert np.allclose(w0['g'], w1['g'])
def test_scalar_heat_disk(Nr, Nphi, dtype): # Bases dealias = 1 c, d, b, phi, r, x, y = build_disk(Nphi, Nr, dealias=dealias, dtype=dtype) xr = radius_disk * np.cos(phi) yr = radius_disk * np.sin(phi) # Fields u = field.Field(name='u', dist=d, bases=(b, ), dtype=dtype) τu = field.Field(name='u', dist=d, bases=(b.S1_basis(), ), dtype=dtype) f = field.Field(dist=d, bases=(b, ), dtype=dtype) f['g'] = 6 * x - 2 g = field.Field(dist=d, bases=(b.S1_basis(), ), dtype=dtype) g['g'] = xr**3 - yr**2 # Problem Lap = lambda A: operators.Laplacian(A, c) Lift = lambda A: operators.Lift(A, b, -1) problem = problems.LBVP([u, τu]) problem.add_equation((Lap(u) + Lift(τu), f)) problem.add_equation((u(r=radius_disk), g)) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() # Check solution u_true = x**3 - y**2 assert np.allclose(u['g'], u_true)
def test_tensor_prod_scalar(Nphi, Nr, basis, ncc_first, dealias, dtype): c, d, b, phi, r, x, y = basis(Nphi, Nr, dealias=dealias, dtype=dtype) f = field.Field(dist=d, bases=(b.radial_basis, ), dtype=dtype) g = field.Field(dist=d, bases=(b, ), dtype=dtype) f['g'] = r**4 g['g'] = 3 * x**2 + 2 * y T = operators.Gradient(operators.Gradient(f, c), c).evaluate() vars = [g] if ncc_first: U0 = T * g else: U0 = g * T U1 = U0.reinitialize(ncc=True, ncc_vars=vars) problem = problems.LBVP(vars) problem.add_equation((f * g, 0)) solver = solvers.LinearBoundaryValueSolver( problem, matsolver='SuperluNaturalSpsolve', matrix_coupling=[False, True]) U1.store_ncc_matrices(vars, solver.subproblems) U0 = U0.evaluate() U0.change_scales(1) U1 = U1.evaluate_as_ncc() assert np.allclose(U0['g'], U1['g'])
def test_ncc_ball(Nmax, Lmax, dtype): # Bases dealias = 1 c, d, b, phi, theta, r, x, y, z = build_ball(2 * (Lmax + 1), Lmax + 1, Nmax + 1, dealias=dealias, dtype=dtype) # Fields u = field.Field(name='u', dist=d, bases=(b, ), dtype=dtype) ncc = field.Field(name='ncc', dist=d, bases=(b.radial_basis, ), dtype=dtype) ncc['g'] = 1 + r**2 F = field.Field(name='F', dist=d, bases=(b, ), dtype=dtype) F['g'] = 1 # Problem problem = problems.LBVP([u]) problem.add_equation((ncc * u, F)) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() # Check solution u_true = 1 / ncc['g'] assert np.allclose(u['g'], u_true)
def test_tensor_dot_tensor(Nphi, Ntheta, Nr, basis, alpha, k_ncc, k_arg, dealias, dtype): c, d, b, phi, theta, r, x, y, z = basis(Nphi, Ntheta, Nr, alpha, dealias=dealias, dtype=dtype) b_ncc = b.radial_basis.clone_with(k=k_ncc) b_arg = b.clone_with(k=k_arg) T = field.Field(dist=d, bases=(b_ncc, ), tensorsig=(c, c), dtype=dtype) U = field.Field(dist=d, bases=(b_arg, ), tensorsig=(c, c), dtype=dtype) T['g'] = np.random.randn(*T['g'].shape) U['g'] = np.random.randn(*U['g'].shape) if isinstance(b, BallBasis): k_out = k_out_ball(k_ncc, k_arg, T, U) else: k_out = k_out_shell(k_ncc, k_arg) if k_out > 0 and dealias < 2: T['c'][:, :, :, :, -k_out:] = 0 U['c'][:, :, :, :, -k_out:] = 0 vars = [U] w0 = dot(T, U) w1 = w0.reinitialize(ncc=True, ncc_vars=vars) problem = problems.LBVP(vars) problem.add_equation((operators.Laplacian(U, c), 0)) solver = solvers.LinearBoundaryValueSolver(problem, ) w1.store_ncc_matrices(vars, solver.subproblems) w0 = w0.evaluate() w1 = w1.evaluate_as_ncc() assert np.allclose(w0['c'], w1['c'])
def test_jacobi_ncc_solve(N, a0, b0, k_ncc, k_arg, dealias, dtype): """ This tests for aliasing errors when solving the equation f(x)*u(x) = f(x)*g(x). With 3/2 dealiasing, the RHS product will generally contain aliasing errors in the last 2*max(k_ncc, k_arg) modes. We can eliminate these by zeroing the corresponding number of modes of f(x) and/or g(x). """ c = coords.Coordinate('x') d = distributor.Distributor((c,)) b = basis.Jacobi(c, size=N, a=a0, b=b0, bounds=(0, 1), dealias=dealias) b_ncc = b.clone_with(a=a0+k_ncc, b=b0+k_ncc) b_arg = b.clone_with(a=a0+k_arg, b=b0+k_arg) f = field.Field(dist=d, bases=(b_ncc,), dtype=dtype) g = field.Field(dist=d, bases=(b_arg,), dtype=dtype) u = field.Field(dist=d, bases=(b_arg,), dtype=dtype) f['g'] = np.random.randn(*f['g'].shape) g['g'] = np.random.randn(*g['g'].shape) kmax = max(k_ncc, k_arg) if kmax > 0 and dealias < 2: f['c'][-kmax:] = 0 g['c'][-kmax:] = 0 problem = problems.LBVP([u]) problem.add_equation((f*u, f*g)) solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() assert np.allclose(u['c'], g['c'])
def test_implicit_transpose_tensor(Nphi, Ntheta, Nr, k, dealias, dtype, basis): c, d, b, phi, theta, r, x, y, z = basis(Nphi, Ntheta, Nr, k, dealias, dtype) ct, st, cp, sp = np.cos(theta), np.sin(theta), np.cos(phi), np.sin(phi) u = field.Field(dist=d, bases=(b, ), tensorsig=(c, ), dtype=dtype) u.preset_scales(b.domain.dealias) u['g'][2] = r**2 * st * (2 * ct**2 * cp - r * ct**3 * sp + r**3 * cp**3 * st**5 * sp**3 + r * ct * st**2 * (cp**3 + sp**3)) u['g'][1] = r**2 * (2 * ct**3 * cp - r * cp**3 * st**4 + r**3 * ct * cp**3 * st**5 * sp**3 - 1 / 16 * r * np.sin(2 * theta)**2 * (-7 * sp + np.sin(3 * phi))) u['g'][0] = r**2 * sp * (-2 * ct**2 + r * ct * cp * st**2 * sp - r**3 * cp**2 * st**5 * sp**3) T = operators.Gradient(u, c).evaluate() Ttg = np.transpose(np.copy(T['g']), (1, 0, 2, 3, 4)) Tt = field.Field(dist=d, bases=(b, ), tensorsig=( c, c, ), dtype=dtype) trans = lambda A: operators.TransposeComponents(A) problem = problems.LBVP([Tt]) problem.add_equation((trans(Tt), T)) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() assert np.allclose(Tt['g'], Ttg)
def test_heat_ball(Nmax, Lmax, dtype): # Bases dealias = 1 c, d, b, phi, theta, r, x, y, z = build_ball(2 * (Lmax + 1), Lmax + 1, Nmax + 1, dealias=dealias, dtype=dtype) # Fields u = field.Field(name='u', dist=d, bases=(b, ), dtype=dtype) τu = field.Field(name='u', dist=d, bases=(b.S2_basis(), ), dtype=dtype) F = field.Field(name='a', dist=d, bases=(b, ), dtype=dtype) F['g'] = 6 # Problem Lap = lambda A: operators.Laplacian(A, c) Lift = lambda A: operators.Lift(A, b, -1) problem = problems.LBVP([u, τu]) problem.add_equation((Lap(u) + Lift(τu), F)) problem.add_equation((u(r=radius_ball), 0)) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() # Check solution u_true = r**2 - 1 assert np.allclose(u['g'], u_true)
def test_scalar_prod_scalar(Nphi, Ntheta, Nr, basis, alpha, k_ncc, k_arg, dealias, dtype): c, d, b, phi, theta, r, x, y, z = basis(Nphi, Ntheta, Nr, alpha, dealias=dealias, dtype=dtype) b_ncc = b.radial_basis.clone_with(k=k_ncc) b_arg = b.clone_with(k=k_arg) f = field.Field(dist=d, bases=(b_ncc, ), dtype=dtype) g = field.Field(dist=d, bases=(b_arg, ), dtype=dtype) f['g'] = np.random.randn(*f['g'].shape) g['g'] = np.random.randn(*g['g'].shape) if isinstance(b, BallBasis): k_out = k_out_ball(k_ncc, k_arg, f, g) else: k_out = k_out_shell(k_ncc, k_arg) if k_out > 0 and dealias < 2: f['c'][:, :, -k_out:] = 0 g['c'][:, :, -k_out:] = 0 vars = [g] w0 = f * g w1 = w0.reinitialize(ncc=True, ncc_vars=vars) problem = problems.LBVP(vars) problem.add_equation((w1, 0)) solver = solvers.LinearBoundaryValueSolver(problem) w1.store_ncc_matrices(vars, solver.subproblems) w0 = w0.evaluate() w1 = w1.evaluate_as_ncc() assert np.allclose(w0['c'], w1['c'])
def test_implicit_transpose_2d_tensor(Nx, Nz, dealias, basis, dtype): c, d, b, x, z = basis(Nx, Nz, dealias, dtype) u = field.Field(dist=d, bases=b, dtype=dtype) ncc = field.Field(name='ncc', dist=d, bases=(b[-1],), dtype=dtype) ncc['g'] = 1/(1+z**2) problem = problems.LBVP([u]) problem.add_equation((ncc*u, 1)) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() assert np.allclose(u['g'], 1/ncc['g'])
def test_3d_scalar_ncc_scalar_separable(Nx, Ny, Nz, dealias, basis, dtype): c, d, b, x, y, z = basis(Nx, Ny, Nz, dealias, dtype) u = field.Field(dist=d, bases=(b[0], b[1]), dtype=dtype) v = field.Field(dist=d, bases=b, dtype=dtype) ncc = field.Field(name='ncc', dist=d, bases=(b[-1],), dtype=dtype) ncc['g'] = 1/(1+z**2) problem = problems.LBVP([v, u]) problem.add_equation((v, 0)) # Hack by adding v since problem must have full dimension problem.add_equation(((ncc*u)(z=1), ncc(z=1))) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() assert np.allclose(u['g'], 1)
def test_jacobi_convert_implicit(N, a, b, k, dtype): c = coords.Coordinate('x') d = distributor.Distributor((c,)) b = basis.Jacobi(c, size=N, a0=a, b0=b, a=a+k, b=b+k, bounds=(0, 1)) x = b.local_grid(1) f = field.Field(dist=d, bases=(b,), dtype=dtype) f['g'] = x**5 fx = operators.Differentiate(f, c).evaluate() g = field.Field(dist=d, bases=(b,), dtype=dtype) problem = problems.LBVP([g]) problem.add_equation((g, fx)) solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() assert np.allclose(g['g'], fx['g'])
def test_cosine_implicit(Nphi, Ntheta, dealias, dtype, rank): c, d, b, phi, theta = build_sphere(Nphi, Ntheta, dealias, dtype) # Random input for all components f = d.TensorField((c, ) * rank, bases=b) f.fill_random(layout='g') f.low_pass_filter(scales=0.75) # Cosine LBVP u = d.TensorField((c, ) * rank, bases=b) problem = problems.LBVP([u], namespace=locals()) problem.add_equation("u + MulCosine(u) = f + MulCosine(f)") solver = problem.build_solver() solver.solve() u.change_scales(b.domain.dealias) f.change_scales(b.domain.dealias) assert np.allclose(u['g'], f['g'])
def test_transpose_implicit(basis, Nphi, Nr, k, dealias, dtype): c, d, b, phi, r, x, y = basis(Nphi, Nr, k, dealias, dtype) # Random tensor field f = d.TensorField((c, c), bases=b) f.fill_random(layout='g') f.low_pass_filter(scales=0.75) # Transpose LBVP u = d.TensorField((c, c), bases=b) problem = problems.LBVP([u], namespace=locals()) problem.add_equation("trans(u) = trans(f)") solver = problem.build_solver() solver.solve() u.change_scales(b.domain.dealias) f.change_scales(b.domain.dealias) assert np.allclose(u['g'], f['g'])
def test_skew_implicit(Nphi, Ntheta, dealias, dtype): c, d, b, phi, theta = build_sphere(Nphi, Ntheta, dealias, dtype) # Random vector field f = d.VectorField(c, bases=b) f.fill_random(layout='g') f.low_pass_filter(scales=0.75) # Skew LBVP u = d.VectorField(c, bases=b) problem = problems.LBVP([u], namespace=locals()) problem.add_equation("skew(u) = skew(f)") solver = problem.build_solver() solver.solve() u.change_scales(b.domain.dealias) f.change_scales(b.domain.dealias) assert np.allclose(u['g'], f['g'])
def test_heat_ncc_shell(Nmax, Lmax, ncc_exponent, ncc_location, ncc_scale, dtype): # Bases dealias = 1 c, d, b, phi, theta, r, x, y, z = build_shell(2 * (Lmax + 1), Lmax + 1, Nmax + 1, dealias=dealias, dtype=dtype) r0, r1 = b.radial_basis.radii # Fields u = field.Field(name='u', dist=d, bases=(b, ), dtype=dtype) τu1 = field.Field(name='τu1', dist=d, bases=(b.S2_basis(), ), dtype=dtype) τu2 = field.Field(name='τu2', dist=d, bases=(b.S2_basis(), ), dtype=dtype) ncc = field.Field(name='ncc', dist=d, bases=(b.radial_basis, ), dtype=dtype) F = field.Field(name='a', dist=d, bases=(b, ), dtype=dtype) # Test Parameters F_value = {0: 6, 1: 2, 2: 1, 3 / 2: 3 / 4} analytic = { 0: r**2 + 6 / r - 7, 1: r + 2 / r - 3, 2: np.log(r) + np.log(4) / r - np.log(4), 3 / 2: np.sqrt(r) + 0.82842712 / r - 1.82842712 } if ncc_location == 'RHS': ncc['g'] = 1 F['g'] = F_value[ncc_exponent] * r**(-ncc_exponent) else: ncc['g'] = r**ncc_exponent F['g'] = F_value[ncc_exponent] u_true = analytic[ncc_exponent] ncc.change_scales(ncc_scale) ncc['g'] # force transform # Problem Lap = lambda A: operators.Laplacian(A, c) Lift = lambda A, n: operators.Lift(A, b, n) problem = problems.LBVP([u, τu1, τu2]) problem.add_equation((ncc * Lap(u) + Lift(τu1, -1) + Lift(τu2, -2), F)) problem.add_equation((u(r=r0), 0)) problem.add_equation((u(r=r1), 0)) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() # Check solution assert np.allclose(u['g'], u_true)
def test_implicit_trace_tensor(Nphi, Ntheta, Nr, k, dealias, basis, dtype): c, d, b, phi, theta, r, x, y, z = basis(Nphi, Ntheta, Nr, k, dealias, dtype) f = field.Field(dist=d, bases=(b, ), dtype=dtype) g = field.Field(dist=d, bases=(b, ), dtype=dtype) g.preset_scales(g.domain.dealias) g['g'] = 3 * x**2 + 2 * y * z I = field.Field(dist=d, bases=(b.radial_basis, ), tensorsig=(c, c), dtype=dtype) I['g'][0, 0] = I['g'][1, 1] = I['g'][2, 2] = 1 trace = lambda A: operators.Trace(A) problem = problems.LBVP([f]) problem.add_equation((trace(I * f), 3 * g)) solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() assert np.allclose(f['c'], g['c'])
def test_implicit_trace_tensor(Nphi, Nr, k, dealias, basis, dtype): c, d, b, phi, r, x, y = basis(Nphi, Nr, k, dealias, dtype) f = field.Field(dist=d, bases=(b, ), dtype=dtype) g = field.Field(dist=d, bases=(b, ), dtype=dtype) g.preset_scales(g.domain.dealias) g['g'] = 3 * x**2 + 2 * y I = field.Field(dist=d, bases=(b.clone_with(shape=(1, Nr), k=0), ), tensorsig=(c, c), dtype=dtype) I['g'][0, 0] = I['g'][1, 1] = 1 trace = lambda A: operators.Trace(A) problem = problems.LBVP([f]) problem.add_equation((trace(I * f), 2 * g)) solver = solvers.LinearBoundaryValueSolver(problem, matrix_coupling=[False, True]) solver.solve() assert np.allclose(f['c'], g['c'])
def test_jacobi_ncc_eval(N, a0, b0, k_ncc, k_arg, dealias, dtype): """ This tests for aliasing errors when evaluating the product f(x) * g(x) as both an NCC operator and with the pseudospectral method. With 3/2 dealiasing, the product will generally contain aliasing errors in the last 2*max(k_ncc, k_arg) modes. We can eliminate these by zeroing the corresponding number of modes of f(x) and/or g(x). """ c = coords.Coordinate('x') d = distributor.Distributor((c,)) b = basis.Jacobi(c, size=N, a=a0, b=b0, bounds=(0, 1), dealias=dealias) b_ncc = b.clone_with(a=a0+k_ncc, b=b0+k_ncc) b_arg = b.clone_with(a=a0+k_arg, b=b0+k_arg) f = field.Field(dist=d, bases=(b_ncc,), dtype=dtype) g = field.Field(dist=d, bases=(b_arg,), dtype=dtype) f['g'] = np.random.randn(*f['g'].shape) g['g'] = np.random.randn(*g['g'].shape) x = b.local_grid(1) f['g'] = np.cos(6*x) g['g'] = np.cos(6*x) kmax = max(k_ncc, k_arg) if kmax > 0 and dealias < 2: f['c'][-kmax:] = 0 g['c'][-kmax:] = 0 vars = [g] w0 = f * g w1 = w0.reinitialize(ncc=True, ncc_vars=vars) problem = problems.LBVP(vars) problem.add_equation((w1, 0)) solver = solvers.LinearBoundaryValueSolver(problem) w1.store_ncc_matrices(vars, solver.subproblems) w0 = w0.evaluate() w2 = field.Field(dist=d, bases=(b,), dtype=dtype) w2.preset_scales(w2.domain.dealias) w2['g'] = w0['g'] w2['c'] w0['c'] print(np.max(np.abs(w2['g'] - w0['g']))) w2 = operators.Convert(w2, w0.domain.bases[0]).evaluate() w1 = w1.evaluate_as_ncc() assert np.allclose(w0['c'], w2['c'])
def test_laplacian_scalar_implicit(Nphi, Ntheta, dealias, dtype): c, d, b, phi, theta = build_sphere(Nphi, Ntheta, dealias, dtype) # Spherical harmonic forcing m, l = 5, 10 f = d.Field(bases=b) f.preset_scales(b.domain.dealias) if np.iscomplexobj(dtype()): f['g'] = sph_harm(m, l, phi, theta) else: f['g'] = sph_harm(m, l, phi, theta).real # Poisson LBVP u = d.Field(bases=b) tau = d.Field() problem = problems.LBVP([u, tau], namespace=locals()) problem.add_equation("lap(u) + tau = f") problem.add_equation("ave(u) = 0") solver = problem.build_solver() solver.solve() u.change_scales(1) f.change_scales(1) assert np.allclose(u['g'], -f['g'] / (l * (l + 1)) * radius**2)
def test_scalar_heat_disk_axisymm(Nr, Nphi, dtype): # Bases dealias = 1 c, d, b, phi, r, x, y = build_disk(Nphi, Nr, dealias=dealias, dtype=dtype) # Fields u = field.Field(name='u', dist=d, bases=(b, ), dtype=dtype) τu = field.Field(name='u', dist=d, bases=(b.S1_basis(), ), dtype=dtype) F = field.Field(name='a', dist=d, bases=(b, ), dtype=dtype) F['g'] = 4 # Problem Lap = lambda A: operators.Laplacian(A, c) Lift = lambda A: operators.Lift(A, b, -1) problem = problems.LBVP([u, τu]) problem.add_equation((Lap(u) + Lift(τu), F)) problem.add_equation((u(r=radius_disk), 0)) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() # Check solution u_true = r**2 - 1 assert np.allclose(u['g'], u_true)
def test_divergence_cleaning(Nphi, Ntheta, dealias, dtype): c, d, b, phi, theta = build_sphere(Nphi, Ntheta, dealias, dtype) # Random vector field f = d.Field(bases=b) f.fill_random(layout='g') f.low_pass_filter(scales=0.75) # Build vector field as grad(f) + skew(grad(f)) g = operators.Gradient(f).evaluate() h = operators.Skew(g).evaluate() # Divergence cleaning LBVP u = d.VectorField(c, bases=b) psi = d.Field(bases=b) tau = d.Field() problem = problems.LBVP([u, psi, tau], namespace=locals()) problem.add_equation("u + grad(psi) = h + g") problem.add_equation("div(u) + tau = 0") problem.add_equation("ave(psi) = 0") solver = problem.build_solver() solver.solve() u.change_scales(1) h.change_scales(1) assert np.allclose(u['g'], h['g'])
def test_heat_ncc_cos_ball(Nmax, Lmax, ncc_scale, dtype): # Bases dealias = 1 c, d, b, phi, theta, r, x, y, z = build_ball(2 * (Lmax + 1), Lmax + 1, Nmax + 1, dealias=dealias, dtype=dtype) # Fields u = field.Field(name='u', dist=d, bases=(b, ), dtype=dtype) τu = field.Field(name='u', dist=d, bases=(b.S2_basis(), ), dtype=dtype) ncc = field.Field(name='ncc', dist=d, bases=(b.radial_basis, ), dtype=dtype) F = field.Field(name='a', dist=d, bases=(b, ), dtype=dtype) # Test Parameters R = radius_ball u_true = np.cos(np.pi / 2 * (r / R)**2) g = -np.pi / 2 / R**2 * (4 * np.pi / 2 * (r / R)**2 * np.cos(np.pi / 2 * (r / R)**2) + 6 * np.sin(np.pi / 2 * (r / R)**2)) ncc['g'] = u_true F['g'] = u_true * g ncc.change_scales(ncc_scale) ncc['g'] # force transform # Problem Lap = lambda A: operators.Laplacian(A, c) Lift = lambda A: operators.Lift(A, b, -1) problem = problems.LBVP([u, τu]) problem.add_equation((ncc * Lap(u) + Lift(τu), F)) problem.add_equation((u(r=radius_ball), 0)) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() # Check solution assert np.allclose(u['g'], u_true)
def test_tensor_dot_tensor(Nphi, Nr, basis, ncc_first, dealias, dtype): c, d, b, phi, r, x, y = basis(Nphi, Nr, dealias=dealias, dtype=dtype) f = field.Field(dist=d, bases=(b.radial_basis, ), dtype=dtype) f['g'] = r**6 U = operators.Gradient(operators.Gradient(f, c), c).evaluate() T = field.Field(dist=d, bases=(b, ), tensorsig=( c, c, ), dtype=dtype) z = 0 theta = np.pi / 2. T['g'][1, 1] = (6 * x**2 + 4 * y * z) / r**2 T['g'][1, 0] = T['g'][0, 1] = 2 * x * (z - 3 * y) / (r**2 * np.sin(theta)) T['g'][0, 0] = 6 * y**2 / (x**2 + y**2) vars = [T] if ncc_first: W0 = dot(T, U) else: W0 = dot(U, T) W1 = W0.reinitialize(ncc=True, ncc_vars=vars) problem = problems.LBVP(vars) problem.add_equation((f * T, 0)) solver = solvers.LinearBoundaryValueSolver( problem, matsolver='SuperluNaturalSpsolve', matrix_coupling=[False, True]) W1.store_ncc_matrices(vars, solver.subproblems) W0 = W0.evaluate() W0.change_scales(1) W1 = W1.evaluate_as_ncc() assert np.allclose(W0['g'], W1['g'])
def __init__(self, Nx, Ny, Lx, Ly, dtype, **kw): self.Nx = Nx self.Ny = Ny self.Lx = Lx self.Ly = Ly self.dtype = dtype self.N = Nx * Ny self.R = 2 * Nx + 2 * Ny self.M = self.N + self.R # Bases self.c = c = coords.CartesianCoordinates('x', 'y') self.d = d = distributor.Distributor((c, )) self.xb = xb = basis.ChebyshevT(c.coords[0], Nx, bounds=(0, Lx)) self.yb = yb = basis.ChebyshevT(c.coords[1], Ny, bounds=(0, Ly)) self.x = x = xb.local_grid(1) self.y = y = yb.local_grid(1) xb2 = xb._new_a_b(1.5, 1.5) yb2 = yb._new_a_b(1.5, 1.5) # Forcing self.f = f = field.Field(name='f', dist=d, bases=(xb2, yb2), dtype=dtype) # Boundary conditions self.uL = uL = field.Field(name='f', dist=d, bases=(yb, ), dtype=dtype) self.uR = uR = field.Field(name='f', dist=d, bases=(yb, ), dtype=dtype) self.uT = uT = field.Field(name='f', dist=d, bases=(xb, ), dtype=dtype) self.uB = uB = field.Field(name='f', dist=d, bases=(xb, ), dtype=dtype) # Fields self.u = u = field.Field(name='u', dist=d, bases=(xb, yb), dtype=dtype) self.tx1 = tx1 = field.Field(name='tx1', dist=d, bases=(xb2, ), dtype=dtype) self.tx2 = tx2 = field.Field(name='tx2', dist=d, bases=(xb2, ), dtype=dtype) self.ty1 = ty1 = field.Field(name='ty1', dist=d, bases=(yb2, ), dtype=dtype) self.ty2 = ty2 = field.Field(name='ty2', dist=d, bases=(yb2, ), dtype=dtype) # Problem Lap = lambda A: operators.Laplacian(A, c) self.problem = problem = problems.LBVP([u, tx1, tx2, ty1, ty2]) problem.add_equation((Lap(u), f)) problem.add_equation((u(y=Ly), uT)) problem.add_equation((u(x=Lx), uR)) problem.add_equation((u(y=0), uB)) problem.add_equation((u(x=0), uL)) # Solver self.solver = solver = solvers.LinearBoundaryValueSolver( problem, bc_top=False, tau_left=False, store_expanded_matrices=False, **kw) # Tau entries L = solver.subproblems[0].L_min.tolil() # Taus for nx in range(Nx): L[Ny - 1 + nx * Ny, Nx * Ny + 0 * Nx + nx] = 1 # tx1 * Py1 L[Ny - 2 + nx * Ny, Nx * Ny + 1 * Nx + nx] = 1 # tx2 * Py2 for ny in range(Ny - 2): L[(Nx - 1) * Ny + ny, Nx * Ny + 2 * Nx + 0 * Ny + ny] = 1 # ty1 * Px1 L[(Nx - 2) * Ny + ny, Nx * Ny + 2 * Nx + 1 * Ny + ny] = 1 # ty2 * Px2 # BC taus not resolution safe if Nx != Ny: raise ValueError("Current implementation requires Nx == Ny.") else: # Remember L is left preconditoined but not right preconditioned L[-7, Nx * Ny + 2 * Nx + 0 * Ny + Ny - 2] = 1 # Right -2 L[-5, Nx * Ny + 2 * Nx + 0 * Ny + Ny - 1] = 1 # Right -1 L[-3, Nx * Ny + 2 * Nx + 1 * Ny + Ny - 2] = 1 # Left -2 L[-1, Nx * Ny + 2 * Nx + 1 * Ny + Ny - 1] = 1 # Left -1 solver.subproblems[0].L_min = L.tocsr() # Neumann operators ux = operators.Differentiate(u, c.coords[0]) uy = operators.Differentiate(u, c.coords[1]) self.duL = -ux(x='left') self.duR = ux(x='right') self.duT = uy(y='right') self.duB = -uy(y='left') # Neumann matrix duT_mat = self.duT.expression_matrices(solver.subproblems[0], vars=[u])[u] duR_mat = self.duR.expression_matrices(solver.subproblems[0], vars=[u])[u] duB_mat = self.duB.expression_matrices(solver.subproblems[0], vars=[u])[u] duL_mat = self.duL.expression_matrices(solver.subproblems[0], vars=[u])[u] self.interior_to_neumann_matrix = sp.vstack( [duT_mat, duR_mat, duB_mat, duL_mat], format='csr')
+2*(1-3*r**2+3*r**4)*(np.cos(phi)-np.sin(phi))) # Potential BC on A ell_func = lambda ell: ell + 1 # Parameters and operators div = lambda A: operators.Divergence(A) grad = lambda A: operators.Gradient(A, c) curl = lambda A: operators.Curl(A) LiftTau = lambda A: operators.LiftTau(A, b, -1) ellp1 = lambda A: operators.SphericalEllProduct(A, c, ell_func) radial = lambda A: operators.RadialComponent(A) angular = lambda A: operators.AngularComponent(A, index=1) # BVP for initial A BVP = problems.LBVP([φ, A, τ_A, τ_φ]) #BVP.add_equation((angular(τ_A),0)) BVP.add_equation((div(A) + LiftTau(τ_φ), 0)) BVP.add_equation((curl(A) + grad(φ) + LiftTau(τ_A), B)) BVP.add_equation((radial(grad(A)(r=radius)) + ellp1(A)(r=radius) / radius, 0)) #, condition = "ntheta != 0") BVP.add_equation((φ(r=radius), 0)) #, condition = "ntheta == 0") solver = solvers.LinearBoundaryValueSolver(BVP) solver.solve() plot_matrices = False if plot_matrices: import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt
if rank == 0: P1['c'][0,-1] = 1 dz = lambda A: operators.Differentiate(A, c.coords[1]) P2 = dz(P1).evaluate() # Fields u = field.Field(name='u', dist=d, bases=(xb,zb), dtype=dtype) F = field.Field(name='F', dist=d, bases=(xb,zb), dtype=dtype) u_true = 0 for n in np.arange(1,Nz//8): u_current_n = 0 for m in np.arange(Nx//4): u_current_m = np.sin(n*z)*np.cos(m*x) u_current_n += u_current_m F['g'] += -m**2*u_current_m u_true += u_current_n F['g'] += -n**2*u_current_n # Problem lap = lambda A: operators.Laplacian(A, c) problem = problems.LBVP([u,t1,t2]) problem.add_equation((lap(u) + P1*t1 + P2*t2, F)) problem.add_equation((u(z=0), 0)) problem.add_equation((u(z=Lz), 0)) # Solver solver = solvers.LinearBoundaryValueSolver(problem) solver.solve() # Check solution print('L1 error on rank {} = {}'.format(rank, np.max(np.abs(u['g']-u_true)))) assert np.allclose(u['g'],u_true)