def test_box_AdvectiveCFL(x_basis_class, Nx, Nz, timestepper, dtype, z_velocity_mag, dealias): # Bases Lx = 2 Lz = 1 c = coords.CartesianCoordinates('x', 'z') d = distributor.Distributor((c, )) xb = x_basis_class(c.coords[0], size=Nx, bounds=(0, Lx), dealias=dealias) x = xb.local_grid(1) zb = basis.ChebyshevT(c.coords[1], size=Nz, bounds=(0, Lz), dealias=dealias) z = zb.local_grid(1) b = (xb, zb) # Fields u = field.Field(name='u', dist=d, tensorsig=(c, ), bases=b, dtype=dtype) print(u.domain.get_basis(c)) # Test Fourier CFL fourier_velocity = lambda x: np.sin(4 * np.pi * x / Lx) chebyshev_velocity = lambda z: -z_velocity_mag * z u['g'][0] = fourier_velocity(x) u['g'][1] = chebyshev_velocity(z) # AdvectiveCFL initialization cfl = operators.AdvectiveCFL(u, c) cfl_freq = cfl.evaluate()['g'] comparison_freq = np.abs(u['g'][0]) / cfl.cfl_spacing(u)[0] comparison_freq += np.abs(u['g'][1]) / cfl.cfl_spacing(u)[1] assert np.allclose(cfl_freq, comparison_freq)
def test_cartesian_output(dtype, dealias, output_scales, output_layout): Nx = Ny = Nz = 16 Lx = Ly = Lz = 2 * np.pi # Bases c = coords.CartesianCoordinates('x', 'y', 'z') d = distributor.Distributor((c, )) Fourier = { np.float64: basis.RealFourier, np.complex128: basis.ComplexFourier }[dtype] xb = Fourier(c.coords[0], size=Nx, bounds=(0, Lx), dealias=dealias) yb = Fourier(c.coords[1], size=Ny, bounds=(0, Ly), dealias=dealias) zb = basis.ChebyshevT(c.coords[2], size=Nz, bounds=(0, Lz), dealias=dealias) x = xb.local_grid(1) y = yb.local_grid(1) z = zb.local_grid(1) # Fields u = field.Field(name='u', dist=d, bases=(xb, yb, zb), dtype=dtype) u['g'] = np.sin(x) * np.sin(y) * np.sin(z) # Problem dt = operators.TimeDerivative problem = problems.IVP([u]) problem.add_equation((dt(u) + u, 0)) # Solver solver = solvers.InitialValueSolver(problem, timesteppers.RK222) # Output tasks = [ u, u(x=0), u(y=0), u(z=0), u(x=0, y=0), u(x=0, z=0), u(y=0, z=0), u(x=0, y=0, z=0) ] with tempfile.TemporaryDirectory(dir='.') as tempdir: tempdir = pathlib.Path(tempdir).stem output = solver.evaluator.add_file_handler(tempdir, iter=1) for task in tasks: output.add_task(task, layout=output_layout, name=str(task), scales=output_scales) solver.evaluator.evaluate_handlers([output]) output.process_virtual_file() # Check solution #post.merge_process_files('test_output') errors = [] with h5py.File(f'{tempdir}/{tempdir}_s1.h5', mode='r') as file: for task in tasks: task_saved = file['tasks'][str(task)][-1] task = task.evaluate() task.change_scales(output_scales) errors.append(np.max(np.abs(task[output_layout] - task_saved))) assert np.allclose(errors, 0)
def build_2d_box(Nx, Nz, dealias, dtype, k=0): c = coords.CartesianCoordinates('x', 'z') d = distributor.Distributor((c,)) if dtype == np.complex128: xb = basis.ComplexFourier(c.coords[0], size=Nx, bounds=(0, Lx)) elif dtype == np.float64: xb = basis.RealFourier(c.coords[0], size=Nx, bounds=(0, Lx)) zb = basis.ChebyshevT(c.coords[1], size=Nz, bounds=(0, Lz)) b = (xb, zb) x = xb.local_grid(1) z = zb.local_grid(1) return c, d, b, x, z
def test_flow_tools_cfl(x_basis_class, Nx, Nz, timestepper, dtype, safety, z_velocity_mag, dealias): # Bases Lx = 2 Lz = 1 c = coords.CartesianCoordinates('x', 'z') d = distributor.Distributor((c, )) xb = x_basis_class(c.coords[0], size=Nx, bounds=(0, Lx), dealias=dealias) x = xb.local_grid(1) zb = basis.ChebyshevT(c.coords[1], size=Nz, bounds=(0, Lz), dealias=dealias) z = zb.local_grid(1) b = (xb, zb) # Fields u = field.Field(name='u', dist=d, tensorsig=(c, ), bases=b, dtype=dtype) # Problem ddt = operators.TimeDerivative problem = problems.IVP([u]) problem.add_equation((ddt(u), 0)) # Solver solver = solvers.InitialValueSolver(problem, timestepper) # cfl initialization dt = 1 cfl = flow_tools.CFL(solver, dt, safety=safety, cadence=1) cfl.add_velocity(u) # Test Fourier CFL fourier_velocity = lambda x: np.sin(4 * np.pi * x / Lx) chebyshev_velocity = lambda z: -z_velocity_mag * z u['g'][0] = fourier_velocity(x) u['g'][1] = chebyshev_velocity(z) solver.step(dt) solver.step( dt ) #need two timesteps to get past stored_dt per compute_timestep logic dt = cfl.compute_timestep() op = operators.AdvectiveCFL(u, c) cfl_freq = np.abs(u['g'][0] / op.cfl_spacing(u)[0]) cfl_freq += np.abs(u['g'][1] / op.cfl_spacing(u)[1]) cfl_freq = np.max(cfl_freq) dt_comparison = safety * (cfl_freq)**(-1) assert np.allclose(dt, dt_comparison)
def test_chebyshev_AdvectiveCFL(Nx, timestepper, dtype, dealias): # Bases Lx = 1 c = coords.CartesianCoordinates('x') d = distributor.Distributor((c, )) xb = basis.ChebyshevT(c.coords[0], size=Nx, bounds=(0, Lx), dealias=dealias) x = xb.local_grid(1) # Fields u = field.Field(name='u', dist=d, tensorsig=(c, ), bases=(xb, ), dtype=dtype) velocity = lambda x: x u['g'][0] = velocity(x) # AdvectiveCFL initialization cfl = operators.AdvectiveCFL(u, c) cfl_freq = cfl.evaluate()['g'] comparison_freq = np.abs(u['g']) / cfl.cfl_spacing(u)[0] assert np.allclose(cfl_freq, comparison_freq)
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')
rank = MPI.COMM_WORLD.rank import logging logger = logging.getLogger(__name__) dtype = np.complex128 #np.float64 Nx = 64 Nz = 32 Lz = 2*np.pi # Bases 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
logger = logging.getLogger(__name__) # Parameters Lx, Ly, Lz = (4, 4, 1) Nx, Ny, Nz = 8, 8, 16 Prandtl = 1 Rayleigh = 3000 timestep = 0.01 stop_iteration = 10 # Bases c = coords.CartesianCoordinates('x', 'y', 'z') d = distributor.Distributor((c, )) xb = basis.ComplexFourier(c.coords[0], size=Nx, bounds=(0, Lx)) yb = basis.ComplexFourier(c.coords[1], size=Ny, bounds=(0, Ly)) zb = basis.ChebyshevT(c.coords[2], size=Nz, bounds=(0, Lz)) # Fields p = field.Field(name='p', dist=d, bases=(xb, yb, zb), dtype=np.complex128) b = field.Field(name='b', dist=d, bases=(xb, yb, zb), dtype=np.complex128) u = field.Field(name='u', dist=d, bases=(xb, yb, zb), dtype=np.complex128, tensorsig=(c, )) # Taus zb2 = basis.ChebyshevV(c.coords[2], size=Nz, bounds=(0, Lz), alpha0=0) t1 = field.Field(name='t4', dist=d, bases=(xb, yb), dtype=np.complex128) t2 = field.Field(name='t4', dist=d, bases=(xb, yb), dtype=np.complex128) t3 = field.Field(name='t4',
import numpy as np from dedalus.core import coords, distributor, basis, field, operators from mpi4py import MPI comm = MPI.COMM_WORLD results = [] ## 2D Fourier * Chebyshev c = coords.CartesianCoordinates('x', 'y') d = distributor.Distributor((c, )) xb = basis.ComplexFourier(c.coords[0], size=16, bounds=(0, 2 * np.pi)) yb = basis.ChebyshevT(c.coords[1], size=16, bounds=(0, 1)) x = xb.local_grid(1) y = yb.local_grid(1) # Gradient of a scalar f = field.Field(dist=d, bases=(xb, yb), dtype=np.complex128) f.name = 'f' f['g'] = np.sin(x) * y**5 u = operators.Gradient(f, c) u = u.evaluate() u.name = 'u' ug = np.array([np.cos(x) * y**5, np.sin(x) * 5 * y**4]) result = np.allclose(u['g'], ug) results.append(result) print(len(results), ':', result, '(gradient of a scalar)') # Gradient of a vector T = operators.Gradient(u, c) T = T.evaluate()
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