def test_poisson_1d_fourier(Nx, dtype, matrix_coupling): # Bases coord = d3.Coordinate('x') dist = d3.Distributor(coord, dtype=dtype) if dtype == np.complex128: basis = d3.ComplexFourier(coord, size=Nx, bounds=(0, 2 * np.pi)) elif dtype == np.float64: basis = d3.RealFourier(coord, size=Nx, bounds=(0, 2 * np.pi)) x = basis.local_grid(1) # Fields u = dist.Field(name='u', bases=basis) g = dist.Field(name='c') # Substitutions dx = lambda A: d3.Differentiate(A, coord) integ = lambda A: d3.Integrate(A, coord) F = dist.Field(bases=basis) F['g'] = -np.sin(x) # Problem problem = d3.LBVP([u, g], namespace=locals()) problem.add_equation("dx(dx(u)) + g = F") problem.add_equation("integ(u) = 0") # Solver solver = problem.build_solver(matrix_coupling=[matrix_coupling]) solver.solve() # Check solution u_true = np.sin(x) assert np.allclose(u['g'], u_true)
def test_poisson_1d_jacobi(Nx, a0, b0, da, db, dtype): # Bases coord = d3.Coordinate('x') dist = d3.Distributor(coord, dtype=dtype) basis = d3.Jacobi(coord, size=Nx, bounds=(0, 2 * np.pi), a=a0 + da, b=b0 + db, a0=a0, b0=b0) x = basis.local_grid(1) # Fields u = dist.Field(name='u', bases=basis) tau1 = dist.Field(name='tau1') tau2 = dist.Field(name='tau2') # Substitutions dx = lambda A: d3.Differentiate(A, coord) lift_basis = basis.clone_with(a=a0 + da + 2, b=b0 + db + 2) lift = lambda A, n: d3.Lift(A, lift_basis, n) F = dist.Field(bases=basis) F['g'] = -np.sin(x) # Problem problem = d3.LBVP([u, tau1, tau2], namespace=locals()) problem.add_equation("dx(dx(u)) + lift(tau1,-1) + lift(tau2,-2) = F") problem.add_equation("u(x='left') = 0") problem.add_equation("u(x='right') = 0") # Solver solver = problem.build_solver() solver.solve() # Check solution u_true = np.sin(x) assert np.allclose(u['g'], u_true)
def build_FFF(N, dealias, dtype): c = d3.CartesianCoordinates('x', 'y', 'z') d = d3.Distributor(c, dtype=dtype) if dtype == np.complex128: xb = d3.ComplexFourier(c.coords[0], size=N, bounds=(0, Lx), dealias=dealias) yb = d3.ComplexFourier(c.coords[1], size=N, bounds=(0, Ly), dealias=dealias) zb = d3.ComplexFourier(c.coords[2], size=N, bounds=(0, Lz), dealias=dealias) elif dtype == np.float64: xb = d3.RealFourier(c.coords[0], size=N, bounds=(0, Lx), dealias=dealias) yb = d3.RealFourier(c.coords[1], size=N, bounds=(0, Ly), dealias=dealias) zb = d3.RealFourier(c.coords[2], size=N, bounds=(0, Lz), dealias=dealias) b = (xb, yb, zb) x = xb.local_grid(dealias) y = yb.local_grid(dealias) z = zb.local_grid(dealias) r = (x, y, z) return c, d, b, r
def lane_emden(Nr, m=1.5, n_rho=3, radius=1, ncc_cutoff = 1e-10, tolerance = 1e-10, dtype=np.complex128, comm=None): # TO-DO: clean this up and make work for ncc ingestion in main script in np.float64 rather than np.complex128 c = de.SphericalCoordinates('phi', 'theta', 'r') d = de.Distributor((c,), comm=comm, dtype=dtype) b = de.BallBasis(c, (1, 1, Nr), radius=radius, dtype=dtype) br = b.radial_basis phi, theta, r = b.local_grids() # Fields f = d.Field(name='f', bases=b) R = d.Field(name='R') τ = d.Field(name='τ', bases=b.S2_basis(radius=radius)) # Parameters and operators lap = lambda A: de.Laplacian(A, c) lift_basis = b.clone_with(k=2) # match laplacian lift = lambda A: de.LiftTau(A, lift_basis, -1) problem = de.NLBVP([f, R, τ]) problem.add_equation((lap(f) + lift(τ), - R**2 * f**m)) problem.add_equation((f(r=0), 1)) problem.add_equation((f(r=radius), np.exp(-n_rho/m, dtype=dtype))) # explicit typing to match domain # Solver solver = problem.build_solver(ncc_cutoff=ncc_cutoff) # Initial guess f['g'] = np.cos(np.pi/2 * r)**2 R['g'] = 5 # Iterations logger.debug('beginning Lane-Emden NLBVP iterations') pert_norm = np.inf while pert_norm > tolerance: solver.newton_iteration() pert_norm = sum(pert.allreduce_data_norm('c', 2) for pert in solver.perturbations) logger.debug(f'Perturbation norm: {pert_norm:.3e}') T = d.Field(name='T', bases=br) ρ = d.Field(name='ρ', bases=br) lnρ = d.Field(name='lnρ', bases=br) T['g'] = f['g'] ρ['g'] = f['g']**m lnρ['g'] = np.log(ρ['g']) structure = {'T':T,'lnρ':lnρ} for key in structure: structure[key].require_scales(1) structure['r'] = r structure['problem'] = {'c':c, 'b':b, 'problem':problem} return structure
logger.info(args) logger.info("saving data in: {}".format(data_dir)) # this assumes h_bot=1, grad_φ = (γ-1)/γ (or L=Hρ) h_bot = 1 h_slope = -1 / (1 + m) grad_φ = (γ - 1) / γ n_h = float(args['--n_h']) Lz = -1 / h_slope * (1 - np.exp(-n_h)) Lx = float(args['--aspect']) * Lz dealias = 2 c = de.CartesianCoordinates('x', 'z') d = de.Distributor(c, dtype=np.float64) xb = de.RealFourier(c.coords[0], size=nx, bounds=(0, Lx), dealias=dealias) zb = de.ChebyshevT(c.coords[1], size=nz, bounds=(0, Lz), dealias=dealias) b = (xb, zb) x = xb.local_grid(1) z = zb.local_grid(1) # Fields T = d.Field(name='T', bases=b) Υ = d.Field(name='Υ', bases=b) s = d.Field(name='s', bases=b) u = d.VectorField(c, name='u', bases=b) # Taus zb1 = zb.clone_with(a=zb.a + 1, b=zb.b + 1) zb2 = zb.clone_with(a=zb.a + 2, b=zb.b + 2)
restart = (len(sys.argv) > 1 and sys.argv[1] == '--restart') # Parameters Nphi, Ntheta, Nr = 128, 64, 96 Rayleigh = 1e6 Prandtl = 1 dealias = 3 / 2 stop_sim_time = 20 + 20 * restart timestepper = d3.SBDF2 max_timestep = 0.05 dtype = np.float64 mesh = None # Bases coords = d3.SphericalCoordinates('phi', 'theta', 'r') dist = d3.Distributor(coords, dtype=dtype, mesh=mesh) basis = d3.BallBasis(coords, shape=(Nphi, Ntheta, Nr), radius=1, dealias=dealias, dtype=dtype) S2_basis = basis.S2_basis() # Fields u = dist.VectorField(coords, name='u', bases=basis) p = dist.Field(name='p', bases=basis) T = dist.Field(name='T', bases=basis) tau_p = dist.Field(name='tau_p') tau_u = dist.VectorField(coords, name='tau u', bases=S2_basis) tau_T = dist.Field(name='tau T', bases=S2_basis)
logger = logging.getLogger(__name__) # Parameters Lx, Lz = 4, 1 Nx, Nz = 256, 64 Rayleigh = 2e6 Prandtl = 1 dealias = 3 / 2 stop_sim_time = 50 timestepper = d3.RK222 max_timestep = 0.125 dtype = np.float64 # Bases coords = d3.CartesianCoordinates('x', 'z') dist = d3.Distributor(coords, dtype=dtype) xbasis = d3.RealFourier(coords['x'], size=Nx, bounds=(0, Lx), dealias=dealias) zbasis = d3.ChebyshevT(coords['z'], size=Nz, bounds=(0, Lz), dealias=dealias) # Fields p = dist.Field(name='p', bases=(xbasis, zbasis)) b = dist.Field(name='b', bases=(xbasis, zbasis)) u = dist.VectorField(coords, name='u', bases=(xbasis, zbasis)) tau_p = dist.Field(name='tau_p') tau_b1 = dist.Field(name='tau_b1', bases=xbasis) tau_b2 = dist.Field(name='tau_b2', bases=xbasis) tau_u1 = dist.VectorField(coords, name='tau_u1', bases=xbasis) tau_u2 = dist.VectorField(coords, name='tau_u2', bases=xbasis) # Substitutions kappa = (Rayleigh * Prandtl)**(-1 / 2)
def heated_polytrope(nz, γ, ε, n_h, tolerance = 1e-8, ncc_cutoff = 1e-10, dealias = 2, verbose=False): import dedalus.public as de cP = γ/(γ-1) m_ad = 1/(γ-1) s_c_over_c_P = scrS = 1 # s_c/c_P = 1 logger.info("γ = {:.3g}, ε={:.3g}".format(γ, ε)) # this assumes h_bot=1, grad_φ = (γ-1)/γ (or L=Hρ) h_bot = 1 # generally, h_slope = -1/(1+m) # start in an adibatic state, heat from there h_slope = -1/(1+m_ad) grad_φ = (γ-1)/γ Lz = -1/h_slope*(1-np.exp(-n_h)) print(n_h, Lz, h_slope) c = de.CartesianCoordinates('z') d = de.Distributor(c, dtype=np.float64) zb = de.ChebyshevT(c.coords[-1], size=nz, bounds=(0, Lz), dealias=dealias) b = zb z = zb.local_grid(1) zd = zb.local_grid(dealias) # Fields θ = d.Field(name='θ', bases=b) Υ = d.Field(name='Υ', bases=b) s = d.Field(name='s', bases=b) u = d.VectorField(c, name='u', bases=b) # Taus lift_basis = zb.clone_with(a=zb.a+2, b=zb.b+2) lift = lambda A, n: de.Lift(A, lift_basis, n) lift_basis1 = zb.clone_with(a=zb.a+1, b=zb.b+1) lift1 = lambda A, n: de.Lift(A, lift_basis1, n) τ_h1 = d.VectorField(c,name='τ_h1') τ_s1 = d.Field(name='τ_s1') τ_s2 = d.Field(name='τ_s2') # Parameters and operators lap = lambda A: de.Laplacian(A, c) grad = lambda A: de.Gradient(A, c) ez, = c.unit_vector_fields(d) # NLBVP goes here # intial guess h0 = d.Field(name='h0', bases=zb) θ0 = d.Field(name='θ0', bases=zb) Υ0 = d.Field(name='Υ0', bases=zb) s0 = d.Field(name='s0', bases=zb) structure = {'h':h0,'s':s0,'θ':θ0,'Υ':Υ0} for key in structure: structure[key].change_scales(dealias) h0['g'] = h_bot + zd*h_slope #(Lz+1)-z θ0['g'] = np.log(h0).evaluate()['g'] Υ0['g'] = (m_ad*θ0).evaluate()['g'] s0['g'] = 0 problem = de.NLBVP([h0, s0, Υ0, τ_s1, τ_s2, τ_h1]) problem.add_equation((grad(h0) + lift1(τ_h1,-1), -grad_φ*ez + h0*grad(s0))) problem.add_equation((-lap(h0) + lift(τ_s1,-1) + lift(τ_s2,-2), ε)) problem.add_equation(((γ-1)*Υ0 + s_c_over_c_P*γ*s0, np.log(h0))) problem.add_equation((Υ0(z=0), 0)) problem.add_equation((h0(z=0), 1)) problem.add_equation((h0(z=Lz), np.exp(-n_h))) # Solver solver = problem.build_solver(ncc_cutoff=ncc_cutoff) pert_norm = np.inf while pert_norm > tolerance: solver.newton_iteration() pert_norm = sum(pert.allreduce_data_norm('c', 2) for pert in solver.perturbations) logger.info('current perturbation norm = {:.3g}'.format(pert_norm)) if verbose: import matplotlib.pyplot as plt fig, ax = plt.subplots() ax2 = ax.twinx() ax.plot(zd, h0['g'], linestyle='dashed', color='xkcd:dark grey', label='h') ax2.plot(zd, np.log(h0).evaluate()['g'], label=r'$\ln h$') ax2.plot(zd, Υ0['g'], label=r'$\ln \rho$') ax2.plot(zd, s0['g'], color='xkcd:brick red', label=r'$s$') ax.legend() ax2.legend() fig.savefig('heated_polytrope_nh{}_eps{}_gamma{:.3g}.pdf'.format(n_h,ε,γ)) for key in structure: structure[key].change_scales(1) return structure
# Parameters Lx = 10 Nx = 1024 a = 1e-4 b = 2e-4 dealias = 3/2 stop_sim_time = 10 timestepper = d3.SBDF2 timestep = 2e-3 dtype = np.float64 # Bases xcoord = d3.Coordinate('x') dist = d3.Distributor(xcoord, dtype=dtype) xbasis = d3.RealFourier(xcoord, size=Nx, bounds=(0, Lx), dealias=dealias) # Fields u = dist.Field(name='u', bases=xbasis) # Substitutions dx = lambda A: d3.Differentiate(A, xcoord) # Problem problem = d3.IVP([u], namespace=locals()) problem.add_equation("dt(u) - a*dx(dx(u)) - b*dx(dx(dx(u))) = - u*dx(u)") # Initial conditions x = dist.local_grid(xbasis) n = 20
radius = 1 Ek = Ekman = float(args['--Ekman']) Co2 = ConvectiveRossbySq = float(args['--ConvectiveRossbySq']) Pr = Prandtl = float(args['--Prandtl']) logger.info("Ek = {}, Co2 = {}, Pr = {}".format(Ek, Co2, Pr)) import dedalus.public as de from dedalus.extras import flow_tools from structure import lane_emden dealias = float(args['--dealias']) c = de.SphericalCoordinates('phi', 'theta', 'r') d = de.Distributor(c, mesh=mesh, dtype=np.float64) b = de.BallBasis(c, shape=(Nφ, Nθ, Nr), radius=radius, dealias=dealias, dtype=np.float64) b_S2 = b.S2_basis() phi, theta, r = b.local_grids() p = d.Field(name='p', bases=b) s = d.Field(name='s', bases=b) u = d.VectorField(c, name='u', bases=b) τ_p = d.Field(name='τ_p') τ_s = d.Field(name='τ_s', bases=b_S2) τ_u = d.VectorField(c, name='τ_u', bases=b_S2)
import dedalus.public as d3 import dedalus from dedalus.tools.parallel import RotateProcesses scales = 1 coords = d3.CartesianCoordinates('x', 'y') dist = d3.Distributor(coords, dtype=float) xb = d3.RealFourier(coords['x'], 32, (0, 1)) yb = d3.Chebyshev(coords['y'], 64, (0, 1)) domain = dedalus.core.domain.Domain(dist, (xb, yb)) for layout in dist.layouts: with RotateProcesses(): print("Rank:", dist.comm.rank) print("Grid space:", layout.grid_space, " Local:", layout.local) print("Global shape:", layout.global_shape(domain, scales), " Chunk shape:", layout.chunk_shape(domain)) print(layout.local_groups(domain, scales)) print()