示例#1
0
 def set_IVP(self, *args, ncc_cutoff=1e-10, **kwargs):
     """
     Constructs and initial value problem of the current object's equation set
     """
     self.problem_type = 'IVP'
     self.problem = de.IVP(self.domain, variables=self.variables, ncc_cutoff=ncc_cutoff)
     self.set_equations(*args, **kwargs)
示例#2
0
    def problem_setup(self, mu=-1):
        # Problem

        #variables: flowfield (u,v)(x,y), pressure p(x,y), vorticity w(x,y)

        self.problem = de.IVP(self.domain, variables=['u', 'v', 'w', 'p'])
        self.problem.parameters['a'] = mu
        self.problem.parameters['b'] = 0.5
        self.problem.parameters['Tau_0'] = self.T0
        self.problem.parameters['Tau_2'] = self.T2
        self.problem.parameters['S'] = -2.5

        #Incompressibility
        self.problem.add_equation("dx(u) + dy(v) = 0",
                                  condition="(nx!=0) or (ny!=0)")
        self.problem.add_equation("p = 0", condition="(nx==0) and (ny==0)")

        #dynamics (-S)*dx(u+v)
        self.problem.add_equation(
            "dt(u) + dx(p) + a*u - Tau_0*(d(u,x=2) + d(u,y=2)) + Tau_2*(d(u,x=4) + d(u,y=4)) = \
                                   -(1-S)*(u*dx(u) + v*dy(u)) + (-S/2)*dx(u*u+v*v) - b*(u*u+v*v)*u"
        )
        self.problem.add_equation(
            "dt(v) + dy(p) + a*v - Tau_0*(d(v,x=2) + d(v,y=2)) + Tau_2*(d(v,x=4) + d(v,y=4)) = \
                                   -(1-S)*(u*dx(v) + v*dy(v)) + (-S/2)*dy(u*u+v*v) - b*(u*u+v*v)*v"
        )
        # self.problem.add_equation("dt(u) + dx(p) + a*u - Tau_0*d(u,x=2) + Tau_2*d(u,x=4) = 0")
        # self.problem.add_equation("dt(v) + dy(p) + a*v - Tau_0*d(v,y=2) + Tau_2*d(v,y=4) = 0")

        #vorticity
        self.problem.add_equation("w - dx(v) + dy(u) = 0")
示例#3
0
    def build_solver(self):
        self.problem = de.IVP(self.domain,
                              variables=['u', 'v', 'w', 'uz', 'vz', 'wz', 'p'])
        self.problem.parameters['Re'] = self.Re
        self.problem.substitutions['ugrad(A, Az)'] = 'u*dx(A) + v*dy(A) + w*Az'
        self.problem.substitutions[
            'Lap(A, Az)'] = 'dx(dx(A)) + dy(dy(A)) + dz(Az)'

        self.problem.add_equation(
            "dt(u) + dx(p) - Lap(u, uz)/Re + w + z*dx(u) = ugrad(u,uz)")
        self.problem.add_equation(
            "dt(v) + dy(p) - Lap(v, vz)/Re + z*dx(v) = ugrad(v,vz)")
        self.problem.add_equation(
            "dt(w) + dz(p) - Lap(w, wz)/Re + z*dx(w) = ugrad(w,wz)")
        self.problem.add_equation("dx(u) + dy(v) + wz = 0")
        self.problem.add_equation("dz(u) + uz = 0")
        self.problem.add_equation("dz(v) + vz = 0")
        self.problem.add_equation("dz(w) + wz = 0")

        self.problem.add_bc("left(u) = 0")
        self.problem.add_bc("right(u) = 0")
        self.problem.add_bc("left(v) = 0")
        self.problem.add_bc("right(v) = 0")
        self.problem.add_bc("left(w) = 0")
        self.problem.add_bc("right(w) = 0", condition="(nx != 0) or (ny != 0)")
        self.problem.add_bc("left(p) = 0", condition="(nx == 0) and (ny == 0)")

        self.solver = self.problem.build_solver(de.timesteppers.RK443)
        logger.info('Solver built')
def serial_run(dt_fine, resolution, end_time):
    save_name = 'test'

    # Here we use parareal split function to create two communicators

    # Fine solver
    logger = logging.getLogger(__name__)
    xbasis_serial = de.Fourier('x', resolution, interval=(0, 5), dealias=1)
    domain_serial = de.Domain([xbasis_serial],
                              grid_dtype=np.float64,
                              comm=dedalus_comm)
    problem_serial = de.IVP(domain_serial, variables=['u'])
    problem_serial.parameters['a'] = a
    problem_serial.parameters['b'] = b
    problem_serial.add_equation("dt(u) - b*dx(dx(u)) = a*dx(u)")
    solver_serial = problem_serial.build_solver(de.timesteppers.RK111)

    # initial conditions
    x_serial = domain_serial.grid(0)
    u_serial = solver_serial.state['u']
    u_serial.set_scales(1)
    mu = 2.5
    sigma = 2
    u_serial['g'] = 100 / (np.sqrt(2 * np.pi * sigma**2)) * np.exp(
        -(x_serial - mu)**2 / (2 * sigma**2))

    for i in range(np.rint(end_time / dt_fine).astype(int)):
        solver_serial.step(dt_fine)

    return np.copy(u_serial['g'])
示例#5
0
def get_solver(setup_problem, XMAX, ZMAX, N_X, N_Z, T_F, KX, KZ, H, RHO0, G,
               A):
    # Bases and domain
    x_basis = de.Fourier('x', N_X, interval=(0, XMAX), dealias=3 / 2)
    z_basis = de.Chebyshev('z', N_Z, interval=(0, ZMAX), dealias=3 / 2)
    domain = de.Domain([x_basis, z_basis], np.float64)
    z = domain.grid(1)

    problem = de.IVP(domain, variables=['P', 'rho', 'ux', 'uz'])
    problem.meta['uz']['z']['dirichlet'] = True
    problem.parameters['L'] = XMAX
    problem.parameters['g'] = G
    problem.parameters['H'] = H
    problem.parameters['A'] = A
    problem.parameters['KX'] = KX
    problem.parameters['KZ'] = KZ
    problem.parameters['omega'] = get_omega(G, H, KX, KZ)

    # rho0 stratification
    rho0 = domain.new_field()
    rho0.meta['x']['constant'] = True
    rho0['g'] = RHO0 * np.exp(-z / H)
    problem.parameters['rho0'] = rho0

    setup_problem(problem, domain)

    # Build solver
    solver = problem.build_solver(de.timesteppers.RK443)
    solver.stop_sim_time = T_F
    solver.stop_wall_time = np.inf
    solver.stop_iteration = np.inf
    return solver, domain
示例#6
0
def mcwilliams_problem(domain, h=0.1, lx=1 / 4, ly=1 / 8, f=1, US=1 / 16):
    problem = de.IVP(domain, variables=['ψ', 'ψz'])

    problem.parameters['h'] = h
    problem.parameters['lx'] = lx
    problem.parameters['ly'] = ly
    problem.parameters['f'] = f
    problem.parameters['N'] = h / (f * lx)
    problem.parameters['US'] = 0.5 * f * lx

    problem.substitutions[
        'uS'] = "               US * exp(z/h - x**2 / (2 * lx**2) - y**2 / (2 * ly**2))"
    problem.substitutions[
        'uSy'] = "- y / ly**2 * US * exp(z/h - x**2 / (2 * lx**2) - y**2 / (2 * ly**2))"
    problem.substitutions[
        'uSz'] = "  1 / h     * US * exp(z/h - x**2 / (2 * lx**2) - y**2 / (2 * ly**2))"

    problem.add_equation(
        "dt(ψ) - dx(dx(ψ)) - dy(dy(ψ)) - f**2 / N**2 * dz(ψz) = f * uSz / N**2 * (dy(ψz) + dy(ψ) / h) + uSy",
        condition="(nx != 0) or (ny != 0)")

    problem.add_equation("ψ = 0", condition="(nx == 0) and (ny == 0)")
    problem.add_equation("ψz = 0", condition="(nx == 0) and (ny == 0)")
    problem.add_equation("dz(ψ) - ψz = 0", condition="(nx != 0) or (ny != 0)")

    problem.add_bc("right(f * ψz) = right(uSz * dy(ψ))",
                   condition="(nx != 0) or (ny != 0)")
    problem.add_bc("left(ψz) = 0", condition="(nx != 0) or (ny != 0)")

    # Build solver
    solver = problem.build_solver(de.timesteppers.SBDF3)

    return solver
示例#7
0
def test_1d_output(x_basis_class, Nx, timestepper, dtype):
    # Bases and domain
    x_basis = x_basis_class('x', Nx, interval=(0, 2 * np.pi))
    domain = de.Domain([x_basis], grid_dtype=dtype)
    # Forcing
    F = domain.new_field(name='F')
    x = domain.grid(0)
    F['g'] = -np.sin(x)
    # Problem
    problem = de.IVP(domain, variables=['u', 'ux'])
    problem.parameters['F'] = F
    problem.add_equation("ux - dx(u) = 0")
    problem.add_equation("-dt(u) + dx(ux) = F")
    problem.add_bc("left(u) - right(u) = 0")
    problem.add_bc("left(ux) - right(ux) = 0")
    # Solver
    solver = problem.build_solver(timestepper)
    # Output
    output = solver.evaluator.add_file_handler('test_output', iter=1)
    output.add_task('u', layout='g', name='ug')
    # Loop
    dt = 1e-5
    iter = 10
    for i in range(iter):
        solver.step(dt)
    # Check solution
    post.merge_process_files('test_output')
    with h5py.File('test_output/test_output_s1.h5', mode='r') as file:
        ug = file['tasks']['ug'][:]
        t = file['scales']['sim_time'][:]
    shutil.rmtree('test_output')
    amp = 1 - np.exp(-t[:, None])
    u_true = amp * np.sin(x[None, :])
    assert np.allclose(ug, u_true)
示例#8
0
def test_heat_1d_nonperiodic(benchmark, x_basis_class, Nx, timestepper, dtype):
    # Bases and domain
    x_basis = x_basis_class('x', Nx, interval=(0, 2 * np.pi))
    domain = de.Domain([x_basis], grid_dtype=dtype)
    # Forcing
    F = domain.new_field(name='F')
    x = domain.grid(0)
    F['g'] = -np.sin(x)
    # Problem
    problem = de.IVP(domain, variables=['u', 'ux'])
    problem.parameters['F'] = F
    problem.add_equation("ux - dx(u) = 0")
    problem.add_equation("-dt(u) + dx(ux) = F")
    problem.add_bc("left(u) - right(u) = 0")
    problem.add_bc("left(ux) - right(ux) = 0")
    # Solver
    solver = problem.build_solver(timestepper)
    dt = 1e-5
    iter = 10
    for i in range(iter):
        solver.step(dt)
    # Check solution
    amp = 1 - np.exp(-solver.sim_time)
    u_true = amp * np.sin(x)
    u = solver.state['u']
    assert np.allclose(u['g'], u_true)
示例#9
0
def get_solver(params):
    ''' sets up solver '''
    x_basis = de.Fourier('x',
                         params['N_X'],
                         interval=(0, params['XMAX']),
                         dealias=3 / 2)
    z_basis = de.Chebyshev('z',
                           params['N_Z'],
                           interval=(0, params['ZMAX']),
                           dealias=3 / 2)
    domain = de.Domain([x_basis, z_basis], np.float64)
    z = domain.grid(1)

    problem = de.IVP(domain,
                     variables=[
                         'P',
                         'rho',
                         'ux',
                         'uz',
                         'ux_z',
                         'uz_z',
                     ])
    problem.parameters.update(params)

    # rho0 stratification
    rho0 = domain.new_field()
    rho0.meta['x']['constant'] = True
    rho0['g'] = params['RHO0'] * np.exp(-z / params['H'])
    problem.parameters['rho0'] = rho0

    problem.substitutions['sponge'] = 'SPONGE_STRENGTH * 0.5 * ' +\
        '(2 + tanh((z - SPONGE_HIGH) / (0.6 * (ZMAX - SPONGE_HIGH))) - ' +\
        'tanh((z - SPONGE_LOW) / (0.6 * (SPONGE_LOW))))'
    problem.add_equation('dx(ux) + dz(uz) = 0')
    problem.add_equation('dt(rho) - rho0 * uz / H' +
                         '= - sponge * rho - ux * dx(rho) - uz * dz(rho) +' +
                         'F * exp(-(z - Z0)**2 / (2 * S**2)) *' +
                         'cos(KX * x - OMEGA * t)')
    problem.add_equation('dt(ux) + dx(P) / rho0' +
                         '- NU * (dx(dx(ux)) + dz(ux_z))' +
                         '= - sponge * ux - ux * dx(ux) - uz * dz(ux)')
    problem.add_equation('dt(uz) + dz(P) / rho0 + rho * g / rho0' +
                         '- NU * (dx(dx(uz)) + dz(uz_z))' +
                         '= - sponge * uz - ux * dx(uz) - uz * dz(uz)')
    problem.add_equation('dz(ux) - ux_z = 0')
    problem.add_equation('dz(uz) - uz_z = 0')

    problem.add_bc('left(uz) = 0')
    problem.add_bc('left(ux) = 0')
    problem.add_bc('right(uz) = 0')
    problem.add_bc('right(ux) = 0')
    problem.add_bc('right(P) = 0')

    # Build solver
    solver = problem.build_solver(de.timesteppers.RK443)
    solver.stop_sim_time = params['T_F']
    solver.stop_wall_time = np.inf
    solver.stop_iteration = np.inf
    return solver, domain
示例#10
0
 def problem_setup(self):
     # Problem
     self.problem = de.IVP(self.domain, variables=['u', 'ux', 'uxx'])
     self.problem.parameters['a'] = 2e-4
     self.problem.parameters['b'] = 1e-4
     self.problem.add_equation("dt(u) - a*dx(ux) - b*dx(uxx) = -u*ux")
     self.problem.add_equation("ux - dx(u) = 0")
     self.problem.add_equation("uxx - dx(ux) = 0")
    def __init__(self,
                 problem_params,
                 dtype_u=dedalus_field,
                 dtype_f=rhs_imex_dedalus_field):
        """
        Initialization routine

        Args:
            problem_params (dict): custom parameters for the example
            dtype_u: mesh data type (will be passed parent class)
            dtype_f: mesh data type (will be passed parent class)
        """

        if 'comm' not in problem_params:
            problem_params['comm'] = None

        # these parameters will be used later, so assert their existence
        essential_keys = ['nvars', 'nu', 'freq', 'comm']
        for key in essential_keys:
            if key not in problem_params:
                msg = 'need %s to instantiate problem, only got %s' % (
                    key, str(problem_params.keys()))
                raise ParameterError(msg)

        # we assert that nvars looks very particular here.. this will be necessary for coarsening in space later on
        if problem_params['freq'] % 2 != 0:
            raise ProblemError('setup requires freq to be an equal number')

        xbasis = de.Fourier('x',
                            problem_params['nvars'][0],
                            interval=(0, 1),
                            dealias=1)
        ybasis = de.Fourier('y',
                            problem_params['nvars'][1],
                            interval=(0, 1),
                            dealias=1)
        domain = de.Domain([xbasis, ybasis],
                           grid_dtype=np.float64,
                           comm=problem_params['comm'])

        # invoke super init, passing number of dofs, dtype_u and dtype_f
        super(heat2d_dedalus_forced, self).__init__(init=domain,
                                                    dtype_u=dtype_u,
                                                    dtype_f=dtype_f,
                                                    params=problem_params)

        self.x = self.init.grid(0, scales=1)
        self.y = self.init.grid(1, scales=1)
        self.rhs = self.dtype_u(self.init, val=0.0)
        self.problem = de.IVP(domain=self.init, variables=['u'])
        self.problem.parameters['nu'] = self.params.nu
        self.problem.add_equation(
            "dt(u) - nu * dx(dx(u)) - nu * dy(dy(u)) = 0")
        self.solver = self.problem.build_solver(de.timesteppers.SBDF1)
        self.u = self.solver.state['u']
示例#12
0
def build_LHS(Nz):

    # Parameters
    terms = 1
    dt = 1e-3
    kx = 50 * np.pi
    sigma = 1
    Prandtl = 1.
    Reynolds = 1e2
    ts = de.timesteppers.SBDF3

    # Create bases and domain
    z_basis = de.Chebyshev('z', Nz, interval=(-1, 1), dealias=3 / 2)
    domain = de.Domain([z_basis], grid_dtype=np.complex128)

    # 2D Boussinesq hydrodynamics
    problem = de.IVP(domain,
                     variables=['p', 'b', 'u', 'w', 'bz', 'uz', 'wz'],
                     ncc_cutoff=1e-10,
                     max_ncc_terms=terms)
    problem.meta[:]['z']['dirichlet'] = True
    problem.parameters['P'] = 1 / Reynolds / Prandtl
    problem.parameters['R'] = 1 / Reynolds
    problem.parameters['kx'] = kx
    problem.parameters['sigma'] = sigma
    problem.substitutions['Bz'] = "exp(-(z-1)**2 / 2 / sigma**2)"
    problem.substitutions['dx(A)'] = "1j*kx*A"
    problem.add_equation("dx(u) + wz = 0")
    problem.add_equation("dt(b) - P*(dx(dx(b)) + dz(bz)) + Bz*w      = 0")
    problem.add_equation("dt(u) - R*(dx(dx(u)) + dz(uz)) + dx(p)     = 0")
    problem.add_equation("dt(w) - R*(dx(dx(w)) + dz(wz)) + dz(p) - b = 0")
    problem.add_equation("bz - dz(b) = 0")
    problem.add_equation("uz - dz(u) = 0")
    problem.add_equation("wz - dz(w) = 0")
    problem.add_bc("left(b) = 0")
    problem.add_bc("left(u) = 0")
    problem.add_bc("left(w) = 0")
    problem.add_bc("right(b) = 0")
    problem.add_bc("right(u) = 0")
    if kx == 0:
        problem.add_bc("right(p) = 0")
    else:
        problem.add_bc("right(w) = 0", )

    # Build solver
    solver = problem.build_solver(ts)

    # Step solver to form pencil LHS
    for i in range(10):
        solver.step(dt)

    return solver.pencils[0].LHS
    def build_problem(self, ncc_cutoff=1e-10):
        """Constructs and initial value problem of the current object's equation set

        Arguments:
        ----------
        ncc_cutoff  : float
            The largest coefficient magnitude to keep track of when building NCCs
        """
        if self.variables is None:
            logger.error("IVP variables must be set before problem is built")
        self.problem = de.IVP(self.de_domain.domain,
                              variables=self.variables,
                              ncc_cutoff=ncc_cutoff)
示例#14
0
def build_solver(nx, ny, Lx, Ly, RA, BE, PR, CC):
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    Nx = nx
    Ny = ny


    #for equilibrium:
    # C = 0, beta = 0, Pr = 1, Ra = 5000
    Ra = RA 
    Pr = PR
    beta = BE
    C = CC

    #for travelling wave
    #Ra = 7.542e5 Pr = 1. beta = 3E4 C = 0

    if rank == 0:
        print("dedalus: solver is built for: Nx "+str(nx)+" Ny: "+str(ny)+" Lx: "+str(Lx)+ " Ly: "+str(Ly)+" and Ra: "+str(Ra))
        print("dedalus: Pr "+str(Pr)+" beta: "+str(beta)+" C: "+str(C))

    x_basis = de.Fourier('x', Nx, interval=(0, Lx), dealias=3/2)
    y_basis = de.SinCos ('y', Ny, interval=(0, Ly), dealias=3/2)

    domain = de.Domain([x_basis, y_basis], grid_dtype=np.float64)


# 2D Boussinesq hydrodynamics
    problem = de.IVP(domain, variables=['psi','theta','zeta'], time='t')
    problem.meta['psi','zeta','theta']['y']['parity'] = -1 # sin basis
    problem.parameters['Pr'] = Pr
    problem.parameters['Ra'] = Ra
    problem.parameters['beta'] = beta
    problem.parameters['sbeta'] = np.sqrt(np.abs(beta))
    problem.parameters['C'] = C

# construct the 2D Jacobian
    problem.substitutions['J(A,B)'] = "dx(A) * dy(B) - dy(A) * dx(B)"

    problem.add_equation("dt(zeta) - beta*dx(psi) + Ra/Pr * dx(theta) + C * sbeta * zeta - dx(dx(zeta)) - dy(dy(zeta)) = -J(psi,zeta)", condition="ny != 0")
    problem.add_equation("dt(theta) + dx(psi) - (dx(dx(theta)) + dy(dy(theta)))/Pr = -J(psi,theta)", condition="ny != 0")
    problem.add_equation("dx(dx(psi)) + dy(dy(psi)) - zeta = 0", condition="ny != 0")
    problem.add_equation("zeta = 0", condition="ny ==0")
    problem.add_equation("theta = 0", condition="ny ==0")
    problem.add_equation("psi = 0", condition="ny ==0")

# Build solver
    solver = problem.build_solver(de.timesteppers.MCNAB2)
    #solver = problem.build_solver(de.timesteppers.SBDF1)
    logger.info('Solver built')
    return solver
示例#15
0
def ivp(param, atmos=None, dtype=np.float64, comm=MPI.COMM_WORLD):
    if atmos is None:
        atmos = Atmosphere(param, dim=2, dtype=dtype, comm=comm)
    # Adiabatic viscous fully-compressible hydrodynamics
    problem = de.IVP(atmos.domain,
                     variables=['a1', 'p1', 'u', 'w', 'uz', 'wz'],
                     ncc_cutoff=param.ivp_cutoff,
                     entry_cutoff=param.matrix_cutoff)
    problem.meta[:]['z']['dirichlet'] = True
    problem.parameters['a0'] = atmos.a0
    problem.parameters['p0'] = atmos.p0
    problem.parameters['a0z'] = atmos.a0z
    problem.parameters['p0z'] = atmos.p0z
    problem.parameters['U'] = param.U
    problem.parameters['μ'] = param.μ
    problem.parameters['γ'] = param.γ
    problem.parameters['k'] = param.k_tide
    problem.parameters['ω'] = param.ω_tide
    problem.parameters['σ'] = param.σ_tide
    problem.parameters['A'] = param.A_tide
    problem.parameters['Lz'] = param.Lz
    problem.substitutions['a0x'] = '0'
    problem.substitutions['p0x'] = '0'
    problem.substitutions['ux'] = "dx(u)"
    problem.substitutions['wx'] = "dx(w)"
    problem.substitutions['div_u'] = "ux + wz"
    problem.substitutions['txx'] = "μ*(2*ux - 2/3*div_u)"
    problem.substitutions['txz'] = "μ*(wx + uz)"
    problem.substitutions['tzz'] = "μ*(2*wz - 2/3*div_u)"
    problem.substitutions['φ'] = "A*exp(σ*t)*cos(k*x)*exp(k*(z - Lz))"
    problem.substitutions['cs20'] = "γ*p0*a0"
    problem.add_equation(
        "dt(u) + U*ux + a0*dx(p1) + a1*p0x - a0*(dx(txx) + dz(txz)) = - (u*ux + w*uz) - a1*dx(p1) + a1*(dx(txx) + dz(txz)) - dx(φ)"
    )
    problem.add_equation(
        "dt(w) + U*wx + a0*dz(p1) + a1*p0z - a0*(dx(txz) + dz(tzz)) = - (u*wx + w*wz) - a1*dz(p1) + a1*(dx(txz) + dz(tzz)) - dz(φ)"
    )
    problem.add_equation(
        "dt(a1) + U*dx(a1) + u*a0x + w*a0z -   a0*div_u = - (u*dx(a1) + w*dz(a1)) +   a1*div_u"
    )
    problem.add_equation(
        "dt(p1) + U*dx(p1) + u*p0x + w*p0z + γ*p0*div_u = - (u*dx(p1) + w*dz(p1)) - γ*p1*div_u"
    )
    problem.add_equation("uz - dz(u) = 0")
    problem.add_equation("wz - dz(w) = 0")
    problem.add_bc("left(txz) = 0")
    problem.add_bc("right(txz) = 0")
    problem.add_bc("left(w) = 0")
    problem.add_bc("right(w) = 0")
    return atmos, problem
 def problem_setup(self,
                   L=2.,
                   nx=192,
                   nz=96,
                   Prandtl_number=1.,
                   Rayleih_number=1e4,
                   bc_type='no_slip'):
     self.L = float(L)
     self.nx = int(nx)
     self.nz = int(nz)
     x_basis = de.Fourier('x', int(nx), interval=(0, L), dealias=3 / 2)
     z_basis = de.Chebyshev('z', int(nz), interval=(0, 1), dealias=3 / 2)
     self.saving_shape = (int(nx * 3 / 2), int(nz * 3 / 2))
     self.domain = de.Domain([x_basis, z_basis], grid_dtype=np.float64)
     self.problem = de.IVP(
         self.domain, variables=['T', 'Tz', 'psi', 'psiz', 'curl', 'curlz'])
     self.problem.parameters['L'] = L
     self.problem.parameters['nx'] = nx
     self.problem.parameters['nz'] = nz
     self.Pr = float(Prandtl_number)
     self.Ra = float(Rayleih_number)
     self.problem.parameters['Ra'] = self.Ra
     self.problem.parameters['Pr'] = self.Pr
     # Stream function relation to the speed
     self.problem.substitutions['u'] = "-dz(psi)"
     self.problem.substitutions['v'] = "dx(psi)"
     # Derivatives values relation to the main values
     self.problem.add_equation("psiz - dz(psi) = 0")
     self.problem.add_equation("curlz - dz(curl) = 0")
     self.problem.add_equation("Tz - dz(T) = 0")
     self.problem.add_equation("curl + dx(dx(psi)) + dz(psiz) = 0")
     self.problem.add_equation(
         "dt(curl)+Ra*Pr*dx(T)-Pr*(dx(dx(curl))+dz(curlz))=-(u*dx(curl)+v*curlz)"
     )
     self.problem.add_equation("dt(T)-dx(dx(T))-dz(Tz)=-(u*dx(T)+v*Tz)")
     self.problem.add_bc("left(T) = 1")
     self.problem.add_bc("right(T) = 0")
     self.problem.add_bc("left(psi) = 0")
     self.problem.add_bc("right(psi) = 0")
     if bc_type not in ['no_slip', 'free_slip']:
         raise ValueError(
             "Boundary Conditions must be 'no_slip' or 'free_slip'")
     else:
         if bc_type == 'no_slip':
             self.problem.add_bc("left(psiz) = 0")
             self.problem.add_bc("right(psiz) = 0")
         if bc_type == 'free_slip':
             self.problem.add_bc("left(dz(psiz)) = 0")
             self.problem.add_bc("right(dz(psiz)) = 0")
示例#17
0
    def __init__(self, de_domain, atmosphere):
        """
        Construct the equation class. Inputs are described in the class docstring.
        """
        self.de_domain = de_domain
        self.atmosphere = atmosphere
        self.variables = [
            'u', 'u_z', 'v', 'v_z', 'w', 'w_z', 'T1', 'T1_z', 'ln_rho1'
        ]
        if not self.de_domain.threeD:
            self.variables.remove('v')
            self.variables.remove('v_z')

        self.problem = de.IVP(self.de_domain.domain, variables=self.variables)
        if not self.de_domain.threeD:
            self.problem.substitutions['v'] = '0'
            self.problem.substitutions['v_z'] = '0'
            self.problem.substitutions['dy(A)'] = '0*A'
示例#18
0
def _get_solver(setup_problem, params, variables):
    ''' get solver for given variables '''
    x_basis = de.Fourier('x',
                         params['N_X'],
                         interval=(0, params['XMAX']),
                         dealias=3/2)
    z_basis = de.Chebyshev('z',
                           params['N_Z'],
                           interval=(0, params['ZMAX']),
                           dealias=3/2)
    domain = de.Domain([x_basis, z_basis], np.float64)
    z = domain.grid(1)

    problem = de.IVP(domain, variables=variables)
    problem.parameters['L'] = params['XMAX']
    problem.parameters['g'] = params['G']
    problem.parameters['H'] = params['H']
    problem.parameters['A'] = params['A']
    problem.parameters['F'] = params['F']
    problem.parameters['KX'] = params['KX']
    problem.parameters['KZ'] = params['KZ']
    problem.parameters['NU'] = params['NU']
    problem.parameters['RHO0'] = params['RHO0']
    problem.parameters['omega'] = params['OMEGA']
    problem.parameters['ZMAX'] = params['ZMAX']

    problem.parameters['Z0'] = 0.2 * params['ZMAX']
    problem.parameters['S'] = params['H']

    # rho0 stratification
    rho0 = domain.new_field()
    rho0.meta['x']['constant'] = True
    rho0['g'] = params['RHO0'] * np.exp(-z / params['H'])
    problem.parameters['rho0'] = rho0

    setup_problem(problem, domain, params)

    # Build solver
    solver = problem.build_solver(de.timesteppers.RK222)
    solver.stop_sim_time = params['T_F']
    solver.stop_wall_time = np.inf
    solver.stop_iteration = np.inf
    return solver, domain
示例#19
0
    def problem_setup(self):
        # 2D Boussinesq hydrodynamics
        self.problem = de.IVP(
            self.domain,
            variables=['p', 'b', 'u', 'v', 'w', 'bz', 'uz', 'vz', 'wz'],
            time='t')
        self.problem.meta['p', 'b', 'w', 'bz', 'wz']['x', 'y']['parity'] = 1
        self.problem.meta['v', 'vz']['x']['parity'] = 1
        self.problem.meta['v', 'vz']['y']['parity'] = -1
        self.problem.meta['u', 'uz']['x']['parity'] = -1
        self.problem.meta['u', 'uz']['y']['parity'] = 1
        self.problem.parameters['P'] = 1
        self.problem.parameters['R'] = self.Pr
        self.problem.parameters['F'] = self.F

        self.problem.add_equation("dx(u) + dy(v) + wz = 0")
        self.problem.add_equation(
            "dt(b) - P*(dx(dx(b)) + dy(dy(b)) + dz(bz))             = - u*dx(b) - v*dy(b) - w*bz"
        )
        self.problem.add_equation(
            "dt(u) - R*(dx(dx(u)) + dy(dy(u)) + dz(uz)) + dx(p)     = - u*dx(u) - v*dy(u) - w*uz"
        )
        self.problem.add_equation(
            "dt(v) - R*(dx(dx(v)) + dy(dy(v)) + dz(vz)) + dy(p)     = - u*dx(v) - v*dy(v) - w*vz"
        )
        self.problem.add_equation(
            "dt(w) - R*(dx(dx(w)) + dy(dy(w)) + dz(wz)) + dz(p) - b = - u*dx(w) - v*dy(w) - w*wz"
        )
        self.problem.add_equation("bz - dz(b) = 0")
        self.problem.add_equation("uz - dz(u) = 0")
        self.problem.add_equation("vz - dz(v) = 0")
        self.problem.add_equation("wz - dz(w) = 0")

        self.problem.add_bc("left(b) = -left(F*z)")
        self.problem.add_bc("left(u) = 0")
        self.problem.add_bc("left(v) = 0")
        self.problem.add_bc("left(w) = 0")
        self.problem.add_bc("right(b) = -right(F*z)")
        self.problem.add_bc("right(u) = 0")
        self.problem.add_bc("right(v) = 0")
        self.problem.add_bc("right(w) = 0", condition="(nx != 0) or (ny != 0)")
        self.problem.add_bc("integ_z(p) = 0",
                            condition="(nx == 0) and (ny == 0)")
示例#20
0
    def problem_setup(self, mu):
        # Problem
        #swift-hohenberg:

        # self.problem = de.IVP(self.domain, variables=['u', 'ux', 'uxx'])
        # self.problem.parameters['r'] = mu
        # self.problem.parameters['qc'] = 0.5
        # self.problem.parameters['v'] = 0.41
        # self.problem.parameters['g'] = 1
        # self.problem.add_equation("dt(u) -(r-qc*qc*qc*qc)*u + 2*qc*qc*uxx + dx(dx(uxx)) = v*u*u - g*u*u*u")
        # self.problem.add_equation("ux - dx(u) = 0")
        # self.problem.add_equation("uxx - dx(ux) = 0")

        #travelling wave:
        self.problem = de.IVP(self.domain, variables=['u', 'ux'])
        self.problem.parameters['k'] = 2 * np.pi / (5 * self.Lc)
        self.problem.parameters['w'] = 2 * np.pi / 200
        self.problem.add_equation("dt(ux) - (w/k)*(w/k)*dx(dx(u)) = 0")
        self.problem.add_equation("dt(u) - ux = 0")
示例#21
0
def get_solver(setup_problem, params):
    ''' get solver '''
    x_basis = de.Fourier('x',
                         params['N_X'],
                         interval=(0, params['XMAX']),
                         dealias=3 / 2)
    z_basis = de.Chebyshev('z',
                           params['N_Z'],
                           interval=(0, params['ZMAX']),
                           dealias=3 / 2)
    domain = de.Domain([x_basis, z_basis], np.float64)
    z = domain.grid(1)

    problem = de.IVP(domain, variables=['P', 'rho', 'ux', 'uz'])
    problem.parameters['L'] = params['XMAX']
    problem.parameters['g'] = params['G']
    problem.parameters['H'] = params['H']
    problem.parameters['A'] = params['A']
    problem.parameters['F'] = params['F']
    problem.parameters['KX'] = params['KX']
    problem.parameters['KZ'] = params['KZ']
    problem.parameters['NU'] = params['NU']
    problem.parameters['RHO0'] = params['RHO0']
    problem.parameters['omega'] = params['OMEGA']
    problem.parameters['ZMAX'] = params['ZMAX']

    # rho0 stratification
    # rho0 = domain.new_field()
    # rho0.meta['x']['constant'] = True
    # rho0['g'] = params['RHO0'] * np.exp(-z / params['H'])
    # problem.parameters['rho0'] = rho0
    problem.parameters['rho0'] = params['RHO0']

    setup_problem(problem, domain, params)

    # Build solver
    solver = problem.build_solver(params['TIMESTEPPER'])
    solver.stop_sim_time = params['T_F']
    solver.stop_wall_time = np.inf
    solver.stop_iteration = np.inf
    return solver, domain
示例#22
0
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)
示例#23
0
def get_solver(params):
    ''' sets up solver '''
    x_basis = de.Fourier('x', N_X, interval=(0, XMAX), dealias=3 / 2)
    z_basis = de.Fourier('z', N_Z, interval=(0, ZMAX), dealias=3 / 2)
    domain = de.Domain([x_basis, z_basis], np.float64)

    problem = de.IVP(domain, variables=['P', 'rho', 'ux', 'uz'])
    problem.parameters.update(params)

    problem.substitutions['sponge'] = 'SPONGE_STRENGTH * 0.5 * ' +\
        '(2 + tanh((z - SPONGE_HIGH) / (SPONGE_WIDTH * (ZMAX - SPONGE_HIGH))) - ' +\
        'tanh((z - SPONGE_LOW) / (SPONGE_WIDTH * (SPONGE_LOW))))'
    problem.substitutions['mask'] = \
        '0.5 * (1 + tanh((z - (Z0 + 3 * S)) / (S / 2)))'
    problem.add_equation('dx(ux) + dz(uz) = 0', condition='nx != 0 or nz != 0')
    problem.add_equation(
        'dt(rho) - RHO0 * uz / H' +
        '- NU * (N_Z/N_X)**6 * dx(dx(dx(dx(dx(dx(rho))))))' +
        '- NU * dz(dz(dz(dz(dz(dz(rho))))))' + '= -sponge * rho' +
        '- mask * (ux * dx(rho) + uz * dz(rho))' +
        '+ F * exp(-(z - Z0)**2 / (2 * S**2)) *cos(KX * x - OMEGA * t)')
    problem.add_equation('dt(ux) + dx(P) / RHO0' +
                         '- NU * (N_Z/N_X)**6 * dx(dx(dx(dx(dx(dx(ux))))))' +
                         '- NU * dz(dz(dz(dz(dz(dz(ux))))))' +
                         '= - sponge * ux' +
                         '- mask * (ux * dx(ux) + uz * dz(ux))')
    problem.add_equation('dt(uz) + dz(P) / RHO0 + rho * g / RHO0' +
                         '- NU * (N_Z/N_X)**6 * dx(dx(dx(dx(dx(dx(uz))))))' +
                         '- NU * dz(dz(dz(dz(dz(dz(uz))))))' +
                         '= -sponge * uz' +
                         '- mask * (ux * dx(uz) + uz * dz(uz))')
    problem.add_equation('P = 0', condition='nx == 0 and nz == 0')

    # Build solver
    solver = problem.build_solver(de.timesteppers.RK443)
    solver.stop_sim_time = T_F
    solver.stop_wall_time = np.inf
    solver.stop_iteration = np.inf
    return solver, domain
示例#24
0
Ha = 1.
Re = 1.
Rm = 1.
Pi = 1.
tau = 0.1

stop_time = 10
data_dir = "scratch"

x = de.Fourier('x', nx, interval=[0, Lx], dealias=3 / 2)
y = de.Chebyshev('y', ny, interval=[-Ly / 2, Ly / 2], dealias=3 / 2)

domain = de.Domain([x, y], grid_dtype='float')

hartmann = de.IVP(domain,
                  variables=['vx', 'vy', 'Az', 'p', 'vx_y', 'vy_y', 'Az_y'])
hartmann.parameters['Ha'] = Ha
hartmann.parameters['Re'] = Re
hartmann.parameters['Rm'] = Rm
hartmann.parameters['Pi'] = Pi  # pressure gradient driving flow
hartmann.parameters['Lx'] = Lx
hartmann.parameters['Ly'] = Ly
hartmann.parameters['tau'] = tau
hartmann.substitutions['Bx'] = "Az_y"
hartmann.substitutions['By'] = "-dx(Az) + 1."
hartmann.substitutions['Lap(A, Ay)'] = "dx(dx(A)) + dy(Ay)"
hartmann.substitutions['Jz'] = "-Lap(Az, Az_y)"
hartmann.substitutions['Avg_x(A)'] = "integ(A,'x')/Lx"

# Navier Stokes
hartmann.add_equation(
示例#25
0
    def __init__(self,
        nx = 32,
        ny = 32,
        nz = 32,
        Lx = 2*pi,      # [m]
        Ly = 2*pi,      # [m]
        Lz = 2*pi,      # [m]
        ν = 1.05e-6,    # Kinematic viscosity [m²/s]

        # "Background" (non-evolving) fields:
        u_bg = "0",
        v_bg = "0",
        w_bg = "0",
        p_bg = "0",

        include_linear_bg = False, # Include linear background terms in model formulation

        closure = None,  # Subgrid closure
        **params         # Additional parameters to be added to dedalus problem
        ):

        Flow.__init__(self, nx, ny, nz, Lx, Ly, Lz)

        self.xlimits = (-Lx/2, Lx/2)
        self.ylimits = (-Ly/2, Ly/2)
        self.zlimits = (-Lz/2, Lz/2)

        # Create bases and domain
        self.xbasis = xbasis = de.Fourier('x', nx, interval=self.xlimits, dealias=3/2)
        self.ybasis = ybasis = de.Fourier('y', ny, interval=self.ylimits, dealias=3/2)
        self.zbasis = zbasis = de.Fourier('z', nz, interval=self.zlimits, dealias=3/2)
        self.domain = domain = de.Domain([xbasis, ybasis, zbasis], grid_dtype=np.float64)

        self.x = domain.grid(0)
        self.y = domain.grid(1)
        self.z = domain.grid(2)

        bind_parameters(self, ν=ν, **params)

        # Problem set-up
        variables = ['p', 'u', 'v', 'w']
        add_closure_variables(variables, closure)

        self.problem = problem = de.IVP(domain, variables=variables, time='t')

        add_parameters(problem, ν=ν, **params)
        bind_parameters(self, ν=ν, **params)

        problem.substitutions['u_bg'] = u_bg
        problem.substitutions['v_bg'] = v_bg
        problem.substitutions['w_bg'] = w_bg
        problem.substitutions['p_bg'] = p_bg

        problem.substitutions['U'] = "u + u_bg"
        problem.substitutions['V'] = "v + v_bg"
        problem.substitutions['W'] = "w + w_bg"

        add_first_derivative_substitutions(problem,
            ['u', 'v', 'w', 'p', 'U', 'V', 'W', 'u_bg', 'v_bg', 'w_bg', 'p_bg'],
            ['x', 'y', 'z']
        )

        add_closure_substitutions(problem, closure, u='U', v='V', w='W')
        add_closure_equations(problem, closure, u='U', v='V', w='W')

        problem.substitutions['div(f1, f2, f3)'] = "dx(f1) + dy(f2) + dz(f3)"

        ## Momentum equations:
        # Primary linear terms
        linear_x = "px - ν*div(ux, uy, uz)"
        linear_y = "py - ν*div(vx, vy, vz)"
        linear_z = "pz - ν*div(wx, wy, wz)"

        # Linear background terms
        if include_linear_bg:
            linear_bg_x = "p_bgx - ν*div(u_bgx, u_bgy, u_bgz)"
            linear_bg_y = "p_bgy - ν*div(v_bgx, v_bgy, v_bgz)"
            linear_bg_z = "p_bgz - ν*div(w_bgx, w_bgy, w_bgz)"
        else:
            linear_bg_x = "0"
            linear_bg_y = "0"
            linear_bg_z = "0"

        xmom = f"dt(u) + {linear_x} + Lu_sgs = - {linear_bg_x} - U*Ux - V*Uy - W*Uz + Nu_sgs"
        ymom = f"dt(v) + {linear_y} + Lv_sgs = - {linear_bg_y} - U*Vx - V*Vy - W*Vz + Nv_sgs"
        zmom = f"dt(w) + {linear_z} + Lw_sgs = - {linear_bg_z} - U*Wx - V*Wy - W*Wz + Nw_sgs"

        problem.add_equation(xmom)
        problem.add_equation(ymom)
        problem.add_equation(zmom)

        # Continuity equation
        problem.add_equation("ux + vy + wz = - u_bgx - v_bgy - w_bgz",
                                condition="(nx != 0) or (ny != 0) or (nz != 0)")

        problem.add_equation("p = 0", condition="(nx == 0) and (ny == 0) and (nz == 0)")
示例#26
0
logger = logging.getLogger(__name__)


# Parameters
Lx, Lz = (4., 1.)
Prandtl = 1.
Rayleigh = 4e9

# Create bases and domain
Nx, Nz = 2048, 512
x_basis = de.Fourier('x', Nx, interval=(0, Lx), dealias=3/2)
z_basis = de.Chebyshev('z', Nz, interval=(-Lz/2, Lz/2), dealias=3/2)
domain = de.Domain([x_basis, z_basis], grid_dtype=np.float64)

# 2D Boussinesq hydrodynamics
problem = de.IVP(domain, variables=['p','b','u','w','bz','uz','wz'])
problem.meta['p','b','u','w']['z']['dirichlet'] = True
problem.parameters['P'] = (Rayleigh * Prandtl)**(-1/2)
problem.parameters['R'] = (Rayleigh / Prandtl)**(-1/2)
problem.parameters['F'] = F = 1
problem.parameters['Lx'] = Lx
problem.add_equation("dx(u) + wz = 0")
problem.add_equation("dt(b) - P*(dx(dx(b)) + dz(bz)) - F*w       = -(u*dx(b) + w*bz)")
problem.add_equation("dt(u) - R*(dx(dx(u)) + dz(uz)) + dx(p)     = -(u*dx(u) + w*uz)")
problem.add_equation("dt(w) - R*(dx(dx(w)) + dz(wz)) + dz(p) - b = -(u*dx(w) + w*wz)")
problem.add_equation("bz - dz(b) = 0")
problem.add_equation("uz - dz(u) = 0")
problem.add_equation("wz - dz(w) = 0")
problem.add_bc("left(b) = 0")
problem.add_bc("left(u) = 0")
problem.add_bc("left(w) = 0")
示例#27
0
Lx, Ly, Lz = (25., 25., 1.)
epsilon = 0.8
Pr = 1.0

Ra_crit = 1707.762  # No-slip top & bottom
Ra = Ra_crit * (1 + epsilon)

# Create bases and domain
start_init_time = time.time()
x_basis = de.SinCos('x', 64, interval=(0, Lx), dealias=3/2)
y_basis = de.SinCos('y', 64, interval=(0, Ly), dealias=3/2)
z_basis = de.Chebyshev('z', 16, interval=(-Lz/2, Lz/2), dealias=3/2)
domain = de.Domain([x_basis, y_basis, z_basis], grid_dtype=np.float64)

# 2D Boussinesq hydrodynamics
problem = de.IVP(domain, variables=['p','b','u','v','w','bz','uz','vz','wz'], time='t')
problem.meta['p','b','w','bz','wz']['x','y']['parity'] = 1
problem.meta['v','vz']['x']['parity'] = 1
problem.meta['v','vz']['y']['parity'] = -1
problem.meta['u','uz']['x']['parity'] = -1
problem.meta['u','uz']['y']['parity'] = 1
problem.parameters['P'] = 1
problem.parameters['R'] = Pr
problem.parameters['F'] = F = Ra*Pr

problem.add_equation("dx(u) + dy(v) + wz = 0")
problem.add_equation("dt(b) - P*(dx(dx(b)) + dy(dy(b)) + dz(bz))             = - u*dx(b) - v*dy(b) - w*bz")
problem.add_equation("dt(u) - R*(dx(dx(u)) + dy(dy(u)) + dz(uz)) + dx(p)     = - u*dx(u) - v*dy(u) - w*uz")
problem.add_equation("dt(v) - R*(dx(dx(v)) + dy(dy(v)) + dz(vz)) + dy(p)     = - u*dx(v) - v*dy(v) - w*vz")
problem.add_equation("dt(w) - R*(dx(dx(w)) + dy(dy(w)) + dz(wz)) + dz(p) - b = - u*dx(w) - v*dy(w) - w*wz")
problem.add_equation("bz - dz(b) = 0")
示例#28
0
        param.force_symmetry))

# Bases and domain
x_basis = de.Fourier('x',
                     param.Nx, [-param.Lx / 2, param.Lx / 2],
                     dealias=3 / 2)
y0_basis = de.SinCos('y0', param.Ny, [0, param.Ly], dealias=3 / 2)
y1_basis = de.SinCos('y1', param.Ny, [0, param.Ly], dealias=3 / 2)
domain = de.Domain([x_basis, y0_basis, y1_basis],
                   grid_dtype=np.float64,
                   mesh=param.mesh)

x, y0, y1 = domain.grids()

# Problem
problem = de.IVP(domain, variables=['cs', 'css', 'ct', 'cts', 'cst', 'ctt'])
problem.meta['cs']['x']['constant'] = True
problem.meta['ct']['x']['constant'] = True

problem.meta['cs']['y0']['parity'] = 1
problem.meta['ct']['y0']['parity'] = 1
problem.meta['cs']['y1']['parity'] = -1
problem.meta['ct']['y1']['parity'] = -1

problem.meta['css']['y0']['parity'] = -1
problem.meta['cts']['y0']['parity'] = -1
problem.meta['cst']['y0']['parity'] = -1
problem.meta['ctt']['y0']['parity'] = -1
problem.meta['css']['y1']['parity'] = -1
problem.meta['cts']['y1']['parity'] = -1
problem.meta['cst']['y1']['parity'] = -1
示例#29
0
nx = 512 * 2

coef_dealias = 2 / 3

n = int(coef_dealias * nx)
dealias = nx / n
nx, ny = (n, n)

# Create bases and domain
x_basis = de.Fourier('x', nx, interval=(0, lx), dealias=dealias)
y_basis = de.Fourier('y', ny, interval=(0, ly), dealias=dealias)
domain = de.Domain([x_basis, y_basis], grid_dtype=np.float64)

# Stream function-vorticity formulation
variables = ['psi']
problem = de.IVP(domain, variables=variables)

Reynolds = 1e4
problem.parameters['Re'] = Reynolds
problem.substitutions['u'] = "dy(psi)"
problem.substitutions['v'] = "-dx(psi)"
problem.substitutions['rot'] = "- dx(dx(psi)) - dy(dy(psi))"
problem.substitutions['rotx'] = "dx(rot)"
problem.substitutions['roty'] = "dy(rot)"
problem.add_equation(
    'dt(rot) - (1/Re)*(dx(rotx) + dy(roty)) = - u*rotx - v*roty',
    condition="(nx != 0) or (ny != 0)")
problem.add_equation("psi = 0", condition="(nx == 0) and (ny == 0)")

# with first-order reduction equations...
# problem.add_equation('rot + dy(u) - dx(v) = 0')
Pr = rpf.Pr
Ra = rpf.Ra
Np = rpf.Np
Ta = rpf.Ta
Lat = rpf.latitude
m = rpf.m
theta = rpf.theta

# Create bases and domain
y_basis = de.Fourier('y', Ny, interval=(0, Ly), dealias=3/2)   # Fourier basis in the x
z_basis = de.Chebyshev('z', Nz, interval=(0, Lz), dealias=3/2) # Chebyshev basis in the z
domain = de.Domain([y_basis, z_basis], grid_dtype=np.float64)  # Defining our domain
z = domain.grid(1, scales=1)                                   # accessing the z values

# 2D Anelastic hydrodynamics
problem = de.IVP(domain, variables=['p', 's', 'u', 'v', 'w', 'sz', 'uz', 'vz', 'wz', 'L_buoy', 'L_diss'])
problem.meta['p','s','u','w']['z']['dirichlet'] = True

# Defining model parameters
problem.parameters['Ly'] = Ly
problem.parameters['Lz'] = Lz
problem.parameters['Ra'] = Ra
problem.parameters['Pr'] = Pr
problem.parameters['Ta'] = Ta
problem.parameters['Lat'] = Lat
problem.parameters['m'] = m
problem.parameters['theta'] = theta
problem.parameters['X'] = Ra/Pr
problem.parameters['Y'] = (Pr*Pr*theta) / Ra
problem.parameters['T'] = Ta**(1/2)