示例#1
0
def test_heat_1d_periodic(x_basis_class, Nx, timestepper, dtype):
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    xb = basis.ComplexFourier(c, size=Nx, bounds=(0, 2 * np.pi))
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb, ), dtype=dtype)
    F = field.Field(name='F', dist=d, bases=(xb, ), dtype=dtype)
    F['g'] = -np.sin(x)
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    dt = operators.TimeDerivative
    problem = problems.IVP([u])
    problem.add_equation((-dt(u) + dx(dx(u)), F))
    # Solver
    solver = solvers.InitialValueSolver(problem, timestepper)
    dt = 1e-5
    iter = 10
    for i in range(iter):
        solver.step(dt)
    # Check solution
    amp = 1 - np.exp(-solver.sim_time)
    u_true = amp * np.sin(x)
    assert np.allclose(u['g'], u_true)
示例#2
0
def test_waves_1d(x_basis_class, Nx, dtype):
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    xb = x_basis_class(c, size=Nx, bounds=(0, np.pi))
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb, ), dtype=dtype)
    a = field.Field(name='a', dist=d, dtype=dtype)
    τ1 = field.Field(name='τ1', dist=d, dtype=dtype)
    τ2 = field.Field(name='τ2', dist=d, dtype=dtype)
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    xb2 = dx(dx(u)).domain.bases[0]
    P1 = field.Field(name='P1', dist=d, bases=(xb2, ), dtype=dtype)
    P2 = field.Field(name='P2', dist=d, bases=(xb2, ), dtype=dtype)
    P1['c'][-1] = 1
    P2['c'][-2] = 1
    problem = problems.EVP([u, τ1, τ2], a)
    problem.add_equation((a * u + dx(dx(u)) + P1 * τ1 + P2 * τ2, 0))
    problem.add_equation((u(x=0), 0))
    problem.add_equation((u(x=np.pi), 0))
    # Solver
    solver = solvers.EigenvalueSolver(problem, matrix_coupling=[True])
    solver.solve_dense(solver.subproblems[0])
    i_sort = np.argsort(solver.eigenvalues)
    sorted_eigenvalues = solver.eigenvalues[i_sort]
    # Check solution
    Nmodes = Nx // 4
    k = np.arange(Nmodes) + 1
    assert np.allclose(sorted_eigenvalues[:Nmodes], k**2)
示例#3
0
def test_waves_1d_first_order(x_basis_class, Nx, dtype):
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    xb = x_basis_class(c, size=Nx, bounds=(0, np.pi))
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb, ), dtype=dtype)
    ux = field.Field(name='ux', dist=d, bases=(xb, ), dtype=dtype)
    a = field.Field(name='a', dist=d, dtype=dtype)
    τ1 = field.Field(name='τ1', dist=d, dtype=dtype)
    τ2 = field.Field(name='τ2', dist=d, dtype=dtype)
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    xb1 = dx(u).domain.bases[0]
    P1 = field.Field(name='P1', dist=d, bases=(xb1, ), dtype=dtype)
    P2 = field.Field(name='P2', dist=d, bases=(xb1, ), dtype=dtype)
    P1['c'][-1] = 1
    P2['c'][-1] = 1
    problem = problems.EVP([u, ux, τ1, τ2], a)
    problem.add_equation((a * u + dx(ux) + P1 * τ1, 0))
    problem.add_equation((ux - dx(u) + P2 * τ2, 0))
    problem.add_equation((u(x=0), 0))
    problem.add_equation((u(x=np.pi), 0))
    # Solver
    solver = solvers.EigenvalueSolver(problem, matrix_coupling=[True])
    solver.solve_dense(solver.subproblems[0])
    i_sort = np.argsort(solver.eigenvalues)
    solver.eigenvalues = solver.eigenvalues[i_sort]
    solver.eigenvectors = solver.eigenvectors[:, i_sort]
    # Check solution
    solver.set_state(0, solver.subproblems[0].subsystems[0])
    eigenfunction = u['g'] / np.max(u['g'])
    sol = np.sin(x) / np.max(np.sin(x))
    assert np.allclose(eigenfunction, sol)
示例#4
0
def test_sin_nlbvp(Nx, dtype, dealias, basis_class):
    ncc_cutoff = 1e-10
    tolerance = 1e-10
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c,))
    xb = basis_class(c, size=Nx, bounds=(0, 1), dealias=dealias)
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb,), dtype=dtype)
    τ = field.Field(name='τ', dist=d, dtype=dtype)
    xb1 = xb.clone_with(a=xb.a+1, b=xb.b+1)
    P = field.Field(name='P', dist=d, bases=(xb1,), dtype=dtype)
    P['c'][-1] = 1
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    problem = problems.NLBVP([u, τ])
    problem.add_equation((dx(u) + τ*P, np.sqrt(1-u*u)))
    problem.add_equation((u(x=0), 0))
    # Solver
    solver = solvers.NonlinearBoundaryValueSolver(problem, ncc_cutoff=ncc_cutoff)
    # Initial guess
    u['g'] = x
    # Iterations
    def error(perts):
        return np.sum([np.sum(np.abs(pert['c'])) for pert in perts])
    err = np.inf
    while err > tolerance:
        solver.newton_iteration()
        err = error(solver.perturbations)
    # Check solution
    u_true = np.sin(x)
    u.change_scales(1)
    assert np.allclose(u['g'], u_true)
示例#5
0
def test_jacobi_differentiate(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()
    assert np.allclose(fx['g'], 5*x**4)
示例#6
0
def test_jacobi_convert_explicit(N, a, b, k, dtype, layout):
    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)
    f[layout]
    g = operators.convert(f, fx.domain.bases).evaluate()
    assert np.allclose(g['g'], f['g'])
示例#7
0
def test_fourier_differentiate(N, bounds, dtype):
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    if dtype == np.float64:
        b = basis.RealFourier(c, size=N, bounds=bounds)
    elif dtype == np.complex128:
        b = basis.ComplexFourier(c, size=N, bounds=bounds)
    x = b.local_grid(1)
    f = field.Field(dist=d, bases=(b, ), dtype=dtype)
    k = 4 * np.pi / (bounds[1] - bounds[0])
    f['g'] = 1 + np.sin(k * x + 0.1)
    fx = operators.Differentiate(f, c).evaluate()
    assert np.allclose(fx['g'], k * np.cos(k * x + 0.1))
示例#8
0
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'])
示例#9
0
def test_heat_1d_periodic(x_basis_class, Nx, dtype):
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    xb = x_basis_class(c, size=Nx, bounds=(0, 2 * np.pi))
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb, ), dtype=dtype)
    a = field.Field(name='a', dist=d, dtype=dtype)
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    problem = problems.EVP([u], a)
    problem.add_equation((a * u + dx(dx(u)), 0))
    # Solver
    solver = solvers.EigenvalueSolver(problem, matrix_coupling=[True])
    solver.solve_dense(solver.subproblems[0])
    # Check solution
    k = xb.wavenumbers
    if x_basis_class is basis.RealFourier:
        k = k[1:]  # Drop one k=0 for msin
    assert np.allclose(solver.eigenvalues, k**2)
示例#10
0
 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')
示例#11
0
c = coords.CartesianCoordinates('x', 'z')
d = distributor.Distributor((c,))
if dtype == np.complex128:
    xb = basis.ComplexFourier(c.coords[0], size=Nx, bounds=(0, 2*np.pi), dealias=3/2)
elif dtype == np.float64:
    xb = basis.RealFourier(c.coords[0], size=Nx, bounds=(0, 2*np.pi), dealias=3/2)
zb = basis.ChebyshevT(c.coords[1], size=Nz, bounds=(0, Lz),dealias=3/2)
x = xb.local_grid(1)
z = zb.local_grid(1)
zb1 = basis.ChebyshevU(c.coords[1], size=Nz, bounds=(0, Lz), alpha0=0)
t1 = field.Field(name='t1', dist=d, bases=(xb,), dtype=dtype)
t2 = field.Field(name='t2', dist=d, bases=(xb,), dtype=dtype)
P1 = field.Field(name='P1', dist=d, bases=(zb1,), dtype=dtype)
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
示例#12
0
# Fields
u = field.Field(dist=d, bases=(zb, b), tensorsig=(c,),dtype=dtype)
w = field.Field(dist=d, bases=(zb, b), dtype=dtype)
p = field.Field(dist=d, bases=(zb, b), dtype=dtype)
tau_u = field.Field(dist=d, bases=(cb,), tensorsig=(c,), dtype=dtype)
tau_w = field.Field(dist=d, bases=(cb,), dtype=dtype)

# Parameters and operators
lap = lambda A: operators.Laplacian(A, c)
div = lambda A: operators.Divergence(A)
grad = lambda A: operators.Gradient(A, c)
curl = lambda A: operators.Curl(A)
dot = lambda A,B: arithmetic.DotProduct(A, B)
cross = lambda A,B: arithmetic.CrossProduct(A, B)
dt = lambda A: operators.TimeDerivative(A)
dz = lambda A: operators.Differentiate(A, zc)

# Problem
def eq_eval(eq_str):
    return [eval(expr) for expr in split_equation(eq_str)]
problem = problems.IVP([u, w, p, tau_u, tau_w])
problem.add_equation(eq_eval("dt(u) - nu*(lap(u) + dz(dz(u))) - grad(p) = 0."), condition='nphi != 0')
problem.add_equation(eq_eval("dt(w) - nu*(lap(w) + dz(dz(w))) - dz(p) = 0."), condition='nphi != 0')
problem.add_equation(eq_eval("u = 0"), condition='nphi == 0')
problem.add_equation(eq_eval("w = 0"), condition='nphi == 0')
problem.add_equation(eq_eval("div(u) + dz(w) = 0"), condition='nphi != 0')
problem.add_equation(eq_eval("p = 0"), condition='nphi == 0')

problem.add_equation(eq_eval("u(r=1) = 0"), condition='nphi != 0')
problem.add_equation(eq_eval("tau_u = 0"), condition='nphi == 0')
problem.add_equation(eq_eval("w(r=1) = 0"), condition='nphi != 0')
示例#13
0
def main(N, alpha, method, tau):
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c,))
    xb = basis.ChebyshevT(c, size=N, bounds=(-1, 1))
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb,), dtype=np.float64)
    ux = field.Field(name='ux', dist=d, bases=(xb,), dtype=np.float64)
    f = field.Field(name='f', dist=d, bases=(xb,), dtype=np.float64)
    t1 = field.Field(name='t1', dist=d, dtype=np.float64)
    t2 = field.Field(name='t2', dist=d, dtype=np.float64)
    pi, sin, cos = np.pi, np.sin, np.cos
    f['g'] = 64*pi**3*(4*pi*sin(4*pi*x)**2*sin(4*pi*cos(4*pi*x)) + cos(4*pi*x)*cos(4*pi*cos(4*pi*x))) + alpha*sin(4*pi*cos(4*pi*x))
    # Tau polynomials
    xb1 = xb._new_a_b(xb.a+1, xb.b+1)
    xb2 = xb._new_a_b(xb.a+2, xb.b+2)
    if tau == 0:
        # First-order classical Chebyshev tau: T[-1], dx(T[-1])
        p1 = field.Field(name='p1', dist=d, bases=(xb,), dtype=np.float64)
        p2 = field.Field(name='p2', dist=d, bases=(xb,), dtype=np.float64)
        p1['c'][-1] = 1
        p2['c'][-1] = 1
    elif tau == 1:
        # First-order ultraspherical tau: U[-1], dx(U[-1])
        p1 = field.Field(name='p1', dist=d, bases=(xb1,), dtype=np.float64)
        p2 = field.Field(name='p2', dist=d, bases=(xb1,), dtype=np.float64)
        p1['c'][-1] = 1
        p2['c'][-1] = 1
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    problem = problems.LBVP([u, ux, t1, t2])
    problem.add_equation((alpha*u - dx(ux) + t1*p1, f))
    problem.add_equation((ux - dx(u) + t2*p2, 0))
    problem.add_equation((u(x=-1), 0))
    problem.add_equation((u(x=+1), 0))
    solver = solvers.LinearBoundaryValueSolver(problem)
    # Methods
    if method == 0:
        # Condition number
        L_exp = solver.subproblems[0].L_exp
        result = np.linalg.cond(L_exp.A)
    elif method == 1:
        # Roundtrip roundoff with uniform u
        A = solver.subproblems[0].L_exp
        v = np.random.rand(A.shape[1])
        f = A * v
        u = solver.subproblem_matsolvers[solver.subproblems[0]].solve(f)
        result = np.max(np.abs(u-v))
    elif method == 2:
        # Manufactured solution
        from mpi4py_fft import fftw as mpi4py_fftw
        solver.solve()
        ue = np.sin(4*np.pi*np.cos(4*np.pi*x))
        d = mpi4py_fftw.aligned(N, fill=0)
        k = 2*(1 + np.arange((N-1)//2))
        d[::2] = (2./N)/np.hstack((1., 1.-k*k))
        w = mpi4py_fftw.aligned_like(d)
        dct = mpi4py_fftw.dctn(w, axes=(0,), type=3)
        weights = dct(d, w)
        result = np.sqrt(np.sum(weights*(u['g']-ue)**2))
    elif method == 3:
        # Roundtrip roundoff with uniform f
        A = solver.subproblems[0].L_exp
        g = np.random.rand(A.shape[0])
        v = solver.subproblem_matsolvers[solver.subproblems[0]].solve(g)
        f = A * v
        u = solver.subproblem_matsolvers[solver.subproblems[0]].solve(f)
        result = np.max(np.abs(u-v))
    return result