def setup_DGadvection(element, vector=False):

    refinements = 3  # number of horizontal cells = 20*(4^refinements)
    R = 1.0
    dt = pi / 3 * 0.01

    mesh = IcosahedralSphereMesh(radius=R, refinement_level=refinements)
    global_normal = Expression(("x[0]", "x[1]", "x[2]"))
    mesh.init_cell_orientations(global_normal)

    fieldlist = ["u", "D"]
    timestepping = TimesteppingParameters(dt=dt)

    state = ShallowWaterState(
        mesh, vertical_degree=None, horizontal_degree=2, family="BDM", timestepping=timestepping, fieldlist=fieldlist
    )

    # interpolate initial conditions
    u0 = Function(state.V[0], name="velocity")
    x = SpatialCoordinate(mesh)
    uexpr = as_vector([-x[1], x[0], 0.0])
    u0.project(uexpr)

    if vector:
        if element is "BDM":
            BrokenSpace = FunctionSpace(mesh, element, 2)
        else:
            BrokenSpace = VectorFunctionSpace(mesh, "DG", 1)
        Space = VectorFunctionSpace(mesh, "CG", 1)
        f = Function(Space, name="f")
        fexpr = Expression(("exp(-pow(x[2],2) - pow(x[1],2))", "0.0", "0.0"))
        f_end = Function(Space)
        f_end_expr = Expression(("exp(-pow(x[2],2) - pow(x[0],2))", "0", "0"))
    else:
        if element is "BDM":
            BrokenSpace = FunctionSpace(mesh, element, 2)
        else:
            BrokenSpace = FunctionSpace(mesh, "DG", 1)
        Space = FunctionSpace(mesh, "CG", 1)
        f = Function(Space, name="f")
        fexpr = Expression("exp(-pow(x[2],2) - pow(x[1],2))")
        f_end = Function(Space)
        f_end_expr = Expression("exp(-pow(x[2],2) - pow(x[0],2))")

    f.interpolate(fexpr)
    f_end.interpolate(f_end_expr)

    return state, BrokenSpace, u0, f, f_end
def setup_SUPGadvection(direction):

    nlayers = 25  # horizontal layers
    columns = 25  # number of columns
    L = 1.0
    m = PeriodicIntervalMesh(columns, L)

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

    # Space for initialising velocity
    W_VectorCG1 = VectorFunctionSpace(mesh, "CG", 1)
    W_CG1 = FunctionSpace(mesh, "CG", 1)

    # vertical coordinate and normal
    z = Function(W_CG1).interpolate(Expression("x[1]"))
    k = Function(W_VectorCG1).interpolate(Expression(("0.","1.")))

    fieldlist = ['u','rho', 'theta']
    timestepping = TimesteppingParameters(dt=0.01)
    parameters = CompressibleParameters()

    state = CompressibleState(mesh, vertical_degree=1, horizontal_degree=1,
                              family="CG",
                              z=z, k=k,
                              timestepping=timestepping,
                              parameters=parameters,
                              fieldlist=fieldlist)

    # interpolate initial conditions
    u0 = Function(state.V[0], name="velocity")
    uexpr = as_vector([1.0, 0.0])
    u0.project(uexpr)

    if len(direction) == 0:
        space = W_CG1
    else:
        space = state.V[2]
    f = Function(space, name='f')
    x = SpatialCoordinate(mesh)
    f_expr = sin(2*pi*x[0])*sin(2*pi*x[1])
    f.interpolate(f_expr)
    f_end = Function(space)
    f_end_expr = sin(2*pi*(x[0]-0.5))*sin(2*pi*x[1])
    f_end.interpolate(f_end_expr)

    return state, u0, f, f_end
Exemple #3
0
def test_mass_transport_solver_convergence(solver_type):
    Lx, Ly = 1.0, 1.0
    u0 = 1.0
    h_in, dh = 1.0, 0.2

    delta_x, error = [], []
    mass_transport = solver_type()
    for N in range(24, 97, 4):
        delta_x.append(Lx / N)

        mesh = firedrake.RectangleMesh(N, N, Lx, Ly)
        x, y = firedrake.SpatialCoordinate(mesh)

        degree = 1
        V = firedrake.VectorFunctionSpace(mesh, family='CG', degree=degree)
        Q = firedrake.FunctionSpace(mesh, family='CG', degree=degree)

        h0 = interpolate(h_in - dh * x / Lx, Q)
        a = firedrake.Function(Q)
        u = interpolate(firedrake.as_vector((u0, 0)), V)
        T = 0.5
        δx = 1.0 / N
        δt = δx / u0
        num_timesteps = int(T / δt)

        h = h0.copy(deepcopy=True)
        for step in range(num_timesteps):
            h = mass_transport.solve(δt, h0=h, a=a, u=u, h_inflow=h0)

        z = x - u0 * num_timesteps * δt
        h_exact = interpolate(h_in - dh / Lx * firedrake.max_value(0, z), Q)
        error.append(norm(h - h_exact) / norm(h_exact))

        print(delta_x[-1], error[-1])

    log_delta_x = np.log2(np.array(delta_x))
    log_error = np.log2(np.array(error))
    slope, intercept = np.polyfit(log_delta_x, log_error, 1)

    print('log(error) ~= {:g} * log(dx) + {:g}'.format(slope, intercept))
    assert slope > degree - 0.1
Exemple #4
0
def test_interpolating_vector_field():
    n = 32
    array_vx = np.array([[(i + j) / n for j in range(n + 1)] for i in range(n + 1)])
    missing = -9999.0
    array_vx[0, 0] = missing
    array_vx = np.flipud(array_vx)

    array_vy = np.array([[(j - i) / n for j in range(n + 1)] for i in range(n + 1)])
    array_vy[-1, -1] = -9999.0
    array_vy = np.flipud(array_vy)

    vx = make_rio_dataset(array_vx, missing)
    vy = make_rio_dataset(array_vy, missing)

    mesh = make_domain(48, 48, xmin=1 / 4, ymin=1 / 4, width=1 / 2, height=1 / 2)
    x, y = firedrake.SpatialCoordinate(mesh)
    V = firedrake.VectorFunctionSpace(mesh, "CG", 1)
    u = firedrake.interpolate(firedrake.as_vector((x + y, x - y)), V)
    v = icepack.interpolate((vx, vy), V)

    assert firedrake.norm(u - v) / firedrake.norm(u) < 1e-10
Exemple #5
0
    def setup(self, state):
        super(GeostrophicImbalance, self).setup(state)
        u = state.fields("u")
        b = state.fields("b")
        p = state.fields("p")
        f = state.parameters.f
        Vu = u.function_space()

        v = TrialFunction(Vu)
        w = TestFunction(Vu)
        a = inner(w, v) * dx
        L = (div(w) * p + inner(w, as_vector([f * u[1], 0.0, b]))) * dx

        bcs = [DirichletBC(Vu, 0.0, "bottom"), DirichletBC(Vu, 0.0, "top")]

        self.imbalance = Function(Vu)
        imbalanceproblem = LinearVariationalProblem(a,
                                                    L,
                                                    self.imbalance,
                                                    bcs=bcs)
        self.imbalance_solver = LinearVariationalSolver(
            imbalanceproblem, solver_parameters={'ksp_type': 'cg'})
Exemple #6
0
    def __init__(self, state):
        super(Fallout, self).__init__(state)

        self.state = state
        self.rain = state.fields('rain')

        # function spaces
        Vt = self.rain.function_space()
        Vu = state.fields('u').function_space()

        # introduce sedimentation rate
        # for now assume all rain falls at terminal velocity
        terminal_velocity = 10  # in m/s
        self.v = state.fields("rainfall_velocity", Vu)
        self.v.project(as_vector([0, -terminal_velocity]))

        # sedimentation will happen using a full advection method
        advection_equation = EmbeddedDGAdvection(state,
                                                 Vt,
                                                 equation_form="advective",
                                                 outflow=True)
        self.advection_method = SSPRK3(state, self.rain, advection_equation)
def test_mass_transport_solver_convergence():
    Lx, Ly = 1.0, 1.0
    u0 = 1.0
    h_in, dh = 1.0, 0.2

    delta_x, error = [], []
    mass_transport = MassTransport()
    for N in range(16, 97, 4):
        delta_x.append(Lx / N)

        mesh = firedrake.RectangleMesh(N, N, Lx, Ly)
        x, y = firedrake.SpatialCoordinate(mesh)

        degree = 1
        V = firedrake.VectorFunctionSpace(mesh, family='CG', degree=degree)
        Q = firedrake.FunctionSpace(mesh, family='CG', degree=degree)

        h = interpolate(h_in - dh * x / Lx, Q)
        a = firedrake.Function(Q)
        u = interpolate(firedrake.as_vector((u0, 0)), V)
        T = 0.5
        num_timesteps = int(0.5 * N * u0 * T / Lx)
        dt = T / num_timesteps

        for k in range(num_timesteps):
            h = mass_transport.solve(dt, h0=h, a=a, u=u)

        z = x - u0 * T
        h_exact = interpolate(h_in - dh / Lx * firedrake.max_value(0, z), Q)
        error.append(norm(h - h_exact) / norm(h_exact))

        print(delta_x[-1], error[-1])

    log_delta_x = np.log2(np.array(delta_x))
    log_error = np.log2(np.array(error))
    slope, intercept = np.polyfit(log_delta_x, log_error, 1)

    assert slope > degree - 0.05
    print(slope, intercept)
Exemple #8
0
def test_strain_heating():
    E_initial = firedrake.interpolate(E_surface + q_bed / α * h * (1 - ζ), Q)

    u0 = 100.0
    du = 100.0
    u_expr = as_vector((u0 + du * x / Lx, 0))
    u = firedrake.interpolate(u_expr, V)
    w = firedrake.interpolate((-du / Lx + dh / Lx / h * u[0]) * ζ, W)

    E_q = E_initial.copy(deepcopy=True)
    E_0 = E_initial.copy(deepcopy=True)

    model = icepack.models.HeatTransport3D()
    from icepack.models.hybrid import (horizontal_strain, vertical_strain,
                                       stresses)
    T = model.temperature(E_q)
    A = icepack.rate_factor(T)
    ε_x, ε_z = horizontal_strain(u, s, h), vertical_strain(u, h)
    τ_x, τ_z = stresses(ε_x, ε_z, A)
    q = inner(τ_x, ε_x) + inner(τ_z, ε_z)

    kwargs = {
        'u': u,
        'w': w,
        'h': h,
        's': s,
        'q_bed': q_bed,
        'E_inflow': E_initial,
        'E_surface': Constant(E_surface)
    }

    dt = 10.0
    final_time = Lx / u0
    num_steps = int(final_time / dt) + 1
    for step in range(num_steps):
        E_q.assign(model.solve(dt, E0=E_q, q=q, **kwargs))
        E_0.assign(model.solve(dt, E0=E_0, q=Constant(0), **kwargs))

    assert assemble(E_q * h * dx) > assemble(E_0 * h * dx)
def initialise_fields(state):

    L = 1.e5
    H = 1.0e4  # Height position of the model top

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

    # spaces
    Vt = theta0.function_space()
    Vr = rho0.function_space()

    # Thermodynamic constants required for setting initial conditions
    # and reference profiles
    g = state.parameters.g
    N = state.parameters.N

    # N^2 = (g/theta)dtheta/dz => dtheta/dz = theta N^2g => theta=theta_0exp(N^2gz)
    x, z = SpatialCoordinate(state.mesh)
    Tsurf = 300.
    thetab = Tsurf * exp(N**2 * z / g)

    theta_b = Function(Vt).interpolate(thetab)
    rho_b = Function(Vr)

    # Calculate hydrostatic exner
    compressible_hydrostatic_balance(state, theta_b, rho_b)

    a = 5.0e3
    deltaTheta = 1.0e-2
    theta_pert = deltaTheta * sin(pi * z / H) / (1 + (x - L / 2)**2 / a**2)
    theta0.interpolate(theta_b + theta_pert)
    rho0.assign(rho_b)
    u0.project(as_vector([20.0, 0.0]))

    state.set_reference_profiles([('rho', rho_b), ('theta', theta_b)])
    def f_g_scattered_plane_wave(self, d):
        """Sets f and g to correspond to the scattering of a plane wave
        by a compactly-supported heterogeneous region.

        Parameters - d - list of the length of the spatial dimension;
        the direction in which the plane wave propagates.
        """

        d = fd.as_vector(d)

        x = fd.SpatialCoordinate(self.V.mesh())

        # Incident wave
        u_I = fd.exp(1j * self._k * fd.dot(x, d))

        identity = fd.as_matrix([[1.0, 0.0], [0.0, 1.0]])

        f = fd.div(fd.dot((identity-self._A),fd.grad(u_I)))\
            + self._k**2.0 * fd.inner((1.0-self._n), u_I)

        self.set_f(f)

        self.set_g(0.0)
Exemple #11
0
def tracer_slice(tmpdir, degree):
    n = 30 if degree == 0 else 15
    m = PeriodicIntervalMesh(n, 1.)
    mesh = ExtrudedMesh(m, layers=n, layer_height=1. / n)

    # Parameters chosen so that dt != 1 and u != 1
    # Gaussian is translated by 1.5 times width of domain to demonstrate
    # that transport is working correctly

    dt = 0.01
    tmax = 0.75
    output = OutputParameters(dirname=str(tmpdir), dumpfreq=25)
    state = State(mesh, dt=dt, output=output)

    uexpr = as_vector([2.0, 0.0])

    x = SpatialCoordinate(mesh)
    width = 1. / 10.
    f0 = 0.5
    fmax = 2.0
    xc_init = 0.25
    xc_end = 0.75
    r_init = sqrt((x[0] - xc_init)**2 + (x[1] - 0.5)**2)
    r_end = sqrt((x[0] - xc_end)**2 + (x[1] - 0.5)**2)
    f_init = f0 + (fmax - f0) * exp(-(r_init / width)**2)
    f_end = f0 + (fmax - f0) * exp(-(r_end / width)**2)

    tol = 0.12

    return TracerSetup(state,
                       tmax,
                       f_init,
                       f_end,
                       "CG",
                       degree,
                       uexpr,
                       tol=tol)
Exemple #12
0
def test_diagnostic_solver_side_friction():
    ice_shelf = icepack.models.IceShelf()
    opts = {'dirichlet_ids': [1], 'side_wall_ids': [3, 4], 'tol': 1e-12}

    mesh = firedrake.RectangleMesh(32, 32, Lx, Ly)
    degree = 2
    V = firedrake.VectorFunctionSpace(mesh, 'CG', degree)
    Q = firedrake.FunctionSpace(mesh, 'CG', degree)

    x, y = firedrake.SpatialCoordinate(mesh)
    u_initial = interpolate(as_vector((exact_u(x), 0)), V)
    h = interpolate(h0 - dh * x / Lx, Q)
    A = interpolate(firedrake.Constant(icepack.rate_factor(T)), Q)

    # Choose the side wall friction coefficient so that, assuming the ice is
    # sliding at the maximum speed for the solution without friction, the
    # stress is 10 kPa.
    from icepack.constants import weertman_sliding_law as m
    τ = 0.01
    u_max = icepack.norm(u_initial, norm_type='Linfty')
    Cs = firedrake.Constant(τ * u_max**(-1 / m))
    u = ice_shelf.diagnostic_solve(u0=u_initial, h=h, A=A, Cs=Cs, **opts)

    assert icepack.norm(u) < icepack.norm(u_initial)
Exemple #13
0
    def static_solver(self):
        def epsilon(u):
            return 0.5 * (fd.nabla_grad(u) + fd.nabla_grad(u).T)
            #return sym(nabla_grad(u))

        def sigma(u):
            d = u.geometric_dimension()  # space dimension
            return self.lam * fd.nabla_div(u) * fd.Identity(
                d) + 2 * self.mu * epsilon(u)

        # Define variational problem
        u = fd.TrialFunction(self.V)
        v = fd.TestFunction(self.V)
        #        f = fd.Constant((0, 0, -self.g)) # body force / rho
        f = fd.Constant((0, 0, 0))  # body force / rho
        T = self.surface_force()

        a = fd.inner(sigma(u), epsilon(v)) * fd.dx
        L = fd.dot(f, v) * fd.dx + fd.dot(T, v) * fd.ds(1)
        # Compute solution
        #  old:        self.DBC = fd.DirichletBC( self.V, fd.Expression([0.,0.,0.]), self.bottom_id)
        self.DBC = fd.DirichletBC(self.V, fd.as_vector([0., 0., 0.]),
                                  self.bottom_id)
        fd.solve(a == L, self.X, bcs=self.DBC)
Exemple #14
0
def test_plot_extruded_field():
    nx, ny = 32, 32
    mesh2d = firedrake.UnitSquareMesh(nx, ny)
    mesh3d = firedrake.ExtrudedMesh(mesh2d, layers=1)
    x, y, z = firedrake.SpatialCoordinate(mesh3d)

    Q = firedrake.FunctionSpace(mesh3d,
                                family='CG',
                                degree=2,
                                vfamily='GL',
                                vdegree=4)
    q = interpolate((x**2 - y**2) * (1 - z**4), Q)
    q_contours = icepack.plot.tricontourf(q)
    assert q_contours is not None

    V = firedrake.VectorFunctionSpace(mesh3d,
                                      dim=2,
                                      family='CG',
                                      degree=2,
                                      vfamily='GL',
                                      vdegree=4)
    u = interpolate(as_vector((1 - z**4, 0)), V)
    u_contours = icepack.plot.tricontourf(u)
    assert u_contours is not None
Exemple #15
0
    def _build_forcing_solvers(self):

        super(CompressibleEadyForcing, self)._build_forcing_solvers()
        # theta_forcing
        dthetady = self.state.parameters.dthetady
        Vt = self.state.spaces("HDiv_v")
        F = TrialFunction(Vt)
        gamma = TestFunction(Vt)
        self.thetaF = Function(Vt)
        u0, _, _ = split(self.x0)

        a = gamma * F * dx
        L = -self.scaling * gamma * (dthetady *
                                     inner(u0, as_vector([0., 1., 0.]))) * dx

        theta_forcing_problem = LinearVariationalProblem(a, L, self.thetaF)

        solver_parameters = {}
        if logger.isEnabledFor(DEBUG):
            solver_parameters["ksp_monitor_true_residual"] = None
        self.theta_forcing_solver = LinearVariationalSolver(
            theta_forcing_problem,
            solver_parameters=solver_parameters,
            options_prefix="ThetaForcingSolver")
N = parameters.N
bref = x[1]*(N**2)
# interpolate the expression to the function
b_b = Function(state.V[2]).interpolate(bref)

# setup constants
a = Constant(5.0e3)
deltab = Constant(1.0e-2)
H = Constant(H)
L = Constant(L)
b_pert = deltab*sin(np.pi*x[1]/H)/(1 + (x[0] - L/2)**2/a**2)
# interpolate the expression to the function
b0.interpolate(b_b + b_pert)

# interpolate velocity to vector valued function space
uinit = Function(W_VectorCG1).interpolate(as_vector([20.0,0.0]))
# project to the function space we actually want to use
# this step is purely because it is not yet possible to interpolate to the
# vector function spaces we require for the compatible finite element
# methods that we use
u0.project(uinit)

# pass these initial conditions to the state.initialise method
state.initialise([u0, p0, b0])
# set the background buoyancy
state.set_reference_profiles(b_b)
# we want to output the perturbation buoyancy, so tell the dump method
# which background field to subtract
state.output.meanfields = {'b':state.bbar}

##############################################################################
Exemple #17
0
from gusto import *
from firedrake import Expression, FunctionSpace, as_vector,\
    VectorFunctionSpace, PeriodicIntervalMesh, ExtrudedMesh, Constant, SpatialCoordinate, exp

nlayers = 70  # horizontal layers
columns = 180  # number of columns
L = 144000.
m = PeriodicIntervalMesh(columns, L)

# build volume mesh
H = 35000.  # Height position of the model top
ext_mesh = ExtrudedMesh(m, layers=nlayers, layer_height=H/nlayers)
Vc = VectorFunctionSpace(ext_mesh, "DG", 2)
coord = SpatialCoordinate(ext_mesh)
x = Function(Vc).interpolate(as_vector([coord[0],coord[1]]))
H = Constant(H)
a = Constant(1000.)
xc = Constant(L/2.)
new_coords = Function(Vc).interpolate(as_vector([x[0], x[1]+(H-x[1])*a**2/(H*((x[0]-xc)**2+a**2))]))
mesh = Mesh(new_coords)

# Space for initialising velocity
W_VectorCG = VectorFunctionSpace(mesh, "CG", 2)
W_CG = FunctionSpace(mesh, "CG", 2)
W_DG = FunctionSpace(mesh, "DG", 2)

# vertical coordinate and normal
z = Function(W_CG).interpolate(Expression("x[1]"))
k = Function(W_VectorCG).interpolate(Expression(("0.","1.")))

dt = 5.0
def setup_condens(dirname):

    # declare grid shape, with length L and height H
    L = 1000.
    H = 1000.
    nlayers = int(H / 100.)
    ncolumns = int(L / 100.)

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

    fieldlist = ['u', 'rho', 'theta']
    timestepping = TimesteppingParameters(dt=1.0, maxk=4, maxi=1)
    output = OutputParameters(dirname=dirname + "/condens",
                              dumpfreq=1,
                              dumplist=['u'],
                              perturbation_fields=['theta', 'rho'])
    parameters = CompressibleParameters()

    state = State(mesh,
                  vertical_degree=1,
                  horizontal_degree=1,
                  family="CG",
                  timestepping=timestepping,
                  output=output,
                  parameters=parameters,
                  fieldlist=fieldlist,
                  diagnostic_fields=[Sum('water_v', 'water_c')])

    # declare initial fields
    u0 = state.fields("u")
    rho0 = state.fields("rho")
    theta0 = state.fields("theta")

    # spaces
    Vpsi = FunctionSpace(mesh, "CG", 2)
    Vt = theta0.function_space()
    Vr = rho0.function_space()

    # make a gradperp
    gradperp = lambda u: as_vector([-u.dx(1), u.dx(0)])

    # declare tracer field and a background field
    water_v0 = state.fields("water_v", Vt)
    water_c0 = state.fields("water_c", Vt)

    # Isentropic background state
    Tsurf = Constant(300.)

    theta_b = Function(Vt).interpolate(Tsurf)
    rho_b = Function(Vr)

    # Calculate initial rho
    compressible_hydrostatic_balance(state, theta_b, rho_b, solve_for_rho=True)

    # set up water_v
    xc = 500.
    zc = 350.
    rc = 250.
    r = sqrt((x[0] - xc)**2 + (x[1] - zc)**2)
    w_expr = conditional(r > rc, 0., 0.25 * (1. + cos((pi / rc) * r)))

    # set up velocity field
    u_max = 10.0

    psi_expr = ((-u_max * L / pi) * sin(2 * pi * x[0] / L) *
                sin(pi * x[1] / L))

    psi0 = Function(Vpsi).interpolate(psi_expr)
    u0.project(gradperp(psi0))
    theta0.interpolate(theta_b)
    rho0.interpolate(rho_b)
    water_v0.interpolate(w_expr)

    state.initialise([('u', u0), ('rho', rho0), ('theta', theta0),
                      ('water_v', water_v0), ('water_c', water_c0)])
    state.set_reference_profiles([('rho', rho_b), ('theta', theta_b)])

    # set up advection schemes
    rhoeqn = AdvectionEquation(state, Vr, equation_form="continuity")
    thetaeqn = SUPGAdvection(state,
                             Vt,
                             supg_params={"dg_direction": "horizontal"},
                             equation_form="advective")

    # build advection dictionary
    advected_fields = []
    advected_fields.append(("u", NoAdvection(state, u0, None)))
    advected_fields.append(("rho", SSPRK3(state, rho0, rhoeqn)))
    advected_fields.append(("theta", SSPRK3(state, theta0, thetaeqn)))
    advected_fields.append(("water_v", SSPRK3(state, water_v0, thetaeqn)))
    advected_fields.append(("water_c", SSPRK3(state, water_c0, thetaeqn)))

    physics_list = [Condensation(state)]

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

    return stepper, 5.0
                                    coords[:, 2], Delta=Delta, data_array=kx_array)
Ky.dat.data[...] = coords2ijk(coords[:, 0], coords[:, 1],
                                    coords[:, 2], Delta=Delta, data_array=ky_array)
Kz.dat.data[...] = coords2ijk(coords[:, 0], coords[:, 1],
                                    coords[:, 2], Delta=Delta, data_array=kz_array)

print("END: Read in reservoir fields")

# Permeability field harmonic interpolation to facets
Kx_facet = fd.conditional(fd.gt(fd.avg(Kx), 0.0), Kx('+')*Kx('-') / fd.avg(Kx), 0.0)
Ky_facet = fd.conditional(fd.gt(fd.avg(Ky), 0.0), Ky('+')*Ky('-') / fd.avg(Ky), 0.0)
Kz_facet = fd.conditional(fd.gt(fd.avg(Kz), 0.0), Kz('+')*Kz('-') / fd.avg(Kz), 0.0)

# We can now define the bilinear and linear forms for the left and right
dx = fd.dx
KdivU = fd.as_vector((Kx_facet*u.dx(0), Ky_facet*u.dx(1), Kz_facet*u.dx(2)))
a = (fd.dot(KdivU, fd.grad(v))) * dx
m = u * v * phi * dx

# Defining the eigenvalue problem

petsc_a = fd.assemble(a).M.handle
petsc_m = fd.assemble(m).M.handle

num_eigenvalues = 3

# Set solver options
opts = PETSc.Options()
opts.setValue("eps_gen_hermitian", None)
#opts.setValue("st_pc_factor_shift_type", "NONZERO")
opts.setValue("eps_type", "krylovschur")
def domainify(vector, x):
    dim = len(x)
    return conditional(
        x[0] > 0.0, vector, as_vector(tuple(0.0 for _ in range(dim)))
    )
def test_3D_dirichlet_regions():
    # Can't do mesh refinement because MeshHierarchy ruins the domain tags
    mesh = Mesh("./3D_mesh.msh")
    dim = mesh.geometric_dimension()
    x = SpatialCoordinate(mesh)
    solver_parameters_amg = {
        "ksp_type": "cg",
        "ksp_converged_reason": None,
        "ksp_rtol": 1e-7,
        "pc_type": "hypre",
        "pc_hypre_type": "boomeramg",
        "pc_hypre_boomeramg_max_iter": 5,
        "pc_hypre_boomeramg_coarsen_type": "PMIS",
        "pc_hypre_boomeramg_agg_nl": 2,
        "pc_hypre_boomeramg_strong_threshold": 0.95,
        "pc_hypre_boomeramg_interp_type": "ext+i",
        "pc_hypre_boomeramg_P_max": 2,
        "pc_hypre_boomeramg_relax_type_all": "sequential-Gauss-Seidel",
        "pc_hypre_boomeramg_grid_sweeps_all": 1,
        "pc_hypre_boomeramg_truncfactor": 0.3,
        "pc_hypre_boomeramg_max_levels": 6,
    }

    S = VectorFunctionSpace(mesh, "CG", 1)
    beta = 1.0
    reg_solver = RegularizationSolver(
        S,
        mesh,
        beta=beta,
        gamma=0.0,
        dx=dx,
        design_domain=0,
        solver_parameters=solver_parameters_amg,
    )

    # Exact solution with free Neumann boundary conditions for this domain
    u_exact = Function(S)
    u_exact_component = (
        (-cos(x[0] * pi * 2) + 1)
        * (-cos(x[1] * pi * 2) + 1)
        * (-cos(x[2] * pi * 2) + 1)
    )

    u_exact.interpolate(
        as_vector(tuple(u_exact_component for _ in range(dim)))
    )
    f = Function(S)
    f_component = (
        -beta
        * (
            4.0
            * pi
            * pi
            * cos(2 * pi * x[0])
            * (-cos(2 * pi * x[1]) + 1)
            * (-cos(2 * pi * x[2]) + 1)
            + 4.0
            * pi
            * pi
            * cos(2 * pi * x[1])
            * (-cos(2 * pi * x[0]) + 1)
            * (-cos(2 * pi * x[2]) + 1)
            + 4.0
            * pi
            * pi
            * cos(2 * pi * x[2])
            * (-cos(2 * pi * x[1]) + 1)
            * (-cos(2 * pi * x[0]) + 1)
        )
        + u_exact_component
    )
    f.interpolate(as_vector(tuple(f_component for _ in range(dim))))

    theta = TestFunction(S)
    rhs_form = inner(f, theta) * dx

    velocity = Function(S)
    rhs = assemble(rhs_form)
    reg_solver.solve(velocity, rhs)
    error = norm(
        project(
            domainify(u_exact, x) - velocity,
            S,
            solver_parameters=solver_parameters_amg,
        )
    )
    assert error < 5e-2
def setup_sw(dirname):
    refinements = 3  # number of horizontal cells = 20*(4^refinements)

    R = 6371220.
    H = 2000.
    day = 24.*60.*60.
    u_0 = 2*pi*R/(12*day)  # Maximum amplitude of the zonal wind (m/s)

    mesh = IcosahedralSphereMesh(radius=R,
                                 refinement_level=refinements, degree=3)
    global_normal = Expression(("x[0]", "x[1]", "x[2]"))
    mesh.init_cell_orientations(global_normal)

    fieldlist = ['u', 'D']
    timestepping = TimesteppingParameters(dt=3600.)
    output = OutputParameters(dirname=dirname+"/sw_linear_w2", steady_state_dump_err={'u':True,'D':True}, dumpfreq=12)
    parameters = ShallowWaterParameters(H=H)
    diagnostics = Diagnostics(*fieldlist)

    state = ShallowWaterState(mesh, vertical_degree=None, horizontal_degree=1,
                              family="BDM",
                              timestepping=timestepping,
                              output=output,
                              parameters=parameters,
                              diagnostics=diagnostics,
                              fieldlist=fieldlist)

    g = parameters.g
    Omega = parameters.Omega

    # Coriolis expression
    R = Constant(R)
    Omega = Constant(parameters.Omega)
    x = SpatialCoordinate(mesh)
    fexpr = 2*Omega*x[2]/R
    V = FunctionSpace(mesh, "CG", 1)
    state.f = Function(V).interpolate(fexpr)  # Coriolis frequency (1/s)
    u_max = Constant(u_0)

    # interpolate initial conditions
    # Initial/current conditions
    u0, D0 = Function(state.V[0]), Function(state.V[1])
    uexpr = as_vector([-u_max*x[1]/R, u_max*x[0]/R, 0.0])
    g = Constant(parameters.g)
    Dexpr = - ((R * Omega * u_max)*(x[2]*x[2]/(R*R)))/g
    u0.project(uexpr)
    D0.interpolate(Dexpr)
    state.initialise([u0, D0])

    advection_dict = {}
    advection_dict["u"] = NoAdvection(state)
    advection_dict["D"] = NoAdvection(state)

    linear_solver = ShallowWaterSolver(state)

    # Set up forcing
    sw_forcing = ShallowWaterForcing(state, linear=True)

    # build time stepper
    stepper = Timestepper(state, advection_dict, linear_solver,
                          sw_forcing)

    return stepper, 2*day
Exemple #23
0
    def split(self, fields):
        from firedrake import replace, as_vector, split
        from firedrake import NonlinearVariationalProblem as NLVP
        fields = tuple(tuple(f) for f in fields)
        splits = self._splits.get(tuple(fields))
        if splits is not None:
            return splits

        splits = []
        problem = self._problem
        splitter = ExtractSubBlock()
        for field in fields:
            F = splitter.split(problem.F, argument_indices=(field, ))
            J = splitter.split(problem.J, argument_indices=(field, field))
            us = problem.u.split()
            V = F.arguments()[0].function_space()
            # Exposition:
            # We are going to make a new solution Function on the sub
            # mixed space defined by the relevant fields.
            # But the form may refer to the rest of the solution
            # anyway.
            # So we pull it apart and will make a new function on the
            # subspace that shares data.
            pieces = [us[i].dat for i in field]
            if len(pieces) == 1:
                val, = pieces
                subu = function.Function(V, val=val)
                subsplit = (subu, )
            else:
                val = op2.MixedDat(pieces)
                subu = function.Function(V, val=val)
                # Split it apart to shove in the form.
                subsplit = split(subu)
            # Permutation from field indexing to indexing of pieces
            field_renumbering = dict([f, i] for i, f in enumerate(field))
            vec = []
            for i, u in enumerate(us):
                if i in field:
                    # If this is a field we're keeping, get it from
                    # the new function. Otherwise just point to the
                    # old data.
                    u = subsplit[field_renumbering[i]]
                if u.ufl_shape == ():
                    vec.append(u)
                else:
                    for idx in numpy.ndindex(u.ufl_shape):
                        vec.append(u[idx])

            # So now we have a new representation for the solution
            # vector in the old problem. For the fields we're going
            # to solve for, it points to a new Function (which wraps
            # the original pieces). For the rest, it points to the
            # pieces from the original Function.
            # IOW, we've reinterpreted our original mixed solution
            # function as being made up of some spaces we're still
            # solving for, and some spaces that have just become
            # coefficients in the new form.
            u = as_vector(vec)
            F = replace(F, {problem.u: u})
            J = replace(J, {problem.u: u})
            if problem.Jp is not None:
                Jp = splitter.split(problem.Jp, argument_indices=(field, field))
                Jp = replace(Jp, {problem.u: u})
            else:
                Jp = None
            bcs = []
            for bc in problem.bcs:
                Vbc = bc.function_space()
                if Vbc.parent is not None and isinstance(Vbc.parent.ufl_element(), VectorElement):
                    index = Vbc.parent.index
                else:
                    index = Vbc.index
                cmpt = Vbc.component
                # TODO: need to test this logic
                if index in field:
                    if len(field) == 1:
                        W = V
                    else:
                        W = V.sub(field_renumbering[index])
                    if cmpt is not None:
                        W = W.sub(cmpt)
                    bcs.append(type(bc)(W,
                                        bc.function_arg,
                                        bc.sub_domain,
                                        method=bc.method))
            new_problem = NLVP(F, subu, bcs=bcs, J=J, Jp=Jp,
                               form_compiler_parameters=problem.form_compiler_parameters)
            new_problem._constant_jacobian = problem._constant_jacobian
            splits.append(type(self)(new_problem, mat_type=self.mat_type, pmat_type=self.pmat_type,
                                     appctx=self.appctx))
        return self._splits.setdefault(tuple(fields), splits)
Exemple #24
0
    def __init__(self,
                 mesh,
                 dt,
                 output=None,
                 parameters=None,
                 diagnostics=None,
                 diagnostic_fields=None):

        if output is None:
            raise RuntimeError(
                "You must provide a directory name for dumping results")
        else:
            self.output = output
        self.parameters = parameters

        if diagnostics is not None:
            self.diagnostics = diagnostics
        else:
            self.diagnostics = Diagnostics()
        if diagnostic_fields is not None:
            self.diagnostic_fields = diagnostic_fields
        else:
            self.diagnostic_fields = []

        # The mesh
        self.mesh = mesh

        self.spaces = SpaceCreator(mesh)

        if self.output.dumplist is None:

            self.output.dumplist = []

        self.fields = StateFields(*self.output.dumplist)

        self.dumpdir = None
        self.dumpfile = None
        self.to_pickup = None

        # figure out if we're on a sphere
        try:
            self.on_sphere = (mesh._base_mesh.geometric_dimension() == 3
                              and mesh._base_mesh.topological_dimension() == 2)
        except AttributeError:
            self.on_sphere = (mesh.geometric_dimension() == 3
                              and mesh.topological_dimension() == 2)

        #  build the vertical normal and define perp for 2d geometries
        dim = mesh.topological_dimension()
        if self.on_sphere:
            x = SpatialCoordinate(mesh)
            R = sqrt(inner(x, x))
            self.k = interpolate(x / R, mesh.coordinates.function_space())
            if dim == 2:
                outward_normals = CellNormal(mesh)
                self.perp = lambda u: cross(outward_normals, u)
        else:
            kvec = [0.0] * dim
            kvec[dim - 1] = 1.0
            self.k = Constant(kvec)
            if dim == 2:
                self.perp = lambda u: as_vector([-u[1], u[0]])

        # setup logger
        logger.setLevel(output.log_level)
        set_log_handler(mesh.comm)
        if parameters is not None:
            logger.info("Physical parameters that take non-default values:")
            logger.info(", ".join("%s: %s" % (k, float(v))
                                  for (k, v) in vars(parameters).items()))

        #  Constant to hold current time
        self.t = Constant(0.0)
        if type(dt) is Constant:
            self.dt = dt
        elif type(dt) in (float, int):
            self.dt = Constant(dt)
        else:
            raise TypeError(
                f'dt must be a Constant, float or int, not {type(dt)}')
thetab = Tsurf*exp(N**2*z/g)

theta_b = Function(state.V[2]).interpolate(thetab)
rho_b = Function(state.V[1])

# Calculate hydrostatic Pi
compressible_hydrostatic_balance(state, theta_b, rho_b)

W_DG1 = FunctionSpace(mesh, "DG", 1)
x = Function(W_DG1).interpolate(Expression("x[0]"))
a = 5.0e3
deltaTheta = 1.0e-2
theta_pert = deltaTheta*sin(np.pi*z/H)/(1 + (x - L/2)**2/a**2)
theta0.interpolate(theta_b + theta_pert)
rho0.assign(rho_b)
u0.project(as_vector([20.0,0.0]))

state.initialise([u0, rho0, theta0])
state.set_reference_profiles(rho_b, theta_b)
state.output.meanfields = {'rho':state.rhobar, 'theta':state.thetabar}

# Set up advection schemes
Vtdg = FunctionSpace(mesh, "DG", 2)
advection_dict = {}
advection_dict["u"] = EulerPoincareForm(state, state.V[0])
advection_dict["rho"] = DGAdvection(state, state.V[1], continuity=True)
advection_dict["theta"] = EmbeddedDGAdvection(state, state.V[2], Vdg=Vtdg, continuity=False)

# Set up linear solver
schur_params = {'pc_type': 'fieldsplit',
                'pc_fieldsplit_type': 'schur',
def setup_sw(dirname, euler_poincare):

    refinements = 3  # number of horizontal cells = 20*(4^refinements)

    mesh = IcosahedralSphereMesh(radius=R, refinement_level=refinements)
    x = SpatialCoordinate(mesh)
    mesh.init_cell_orientations(x)

    fieldlist = ['u', 'D']
    timestepping = TimesteppingParameters(dt=1500.)
    output = OutputParameters(dirname=dirname + "/sw",
                              dumplist_latlon=['D', 'D_error'],
                              steady_state_error_fields=['D', 'u'])
    parameters = ShallowWaterParameters(H=H)
    diagnostic_fields = [
        RelativeVorticity(),
        AbsoluteVorticity(),
        PotentialVorticity(),
        ShallowWaterPotentialEnstrophy('RelativeVorticity'),
        ShallowWaterPotentialEnstrophy('AbsoluteVorticity'),
        ShallowWaterPotentialEnstrophy('PotentialVorticity'),
        Difference('RelativeVorticity', 'AnalyticalRelativeVorticity'),
        Difference('AbsoluteVorticity', 'AnalyticalAbsoluteVorticity'),
        Difference('PotentialVorticity', 'AnalyticalPotentialVorticity'),
        Difference('SWPotentialEnstrophy_from_PotentialVorticity',
                   'SWPotentialEnstrophy_from_RelativeVorticity'),
        Difference('SWPotentialEnstrophy_from_PotentialVorticity',
                   'SWPotentialEnstrophy_from_AbsoluteVorticity'),
        MeridionalComponent('u'),
        ZonalComponent('u'),
        RadialComponent('u')
    ]

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

    # interpolate initial conditions
    u0 = state.fields("u")
    D0 = state.fields("D")
    uexpr = as_vector([-u_max * x[1] / R, u_max * x[0] / R, 0.0])
    Omega = parameters.Omega
    g = parameters.g
    Dexpr = H - ((R * Omega * u_max + u_max * u_max / 2.0) * (x[2] * x[2] /
                                                              (R * R))) / g
    # Coriolis
    fexpr = 2 * Omega * x[2] / R
    V = FunctionSpace(mesh, "CG", 1)
    f = state.fields("coriolis", Function(V))
    f.interpolate(fexpr)  # Coriolis frequency (1/s)

    u0.project(uexpr)
    D0.interpolate(Dexpr)
    state.initialise([('u', u0), ('D', D0)])

    if euler_poincare:
        ueqn = EulerPoincare(state, u0.function_space())
        sw_forcing = ShallowWaterForcing(state, euler_poincare=True)
    else:
        ueqn = VectorInvariant(state, u0.function_space())
        sw_forcing = ShallowWaterForcing(state, euler_poincare=False)

    Deqn = AdvectionEquation(state,
                             D0.function_space(),
                             equation_form="continuity")
    advected_fields = []
    advected_fields.append(("u", ThetaMethod(state, u0, ueqn)))
    advected_fields.append(("D", SSPRK3(state, D0, Deqn)))

    linear_solver = ShallowWaterSolver(state)

    # build time stepper
    stepper = CrankNicolson(state, advected_fields, linear_solver, sw_forcing)

    vspace = FunctionSpace(state.mesh, "CG", 3)
    vexpr = (2 * u_max / R) * x[2] / R
    vrel_analytical = state.fields("AnalyticalRelativeVorticity", vspace)
    vrel_analytical.interpolate(vexpr)
    vabs_analytical = state.fields("AnalyticalAbsoluteVorticity", vspace)
    vabs_analytical.interpolate(vexpr + f)
    pv_analytical = state.fields("AnalyticalPotentialVorticity", vspace)
    pv_analytical.interpolate((vexpr + f) / D0)

    return stepper, 0.25 * day
    tmax = dt
else:
    tmax = 9000.


nlayers = 70  # horizontal layers
columns = 180  # number of columns
L = 144000.
m = PeriodicIntervalMesh(columns, L)

# build volume mesh
H = 35000.  # Height position of the model top
ext_mesh = ExtrudedMesh(m, layers=nlayers, layer_height=H/nlayers)
Vc = VectorFunctionSpace(ext_mesh, "DG", 2)
coord = SpatialCoordinate(ext_mesh)
x = Function(Vc).interpolate(as_vector([coord[0], coord[1]]))
a = 1000.
xc = L/2.
x, z = SpatialCoordinate(ext_mesh)
hm = 1.
zs = hm*a**2/((x-xc)**2 + a**2)

smooth_z = True
dirname = 'nh_mountain'
if smooth_z:
    dirname += '_smootherz'
    zh = 5000.
    xexpr = as_vector([x, conditional(z < zh, z + cos(0.5*pi*z/zh)**6*zs, z)])
else:
    xexpr = as_vector([x, z + ((H-z)/H)*zs])
Exemple #28
0
#
#np.save('./spe10z85_kx.npy', kx_array)
#np.save('./spe10z85_ky.npy', ky_array)
#np.save('./spe10z85_phi.npy', phi_array)
kx_geomean = np.exp(np.log(kx_array).sum()/(Nx*Ny))
ky_geomean = np.exp(np.log(ky_array).sum()/(Nx*Ny))
Kx_hom = fd.Constant(kx_geomean)
Ky_hom = fd.Constant(ky_geomean)
phi_hom = fd.Constant(phi_array.mean())
print("END: Read in reservoir fields")
# -----------------------------------------------------------------------------
# Solve homogeneous problem
# -----------------------------------------------------------------------------
print("START: Solve homogeneous problem")
dx = fd.dx
KdivU = fd.as_vector((Kx_hom*u.dx(0), Ky_hom*u.dx(1)))
a = (fd.dot(KdivU, fd.grad(v))) * dx
m = u * v * phi_hom * dx

# Defining the eigenvalue problem

petsc_a = fd.assemble(a).M.handle
petsc_m = fd.assemble(m).M.handle

num_eigenvalues = 30

# Set solver options
opts = PETSc.Options()
opts.setValue("eps_gen_hermitian", None)
opts.setValue("st_pc_factor_shift_type", "NONZERO")
opts.setValue('st_type', 'sinvert')
Exemple #29
0
fieldlist = ['u', 'rho', 'theta']
timestepping = TimesteppingParameters(dt=dt)

dirname = 'sk_hydrostatic'

output = OutputParameters(dirname=dirname,
                          dumpfreq=50,
                          dumplist=['u'],
                          perturbation_fields=['theta', 'rho'],
                          log_level='INFO')

parameters = CompressibleParameters()
diagnostics = Diagnostics(*fieldlist)
diagnostic_fields = [CourantNumber()]

Omega = as_vector((0., 0., 0.5e-4))

state = State(mesh,
              vertical_degree=1,
              horizontal_degree=1,
              family="RTCF",
              Coriolis=Omega,
              timestepping=timestepping,
              output=output,
              parameters=parameters,
              diagnostics=diagnostics,
              fieldlist=fieldlist,
              diagnostic_fields=diagnostic_fields)

# Initial conditions
u0 = state.fields("u")
# rescaling
beta = 1.0
f = f / beta
L = beta * L

# Construct 2D periodic base mesh
m = PeriodicRectangleMesh(columns, 1, 2. * L, 1.e5, quadrilateral=True)

# build 3D mesh by extruding the base mesh
mesh = ExtrudedMesh(m, layers=nlayers, layer_height=H / nlayers)

##############################################################################
# set up all the other things that state requires
##############################################################################
# Coriolis expression
Omega = as_vector([0., 0., f * 0.5])

# list of prognostic fieldnames
# this is passed to state and used to construct a dictionary,
# state.field_dict so that we can access fields by name
# u is the 3D velocity
# p is the pressure
# b is the buoyancy
fieldlist = ['u', 'p', 'b']

# class containing timestepping parameters
# all values not explicitly set here use the default values provided
# and documented in configuration.py
timestepping = TimesteppingParameters(dt=dt)

# class containing output parameters
def test_3D_cartesian_recovery(geometry, element, mesh, expr):

    family = "RTCF" if element == "quadrilateral" else "BDM"

    # horizontal base spaces
    cell = mesh._base_mesh.ufl_cell().cellname()
    u_hori = FiniteElement(family, 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

    # DG1
    DG1_hori = FiniteElement("DG", cell, 1, variant="equispaced")
    DG1_vert = FiniteElement("DG", interval, 1, variant="equispaced")
    DG1_elt = TensorProductElement(DG1_hori, DG1_vert)
    DG1 = FunctionSpace(mesh, DG1_elt)
    vec_DG1 = VectorFunctionSpace(mesh, DG1_elt)

    # spaces
    DG0 = FunctionSpace(mesh, "DG", 0)
    CG1 = FunctionSpace(mesh, "CG", 1)
    Vt = FunctionSpace(mesh, theta_element)
    Vt_brok = FunctionSpace(mesh, BrokenElement(theta_element))
    Vu = FunctionSpace(mesh, v_element)
    vec_CG1 = VectorFunctionSpace(mesh, "CG", 1)

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

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

    # make the recoverers and do the recovery
    rho_recoverer = Recoverer(rho_DG0, rho_CG1, VDG=DG1, boundary_method=Boundary_Method.dynamics)
    theta_recoverer = Recoverer(theta_Vt, theta_CG1, VDG=DG1, boundary_method=Boundary_Method.dynamics)
    v_recoverer = Recoverer(v_Vu, v_CG1, VDG=vec_DG1, 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)

    tolerance = 1e-7
    error_message = ("""
                     Incorrect recovery for {variable} with {boundary} boundary method
                     on {geometry} 3D Cartesian domain with {element} elements
                     """)
    assert rho_diff < tolerance, error_message.format(variable='rho', boundary='dynamics',
                                                      geometry=geometry, element=element)
    assert v_diff < tolerance, error_message.format(variable='v', boundary='dynamics',
                                                    geometry=geometry, element=element)
    assert theta_diff < tolerance, error_message.format(variable='rho', boundary='dynamics',
                                                        geometry=geometry, element=element)
    assert rho_Vt_diff < tolerance, error_message.format(variable='rho', boundary='physics',
                                                         geometry=geometry, element=element)
Exemple #32
0
    def __init__(self, state, V):
        super(EulerPoincareForm, self).__init__(state)

        dt = state.timestepping.dt
        w = TestFunction(V)
        u = TrialFunction(V)
        self.u0 = Function(V)
        ustar = 0.5*(self.u0 + u)
        n = FacetNormal(state.mesh)
        Upwind = 0.5*(sign(dot(self.ubar, n))+1)

        if state.mesh.geometric_dimension() == 3:

            if V.extruded:
                surface_measure = (dS_h + dS_v)
            else:
                surface_measure = dS

            # <w,curl(u) cross ubar + grad( u.ubar)>
            # =<curl(u),ubar cross w> - <div(w), u.ubar>
            # =<u,curl(ubar cross w)> -
            #      <<u_upwind, [[n cross(ubar cross w)cross]]>>

            both = lambda u: 2*avg(u)

            Eqn = (
                inner(w, u-self.u0)*dx
                + dt*inner(ustar, curl(cross(self.ubar, w)))*dx
                - dt*inner(both(Upwind*ustar),
                           both(cross(n, cross(self.ubar, w))))*surface_measure
                - dt*div(w)*inner(ustar, self.ubar)*dx
            )

        # define surface measure and terms involving perp differently
        # for slice (i.e. if V.extruded is True) and shallow water
        # (V.extruded is False)
        else:
            if V.extruded:
                surface_measure = (dS_h + dS_v)
                perp = lambda u: as_vector([-u[1], u[0]])
                perp_u_upwind = Upwind('+')*perp(ustar('+')) + Upwind('-')*perp(ustar('-'))
            else:
                surface_measure = dS
                outward_normals = CellNormal(state.mesh)
                perp = lambda u: cross(outward_normals, u)
                perp_u_upwind = Upwind('+')*cross(outward_normals('+'),ustar('+')) + Upwind('-')*cross(outward_normals('-'),ustar('-'))

            Eqn = (
                (inner(w, u-self.u0)
                 - dt*inner(w, div(perp(ustar))*perp(self.ubar))
                 - dt*div(w)*inner(ustar, self.ubar))*dx
                - dt*inner(jump(inner(w, perp(self.ubar)), n),
                           perp_u_upwind)*surface_measure
                + dt*jump(inner(w,
                                perp(self.ubar))*perp(ustar), n)*surface_measure
            )

        a = lhs(Eqn)
        L = rhs(Eqn)
        self.u1 = Function(V)
        uproblem = LinearVariationalProblem(a, L, self.u1)
        self.usolver = LinearVariationalSolver(uproblem,
                                               options_prefix='EPAdvection')
        'ksp_type': 'preonly',
        'pc_type': 'bjacobi',
        'sub_pc_type': 'ilu'
    }
}

compressible_hydrostatic_balance(state, theta_b, rho_b, params=piparams)

PETSc.Sys.Print("Finished computing hydrostatic varaibles...\n")

a = 5.0e3
deltaTheta = 1.0e-2
theta_pert = deltaTheta * sin(np.pi * z / H) / (1 + (x - L / 2)**2 / a**2)
theta0.interpolate(theta_b + theta_pert)
rho0.assign(rho_b)
u0.project(as_vector([20.0, 0.0]))

state.initialise([('u', u0), ('rho', rho0), ('theta', theta0)])
state.set_reference_profiles([('rho', rho_b), ('theta', theta_b)])

# Set up advection schemes
ueqn = EulerPoincare(state, Vu)
rhoeqn = AdvectionEquation(state, Vr, equation_form="continuity")

supg = True
if supg:
    thetaeqn = SUPGAdvection(state, Vt, equation_form="advective")
else:
    thetaeqn = EmbeddedDGAdvection(state,
                                   Vt,
                                   equation_form="advective",
g = parameters.g
Omega = parameters.Omega

# Coriolis expression
R = Constant(R)
Omega = Constant(parameters.Omega)
x = SpatialCoordinate(mesh)
fexpr = 2*Omega*x[2]/R
V = FunctionSpace(mesh, "CG", 1)
state.f = Function(V).interpolate(fexpr)  # Coriolis frequency (1/s)
u_max = Constant(u_0)

# interpolate initial conditions
# Initial/current conditions
u0, D0 = Function(state.V[0]), Function(state.V[1])
uexpr = as_vector([-u_max*x[1]/R, u_max*x[0]/R, 0.0])
g = Constant(parameters.g)
Dexpr = - ((R * Omega * u_max)*(x[2]*x[2]/(R*R)))/g
u0.project(uexpr)
D0.interpolate(Dexpr)
state.initialise([u0, D0])

advection_dict = {}
advection_dict["u"] = NoAdvection(state)
advection_dict["D"] = NoAdvection(state)

linear_solver = ShallowWaterSolver(state)

# Set up forcing
sw_forcing = ShallowWaterForcing(state)
Exemple #35
0
def heat_exchanger_optimization(mu=0.03, n_iters=1000):

    output_dir = "2D/"

    path = os.path.abspath(__file__)
    dir_path = os.path.dirname(path)
    mesh = fd.Mesh(f"{dir_path}/2D_mesh.msh")
    # Perturb the mesh coordinates. Necessary to calculate shape derivatives
    S = fd.VectorFunctionSpace(mesh, "CG", 1)
    s = fd.Function(S, name="deform")
    mesh.coordinates.assign(mesh.coordinates + s)

    # Initial level set function
    x, y = fd.SpatialCoordinate(mesh)
    PHI = fd.FunctionSpace(mesh, "CG", 1)
    phi_expr = sin(y * pi / 0.2) * cos(x * pi / 0.2) - fd.Constant(0.8)
    # Avoid recording the operation interpolate into the tape.
    # Otherwise, the shape derivatives will not be correct
    with fda.stop_annotating():
        phi = fd.interpolate(phi_expr, PHI)
        phi.rename("LevelSet")
        fd.File(output_dir + "phi_initial.pvd").write(phi)

    # Physics
    mu = fd.Constant(mu)  # viscosity
    alphamin = 1e-12
    alphamax = 2.5 / (2e-4)
    parameters = {
        "mat_type": "aij",
        "ksp_type": "preonly",
        "ksp_converged_reason": None,
        "pc_type": "lu",
        "pc_factor_mat_solver_type": "mumps",
    }
    stokes_parameters = parameters
    temperature_parameters = parameters
    u_inflow = 2e-3
    tin1 = fd.Constant(10.0)
    tin2 = fd.Constant(100.0)

    P2 = fd.VectorElement("CG", mesh.ufl_cell(), 2)
    P1 = fd.FiniteElement("CG", mesh.ufl_cell(), 1)
    TH = P2 * P1
    W = fd.FunctionSpace(mesh, TH)

    U = fd.TrialFunction(W)
    u, p = fd.split(U)
    V = fd.TestFunction(W)
    v, q = fd.split(V)

    epsilon = fd.Constant(10000.0)

    def hs(phi, epsilon):
        return fd.Constant(alphamax) * fd.Constant(1.0) / (
            fd.Constant(1.0) + exp(-epsilon * phi)) + fd.Constant(alphamin)

    def stokes(phi, BLOCK_INLET_MOUTH, BLOCK_OUTLET_MOUTH):
        a_fluid = mu * inner(grad(u), grad(v)) - div(v) * p - q * div(u)
        darcy_term = inner(u, v)
        return (a_fluid * dx + hs(phi, epsilon) * darcy_term * dx(0) +
                alphamax * darcy_term *
                (dx(BLOCK_INLET_MOUTH) + dx(BLOCK_OUTLET_MOUTH)))

    # Dirichlet boundary conditions
    inflow1 = fd.as_vector([
        u_inflow * sin(
            ((y - (line_sep -
                   (dist_center + inlet_width))) * pi) / inlet_width),
        0.0,
    ])
    inflow2 = fd.as_vector([
        u_inflow * sin(((y - (line_sep + dist_center)) * pi) / inlet_width),
        0.0,
    ])

    noslip = fd.Constant((0.0, 0.0))

    # Stokes 1
    bcs1_1 = fd.DirichletBC(W.sub(0), noslip, WALLS)
    bcs1_2 = fd.DirichletBC(W.sub(0), inflow1, INLET1)
    bcs1_3 = fd.DirichletBC(W.sub(1), fd.Constant(0.0), OUTLET1)
    bcs1_4 = fd.DirichletBC(W.sub(0), noslip, INLET2)
    bcs1_5 = fd.DirichletBC(W.sub(0), noslip, OUTLET2)
    bcs1 = [bcs1_1, bcs1_2, bcs1_3, bcs1_4, bcs1_5]

    # Stokes 2
    bcs2_1 = fd.DirichletBC(W.sub(0), noslip, WALLS)
    bcs2_2 = fd.DirichletBC(W.sub(0), inflow2, INLET2)
    bcs2_3 = fd.DirichletBC(W.sub(1), fd.Constant(0.0), OUTLET2)
    bcs2_4 = fd.DirichletBC(W.sub(0), noslip, INLET1)
    bcs2_5 = fd.DirichletBC(W.sub(0), noslip, OUTLET1)
    bcs2 = [bcs2_1, bcs2_2, bcs2_3, bcs2_4, bcs2_5]

    # Forward problems
    U1, U2 = fd.Function(W), fd.Function(W)
    L = inner(fd.Constant((0.0, 0.0, 0.0)), V) * dx
    problem = fd.LinearVariationalProblem(stokes(-phi, INMOUTH2, OUTMOUTH2),
                                          L,
                                          U1,
                                          bcs=bcs1)
    solver_stokes1 = fd.LinearVariationalSolver(
        problem,
        solver_parameters=stokes_parameters,
        options_prefix="stokes_1")
    solver_stokes1.solve()
    problem = fd.LinearVariationalProblem(stokes(phi, INMOUTH1, OUTMOUTH1),
                                          L,
                                          U2,
                                          bcs=bcs2)
    solver_stokes2 = fd.LinearVariationalSolver(
        problem,
        solver_parameters=stokes_parameters,
        options_prefix="stokes_2")
    solver_stokes2.solve()

    # Convection difussion equation
    ks = fd.Constant(1e0)
    cp_value = 5.0e5
    cp = fd.Constant(cp_value)
    T = fd.FunctionSpace(mesh, "DG", 1)
    t = fd.Function(T, name="Temperature")
    w = fd.TestFunction(T)

    # Mesh-related functions
    n = fd.FacetNormal(mesh)
    h = fd.CellDiameter(mesh)
    u1, p1 = fd.split(U1)
    u2, p2 = fd.split(U2)

    def upwind(u):
        return (dot(u, n) + abs(dot(u, n))) / 2.0

    u1n = upwind(u1)
    u2n = upwind(u2)

    # Penalty term
    alpha = fd.Constant(500.0)
    # Bilinear form
    a_int = dot(grad(w), ks * grad(t) - cp * (u1 + u2) * t) * dx

    a_fac = (fd.Constant(-1.0) * ks * dot(avg(grad(w)), jump(t, n)) * dS +
             fd.Constant(-1.0) * ks * dot(jump(w, n), avg(grad(t))) * dS +
             ks("+") *
             (alpha("+") / avg(h)) * dot(jump(w, n), jump(t, n)) * dS)

    a_vel = (dot(
        jump(w),
        cp * (u1n("+") + u2n("+")) * t("+") - cp *
        (u1n("-") + u2n("-")) * t("-"),
    ) * dS + dot(w,
                 cp * (u1n + u2n) * t) * ds)

    a_bnd = (dot(w,
                 cp * dot(u1 + u2, n) * t) * (ds(INLET1) + ds(INLET2)) +
             w * t * (ds(INLET1) + ds(INLET2)) - w * tin1 * ds(INLET1) -
             w * tin2 * ds(INLET2) + alpha / h * ks * w * t *
             (ds(INLET1) + ds(INLET2)) - ks * dot(grad(w), t * n) *
             (ds(INLET1) + ds(INLET2)) - ks * dot(grad(t), w * n) *
             (ds(INLET1) + ds(INLET2)))

    aT = a_int + a_fac + a_vel + a_bnd

    LT_bnd = (alpha / h * ks * tin1 * w * ds(INLET1) +
              alpha / h * ks * tin2 * w * ds(INLET2) -
              tin1 * ks * dot(grad(w), n) * ds(INLET1) -
              tin2 * ks * dot(grad(w), n) * ds(INLET2))

    problem = fd.LinearVariationalProblem(derivative(aT, t), LT_bnd, t)
    solver_temp = fd.LinearVariationalSolver(
        problem,
        solver_parameters=temperature_parameters,
        options_prefix="temperature",
    )
    solver_temp.solve()
    # fd.solve(eT == 0, t, solver_parameters=temperature_parameters)

    # Cost function: Flux at the cold outlet
    scale_factor = 4e-4
    Jform = fd.assemble(
        fd.Constant(-scale_factor * cp_value) * inner(t * u1, n) * ds(OUTLET1))
    # Constraints: Pressure drop on each fluid
    power_drop = 1e-2
    Power1 = fd.assemble(p1 / power_drop * ds(INLET1))
    Power2 = fd.assemble(p2 / power_drop * ds(INLET2))

    phi_pvd = fd.File("phi_evolution.pvd")

    def deriv_cb(phi):
        with stop_annotating():
            phi_pvd.write(phi[0])

    c = fda.Control(s)

    # Reduced Functionals
    Jhat = LevelSetFunctional(Jform, c, phi, derivative_cb_pre=deriv_cb)
    P1hat = LevelSetFunctional(Power1, c, phi)
    P1control = fda.Control(Power1)

    P2hat = LevelSetFunctional(Power2, c, phi)
    P2control = fda.Control(Power2)

    Jhat_v = Jhat(phi)
    print("Initial cost function value {:.5f}".format(Jhat_v), flush=True)
    print("Power drop 1 {:.5f}".format(Power1), flush=True)
    print("Power drop 2 {:.5f}".format(Power2), flush=True)

    beta_param = 0.08
    # Regularize the shape derivatives only in the domain marked with 0
    reg_solver = RegularizationSolver(S,
                                      mesh,
                                      beta=beta_param,
                                      gamma=1e5,
                                      dx=dx,
                                      design_domain=0)

    tol = 1e-5
    dt = 0.05
    params = {
        "alphaC": 1.0,
        "debug": 5,
        "alphaJ": 1.0,
        "dt": dt,
        "K": 1e-3,
        "maxit": n_iters,
        "maxtrials": 5,
        "itnormalisation": 10,
        "tol_merit":
        5e-3,  # new merit can be within 0.5% of the previous merit
        # "normalize_tol" : -1,
        "tol": tol,
    }

    solver_parameters = {
        "reinit_solver": {
            "h_factor": 2.0,
        }
    }
    # Optimization problem
    problem = InfDimProblem(
        Jhat,
        reg_solver,
        ineqconstraints=[
            Constraint(P1hat, 1.0, P1control),
            Constraint(P2hat, 1.0, P2control),
        ],
        solver_parameters=solver_parameters,
    )
    results = nlspace_solve(problem, params)

    return results
Exemple #36
0
# 3.1) Define trial and test functions
w = fd.TestFunction(X)

# 3.2) Set initial conditions
c0 = fd.Function(X, name="conc0")
c = fd.Function(X, name="conc")

# 3.3) set boundary conditions
t_bc = fd.DirichletBC(X, cIn, inlet)

# ======================
# 3.4) Variational Form
# coefficients
# advective velocity
vel = fd.Function(V, name='velocity').interpolate(fd.as_vector([1.0, 0.]))
K = fd.Constant(K)
Diff = fd.Constant(Diff)
Dt = fd.Constant(1e-3)
c_mid = 0.5 * (c + c0)  # Crank-Nicolson timestepping
fc = fd.Constant(s)

# weak form (transport)
F1 = w * (c - c0) * fd.dx + Dt * (
    w * fd.dot(vel, fd.grad(c_mid)) + Diff * fd.dot(fd.grad(w), fd.grad(c_mid))
    + w * K * c_mid - fc * w) * fd.dx  # - Dt*h_n*w*fd.ds(outlet)

# strong form
R = (c - c0) + Dt * (fd.dot(vel, fd.grad(c_mid)) -
                     Diff * fd.div(fd.grad(c_mid)) + K * c_mid - fc)
Exemple #37
0
def test_line_search():
    mesh = fd.UnitSquareMesh(50, 50)

    # Shape derivative
    S = fd.VectorFunctionSpace(mesh, "CG", 1)
    s = fd.Function(S, name="deform")
    mesh.coordinates.assign(mesh.coordinates + s)

    # Level set
    PHI = fd.FunctionSpace(mesh, "CG", 1)
    x, y = fd.SpatialCoordinate(mesh)

    with fda.stop_annotating():
        phi = fd.interpolate(-(x - 0.5), PHI)
        phi.rename("original")

    solver_parameters = {
        "ts_atol": 1e-4,
        "ts_rtol": 1e-4,
        "ts_dt": 1e-2,
        "ts_exact_final_time": "matchstep",
        "ts_monitor": None,
    }

    ## Search direction
    with fda.stop_annotating():
        delta_x = fd.interpolate(fd.as_vector([-100 * x, 0.0]), S)
        delta_x.rename("velocity")

    # Cost function
    J = fd.assemble(hs(-phi) * dx)

    # Reduced Functional
    c = fda.Control(s)
    Jhat = LevelSetFunctional(J, c, phi)

    # InfDim Problem
    beta_param = 0.08
    reg_solver = RegularizationSolver(S,
                                      mesh,
                                      beta=beta_param,
                                      gamma=1e5,
                                      dx=dx)
    solver_parameters = {"hj_solver": solver_parameters}
    problem = InfDimProblem(Jhat,
                            reg_solver,
                            solver_parameters=solver_parameters)

    new_phi = fd.Function(PHI, name="new_ls")
    orig_phi = fd.Function(PHI)
    with fda.stop_annotating():
        orig_phi.assign(phi)
        problem.delta_x.assign(delta_x)

    AJ, AC = 1.0, 1.0
    C = np.array([])
    merit = merit_eval_new(AJ, J, AC, C)

    rtol = 1e-4
    new_phi, newJ, newG, newH = line_search(
        problem,
        orig_phi,
        new_phi,
        merit_eval_new,
        merit,
        AJ,
        AC,
        dt=1.0,
        tol_merit=rtol,
        maxtrials=20,
    )

    assert_allclose(newJ, J, rtol=rtol)
Exemple #38
0
def facet_normal_2(mesh):
    r"""Compute the horizontal component of the unit outward normal vector
    to a mesh"""
    ν = firedrake.FacetNormal(mesh)
    return firedrake.as_vector((ν[0], ν[1]))
    diagnostic_fields = [Sum('D', 'topography')]

    state = State(mesh, horizontal_degree=1,
                  family="BDM",
                  timestepping=timestepping,
                  output=output,
                  parameters=parameters,
                  diagnostic_fields=diagnostic_fields,
                  fieldlist=fieldlist)

    # interpolate initial conditions
    u0 = state.fields('u')
    D0 = state.fields('D')
    x = SpatialCoordinate(mesh)
    u_max = 20.   # Maximum amplitude of the zonal wind (m/s)
    uexpr = as_vector([-u_max*x[1]/R, u_max*x[0]/R, 0.0])
    theta, lamda = latlon_coords(mesh)
    Omega = parameters.Omega
    g = parameters.g
    Rsq = R**2
    R0 = pi/9.
    R0sq = R0**2
    lamda_c = -pi/2.
    lsq = (lamda - lamda_c)**2
    theta_c = pi/6.
    thsq = (theta - theta_c)**2
    rsq = Min(R0sq, lsq+thsq)
    r = sqrt(rsq)
    bexpr = 2000 * (1 - r/R0)
    Dexpr = H - ((R * Omega * u_max + 0.5*u_max**2)*x[2]**2/Rsq)/g - bexpr
Exemple #40
0
def setup_sw(dirname, dt, u_transport_option):

    refinements = 3  # number of horizontal cells = 20*(4^refinements)

    mesh = IcosahedralSphereMesh(radius=R,
                                 refinement_level=refinements)
    x = SpatialCoordinate(mesh)
    mesh.init_cell_orientations(x)

    output = OutputParameters(dirname=dirname+"/sw", dumplist_latlon=['D', 'D_error'], steady_state_error_fields=['D', 'u'])
    parameters = ShallowWaterParameters(H=H)
    diagnostic_fields = [RelativeVorticity(), AbsoluteVorticity(),
                         PotentialVorticity(),
                         ShallowWaterPotentialEnstrophy('RelativeVorticity'),
                         ShallowWaterPotentialEnstrophy('AbsoluteVorticity'),
                         ShallowWaterPotentialEnstrophy('PotentialVorticity'),
                         Difference('RelativeVorticity',
                                    'AnalyticalRelativeVorticity'),
                         Difference('AbsoluteVorticity',
                                    'AnalyticalAbsoluteVorticity'),
                         Difference('PotentialVorticity',
                                    'AnalyticalPotentialVorticity'),
                         Difference('SWPotentialEnstrophy_from_PotentialVorticity',
                                    'SWPotentialEnstrophy_from_RelativeVorticity'),
                         Difference('SWPotentialEnstrophy_from_PotentialVorticity',
                                    'SWPotentialEnstrophy_from_AbsoluteVorticity'),
                         MeridionalComponent('u'),
                         ZonalComponent('u'),
                         RadialComponent('u')]

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

    Omega = parameters.Omega
    fexpr = 2*Omega*x[2]/R
    eqns = ShallowWaterEquations(state, family="BDM", degree=1,
                                 fexpr=fexpr,
                                 u_transport_option=u_transport_option)

    # interpolate initial conditions
    u0 = state.fields("u")
    D0 = state.fields("D")
    uexpr = as_vector([-u_max*x[1]/R, u_max*x[0]/R, 0.0])
    g = parameters.g
    Dexpr = H - ((R * Omega * u_max + u_max*u_max/2.0)*(x[2]*x[2]/(R*R)))/g

    u0.project(uexpr)
    D0.interpolate(Dexpr)

    vspace = FunctionSpace(state.mesh, "CG", 3)
    vexpr = (2*u_max/R)*x[2]/R
    f = state.fields("coriolis")
    vrel_analytical = state.fields("AnalyticalRelativeVorticity", vspace)
    vrel_analytical.interpolate(vexpr)
    vabs_analytical = state.fields("AnalyticalAbsoluteVorticity", vspace)
    vabs_analytical.interpolate(vexpr + f)
    pv_analytical = state.fields("AnalyticalPotentialVorticity", vspace)
    pv_analytical.interpolate((vexpr+f)/D0)

    return state, eqns