def __init__(self, nx, ny, nz, Lx, Ly, Lz, threeD=False, mesh=None): """ Initializes the dedalus domain object. Many of the inputs match those in the class attribute docstring. Other attributes: ----------------- mesh : list of ints The CPU grid on which the domain is distributed. """ self.nx, self.ny, self.nz = nx, ny, nz self.Lx, self.Ly, self.Lz = Lx, Ly, Lz self.threeD = threeD x_basis = de.Fourier('x', nx, interval=(-Lx / 2, Lx / 2), dealias=3 / 2) self.bases = [ x_basis, ] if threeD: y_basis = de.Fourier('y', ny, interval=(-Ly / 2, Ly / 2), dealias=3 / 2) self.bases += [y_basis] if isinstance(nz, list) and isinstance(Lz, list): Lz_int = 0 z_basis_list = [] for Lz_i, nz_i in zip(Lz, nz): Lz_top = Lz_i + Lz_int z_basis = de.Chebyshev('z', nz_i, interval=[Lz_int, Lz_top], dealias=3 / 2) z_basis_list.append(z_basis) Lz_int = Lz_top self.Lz = Lz_int self.nz = np.sum(nz) self.Lz_list = Lz self.nz_list = nz z_basis = de.Compound('z', tuple(z_basis_list), dealias=3 / 2) else: z_basis = de.Chebyshev('z', nz, interval=(0, Lz), dealias=3 / 2) self.Lz_list = None self.nz_list = None self.bases += [z_basis] self.domain = de.Domain(self.bases, grid_dtype=np.float64, mesh=mesh, comm=MPI.COMM_WORLD) self.x = self.domain.grid(0) if threeD: self.y = self.domain.grid(1) else: self.y = None self.z = self.domain.grid(-1)
def DoubleChebyshev(name, N, interval=(-1, 1), dealias=1): N0 = int(N // 2) N1 = N - N0 L = interval[1] - interval[0] int0 = (interval[0], interval[0] + L / 2) int1 = (interval[0] + L / 2, interval[1]) b0 = de.Chebyshev('b0', N0, interval=int0, dealias=dealias) b1 = de.Chebyshev('b1', N1, interval=int1, dealias=dealias) return de.Compound(name, (b0, b1), dealias=dealias)
def DoubleLaguerre(name, N, interval=(-1,1), dealias=1): N0 = int(N // 2) N1 = N - N0 L = interval[1] - interval[0] C = (interval[0] + interval[1]) / 2 int0 = (C, C + L/2) int1 = (C, C - L/2) b0 = de.Chebyshev('b0', N0, interval=int0, dealias=dealias) b1 = de.Chebyshev('b1', N1, interval=int1, dealias=dealias) return de.Compound(name, (b0, b1), dealias=dealias)
def ChebLag(name, N, edge=0.0, stretch=1.0, cwidth=1.0, dealias=1): b1 = de.Chebyshev('b1', int(N // 2), interval=(edge, edge + cwidth), dealias=dealias) b2 = de.Laguerre('b2', int(N // 2), edge=edge + cwidth, stretch=stretch, dealias=dealias) return de.Compound(name, (b1, b2), dealias=dealias)
def DoubleLaguerre(name, N, center=0.0, stretch=1.0, dealias=1): b0 = de.Laguerre('b0', int(N // 2), edge=center, stretch=-stretch, dealias=dealias) b1 = de.Laguerre('b1', int(N // 2), edge=center, stretch=stretch, dealias=dealias) return de.Compound(name, (b0, b1), dealias=dealias)
def LCCL(name, N, center=0.0, stretch=1.0, cwidth=1.0, dealias=1): b1 = de.Laguerre('b1', int(N // 4), edge=center - cwidth, stretch=-stretch, dealias=dealias) b2 = de.Chebyshev('b2', int(N // 4), interval=(center - cwidth, center), dealias=dealias) b3 = de.Chebyshev('b3', int(N // 4), interval=(center, center + cwidth), dealias=dealias) b4 = de.Laguerre('b4', int(N // 4), edge=center + cwidth, stretch=stretch, dealias=dealias) return de.Compound(name, (b1, b2, b3, b4), dealias=dealias)
def build_LHS(Nz, bw, format, entry_cutoff=0): # Parameters dt = 1e-3 kx = 50 * np.pi sigma = 1 ts = de.timesteppers.RK222 # Create bases and domain z1 = de.Chebyshev('z', Nz, interval=(-1, 1), dealias=3 / 2) z2 = de.Chebyshev('z', Nz, interval=(1, 2), dealias=3 / 2) z3 = de.Chebyshev('z', Nz, interval=(2, 3), dealias=3 / 2) z_basis = de.Compound('z', [z1, z2, z3]) domain = de.Domain([z_basis], grid_dtype=np.complex128) # 2D Boussinesq hydrodynamics problem = de.IVP(domain, variables=['T', 'Tz'], ncc_cutoff=0, max_ncc_terms=bw, entry_cutoff=entry_cutoff) problem.meta[:]['z']['dirichlet'] = True problem.parameters['kx'] = kx problem.parameters['sigma'] = sigma problem.substitutions['kappa'] = "exp(-(z-1)**2 / 2 / sigma**2)" problem.substitutions['dx(A)'] = "1j*kx*A" problem.add_equation("dt(T) - dx(kappa*dx(T)) - dz(kappa*Tz) = 0") problem.add_equation("Tz - dz(T) = 0") problem.add_bc("left(T) = 0") problem.add_bc("right(T) = 0") # Build solver solver = problem.build_solver(ts) # Step solver to form pencil LHS for i in range(1): solver.step(dt) return solver, solver.pencils[0].LHS.asformat(format)
def erf_tanh_compound(nx, intervals, center, width, fig_name='erf_tanh_compound.png'): x_basis_list = [] for i in range(len(nx)): print('sub interval {} : {} (nx={})'.format(i, intervals[i], nx[i])) x_basis = de.Chebyshev('x', nx[i], interval=intervals[i], dealias=3 / 2) x_basis_list.append(x_basis) x_basis = de.Compound('x', tuple(x_basis_list), dealias=3 / 2) domain = de.Domain([x_basis]) make_plots(domain, fig_name=fig_name, intervals=intervals, nx_intervals=np.cumsum(nx))
def basis_from_basis(basis, factor): """duplicates input basis with number of modes multiplied by input factor. the new number of modes will be cast to an integer inputs ------ basis : a dedalus basis factor : a float that will multiply the grid size by basis """ basis_type = basis.__class__.__name__ n_hi = int(basis.base_grid_size * factor) if type(basis) == de.Compound: sub_bases = [] for sub_basis in basis.subbases: sub_basis_type = sub_basis.__class__.__name__ try: nb = bases_register[sub_basis_type]( basis.name, n_hi, interval=sub_basis.interval) except KeyError: raise KeyError( "Don't know how to make a basis of type {}".format( basis_type)) sub_bases.append(nb) new_basis = de.Compound(basis.name, tuple(sub_bases)) else: try: new_basis = bases_register[basis_type](basis.name, n_hi, interval=basis.interval) except KeyError: raise KeyError( "Don't know how to make a basis of type {}".format(basis_type)) return new_basis
Rayleigh = 1e10 * 8 Prandtl = 1. nu = 1 / np.sqrt(Rayleigh / Prandtl) kappa = 1 / np.sqrt(Rayleigh * Prandtl) S = 100 T_top = -200 N2 = np.abs(S * T_top * 2) f = np.sqrt(N2) / (2 * np.pi) N = int(256) # Create bases and domain z_basis_conv1 = de.Chebyshev('z', int(N / 2), interval=(0, z_match)) z_basis_rad1 = de.Chebyshev('z', int(N), interval=(z_match, Lz)) z_basis1 = de.Compound('z', [z_basis_conv1, z_basis_rad1]) domain1 = de.Domain([z_basis1], grid_dtype=np.complex128, comm=MPI.COMM_SELF) int_field = domain1.new_field() u_field = domain1.new_field() ratio = [] for k in range(1, 21): data = pickle.load(open('eigenvalues/eigenvalue_data_k%i.pkl' % k, 'rb')) u = data['u'] w = data['w'] freq = data['values'] ratio = [] for i in range(u.shape[0]):
def __init__(self, atmosphere, resolution, aspect, mesh=None, dealias=3/2, comm=MPI.COMM_WORLD, dtype=np.float64): """ Initializes a 2- or 3D domain. Horizontal directions (x, y) are Fourier decompositions, Vertical direction is either a Chebyshev (if nz, Lz are integers) or a compound Chebyshev (if nz, Lz are lists) domain. Parameters ---------- All parameters match class attributes, as described in the class docstring. """ self.atmosphere = atmosphere self.resolution = resolution self.aspect = aspect self.dimensions = len(self.resolution) self.mesh = mesh self.dealias = dealias self.dtype = dtype self.comm = comm #setup horizontal directions L_horiz = self.aspect*self.atmosphere.atmo_params['Lz'] self.bases = [] if self.dimensions >= 2: x_basis = de.Fourier('x', self.resolution[1], interval=(-L_horiz/2, L_horiz/2), dealias=dealias) self.bases += [x_basis] if self.dimensions == 3: y_basis = de.Fourier('y', self.resolution[2], interval=(-L_horiz/2, L_horiz/2), dealias=dealias) self.bases += [y_basis] #setup vertical direction if isinstance(self.resolution[0], list): Lz_int = 0 z_basis_list = [] for Lz_i, nz_i in zip(self.atmosphere.atmo_params['Lz_list'], self.resolution[0]): Lz_top = Lz_i + Lz_int z_basis = de.Chebyshev('z', nz_i, interval=[Lz_int, Lz_top], dealias=dealias) z_basis_list.append(z_basis) Lz_int = Lz_top self.Lz = Lz_int self.nz = np.sum(nz) self.Lz_list = Lz self.nz_list = nz z_basis = de.Compound('z', tuple(z_basis_list), dealias=dealias) else: z_basis = de.Chebyshev('z', self.resolution[0], interval=(0, self.atmosphere.atmo_params['Lz']), dealias=dealias) self.Lz_list = None self.nz_list = None #create domain self.bases += [z_basis] self.domain = de.Domain(self.bases, grid_dtype=dtype, mesh=mesh, comm=comm) #store grid data if self.dimensions >= 2: self.x = self.domain.grid(0) self.x_de = self.domain.grid(0, scales=dealias) else: self.x, self.x_de = None, None if self.dimensions == 3: self.y = self.domain.grid(1) self.y_de = self.domain.grid(1, scales=dealias) else: self.y, self.y_de = None, None self.z = self.domain.grid(-1) self.z_de = self.domain.grid(-1, scales=dealias) self.atmosphere.build_atmosphere(self)
def solve_hires(self, tol=1e-10): old_evp = self.EVP old_d = old_evp.domain old_x = old_d.bases[0] old_x_grid = old_d.grid(0, scales=old_d.dealias) if type(old_x) == de.Compound: bases = [] for basis in old_x.subbases: old_x_type = basis.__class__.__name__ n_hi = int(basis.base_grid_size * self.factor) if old_x_type == "Chebyshev": x = de.Chebyshev(basis.name, n_hi, interval=basis.interval) elif old_x_type == "Fourier": x = de.Fourier(basis.name, n_hi, interval=basis.interval) else: raise ValueError( "Don't know how to make a basis of type {}".format( old_x_type)) bases.append(x) x = de.Compound(old_x.name, tuple(bases)) else: old_x_type = old_x.__class__.__name__ n_hi = int(old_x.coeff_size * self.factor) if old_x_type == "Chebyshev": x = de.Chebyshev(old_x.name, n_hi, interval=old_x.interval) elif old_x_type == "Fourier": x = de.Fourier(old_x.name, n_hi, interval=old_x.interval) else: raise ValueError( "Don't know how to make a basis of type {}".format( old_x_type)) d = de.Domain([x], comm=old_d.dist.comm) self.EVP_hires = de.EVP(d, old_evp.variables, old_evp.eigenvalue, tolerance=tol) x_grid = d.grid(0, scales=d.dealias) for k, v in old_evp.substitutions.items(): self.EVP_hires.substitutions[k] = v for k, v in old_evp.parameters.items(): if type(v) == Field: #NCCs new_field = d.new_field() v.set_scales(self.factor, keep_data=True) new_field['g'] = v['g'] self.EVP_hires.parameters[k] = new_field else: #scalars self.EVP_hires.parameters[k] = v for e in old_evp.equations: self.EVP_hires.add_equation(e['raw_equation']) try: for b in old_evp.boundary_conditions: self.EVP_hires.add_bc(b['raw_equation']) except AttributeError: # after version befc23584fea, Dedalus no longer # distingishes BCs from other equations pass solver = self.EVP_hires.build_solver() if self.sparse: solver.solve_sparse(solver.pencils[self.pencil], N=10, target=0, rebuild_coeffs=True) else: solver.solve_dense(solver.pencils[self.pencil], rebuild_coeffs=True) self.evalues_hires = solver.eigenvalues
logger.info(r_bot) logger.info(r_top) N = 256 r_int1 = 0.5 r_int2 = 0.8 r_int3 = r_top #r_int3 = 0.95 # Create bases and domain r_basis1 = de.Chebyshev('r', 2 * N, interval=(r_bot, r_int1)) r_basis2 = de.Chebyshev('r', N, interval=(r_int1, r_int2)) r_basis3 = de.Chebyshev('r', N, interval=(r_int2, r_int3)) r_basis = de.Compound('r', [r_basis1, r_basis2, r_basis3]) domain = de.Domain([r_basis], grid_dtype=np.float64, comm=MPI.COMM_SELF) r_d = domain.grid(0) def dedalus_interp(array): field = domain.new_field() interp = interpolate.interp1d(r / r[-1], array, kind='cubic') field['g'] = interp(r_d) return field rho0 = dedalus_interp(rho) g = dedalus_interp(g) Gamma1 = dedalus_interp(Gamma_1)
if not os.path.isdir('k%i' %k): os.mkdir('k%i' %k) MPI.COMM_WORLD.Barrier() # want f_min(k) and f_max(k) f_min = 0.5*k**(3/4) f_max = 1*k**(3/4) f_list = np.exp(np.linspace(np.log(f_min), np.log(f_max), num=100)) logger.info(f_list) N = int(512) # Create bases and domain z_basis_conv = de.Chebyshev('z', int(N), interval=(0,z_match)) z_basis_rad = de.Chebyshev('z', int(N/2),interval=(z_match,Lz)) z_basis = de.Compound('z',[z_basis_conv,z_basis_rad], dealias=3/2) domain = de.Domain([z_basis], grid_dtype=np.complex128, comm=MPI.COMM_SELF) T0 = domain.new_field() T0.set_scales(1024*3/2/N) data = np.loadtxt('T.dat') T0['g'] = data[1,:] T0.set_scales(1) z = domain.grid(0) T0z = T0.differentiate(0) T0z.set_scales(1) T0z['g'] *= 0.5*(1 + np.tanh( (z - 0.4)/0.01 ))
def run_salty_boussinesq_vpf(simname, ϵ, dt, comm, logger): ν = 1e-2 κ = 1e-2 γ = 1e-2 μ = 1e-2 M = .2 N = 0 L = 1 β = 4 / 2.6482282 #ϵ = #np.sqrt(1e-4) η = (β * ϵ)**2 / ν α = (5 / 6) * (L / κ) * ϵ nx = 128 nz = 256 #dt = float(sys.argv[2])#2e-4 timestepper = 'SBDF2' #simname = f'salty-boussinesq-melting-vpf-tangent-{timestepper}-{ϵ:.0e}-conserved-passive' flt.makedir(f'{savedir}/frames/{simname}') tend = 10 save_step = 1 save_freq = round(save_step / dt) xbasis = de.Fourier('x', nx, interval=(0, 4), dealias=3 / 2) zb0 = de.Chebyshev('z0', 32, interval=(0, 10 * ϵ), dealias=3 / 2) zb1 = de.Chebyshev('z1', 64, interval=(10 * ϵ, 1 - 10 * ϵ), dealias=3 / 2) zb2 = de.Chebyshev('z2', 32, interval=(1 - 10 * ϵ, 1), dealias=3 / 2) zbasis = de.Compound('z', [zb0, zb1, zb2]) domain = de.Domain([xbasis, zbasis], grid_dtype=np.float64, comm=comm) flt.save_domain(f'{savedir}/domain-{simname}.h5', domain) x, z = domain.grids(scales=domain.dealias) xx, zz = x + 0 * z, 0 * x + z xc = xx dims = range(1, 3) # Define GeneralFunction subclass to handle parities GeneralFunction = de.operators.GeneralFunction class HorizontalFunction(GeneralFunction): def __init__( self, domain, layout, func=None, args=[], kw={}, out=None, ): super().__init__( domain, layout, func=func, args=args, kw=kw, out=out, ) def meta_constant(self, axis): if axis == 1 or axis == 'z': return True else: return False refname = 'salty-boussinesq-melting-tangent-conserved-passive' reffile = glob.glob(f'{savedir}/interface-{refname}/*.h5')[0] t0s, x0s = flt.load_data(reffile, 'sim_time', 'x/1.0', group='scales') h0s, ht0s = flt.load_data(reffile, 'h', 'ht', group='tasks') from scipy.interpolate import RectBivariateSpline h0s, ht0s = np.squeeze(h0s), np.squeeze(ht0s) hspline = RectBivariateSpline(t0s, x0s, h0s) htspline = RectBivariateSpline(t0s, x0s, ht0s) def h_func(*args): return hspline(args[0].value, args[1].data[:, 0]).T def ht_func(*args): return htspline(args[0].value, args[1].data[:, 0]).T def h_op(*args, domain=domain, h_func=h_func): return HorizontalFunction(domain, layout='g', func=h_func, args=args) def ht_op(*args, domain=domain, ht_func=ht_func): return HorizontalFunction(domain, layout='g', func=ht_func, args=args) de.operators.parseables['h_op'] = h_op de.operators.parseables['ht_op'] = ht_op problem = de.IVP(domain, variables=[ 'u11', 'u12', 'u21', 'u22', 'p1', 'q1', 'p2', 'q2', 'T1', 'T1_2', 'T2', 'T2_2', 'C1', 'C1_2', 'C2', 'C2_2', 'f1', 'f1_2', 'f2', 'f2_2', 'E', 'S' ]) problem.meta[:]['z']['dirichlet'] = True problem.meta['E', 'S']['x', 'z']['constant'] = True problem.parameters['ν'] = ν problem.parameters['κ'] = κ problem.parameters['γ'] = γ problem.parameters['μ'] = μ problem.parameters['M'] = M problem.parameters['N'] = N problem.parameters['δ'] = 1e-4 problem.parameters['ε'] = ϵ problem.parameters['L'] = L problem.parameters['η'] = η problem.parameters['α'] = α As = [4] * 5 for i in range(len(As)): problem.parameters[f'A{i+1}'] = As[i] problem.substitutions['h'] = 'h_op(t,x)' problem.substitutions['ht'] = 'ht_op(t,x)' problem.substitutions['d_1(A)'] = 'dx(A)' problem.substitutions['d_2(A)'] = 'dz(A)' problem.substitutions['T1_1'] = 'd_1(T1)' problem.substitutions['T2_1'] = 'd_1(T2)' problem.substitutions['C1_1'] = 'd_1(C1)' problem.substitutions['C2_1'] = 'd_1(C2)' problem.substitutions['f1_1'] = 'd_1(f1)' problem.substitutions['f2_1'] = 'd_1(f2)' problem.substitutions['hx'] = 'd_1(h)' problem.substitutions['angle'] = 'sqrt(1 + hx**2)' problem.substitutions['omz1'] = 'sqrt(1 + (hx)**2)/(2-h)' problem.substitutions['omz2'] = 'sqrt(1 + (hx)**2)/h' problem.substitutions['curvature'] = 'dx(hx)/angle**3' problem.substitutions['xc'] = 'x' problem.substitutions['zc1'] = 'h + (2-h)*z' problem.substitutions['zc2'] = 'h*z' problem.substitutions['d_0(A)'] = '0' for l in [1, 2]: problem.substitutions[f'Kdet{l}'] = Kdet[l] for i in range(3): for j in range(3): problem.substitutions[f'J{l}{i}{j}'] = J.get((l, i, j), '0') problem.substitutions[f'K{l}{i}{j}'] = K.get((l, i, j), '0') problem.substitutions[f'g{l}{i}{j}'] = g.get((l, i, j), '0') for k in range(3): problem.substitutions[f'G{l}{i}_{j}{k}'] = G.get( (l, i, j, k), '0') for i in dims: for j in dims: problem.substitutions[ f'cd_{i}_u{l}{j}'] = f'd_{i}(u{l}{j})' + ' + '.join( [''] + [ f'G{l}{j}_{k}{i}*u{l}{k}' for k in dims if G.get((l, j, k, i), 0) ]) problem.substitutions[f'div{l}'] = f'cd_1_u{l}1 + cd_2_u{l}2' problem.substitutions[f'vorticity{l}'] = f'Kdet{l}*' + '({})'.format( ' + '.join([ f'{eps[i,j]}*g{l}{i}{k}*cd_{k}_u{l}{j}' for k in dims for j in dims for i in dims if eps.get((i, j), 0) ])) for j in dims: problem.substitutions[ f'curl_vorticity{l}{j}'] = f'(1/Kdet{l})*' + '({})'.format( ' + '.join(f'{eps[i,j]}*d_{i}(q{l})' for i in dims if eps.get((i, j), 0))) for k in dims: problem.substitutions[ f'q_cross_u{l}{k}'] = f'Kdet{l}*q{l}*' + '({})'.format( ' + '.join(f'{eps[i,j]}*g{l}{i}{k}*u{l}{j}' for i in dims for j in dims if eps.get((i, j), 0))) for j in dims: problem.substitutions[f'grad_p{l}{j}'] = ' + '.join( [f'g{l}{i}{j}*d_{i}(p{l})' for i in dims]) for j in dims: problem.substitutions[f'f{l}{j}'] = f'(T{l}+N*C{l})*J{l}2{j}' for j in dims: problem.substitutions[f'adv_u{l}{j}'] = ' + '.join([ f'J{l}0{i}*d_{i}(u{l}{j})' for i in dims if J.get((l, 0, i), 0) ] + [ f'J{l}0{i}*u{l}{k}*G{l}{j}_{k}{i}' for i in range(3) for k in dims if J.get((l, 0, i), 0) and G.get((l, j, k, i)) ]) for i in dims: problem.substitutions[ f'dτu{l}{i}'] = f'- adv_u{l}{i} + ν*curl_vorticity{l}{i} - grad_p{l}{i} + q_cross_u{l}{i} - (f{l}/η)*u{l}{i} + f{l}{i}' for i in dims: problem.substitutions[f'dtu{l}{i}'] = f'dτu{l}{i} + adv_u{l}{i}' problem.substitutions[f'lapT{l}'] = '{} - ({})'.format( ' + '.join( [f'g{l}{i}{j}*d_{i}(T{l}_{j})' for i in dims for j in dims]), ' + '.join([ f'g{l}{i}{j}*T{l}_{k}*G{l}{k}_{i}{j}' for i in dims for j in dims for k in dims if G.get((l, k, i, j)) ])) problem.substitutions[f'lapC{l}'] = '{} - ({})'.format( ' + '.join( [f'g{l}{i}{j}*d_{i}(C{l}_{j})' for i in dims for j in dims]), ' + '.join([ f'g{l}{i}{j}*C{l}_{k}*G{l}{k}_{i}{j}' for i in dims for j in dims for k in dims if G.get((l, k, i, j)) ])) problem.substitutions[f'lapf{l}'] = '{} - ({})'.format( ' + '.join( [f'g{l}{i}{j}*d_{i}(f{l}_{j})' for i in dims for j in dims]), ' + '.join([ f'g{l}{i}{j}*f{l}_{k}*G{l}{k}_{i}{j}' for i in dims for j in dims for k in dims if G.get((l, k, i, j)) ])) problem.substitutions[f'udotT{l}'] = f'u{l}1*T{l}_1 + u{l}2*T{l}_2' problem.substitutions[f'udotC{l}'] = f'u{l}1*C{l}_1 + u{l}2*C{l}_2' problem.substitutions[ f'ndotT{l}'] = f'left(( g{l}21*T{l}_1 + g{l}22*T{l}_2)/omz{l})' problem.substitutions[ f'ndotf{l}'] = f'left(( g{l}21*f{l}_1 + g{l}22*f{l}_2)/omz{l})' problem.substitutions[ f'f_flux{l}'] = f'-ε**(-2)*f{l}*(1-f{l})*(γ*(1-2*f{l}) + ε*(T{l}+M*C{l}))' problem.substitutions[f'dtf{l}'] = f'(1/α)*(γ*lapf{l} + f_flux{l})' problem.substitutions[f'dτf{l}'] = f'dtf{l} - ' + '({})'.format( ' + '.join( [f'J{l}0{i}*f{l}_{i}' for i in dims if J.get((l, 0, i))])) problem.substitutions[f'gradfdotgradC{l}'] = ' + '.join( [f'g{l}{i}{j}*f{l}_{i}*C{l}_{j}' for i in dims for j in dims]) problem.substitutions[ f'dτT{l}'] = 'κ*({}) - ({}) + ({}) - ({})'.format( f'lapT{l}', f'udotT{l}', f'L*dtf{l}', ' + '.join( [f'J{l}0{i}*T{l}_{i}' for i in dims if J.get((l, 0, i))])) problem.substitutions[ f'dτC{l}'] = 'μ*({}) - ({}) + ({}) - ({})'.format( f'lapC{l}', f'udotC{l}', f'(dtf{l}*C{l} - μ*gradfdotgradC{l})/(1-f{l}+δ)', ' + '.join( [f'J{l}0{i}*C{l}_{i}' for i in dims if J.get((l, 0, i))])) # problem.substitutions['dτh'] = ' - (1/2)*(left(dtf1/(J122*f1_2)) + right(dtf2/(J222*f2_2)))' # # Cartesian quantities # problem.substitutions[f'ux{l}'] = ' + '.join(f'u{l}{j}*K{l}{j}1' for j in dims if K.get((l,j,1))) # problem.substitutions[f'uz{l}'] = ' + '.join(f'u{l}{j}*K{l}{j}2' for j in dims if K.get((l,j,2))) # problem.substitutions[f'kenergy{l}'] = f'0.5*(ux{l}**2 + uz{l}**2)' # problem.substitutions[f'pr{l}'] = f'p{l} - kenergy{l}' # problem.substitutions[f'dxc{l}(A)'] = ' + '.join(f'J{l}1{j}*d_{j}(A)' for j in dims if J.get((l,1,j))) # problem.substitutions[f'dzc{l}(A)'] = ' + '.join(f'J{l}2{j}*d_{j}(A)' for j in dims if J.get((l,2,j))) # problem.substitutions[f'dtux{l}'] = f'- dxc{l}(p{l}) - ν*dzc{l}(q{l}) + q{l}*uz{l}' # problem.substitutions[f'dtuz{l}'] = f'- dzc{l}(p{l}) + ν*dxc{l}(q{l}) - q{l}*ux{l}' # problem.substitutions[f'dtT1'] = f'- dzc{l}(p{l}) + ν*dxc{l}(q{l}) - q{l}*ux{l}' for l in [1, 2]: problem.add_equation( f' A1*(d_1(u{l}1) + d_2(u{l}2)) = A1*(d_1(u{l}1) + d_2(u{l}2)) - div{l}' ) problem.add_equation( f'q{l} + A2*(d_2(u{l}1) - d_1(u{l}2)) = A2*(d_2(u{l}1) - d_1(u{l}2)) + vorticity{l}' ) problem.add_equation( f'dt(u{l}1) + A3*d_1(p{l}) + A4*ν*d_2(q{l}) = A3*d_1(p{l}) + A4*ν*d_2(q{l}) + dτu{l}1' ) problem.add_equation( f'dt(u{l}2) + A3*d_2(p{l}) - A4*ν*d_1(q{l}) - T2 = - T2 + A3*d_2(p{l}) - A4*ν*d_1(q{l}) + dτu{l}2' ) problem.add_equation(f'T{l}_2 - d_2(T{l}) = 0') problem.add_equation( f'dt(T{l}) - κ*A5*(d_1(T{l}_1) + d_2(T{l}_2)) = - κ*A5*(d_1(T{l}_1) + d_2(T{l}_2)) + dτT{l}' ) problem.add_equation(f'C{l}_2 - d_2(C{l}) = 0') problem.add_equation( f'dt(C{l}) - μ*A5*(d_1(C{l}_1) + d_2(C{l}_2)) = - μ*A5*(d_1(C{l}_1) + d_2(C{l}_2)) + dτC{l}' ) problem.add_equation(f'f{l}_2 - d_2(f{l}) = 0') problem.add_equation( f'α*dt(f{l})-γ*A5*(d_1(f{l}_1) + d_2(f{l}_2)) = - γ*A5*(d_1(f{l}_1) + d_2(f{l}_2)) + α*dτf{l}' ) # problem.add_equation('ht - (κ/L)*(right(T2_2) - right(T1_2)) = - (κ/L)*(right(T2_2) - right(T1_2)) + dτh') # problem.add_equation('ht = -100*(left(f1) - .5)') # problem.add_equation('dt(h) - ht = 0') problem.add_equation( 'E = integ(Kdet1*(T1 + L*(1-f1)) + Kdet2*(T2 + L*(1-f2)))') problem.add_equation('S = integ(Kdet1*(1-f1)*C1 + Kdet2*(1-f2)*C2)') problem.add_bc('right(u11) = 0') problem.add_bc('right(u12) = 0', condition='nx != 0') # problem.add_bc('right(T1) = -1') problem.add_bc('right(T1_2) = 0') problem.add_bc('right(C1_2) = 0') problem.add_bc('right(f1_2) = 0') problem.add_bc('left(u11) - right(u21) = 0') problem.add_bc( 'left(u12) - right(u22) = left((h-1)*u12) + right((h-1)*u22)') problem.add_bc('left(p1) - right(p2) = 0') problem.add_bc('left(q1) - right(q2) = 0') problem.add_bc('right(T2) - left(T1) = 0') problem.add_bc('right(C2) - left(C1) = 0') problem.add_bc('right(f2) - left(f1) = 0') # problem.add_bc('right(f2) = 0.5') problem.add_bc( 'left(T1_2) - right(T2_2) = left((1-h)*T1_2) + right((1-h)*T2_2)') problem.add_bc( 'left(C1_2) - right(C2_2) = left((1-h)*C1_2) + right((1-h)*C2_2)') problem.add_bc( 'left(f1_2) - right(f2_2) = left((1-h)*f1_2) + right((1-h)*f2_2)') problem.add_bc('left(p2) = 0', condition='nx == 0') problem.add_bc('left(u21) = 0') problem.add_bc('left(u22) = 0') problem.add_bc('left(T2_2) = 0') # problem.add_bc('left(T2) = 1') problem.add_bc('left(C2_2) = 0') problem.add_bc('left(f2_2) = 0') solver = problem.build_solver(eval(f'de.timesteppers.{timestepper}')) solver.stop_sim_time = tend fields = {fname: solver.state[fname] for fname in problem.variables} for fname, field in fields.items(): field.set_scales(domain.dealias) hop, htop = solver.evaluator.vars['h'], solver.evaluator.vars['ht'] h, ht = hop.evaluate(), htop.evaluate() T1, T2, C1, C2, f1, f2, E, S = [ fields[name] for name in ['T1', 'T2', 'C1', 'C2', 'f1', 'f2', 'E', 'S'] ] xc = xx zc1 = h['g'] + (2 - h['g']) * zz zc2 = h['g'] * zz h['g'] = 1 T1['g'] = 1 - zc1 T2['g'] = 1 - zc2 + np.exp(-((xc - 2)**2 + (zc2 - .5)**2) * 5**2) T1.differentiate('z', out=fields['T1_2']) T2.differentiate('z', out=fields['T2_2']) C1['g'] = 0.05 + (1 - 0.05) * .5 * (1 - np.tanh(10 * (zc1 - .5))) C2['g'] = 0.05 + (1 - 0.05) * .5 * (1 - np.tanh(10 * (zc2 - .5))) C1.differentiate('z', out=fields['C1_2']) C2.differentiate('z', out=fields['C2_2']) zc1 = h['g'] + (2 - h['g']) * zz zc2 = h['g'] * zz f1['g'] = .5 * (1 + np.tanh( (1 / (2 * ϵ)) * (zc1 - h['g']) / np.sqrt(1 + d(h, 'x')**2)['g'])) f2['g'] = .5 * (1 + np.tanh( (1 / (2 * ϵ)) * (zc2 - h['g']) / np.sqrt(1 + d(h, 'x')**2)['g'])) f1.differentiate('z', out=fields['f1_2']) f2.differentiate('z', out=fields['f2_2']) E['g'] = (h * (T2 + L * (1 - f2)) + (2 - h) * (T1 + L * (1 - f1))).evaluate().integrate()['g'] S['g'] = (h * (1 - f2) * C2 + (2 - h) * (1 - f1) * C1).evaluate().integrate()['g'] analysis = solver.evaluator.add_file_handler( f'{savedir}/analysis-{simname}', iter=save_freq, max_writes=100, mode='overwrite') for task in problem.variables + ['h', 'ht', 'zc1', 'zc2']: analysis.add_task(task) while solver.ok: if solver.iteration % 100 == 0: logger.info(solver.iteration) if np.any(np.isnan(T2['g'])): break solver.step(dt) solver.step(dt)
def set_domain(self, nx=256, Lx=4, ny=256, Ly=4, nz=128, Lz=1, grid_dtype=np.float64, comm=MPI.COMM_WORLD, mesh=None): """ Here the dedalus domain is created for the equation set Inputs: nx, ny, nz - Number of grid points in the x, y, z directions Lx, Ly, Lz - Physical size of the x, y, z direction grid_dtype - Datatype to use for grid points in the problem comm - Comm group over which to solve. Use COMM_SELF for EVP mesh - The processor mesh over which the problem is solved. """ # the naming conventions here force cartesian, generalize to spheres etc. make sense? self.mesh = mesh if not isinstance(nz, list): nz = [nz] if not isinstance(Lz, list): Lz = [Lz] if len(nz) > 1: logger.info("Setting compound basis in vertical (z) direction") z_basis_list = [] Lz_interface = 0. for iz, nz_i in enumerate(nz): Lz_top = Lz[iz] + Lz_interface z_basis = de.Chebyshev('z', nz_i, interval=[Lz_interface, Lz_top], dealias=3 / 2) z_basis_list.append(z_basis) Lz_interface = Lz_top self.compound = True z_basis = de.Compound('z', tuple(z_basis_list), dealias=3 / 2) elif len(nz) == 1: logger.info( "Setting single chebyshev basis in vertical (z) direction") z_basis = de.Chebyshev('z', nz[0], interval=[0, Lz[0]], dealias=3 / 2) if self.dimensions > 1: x_basis = de.Fourier('x', nx, interval=[0., Lx], dealias=3 / 2) if self.dimensions > 2: y_basis = de.Fourier('y', ny, interval=[0., Ly], dealias=3 / 2) if self.dimensions == 1: bases = [z_basis] elif self.dimensions == 2: bases = [x_basis, z_basis] elif self.dimensions == 3: bases = [x_basis, y_basis, z_basis] else: logger.error('>3 dimensions not implemented') self.domain = de.Domain(bases, grid_dtype=grid_dtype, comm=comm, mesh=mesh) self.z = self.domain.grid(-1) # need to access globally-sized z-basis self.Lz = self.domain.bases[-1].interval[1] - self.domain.bases[ -1].interval[0] # global size of Lz self.nz = self.domain.bases[-1].coeff_size self.z_dealias = self.domain.grid(axis=-1, scales=self.domain.dealias) if self.dimensions == 1: self.Lx, self.Ly = 0, 0 if self.dimensions > 1: self.x = self.domain.grid(0) self.Lx = self.domain.bases[0].interval[1] - self.domain.bases[ 0].interval[0] # global size of Lx self.nx = self.domain.bases[0].coeff_size self.delta_x = self.Lx / self.nx if self.dimensions > 2: self.y = self.domain.grid(1) self.Ly = self.domain.bases[1].interval[1] - self.domain.bases[ 0].interval[0] # global size of Lx self.ny = self.domain.bases[1].coeff_size self.delta_y = self.Ly / self.ny
from dedalus import public as de import numpy as np import matplotlib.pyplot as plt de.logging_setup.rootlogger.setLevel('ERROR') xbasis = de.Chebyshev('x', 32, interval=(0, 5), dealias=3 / 2) grid_normal = xbasis.grid(scale=1) grid_dealias = xbasis.grid(scale=3 / 2) plt.figure(figsize=(10, 1)) plt.plot(grid_normal, np.zeros_like(grid_normal) + 1, 'o', markersize=5) plt.plot(grid_dealias, np.zeros_like(grid_dealias) - 1, 'o', markersize=5) plt.ylim([-2, 2]) plt.gca().yaxis.set_ticks([]) xb1 = de.Chebyshev('x1', 16, interval=(0, 2)) xb2 = de.Chebyshev('x2', 32, interval=(2, 8)) xb3 = de.Chebyshev('x3', 16, interval=(8, 10)) xbasis = de.Compound('x', (xb1, xb2, xb3)) compound_grid = xbasis.grid(scale=1) plt.figure(figsize=(10, 1)) plt.plot(compound_grid, np.zeros_like(compound_grid), 'o', markersize=5) plt.gca().yaxis.set_ticks([])
Rayleigh = 2e8*8 Prandtl = 1. nu = 1/np.sqrt(Rayleigh/Prandtl) kappa = 1/np.sqrt(Rayleigh*Prandtl) S = 100 T_top = -60 N2 = np.abs(S*T_top*2) f = np.sqrt(N2)/(2*np.pi) N = int(256) # Create bases and domain z_basis_conv1 = de.Chebyshev('z', int(N/2), interval=(0,z_match)) z_basis_rad1 = de.Chebyshev('z', int(N),interval=(z_match,Lz)) z_basis1 = de.Compound('z',[z_basis_conv1,z_basis_rad1]) domain1 = de.Domain([z_basis1], grid_dtype=np.complex128, comm=MPI.COMM_SELF) z_basis_conv2 = de.Chebyshev('z', int(3*N/4), interval=(0,z_match)) z_basis_rad2 = de.Chebyshev('z', int(3*N/2),interval=(z_match,Lz)) z_basis2 = de.Compound('z',[z_basis_conv2,z_basis_rad2]) domain2 = de.Domain([z_basis2], grid_dtype=np.complex128, comm=MPI.COMM_SELF) z_basis_conv_old = de.Chebyshev('z', int(N), interval=(0,z_match)) z_basis_rad_old = de.Chebyshev('z', int(N/2),interval=(z_match,Lz)) z_basis_old = de.Compound('z',[z_basis_conv_old,z_basis_rad_old]) domain_old = de.Domain([z_basis_old], grid_dtype=np.complex128, comm=MPI.COMM_SELF) def build_solver(domain, domain_old, N, N_old, k): # We have N >= N_old # but N/2 < N_old
rayleigh_benard.add_bc('right(b) = 0') rayleigh_benard.add_bc('left(w) = 0') rayleigh_benard.add_bc('right(w) = 0') if stress_free: rayleigh_benard.add_bc('left(uz) = 0') rayleigh_benard.add_bc('right(uz) = 0') else: rayleigh_benard.add_bc('left(u) = 0') rayleigh_benard.add_bc('right(u) = 0') return rayleigh_benard @pytest.mark.parametrize('z', [ de.Chebyshev('z', 16, interval=(0, 1)), de.Compound('z', (de.Chebyshev( 'z', 10, interval=(0, 0.5)), de.Chebyshev('z', 10, interval=(0.5, 1)))) ]) @pytest.mark.parametrize('sparse', [True, False]) def test_rbc_growth(z, sparse): d = de.Domain([z]) rayleigh_benard = rbc_problem('EVP', d) EP = eig.Eigenproblem(rayleigh_benard) growth, index, freq = EP.growth_rate(sparse=sparse) assert np.allclose((growth, freq), (0.0018125573647729994, 0.)) @pytest.mark.parametrize('z', [de.Chebyshev('z', 16, interval=(0, 1))]) def test_rbc_output(z):
def _set_domain(self, nx=256, Lx=4, ny=256, Ly=4, nz=128, Lz=1, grid_dtype=np.float64, comm=MPI.COMM_WORLD, mesh=None): # the naming conventions here force cartesian, generalize to spheres etc. make sense? self.mesh=mesh if not isinstance(nz, list): nz = [nz] if not isinstance(Lz, list): Lz = [Lz] if len(nz)>1: logger.info("Setting compound basis in vertical (z) direction") z_basis_list = [] Lz_interface = 0. for iz, nz_i in enumerate(nz): Lz_top = Lz[iz]+Lz_interface z_basis = de.Chebyshev('z', nz_i, interval=[Lz_interface, Lz_top], dealias=3/2) z_basis_list.append(z_basis) Lz_interface = Lz_top self.compound = True z_basis = de.Compound('z', tuple(z_basis_list), dealias=3/2) elif len(nz)==1: logger.info("Setting single chebyshev basis in vertical (z) direction") self.compound = False z_basis = de.Chebyshev('z', nz[0], interval=[0, Lz[0]], dealias=3/2) if self.dimensions > 1: x_basis = de.Fourier( 'x', nx, interval=[0., Lx], dealias=3/2) if self.dimensions > 2: y_basis = de.Fourier( 'y', ny, interval=[0., Ly], dealias=3/2) if self.dimensions == 1: bases = [z_basis] elif self.dimensions == 2: bases = [x_basis, z_basis] elif self.dimensions == 3: bases = [x_basis, y_basis, z_basis] else: logger.error('>3 dimensions not implemented') self.domain = de.Domain(bases, grid_dtype=grid_dtype, comm=comm, mesh=mesh) self.z = self.domain.grid(-1) # need to access globally-sized z-basis self.Lz = self.domain.bases[-1].interval[1] - self.domain.bases[-1].interval[0] # global size of Lz self.nz = self.domain.bases[-1].coeff_size self.z_dealias = self.domain.grid(axis=-1, scales=self.domain.dealias) if self.dimensions == 1: self.x, self.Lx, self.nx, self.delta_x = None, 0, None, None self.y, self.Ly, self.ny, self.delta_y = None, 0, None, None if self.dimensions > 1: self.x = self.domain.grid(0) self.Lx = self.domain.bases[0].interval[1] - self.domain.bases[0].interval[0] # global size of Lx self.nx = self.domain.bases[0].coeff_size self.delta_x = self.Lx/self.nx if self.dimensions > 2: self.y = self.domain.grid(1) self.Ly = self.domain.bases[1].interval[1] - self.domain.bases[0].interval[0] # global size of Lx self.ny = self.domain.bases[1].coeff_size self.delta_y = self.Ly/self.ny
plt.close() plt.figure(figsize=(6, 1.5), dpi=100) plt.plot(grid_normal, 0 * grid_normal + 1, 'o', markersize=5) plt.plot(grid_dealias, 0 * grid_dealias - 1, 'o', markersize=5) plt.xlabel('x') plt.title('Chebyshev grid with scales 1 and 3/2') plt.ylim([-2, 2]) plt.gca().yaxis.set_ticks([]) plt.tight_layout() plt.savefig("fig/Chebyshev_grid_with_scales_1_and_1.5.png") # Compound bases xb1 = de.Chebyshev('x1', 16, interval=(0, 2)) xb2 = de.Chebyshev('x2', 32, interval=(2, 8)) xb3 = de.Chebyshev('x3', 16, interval=(8, 10)) xbasis = de.Compound( 'x', (xb1, xb2, xb3)) # Define compound bases by three individual bases compound_grid = xbasis.grid(scale=1) plt.close() plt.figure(figsize=(6, 1.5), dpi=100) plt.plot(compound_grid, 0 * compound_grid, 'o', markersize=5) plt.xlabel('x') plt.title('Compound Chebyshev grid') plt.gca().yaxis.set_ticks([]) plt.tight_layout() plt.savefig("fig/Compound_Chebyshev_grid.png") # Creating a domain xbasis = de.Fourier('x', 32, interval=(0, 2), dealias=3 / 2) # Periodic ybasis = de.Fourier('y', 32, interval=(0, 2), dealias=3 / 2)