def test_curl_implicit_FFC(basis, N, dealias, dtype): c, d, b, r = basis(N, dealias, dtype) Lz = b[2].bounds[1] lift_basis = b[2].clone_with(a=1 / 2, b=1 / 2) # First derivative basis lift = lambda A, n: d3.Lift(A, lift_basis, n) integ = lambda A: d3.Integrate( d3.Integrate(d3.Integrate(A, c.coords[0]), c.coords[1]), c.coords[2]) tau1 = d.VectorField(c, name='tau1', bases=b[0:2]) tau2 = d.Field(name='tau2', bases=b[0:2]) # ABC vector field k = 2 * np.pi * np.array([1 / Lx, 1 / Ly, 1 / Lz]) f = d.VectorField(c, bases=b) f.preset_scales(dealias) f['g'][0] = np.sin(k[2] * r[2]) + np.cos(k[1] * r[1]) f['g'][1] = np.sin(k[0] * r[0]) + np.cos(k[2] * r[2]) f['g'][2] = np.sin(k[1] * r[1]) + np.cos(k[0] * r[0]) g = d.VectorField(c, bases=b) g.preset_scales(dealias) g['g'][0] = k[2] * np.sin(k[2] * r[2]) + k[1] * np.cos(k[1] * r[1]) g['g'][1] = k[0] * np.sin(k[0] * r[0]) + k[2] * np.cos(k[2] * r[2]) g['g'][2] = k[1] * np.sin(k[1] * r[1]) + k[0] * np.cos(k[0] * r[0]) # Skew LBVP u = d.VectorField(c, name='u', bases=b) phi = d.Field(name='phi', bases=b) problem = d3.LBVP([u, phi, tau1, tau2], namespace=locals()) problem.add_equation("curl(u) + grad(phi) + lift(tau1,-1) = g") problem.add_equation("div(u) + lift(tau2,-1) = 0") problem.add_equation("u(z=0) = f(z=0)") problem.add_equation("phi(z=0) = 0") solver = problem.build_solver() solver.solve() assert np.allclose(u['c'], f['c'])
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)
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) lift1 = lambda A, n: de.Lift(A, zb1, n) lift = lambda A, n: de.Lift(A, zb2, n) τ_h1 = d.VectorField(c, name='τ_h1') τ_s1 = d.Field(name='τ_s1') τ_s2 = d.Field(name='τ_s2') τ_u1 = d.VectorField(c, name='τ_u1') τ_u2 = d.VectorField(c, name='τ_u2') # Parameters and operators div = lambda A: de.Divergence(A, index=0) lap = lambda A: de.Laplacian(A, c) grad = lambda A: de.Gradient(A, c) #curl = lambda A: de.operators.Curl(A) cross = lambda A, B: de.CrossProduct(A, B) trace = lambda A: de.Trace(A) trans = lambda A: de.TransposeComponents(A)
# 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) # Substitutions phi, theta, r = dist.local_grids(basis) r_vec = dist.VectorField(coords, bases=basis.radial_basis) r_vec['g'][2] = r T_source = 6 kappa = (Rayleigh * Prandtl)**(-1 / 2) nu = (Rayleigh / Prandtl)**(-1 / 2) lift = lambda A: d3.Lift(A, basis, -1) strain_rate = d3.grad(u) + d3.trans(d3.grad(u)) shear_stress = d3.angular(d3.radial(strain_rate(r=1), index=1)) # Problem problem = d3.IVP([p, u, T, tau_p, tau_u, tau_T], namespace=locals()) problem.add_equation("div(u) + tau_p = 0") problem.add_equation( "dt(u) - nu*lap(u) + grad(p) - r_vec*T + lift(tau_u) = - cross(curl(u),u)") problem.add_equation( "dt(T) - kappa*lap(T) + lift(tau_T) = - u@grad(T) + kappa*T_source") problem.add_equation("shear_stress = 0") # Stress free problem.add_equation("radial(u(r=1)) = 0") # No penetration problem.add_equation("radial(grad(T)(r=1)) = -2") problem.add_equation("integ(p) = 0") # Pressure gauge
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) nu = (Rayleigh / Prandtl)**(-1 / 2) x, z = dist.local_grids(xbasis, zbasis) ex, ez = coords.unit_vector_fields(dist) lift_basis = zbasis.derivative_basis(1) lift = lambda A: d3.Lift(A, lift_basis, -1) grad_u = d3.grad(u) + ez * lift(tau_u1) # First-order reduction grad_b = d3.grad(b) + ez * lift(tau_b1) # First-order reduction # Problem # First-order form: "div(f)" becomes "trace(grad_f)" # First-order form: "lap(f)" becomes "div(grad_f)" problem = d3.IVP([p, b, u, tau_p, tau_b1, tau_b2, tau_u1, tau_u2], namespace=locals()) problem.add_equation("trace(grad_u) + tau_p = 0") problem.add_equation("dt(b) - kappa*div(grad_b) + lift(tau_b2) = - u@grad(b)") problem.add_equation( "dt(u) - nu*div(grad_u) + grad(p) - b*ez + lift(tau_u2) = - u@grad(u)") problem.add_equation("b(z=0) = Lz") problem.add_equation("u(z=0) = 0") problem.add_equation("b(z=Lz) = 0")
tau_2 = dist.Field(name='tau_2', bases=xbasis) # Forcing x, y = dist.local_grids(xbasis, ybasis) f = dist.Field(bases=(xbasis, ybasis)) g = dist.Field(bases=xbasis) h = dist.Field(bases=xbasis) f.fill_random('g', seed=40) f.low_pass_filter(shape=(64, 32)) g['g'] = np.sin(8 * x) * 0.025 h['g'] = 0 # Substitutions dy = lambda A: d3.Differentiate(A, coords['y']) lift_basis = ybasis.derivative_basis(2) lift = lambda A, n: d3.Lift(A, lift_basis, n) # Problem problem = d3.LBVP([u, tau_1, tau_2], namespace=locals()) problem.add_equation("lap(u) + lift(tau_1,-1) + lift(tau_2,-2) = f") problem.add_equation("u(y=0) = g") problem.add_equation("dy(u)(y=Ly) = h") # Solver solver = problem.build_solver() solver.solve() # Gather global data x = xbasis.global_grid() y = ybasis.global_grid() ug = u.allgather_data('g')
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