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
from dedalus.extras import flow_tools 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)
logger.info("Ma2 = {:.3g}, Pr = {:.3g}, γ = {:.3g}, ε={:.3g}".format( Ma2, Pr, γ, ε)) # 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) / γ n_h = float(args['--n_h']) Lz = -1 / h_slope * (1 - np.exp(-n_h)) print(n_h, Lz, h_slope) dealias = 2 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 zb1 = zb.clone_with(a=zb.a + 1, b=zb.b + 1) zb2 = zb.clone_with(a=zb.a + 2, b=zb.b + 2)
import logging 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
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