Example #1
0
def setup_balance(dirname):

    # set up grid and time stepping parameters
    dt = 1.
    tmax = 5.
    deltax = 400
    L = 2000.
    H = 10000.

    nlayers = int(H / deltax)
    ncolumns = int(L / deltax)

    m = PeriodicIntervalMesh(ncolumns, L)
    mesh = ExtrudedMesh(m, layers=nlayers, layer_height=H / nlayers)

    output = OutputParameters(dirname=dirname + '/dry_balance',
                              dumpfreq=10,
                              dumplist=['u'])
    parameters = CompressibleParameters()

    state = State(mesh, dt=dt, output=output, parameters=parameters)

    eqns = CompressibleEulerEquations(state, "CG", 1)

    # Initial conditions
    rho0 = state.fields("rho")
    theta0 = state.fields("theta")

    # Isentropic background state
    Tsurf = Constant(300.)
    theta0.interpolate(Tsurf)

    # Calculate hydrostatic exner
    compressible_hydrostatic_balance(state, theta0, rho0, solve_for_rho=True)

    state.set_reference_profiles([('rho', rho0), ('theta', theta0)])

    # Set up transport schemes
    transported_fields = [
        ImplicitMidpoint(state, "u"),
        SSPRK3(state, "rho"),
        SSPRK3(state, "theta", options=EmbeddedDGOptions())
    ]

    # Set up linear solver
    linear_solver = CompressibleSolver(state, eqns)

    # build time stepper
    stepper = CrankNicolson(state,
                            eqns,
                            transported_fields,
                            linear_solver=linear_solver)

    return stepper, tmax
Example #2
0
def mesh(geometry):

    Lx = 100.
    deltax = Lx / 5.
    ncolumnsx = int(Lx/deltax)

    if geometry == "periodic":
        m = PeriodicIntervalMesh(ncolumnsx, Lx)
    elif geometry == "non-periodic":
        m = IntervalMesh(ncolumnsx, Lx)

    return m
Example #3
0
def setup_IPdiffusion(dirname, vector, DG):

    dt = 0.01
    L = 10.
    m = PeriodicIntervalMesh(50, L)
    mesh = ExtrudedMesh(m, layers=50, layer_height=0.2)

    fieldlist = ['u', 'D']
    timestepping = TimesteppingParameters(dt=dt)
    parameters = CompressibleParameters()
    output = OutputParameters(dirname=dirname)

    state = State(mesh,
                  vertical_degree=1,
                  horizontal_degree=1,
                  family="CG",
                  timestepping=timestepping,
                  parameters=parameters,
                  output=output,
                  fieldlist=fieldlist)

    x = SpatialCoordinate(mesh)
    if vector:
        kappa = Constant([[0.05, 0.], [0., 0.05]])
        if DG:
            Space = VectorFunctionSpace(mesh, "DG", 1)
        else:
            Space = state.spaces("HDiv")
        fexpr = as_vector([exp(-(L / 2. - x[0])**2 - (L / 2. - x[1])**2), 0.])
    else:
        kappa = 0.05
        if DG:
            Space = state.spaces("DG")
        else:
            Space = state.spaces("HDiv_v")
        fexpr = exp(-(L / 2. - x[0])**2 - (L / 2. - x[1])**2)

    f = state.fields("f", Space)
    try:
        f.interpolate(fexpr)
    except NotImplementedError:
        # finat elements raise NotImplementedError if they don't
        # advertise a dual for interpolation.
        f.project(fexpr)

    mu = 5.
    f_diffusion = InteriorPenalty(state,
                                  f.function_space(),
                                  kappa=kappa,
                                  mu=mu)
    diffused_fields = [("f", f_diffusion)]
    stepper = AdvectionDiffusion(state, diffused_fields=diffused_fields)
    return stepper
def setup_fallout(dirname):

    # declare grid shape, with length L and height H
    L = 10.
    H = 10.
    nlayers = 10
    ncolumns = 10

    # make mesh
    m = PeriodicIntervalMesh(ncolumns, L)
    mesh = ExtrudedMesh(m, layers=nlayers, layer_height=(H / nlayers))
    x = SpatialCoordinate(mesh)

    dt = 0.1
    output = OutputParameters(dirname=dirname + "/fallout",
                              dumpfreq=10,
                              dumplist=['rain_mixing_ratio'])
    parameters = CompressibleParameters()
    diagnostic_fields = [Precipitation()]
    state = State(mesh,
                  dt=dt,
                  output=output,
                  parameters=parameters,
                  diagnostic_fields=diagnostic_fields)

    Vrho = state.spaces("DG1_equispaced")
    problem = [(AdvectionEquation(state, Vrho, "rho", ufamily="CG",
                                  udegree=1), ForwardEuler(state))]
    state.fields("rho").assign(1.)

    physics_list = [Fallout(state)]
    rain0 = state.fields("rain_mixing_ratio")

    # set up rain
    xc = L / 2
    zc = H / 2
    rc = H / 4
    r = sqrt((x[0] - xc)**2 + (x[1] - zc)**2)
    rain_expr = conditional(r > rc, 0., 1e-3 * (cos(pi * r / (rc * 2)))**2)

    rain0.interpolate(rain_expr)

    # build time stepper
    stepper = PrescribedTransport(state, problem, physics_list=physics_list)

    return stepper, 10.0
Example #5
0
def mesh(geometry):

    L = 100.
    H = 100.

    deltax = L / 5.
    deltaz = H / 5.
    nlayers = int(H / deltaz)
    ncolumns = int(L / deltax)

    if geometry == "periodic":
        m = PeriodicIntervalMesh(ncolumns, L)
    elif geometry == "non-periodic":
        m = IntervalMesh(ncolumns, L)

    extruded_mesh = ExtrudedMesh(m, layers=nlayers, layer_height=deltaz)

    return extruded_mesh
Example #6
0
def state(tmpdir, geometry):
    """
    returns an instance of the State class, having set up either spherical
    geometry or 2D vertical slice geometry
    """

    output = OutputParameters(dirname=str(tmpdir), dumplist=["f"], dumpfreq=15)

    if geometry == "sphere":
        mesh = IcosahedralSphereMesh(radius=1, refinement_level=3, degree=1)
        x = SpatialCoordinate(mesh)
        mesh.init_cell_orientations(x)
        family = "BDM"
        vertical_degree = None
        fieldlist = ["u", "D"]
        dt = pi / 3. * 0.01
        uexpr = as_vector([-x[1], x[0], 0.0])

    if geometry == "slice":
        m = PeriodicIntervalMesh(15, 1.)
        mesh = ExtrudedMesh(m, layers=15, layer_height=1. / 15.)
        family = "CG"
        vertical_degree = 1
        fieldlist = ["u", "rho", "theta"]
        dt = 0.01
        x = SpatialCoordinate(mesh)
        uexpr = as_vector([1.0, 0.0])

    timestepping = TimesteppingParameters(dt=dt)
    state = State(mesh,
                  vertical_degree=vertical_degree,
                  horizontal_degree=1,
                  family=family,
                  timestepping=timestepping,
                  output=output,
                  fieldlist=fieldlist)

    u0 = state.fields("u")
    u0.project(uexpr)
    return state
def setup_checkpointing(dirname):

    nlayers = 5  # horizontal layers
    columns = 15  # number of columns
    L = 3.e5
    m = PeriodicIntervalMesh(columns, L)
    dt = 2.0

    # build volume mesh
    H = 1.0e4  # Height position of the model top
    mesh = ExtrudedMesh(m, layers=nlayers, layer_height=H / nlayers)

    output = OutputParameters(dirname=dirname,
                              dumpfreq=1,
                              chkptfreq=2,
                              log_level='INFO')
    parameters = CompressibleParameters()

    state = State(mesh, dt=dt, output=output, parameters=parameters)

    eqns = CompressibleEulerEquations(state, "CG", 1)

    # Set up transport schemes
    transported_fields = []
    transported_fields.append(SSPRK3(state, "u"))
    transported_fields.append(SSPRK3(state, "rho"))
    transported_fields.append(SSPRK3(state, "theta"))

    # Set up linear solver
    linear_solver = CompressibleSolver(state, eqns)

    # build time stepper
    stepper = CrankNicolson(state,
                            eqns,
                            transported_fields,
                            linear_solver=linear_solver)

    return state, stepper, dt
Example #8
0
def setup_limiters(dirname):

    dt = 0.01
    Ld = 1.
    tmax = 0.2
    rotations = 0.1
    m = PeriodicIntervalMesh(20, Ld)
    mesh = ExtrudedMesh(m, layers=20, layer_height=(Ld / 20))
    output = OutputParameters(
        dirname=dirname,
        dumpfreq=1,
        dumplist=['u', 'chemical', 'moisture_higher', 'moisture_lower'])
    parameters = CompressibleParameters()
    timestepping = TimesteppingParameters(dt=dt, maxk=4, maxi=1)
    fieldlist = [
        'u', 'rho', 'theta', 'chemical', 'moisture_higher', 'moisture_lower'
    ]
    diagnostic_fields = []
    state = State(mesh,
                  vertical_degree=1,
                  horizontal_degree=1,
                  family="CG",
                  timestepping=timestepping,
                  output=output,
                  parameters=parameters,
                  fieldlist=fieldlist,
                  diagnostic_fields=diagnostic_fields)

    x, z = SpatialCoordinate(mesh)

    Vr = state.spaces("DG")
    Vt = state.spaces("HDiv_v")
    Vpsi = FunctionSpace(mesh, "CG", 2)

    cell = mesh._base_mesh.ufl_cell().cellname()
    DG0_element = FiniteElement("DG", cell, 0)
    CG1_element = FiniteElement("CG", interval, 1)
    Vt0_element = TensorProductElement(DG0_element, CG1_element)
    Vt0 = FunctionSpace(mesh, Vt0_element)
    Vt0_brok = FunctionSpace(mesh, BrokenElement(Vt0_element))
    VCG1 = FunctionSpace(mesh, "CG", 1)

    u = state.fields("u", dump=True)
    chemical = state.fields("chemical", Vr, dump=True)
    moisture_higher = state.fields("moisture_higher", Vt, dump=True)
    moisture_lower = state.fields("moisture_lower", Vt0, dump=True)

    x_lower = 2 * Ld / 5
    x_upper = 3 * Ld / 5
    z_lower = 6 * Ld / 10
    z_upper = 8 * Ld / 10
    bubble_expr_1 = conditional(
        x > x_lower,
        conditional(
            x < x_upper,
            conditional(z > z_lower, conditional(z < z_upper, 1.0, 0.0), 0.0),
            0.0), 0.0)

    bubble_expr_2 = conditional(
        x > z_lower,
        conditional(
            x < z_upper,
            conditional(z > x_lower, conditional(z < x_upper, 1.0, 0.0), 0.0),
            0.0), 0.0)

    chemical.assign(1.0)
    moisture_higher.assign(280.)
    chem_pert_1 = Function(Vr).interpolate(bubble_expr_1)
    chem_pert_2 = Function(Vr).interpolate(bubble_expr_2)
    moist_h_pert_1 = Function(Vt).interpolate(bubble_expr_1)
    moist_h_pert_2 = Function(Vt).interpolate(bubble_expr_2)
    moist_l_pert_1 = Function(Vt0).interpolate(bubble_expr_1)
    moist_l_pert_2 = Function(Vt0).interpolate(bubble_expr_2)

    chemical.assign(chemical + chem_pert_1 + chem_pert_2)
    moisture_higher.assign(moisture_higher + moist_h_pert_1 + moist_h_pert_2)
    moisture_lower.assign(moisture_lower + moist_l_pert_1 + moist_l_pert_2)

    # set up solid body rotation for advection
    # we do this slightly complicated stream function to make the velocity 0 at edges
    # thus we avoid odd effects at boundaries
    xc = Ld / 2
    zc = Ld / 2
    r = sqrt((x - xc)**2 + (z - zc)**2)
    omega = rotations * 2 * pi / tmax
    r_out = 9 * Ld / 20
    r_in = 2 * Ld / 5
    A = omega * r_in / (2 * (r_in - r_out))
    B = -omega * r_in * r_out / (r_in - r_out)
    C = omega * r_in**2 * r_out / (r_in - r_out) / 2
    psi_expr = conditional(
        r < r_in, omega * r**2 / 2,
        conditional(r < r_out, A * r**2 + B * r + C,
                    A * r_out**2 + B * r_out + C))
    psi = Function(Vpsi).interpolate(psi_expr)

    gradperp = lambda v: as_vector([-v.dx(1), v.dx(0)])
    u.project(gradperp(psi))

    state.initialise([('u', u), ('chemical', chemical),
                      ('moisture_higher', moisture_higher),
                      ('moisture_lower', moisture_lower)])

    # set up advection schemes
    dg_opts = EmbeddedDGOptions()
    recovered_opts = RecoveredOptions(embedding_space=Vr,
                                      recovered_space=VCG1,
                                      broken_space=Vt0_brok,
                                      boundary_method=Boundary_Method.dynamics)

    chemeqn = AdvectionEquation(state, Vr, equation_form="advective")
    moisteqn_higher = EmbeddedDGAdvection(state,
                                          Vt,
                                          equation_form="advective",
                                          options=dg_opts)
    moisteqn_lower = EmbeddedDGAdvection(state,
                                         Vt0,
                                         equation_form="advective",
                                         options=recovered_opts)

    # build advection dictionary
    advected_fields = []
    advected_fields.append(('chemical',
                            SSPRK3(state,
                                   chemical,
                                   chemeqn,
                                   limiter=VertexBasedLimiter(Vr))))
    advected_fields.append(('moisture_higher',
                            SSPRK3(state,
                                   moisture_higher,
                                   moisteqn_higher,
                                   limiter=ThetaLimiter(Vt))))
    advected_fields.append(('moisture_lower',
                            SSPRK3(state,
                                   moisture_lower,
                                   moisteqn_lower,
                                   limiter=VertexBasedLimiter(Vr))))

    # build time stepper
    stepper = AdvectionDiffusion(state, advected_fields)

    return stepper, tmax
Example #9
0
def setup_2d_recovery(dirname):

    L = 100.
    H = 100.

    deltax = L / 5.
    deltay = H / 5.
    nlayers = int(H / deltay)
    ncolumns = int(L / deltax)

    m = PeriodicIntervalMesh(ncolumns, L)
    mesh = ExtrudedMesh(m, layers=nlayers, layer_height=H / nlayers)
    x, y = SpatialCoordinate(mesh)

    # horizontal base spaces
    cell = mesh._base_mesh.ufl_cell().cellname()
    u_hori = FiniteElement("CG", cell, 1)
    w_hori = FiniteElement("DG", cell, 0)

    # vertical base spaces
    u_vert = FiniteElement("DG", interval, 0)
    w_vert = FiniteElement("CG", interval, 1)

    # build elements
    u_element = HDiv(TensorProductElement(u_hori, u_vert))
    w_element = HDiv(TensorProductElement(w_hori, w_vert))
    theta_element = TensorProductElement(w_hori, w_vert)
    v_element = u_element + w_element

    # spaces
    VDG0 = FunctionSpace(mesh, "DG", 0)
    VCG1 = FunctionSpace(mesh, "CG", 1)
    VDG1 = FunctionSpace(mesh, "DG", 1)
    Vt = FunctionSpace(mesh, theta_element)
    Vt_brok = FunctionSpace(mesh, BrokenElement(theta_element))
    Vu = FunctionSpace(mesh, v_element)
    VuCG1 = VectorFunctionSpace(mesh, "CG", 1)
    VuDG1 = VectorFunctionSpace(mesh, "DG", 1)

    # set up initial conditions
    np.random.seed(0)
    expr = np.random.randn() + np.random.randn() * y

    # our actual theta and rho and v
    rho_CG1_true = Function(VCG1).interpolate(expr)
    theta_CG1_true = Function(VCG1).interpolate(expr)
    v_CG1_true = Function(VuCG1).interpolate(as_vector([expr, expr]))
    rho_Vt_true = Function(Vt).interpolate(expr)

    # make the initial fields by projecting expressions into the lowest order spaces
    rho_DG0 = Function(VDG0).interpolate(expr)
    rho_CG1 = Function(VCG1)
    theta_Vt = Function(Vt).interpolate(expr)
    theta_CG1 = Function(VCG1)
    v_Vu = Function(Vu).project(as_vector([expr, expr]))
    v_CG1 = Function(VuCG1)
    rho_Vt = Function(Vt)

    # make the recoverers and do the recovery
    rho_recoverer = Recoverer(rho_DG0,
                              rho_CG1,
                              VDG=VDG1,
                              boundary_method=Boundary_Method.dynamics)
    theta_recoverer = Recoverer(theta_Vt,
                                theta_CG1,
                                VDG=VDG1,
                                boundary_method=Boundary_Method.dynamics)
    v_recoverer = Recoverer(v_Vu,
                            v_CG1,
                            VDG=VuDG1,
                            boundary_method=Boundary_Method.dynamics)
    rho_Vt_recoverer = Recoverer(rho_DG0,
                                 rho_Vt,
                                 VDG=Vt_brok,
                                 boundary_method=Boundary_Method.physics)

    rho_recoverer.project()
    theta_recoverer.project()
    v_recoverer.project()
    rho_Vt_recoverer.project()

    rho_diff = errornorm(rho_CG1, rho_CG1_true) / norm(rho_CG1_true)
    theta_diff = errornorm(theta_CG1, theta_CG1_true) / norm(theta_CG1_true)
    v_diff = errornorm(v_CG1, v_CG1_true) / norm(v_CG1_true)
    rho_Vt_diff = errornorm(rho_Vt, rho_Vt_true) / norm(rho_Vt_true)

    return (rho_diff, theta_diff, v_diff, rho_Vt_diff)
Example #10
0
def run_incompressible(tmpdir):

    dt = 6.0
    tmax = 2*dt
    nlayers = 10  # horizontal layers
    ncols = 10  # number of columns
    Lx = 1000.0
    Lz = 1000.0
    m = PeriodicIntervalMesh(ncols, Lx)
    mesh = ExtrudedMesh(m, layers=nlayers, layer_height=Lz/nlayers)

    output = OutputParameters(dirname=tmpdir+"/incompressible",
                              dumpfreq=2, chkptfreq=2)
    parameters = CompressibleParameters()

    state = State(mesh,
                  dt=dt,
                  output=output,
                  parameters=parameters)

    eqns = IncompressibleBoussinesqEquations(state, "CG", 1)

    # Initial conditions
    p0 = state.fields("p")
    b0 = state.fields("b")

    # z.grad(bref) = N**2
    x, z = SpatialCoordinate(mesh)
    N = parameters.N
    bref = z*(N**2)

    b_b = Function(b0.function_space()).interpolate(bref)
    incompressible_hydrostatic_balance(state, b_b, p0)
    state.initialise([('p', p0),
                      ('b', b_b)])

    # Add perturbation
    r = sqrt((x-Lx/2)**2 + (z-Lz/2)**2)
    b_pert = 0.1*exp(-(r/(Lx/5)**2))
    b0.interpolate(b_b + b_pert)

    # Set up transport schemes
    b_opts = SUPGOptions()
    transported_fields = [ImplicitMidpoint(state, "u"),
                          SSPRK3(state, "b", options=b_opts)]

    # Set up linear solver for the timestepping scheme
    linear_solver = IncompressibleSolver(state, eqns)

    # build time stepper
    stepper = CrankNicolson(state, eqns, transported_fields,
                            linear_solver=linear_solver)

    # Run
    stepper.run(t=0, tmax=tmax)

    # State for checking checkpoints
    checkpoint_name = 'incompressible_chkpt'
    new_path = join(abspath(dirname(__file__)), '..', f'data/{checkpoint_name}')
    check_output = OutputParameters(dirname=tmpdir+"/incompressible",
                                    checkpoint_pickup_filename=new_path)
    check_state = State(mesh, dt=dt, output=check_output)
    check_eqn = IncompressibleBoussinesqEquations(check_state, "CG", 1)
    check_stepper = CrankNicolson(check_state, check_eqn, [])
    check_stepper.run(t=0, tmax=0, pickup=True)

    return state, check_state
Example #11
0
def setup_limiters(dirname, direction, grid_params, ic_params):

    # declare grid shape
    L, H, ncolumns, nlayers = grid_params

    # make mesh
    m = PeriodicIntervalMesh(ncolumns, L)
    mesh = ExtrudedMesh(m, layers=nlayers, layer_height=(H / nlayers))
    x, z = SpatialCoordinate(mesh)

    fieldlist = ['u']
    timestepping = TimesteppingParameters(dt=1.0)
    output = OutputParameters(dirname=dirname,
                              dumpfreq=5,
                              dumplist=['u'],
                              perturbation_fields=['theta0', 'theta1'])
    parameters = CompressibleParameters()

    state = State(mesh,
                  vertical_degree=1,
                  horizontal_degree=1,
                  family="CG",
                  timestepping=timestepping,
                  output=output,
                  parameters=parameters,
                  fieldlist=fieldlist)

    # make elements
    # v is continuous in vertical, h is horizontal
    cell = mesh._base_mesh.ufl_cell().cellname()
    DG0_element = FiniteElement("DG", cell, 0)
    CG1_element = FiniteElement("CG", cell, 1)
    DG1_element = FiniteElement("DG", cell, 1)
    CG2_element = FiniteElement("CG", cell, 2)
    V0_element = TensorProductElement(DG0_element, CG1_element)
    V1_element = TensorProductElement(DG1_element, CG2_element)

    # spaces
    VDG1 = FunctionSpace(mesh, "DG", 1)
    VCG1 = FunctionSpace(mesh, "CG", 1)
    V0 = FunctionSpace(mesh, V0_element)
    V1 = FunctionSpace(mesh, V1_element)
    V0_brok = FunctionSpace(mesh, BrokenElement(V0.ufl_element()))

    # declare initial fields
    u0 = state.fields("u")
    theta0 = state.fields("theta0", V0)
    theta1 = state.fields("theta1", V1)
    Tsurf, xc, zc, rc, u_max = ic_params

    # Isentropic background state
    thetab = Constant(Tsurf)
    theta_b1 = Function(V1).interpolate(thetab)
    theta_b0 = Function(V0).interpolate(thetab)

    # set up bubble
    theta_expr = conditional(
        sqrt((x - xc)**2.0) < rc,
        conditional(sqrt((z - zc)**2.0) < rc, Constant(2.0), Constant(0.0)),
        Constant(0.0))
    theta_pert1 = Function(V1).interpolate(theta_expr)
    theta_pert0 = Function(V0).interpolate(theta_expr)

    if direction == "horizontal":
        Vpsi = FunctionSpace(mesh, "CG", 2)
        psi_expr = -u_max * z
        psi0 = Function(Vpsi).interpolate(psi_expr)
        gradperp = lambda u: as_vector([-u.dx(1), u.dx(0)])
        u0.project(gradperp(psi0))
    elif direction == "vertical":
        u0.project(as_vector([0, -u_max]))
    theta0.interpolate(theta_b0 + theta_pert0)
    theta1.interpolate(theta_b1 + theta_pert1)

    state.initialise([('u', u0), ('theta1', theta1), ('theta0', theta0)])
    state.set_reference_profiles([('theta1', theta_b1), ('theta0', theta_b0)])

    # set up advection schemes
    dg_opts = EmbeddedDGOptions()
    recovered_opts = RecoveredOptions(embedding_space=VDG1,
                                      recovered_space=VCG1,
                                      broken_space=V0_brok)
    thetaeqn1 = EmbeddedDGAdvection(state,
                                    V1,
                                    equation_form="advective",
                                    options=dg_opts)
    thetaeqn0 = EmbeddedDGAdvection(state,
                                    V0,
                                    equation_form="advective",
                                    options=recovered_opts)

    # build advection dictionary
    advected_fields = []
    advected_fields.append(
        ('theta1', SSPRK3(state, theta1, thetaeqn1, limiter=ThetaLimiter(V1))))
    advected_fields.append(('theta0',
                            SSPRK3(state,
                                   theta0,
                                   thetaeqn0,
                                   limiter=VertexBasedLimiter(VDG1))))

    # build time stepper
    stepper = AdvectionDiffusion(state, advected_fields)

    return stepper, 40.0
Example #12
0
def run_cond_evap(dirname, process):
    # declare grid shape, with length L and height H
    L = 1000.
    H = 1000.
    nlayers = int(H / 10.)
    ncolumns = int(L / 10.)

    # make mesh
    m = PeriodicIntervalMesh(ncolumns, L)
    mesh = ExtrudedMesh(m, layers=nlayers, layer_height=(H / nlayers))
    x, z = SpatialCoordinate(mesh)

    dt = 2.0
    tmax = dt
    output = OutputParameters(dirname=dirname + "/cond_evap",
                              dumpfreq=1,
                              dumplist=['u'])
    parameters = CompressibleParameters()

    state = State(mesh,
                  dt=dt,
                  output=output,
                  parameters=parameters,
                  diagnostic_fields=[
                      Sum('vapour_mixing_ratio', 'cloud_liquid_mixing_ratio')
                  ])

    # spaces
    Vt = state.spaces("theta", degree=1)
    Vr = state.spaces("DG", "DG", degree=1)

    # Set up equation -- use compressible to set up these spaces
    # However the equation itself will be unused
    _ = CompressibleEulerEquations(state, "CG", 1)

    # Declare prognostic fields
    rho0 = state.fields("rho")
    theta0 = state.fields("theta")
    water_v0 = state.fields("vapour_mixing_ratio", Vt)
    water_c0 = state.fields("cloud_liquid_mixing_ratio", Vt)

    # Set a background state with constant pressure and temperature
    pressure = Function(Vr).interpolate(Constant(100000.))
    temperature = Function(Vt).interpolate(Constant(300.))
    theta_d = td.theta(parameters, temperature, pressure)
    mv_sat = td.r_v(parameters, Constant(1.0), temperature, pressure)
    Lv_over_cpT = td.Lv(parameters,
                        temperature) / (parameters.cp * temperature)

    # Apply perturbation
    xc = L / 2.
    zc = H / 2.
    rc = L / 4.
    r = sqrt((x - xc)**2 + (z - zc)**2)
    pert = conditional(r < rc, 1.0, 0.0)

    if process == "evaporation":
        water_v0.interpolate(0.96 * mv_sat)
        water_c0.interpolate(0.005 * mv_sat * pert)
        # Approximate answers
        # Rate of change is roughly (m_sat - m_v) / 4 so should evaporate everything
        mc_true = Function(Vt).interpolate(Constant(0.0))
        theta_d_true = Function(Vt).interpolate(theta_d + 0.005 * mv_sat *
                                                pert * Lv_over_cpT)
        mv_true = Function(Vt).interpolate(mv_sat * (0.96 + 0.005 * pert))
    elif process == "condensation":
        water_v0.interpolate(mv_sat * (1.0 + 0.04 * pert))
        # Approximate answers -- rate of change is roughly (m_v - m_sat) / 4
        mc_true = Function(Vt).interpolate(0.01 * mv_sat * pert)
        theta_d_true = Function(Vt).interpolate(theta_d - 0.01 * mv_sat *
                                                pert * Lv_over_cpT)
        mv_true = Function(Vt).interpolate(mv_sat * (1.0 + 0.03 * pert))

    # Set prognostic variables
    theta0.project(theta_d * (1 + water_v0 * parameters.R_v / parameters.R_d))
    rho0.interpolate(pressure /
                     (temperature * parameters.R_d *
                      (1 + water_v0 * parameters.R_v / parameters.R_d)))
    mc_init = Function(Vt).assign(water_c0)

    # Have empty problem as only thing is condensation / evaporation
    problem = []
    physics_list = [Condensation(state)]

    # build time stepper
    stepper = PrescribedTransport(state, problem, physics_list=physics_list)

    stepper.run(t=0, tmax=tmax)

    return state, mv_true, mc_true, theta_d_true, mc_init
# ---------------
# 1D mesh support ncells, Length (left coords), right coords (opt.)
#  m= IntervalMesh(nx,-L,L)
m = IntervalMesh(nx, L)
xIM = m.coordinates.dat.data


# -> UnitIntervalMesh
# -------------------
m = UnitIntervalMesh(nx)
xUIM = m.coordinates.dat.data


# -> PeriodicInternalMesh
# -----------------------
m = PeriodicIntervalMesh(nx, L)
xPIM = m.coordinates.dat.data

y = np.ones([nx+1, ])
plt.plot(xIM, 0*y, color="black", marker="o", label="IntervalMesh")
plt.plot(xUIM, 1*y, color="red", marker="o", label="UnitIntervalMesh")
plt.plot(xPIM, 2*np.ones(np.shape(xPIM)), color="blue",
         marker="o", label="PeriodicInternalMesh")
plt.legend()
plt.savefig("plots/oneDimensionMesh.png")


# TwoDimensional Meshes
# -> RectangleMesh
# ----------------
# support quadrilateral input (True or False)