Ejemplo n.º 1
0
def test_vector_field():
    Nx, Ny = 16, 16
    mesh2d = firedrake.UnitSquareMesh(Nx, Ny)
    mesh3d = firedrake.ExtrudedMesh(mesh2d, layers=1)
    x, y, z = firedrake.SpatialCoordinate(mesh3d)

    V3D = firedrake.VectorFunctionSpace(mesh3d,
                                        "CG",
                                        2,
                                        vfamily="GL",
                                        vdegree=5,
                                        dim=2)
    u3d = firedrake.interpolate(firedrake.as_vector((1 - z**4, 0)), V3D)
    u_avg = depth_average(u3d)

    V2D = firedrake.VectorFunctionSpace(mesh2d, "CG", 2)
    x, y = firedrake.SpatialCoordinate(mesh2d)
    u2d = firedrake.interpolate(firedrake.as_vector((4 / 5, 0)), V2D)

    assert norm(u_avg - u2d) / norm(u2d) < 1 / (Nx * Ny)**2

    V0 = firedrake.VectorFunctionSpace(mesh3d,
                                       "CG",
                                       2,
                                       vfamily="GL",
                                       vdegree=0,
                                       dim=2)
    u_lift = lift3d(u_avg, V0)
    assert norm(depth_average(u_lift) - u2d) / norm(u2d) < 1 / (Nx * Ny)**2
Ejemplo n.º 2
0
def test_diagnostic_solver():
    Nx, Ny = 32, 32
    mesh2d = firedrake.RectangleMesh(Nx, Ny, Lx, Ly)
    mesh = firedrake.ExtrudedMesh(mesh2d, layers=1)
    Q = firedrake.FunctionSpace(mesh,
                                family='CG',
                                degree=2,
                                vfamily='DG',
                                vdegree=0)

    x, y, ζ = firedrake.SpatialCoordinate(mesh)
    h = firedrake.interpolate(h0 - dh * x / Lx, Q)
    s = firedrake.interpolate(d + h0 - dh + ds * (1 - x / Lx), Q)
    u_expr = firedrake.as_vector(((0.95 + 0.05 * ζ) * exact_u(x), 0))

    A = firedrake.Constant(icepack.rate_factor(254.15))
    C = firedrake.Constant(0.001)

    model = icepack.models.HybridModel()
    opts = {'dirichlet_ids': [1, 3, 4], 'tol': 1e-12}

    max_degree = 5
    Nz = 32
    xs = np.array([(Lx / 2, Ly / 2, k / Nz) for k in range(Nz + 1)])
    us = np.zeros((max_degree + 1, Nz + 1))
    for vdegree in range(max_degree, 0, -1):
        solver = icepack.solvers.FlowSolver(model, **opts)
        V = firedrake.VectorFunctionSpace(mesh,
                                          dim=2,
                                          family='CG',
                                          degree=2,
                                          vfamily='GL',
                                          vdegree=vdegree)
        u0 = firedrake.interpolate(u_expr, V)
        u = solver.diagnostic_solve(velocity=u0,
                                    thickness=h,
                                    surface=s,
                                    fluidity=A,
                                    friction=C)

        V0 = firedrake.VectorFunctionSpace(mesh,
                                           dim=2,
                                           family='CG',
                                           degree=2,
                                           vfamily='DG',
                                           vdegree=0)

        depth_avg_u = firedrake.project(u, V0)
        shear_u = firedrake.project(u - depth_avg_u, V)
        assert icepack.norm(shear_u, norm_type='Linfty') > 1e-2

        us_center = np.array(u.at(xs, tolerance=1e-6))
        us[vdegree, :] = np.sqrt(np.sum(us_center**2, 1))

        norm = np.linalg.norm(us[max_degree, :])
        error = np.linalg.norm(us[vdegree, :] - us[max_degree, :]) / norm
        print(error, flush=True)
        assert error < 1e-2
Ejemplo n.º 3
0
def test_order_0():
    def h_expr(x):
        return h0 - dh * x / Lx

    def s_expr(x):
        return d + h0 - dh + ds * (1 - x / Lx)

    A = firedrake.Constant(icepack.rate_factor(254.15))
    C = firedrake.Constant(0.001)
    opts = {'dirichlet_ids': [1], 'side_wall_ids': [3, 4], 'tolerance': 1e-14}

    Nx, Ny = 64, 64
    mesh2d = firedrake.RectangleMesh(Nx, Ny, Lx, Ly)
    x, y = firedrake.SpatialCoordinate(mesh2d)
    Q2d = firedrake.FunctionSpace(mesh2d, family='CG', degree=2)
    V2d = firedrake.VectorFunctionSpace(mesh2d, family='CG', degree=2)
    h = firedrake.interpolate(h_expr(x), Q2d)
    s = firedrake.interpolate(s_expr(x), Q2d)
    u_expr = firedrake.as_vector((exact_u(x), 0))
    u0 = firedrake.interpolate(u_expr, V2d)

    model2d = icepack.models.IceStream()
    solver2d = icepack.solvers.FlowSolver(model2d, **opts)
    u2d = solver2d.diagnostic_solve(velocity=u0,
                                    thickness=h,
                                    surface=s,
                                    fluidity=A,
                                    friction=C)

    mesh = firedrake.ExtrudedMesh(mesh2d, layers=1)
    x, y, ζ = firedrake.SpatialCoordinate(mesh)
    Q3d = firedrake.FunctionSpace(mesh,
                                  family='CG',
                                  degree=2,
                                  vfamily='DG',
                                  vdegree=0)
    V3d = firedrake.VectorFunctionSpace(mesh,
                                        dim=2,
                                        family='CG',
                                        degree=2,
                                        vfamily='GL',
                                        vdegree=0)
    h = firedrake.interpolate(h_expr(x), Q3d)
    s = firedrake.interpolate(s_expr(x), Q3d)
    u_expr = firedrake.as_vector((exact_u(x), 0))
    u0 = firedrake.interpolate(u_expr, V3d)

    model3d = icepack.models.HybridModel()
    solver3d = icepack.solvers.FlowSolver(model3d, **opts)
    u3d = solver3d.diagnostic_solve(velocity=u0,
                                    thickness=h,
                                    surface=s,
                                    fluidity=A,
                                    friction=C)

    U2D, U3D = u2d.dat.data_ro, u3d.dat.data_ro
    assert np.linalg.norm(U3D - U2D) / np.linalg.norm(U2D) < 1e-2
Ejemplo n.º 4
0
 def get_functionspace(self):
     """Construct trial/test space for state and adjoint equations."""
     if self.mini:
         # MINI elements
         mini = fd.FiniteElement("CG", fd.triangle, 1) \
             + fd.FiniteElement("B", fd.triangle, 3)
         Vvel = fd.VectorFunctionSpace(self.mesh_m, mini)
     else:
         # P2/P1 Taylor-Hood elements
         Vvel = fd.VectorFunctionSpace(self.mesh_m, "Lagrange", 2)
     Vpres = fd.FunctionSpace(self.mesh_m, "CG", 1)
     return Vvel * Vpres
Ejemplo n.º 5
0
    def __init__(self, mesh_r, refinements=1, order=1):
        mh = fd.MeshHierarchy(mesh_r, refinements)
        self.mesh_hierarchy = mh

        # Control space on coarsest mesh
        self.mesh_r_coarse = self.mesh_hierarchy[0]
        self.V_r_coarse = fd.VectorFunctionSpace(self.mesh_r_coarse, "CG",
                                                 order)

        # Create self.id and self.T on refined mesh.
        element = self.V_r_coarse.ufl_element()

        self.intermediate_Ts = []
        for i in range(refinements - 1):
            mesh = self.mesh_hierarchy[i + 1]
            V = fd.FunctionSpace(mesh, element)
            self.intermediate_Ts.append(fd.Function(V))

        self.mesh_r = self.mesh_hierarchy[-1]
        element = self.V_r_coarse.ufl_element()
        self.V_r = fd.FunctionSpace(self.mesh_r, element)

        X = fd.SpatialCoordinate(self.mesh_r)
        self.id = fd.Function(self.V_r).interpolate(X)
        self.T = fd.Function(self.V_r, name="T")
        self.T.assign(self.id)
        self.mesh_m = fda.Mesh(self.T)
        self.V_m = fd.FunctionSpace(self.mesh_m, element)
Ejemplo n.º 6
0
def test_diagnostic_solver_convergence():
    # Create an ice shelf model
    ice_shelf = icepack.models.IceShelf()
    opts = {'dirichlet_ids': [1], 'side_wall_ids': [3, 4], 'tol': 1e-12}

    # Solve the ice shelf model for successively higher mesh resolution
    for degree in range(1, 4):
        delta_x, error = [], []
        for N in range(16, 97 - 32 * (degree - 1), 4):
            mesh = firedrake.RectangleMesh(N, N, Lx, Ly)
            x, y = firedrake.SpatialCoordinate(mesh)

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

            u_exact = interpolate(as_vector((exact_u(x), 0)), V)
            u_guess = interpolate(u_exact + as_vector((perturb_u(x, y), 0)), V)

            h = interpolate(h0 - dh * x / Lx, Q)
            A = interpolate(firedrake.Constant(icepack.rate_factor(T)), Q)

            u = ice_shelf.diagnostic_solve(h=h, A=A, u0=u_guess, **opts)
            error.append(norm(u_exact - u) / norm(u_exact))
            delta_x.append(Lx / N)

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

        # Fit the error curve and check that the convergence rate is what we
        # expect
        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.8
Ejemplo n.º 7
0
    def interpolate(self, mesh, k0L):
        V = fd.VectorFunctionSpace(mesh, "CG", 1)
        x = fd.SpatialCoordinate(mesh)

        pw = fd.interpolate(self.p * fd.exp(1j * k0L * fd.dot(self.s, x)), V)

        return pw
Ejemplo n.º 8
0
    def __init__(self, mesh_r):
        # Create mesh_r and V_r
        self.mesh_r = mesh_r
        element = self.mesh_r.coordinates.function_space().ufl_element()
        self.V_r = fd.FunctionSpace(self.mesh_r, element)

        # Create self.id and self.T, self.mesh_m, and self.V_m.
        X = fd.SpatialCoordinate(self.mesh_r)
        self.id = fd.interpolate(X, self.V_r)
        self.T = fd.Function(self.V_r, name="T")
        self.T.assign(self.id)
        self.mesh_m = fd.Mesh(self.T)
        self.V_m = fd.FunctionSpace(self.mesh_m, element)
        self.is_DG = False

        """
        ControlSpace for discontinuous coordinate fields
        (e.g.  periodic domains)

        In Firedrake, periodic meshes are implemented using a discontinuous
        field. This implies that self.V_r contains discontinuous functions.
        To ensure domain updates do not create holes in the domain,
        use a continuous subspace self.V_c of self.V_r as control space.
        """
        if element.family() == 'Discontinuous Lagrange':
            self.is_DG = True
            self.V_c = fd.VectorFunctionSpace(self.mesh_r,
                                              "CG", element._degree)
            self.Ip = fd.Interpolator(fd.TestFunction(self.V_c),
                                      self.V_r).callable().handle
Ejemplo n.º 9
0
def setupMesh(meshFile, degree=2, meshOversample=None, savegmsh=False):
    """
    Read argus mesh file and return mesh alongw ith function spaces

    Parameters
    ----------
    meshFile : str
        argus meshfile name
    degree : int, optional
        degree of function spaces, by default 2

    Returns
    -------
    mesh
        firedrake mesh
    Q, V
        firedrake scalar and vectory functions
    """
    # Input the mesh
    maxOversample = 4  # Arbitrary could be increased
    mesh, opts = argusToFiredrakeMesh(meshFile, savegmsh=savegmsh)
    if meshOversample is not None:
        numLevels = meshOversample - 1
        if numLevels < 0 or numLevels > (maxOversample - 1):
            myerror(f'meshOverample={meshOversample} but  0 < '
                    'meshOversample < 4')
        mesh = firedrake.MeshHierarchy(mesh, numLevels)[numLevels]
    # Create scalar and vector function spaces
    Q = firedrake.FunctionSpace(mesh, family='CG', degree=degree)
    V = firedrake.VectorFunctionSpace(mesh, family='CG', degree=degree)
    return mesh, Q, V, opts
Ejemplo n.º 10
0
def test_diagnostic_solver_convergence():
    shallow_ice = icepack.models.ShallowIce()

    for degree in range(1, 4):
        delta_x, error = [], []
        for N in range(10, 110 - 20 * (degree - 1), 10):

            mesh = make_mesh(R_mesh, R / N)

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

            h_expr = Bueler_profile(mesh, R)
            u_exact = interpolate(exact_u(h_expr, Q), V)

            h = interpolate(h_expr, Q)
            s = interpolate(h_expr, Q)
            u = firedrake.Function(V)

            u_num = shallow_ice.diagnostic_solve(u0=u, h=h, s=s, A=A)
            error.append(norm(u_exact - u_num) / norm(u_exact))
            delta_x.append(R / N)

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

            assert assemble(shallow_ice.scale(u=u_num)) > 0

        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 > 0.9
Ejemplo n.º 11
0
def test_diagnostic_solver_side_friction():
    model = icepack.models.IceShelf()
    opts = {"dirichlet_ids": [1], "side_wall_ids": [3, 4]}

    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))

    solver = icepack.solvers.FlowSolver(model, **opts)
    fields = {
        "velocity": u_initial,
        "thickness": h,
        "fluidity": A,
        "side_friction": Cs
    }
    u = solver.diagnostic_solve(**fields)

    assert icepack.norm(u) < icepack.norm(u_initial)
Ejemplo n.º 12
0
def test_hybrid_prognostic_solve():
    Lx, Ly = 20e3, 20e3
    h0, dh = 500.0, 100.0
    T = 254.15
    u_in = 100.0

    model = icepack.models.HybridModel()
    opts = {'dirichlet_ids': [1], 'side_wall_ids': [3, 4], 'tol': 1e-12}

    Nx, Ny = 32, 32
    mesh2d = firedrake.RectangleMesh(Nx, Ny, Lx, Ly)
    mesh = firedrake.ExtrudedMesh(mesh2d, layers=1)

    V = firedrake.VectorFunctionSpace(mesh,
                                      dim=2,
                                      family='CG',
                                      degree=2,
                                      vfamily='GL',
                                      vdegree=1)
    Q = firedrake.FunctionSpace(mesh,
                                family='CG',
                                degree=2,
                                vfamily='DG',
                                vdegree=0)

    x, y, ζ = firedrake.SpatialCoordinate(mesh)
    height_above_flotation = 10.0
    d = -ρ_I / ρ_W * (h0 - dh) + height_above_flotation
    ρ = ρ_I - ρ_W * d**2 / (h0 - dh)**2

    Z = icepack.rate_factor(T) * (ρ * g * h0 / 4)**n
    q = 1 - (1 - (dh / h0) * (x / Lx))**(n + 1)
    ux = u_in + Z * q * Lx * (h0 / dh) / (n + 1)
    u0 = interpolate(firedrake.as_vector((ux, 0)), V)

    thickness = h0 - dh * x / Lx
    β = 1 / 2
    α = β * ρ / ρ_I * dh / Lx
    h = interpolate(h0 - dh * x / Lx, Q)
    h_inflow = h.copy(deepcopy=True)
    ds = (1 + β) * ρ / ρ_I * dh
    s = interpolate(d + h0 - dh + ds * (1 - x / Lx), Q)
    b = interpolate(s - h, Q)

    C = interpolate(α * (ρ_I * g * thickness) * ux**(-1 / m), Q)
    A = firedrake.Constant(icepack.rate_factor(T))

    final_time, dt = 1.0, 1.0 / 12
    num_timesteps = int(final_time / dt)

    u = model.diagnostic_solve(u0=u0, h=h, s=s, C=C, A=A, **opts)
    a0 = firedrake.Constant(0)
    a = interpolate((model.prognostic_solve(dt, h0=h, a=a0, u=u) - h) / dt, Q)

    for k in range(num_timesteps):
        h = model.prognostic_solve(dt, h0=h, a=a, u=u, h_inflow=h_inflow)
        s = icepack.compute_surface(h=h, b=b)
        u = model.diagnostic_solve(u0=u, h=h, s=s, C=C, A=A, **opts)

    assert icepack.norm(h, norm_type='Linfty') < np.inf
Ejemplo n.º 13
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, family='CG', degree=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
Ejemplo n.º 14
0
def vectorspaces(mesh, vertical_higher_order=0):
    '''On an extruded mesh, build finite element spaces for velocity u,
    pressure p, and vertical displacement c.  Construct component spaces by
    explicitly applying TensorProductElement().  Elements are Q2 prisms
    [P2(triangle)xP2(interval)] for velocity, Q1 prisms [P1(triangle)xP1(interval)]
    for pressure, and Q1 prisms [P1(triangle)xP1(interval)] for displacement.
    Optionally the base mesh can be built from quadrilaterals and/or
    the vertical factors can be higher order for velocity and pressure.'''

    if mesh._base_mesh.cell_dimension() not in {1, 2}:
        raise ValueError('only 2D and 3D extruded meshes are allowed')
    ThreeD = (mesh._base_mesh.cell_dimension() == 2)
    quad = (mesh._base_mesh.ufl_cell() == fd.quadrilateral)
    if quad and not ThreeD:
        raise ValueError('base mesh from quadilaterals only possible in 3D')
    zudeg, zpdeg = _degreexz[vertical_higher_order]

    # velocity u (vector)
    if ThreeD:
        if quad:
            xuE = fd.FiniteElement('Q', fd.quadrilateral, 2)
        else:
            xuE = fd.FiniteElement('P', fd.triangle, 2)
    else:
        xuE = fd.FiniteElement('P', fd.interval, 2)
    zuE = fd.FiniteElement('P', fd.interval, zudeg)
    uE = fd.TensorProductElement(xuE, zuE)
    Vu = fd.VectorFunctionSpace(mesh, uE)

    # pressure p (scalar)
    #   Note Isaac et al (2015) recommend discontinuous pressure space
    #   to get mass conservation.  Switching base mesh elements to dP0
    #   (or dQ0 for base quads) is inconsistent w.r.t. velocity result;
    #   (unstable?) and definitely more expensive.
    if ThreeD:
        if quad:
            xpE = fd.FiniteElement('Q', fd.quadrilateral, 1)
        else:
            xpE = fd.FiniteElement('P', fd.triangle, 1)
    else:
        xpE = fd.FiniteElement('P', fd.interval, 1)
    zpE = fd.FiniteElement('P', fd.interval, zpdeg)
    pE = fd.TensorProductElement(xpE, zpE)
    Vp = fd.FunctionSpace(mesh, pE)

    # vertical displacement c (scalar)
    if ThreeD:
        if quad:
            xcE = fd.FiniteElement('Q', fd.quadrilateral, 1)
        else:
            xcE = fd.FiniteElement('P', fd.triangle, 1)
    else:
        xcE = fd.FiniteElement('P', fd.interval, 1)
    zcE = fd.FiniteElement('P', fd.interval, 1)
    cE = fd.TensorProductElement(xcE, zcE)
    Vc = fd.FunctionSpace(mesh, cE)

    return Vu, Vp, Vc
Ejemplo n.º 15
0
def test_diagnostic_solver_parameterization():
    # Define a new viscosity functional, parameterized in terms of the
    # rheology `B` instead of the fluidity `A`
    from firedrake import inner, grad, sym, tr as trace, Identity, sqrt

    def M(ε, B):
        I = Identity(2)
        tr_ε = trace(ε)
        ε_e = sqrt((inner(ε, ε) + tr_ε**2) / 2)
        μ = 0.5 * B * ε_e**(1/n - 1)
        return 2 * μ * (ε + tr_ε * I)

    def ε(u):
        return sym(grad(u))

    def viscosity(**kwargs):
        u = kwargs['velocity']
        h = kwargs['thickness']
        B = kwargs['rheology']
        return n/(n + 1) * h * inner(M(ε(u), B), ε(u))

    # Make a model object with our new viscosity functional
    model = icepack.models.IceShelf(viscosity=viscosity)
    opts = {'dirichlet_ids': [1, 3, 4]}

    # Same as before
    delta_x, error = [], []
    for N in range(16, 65, 4):
        mesh = firedrake.RectangleMesh(N, N, Lx, Ly)
        x, y = firedrake.SpatialCoordinate(mesh)

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

        u_exact = interpolate(as_vector((exact_u(x), 0)), V)
        u_guess = interpolate(as_vector((exact_u(x) + perturb_u(x, y), 0)), V)
        h = interpolate(h0 - dh * x / Lx, Q)
        B = interpolate(firedrake.Constant(icepack.rate_factor(T)**(-1/n)), Q)

        solver = icepack.solvers.FlowSolver(model, **opts)
        u = solver.diagnostic_solve(
            velocity=u_guess,
            thickness=h,
            rheology=B
        )
        error.append(norm(u_exact - u) / norm(u_exact))
        delta_x.append(Lx / N)

        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.05
Ejemplo n.º 16
0
def VectorFunctionSpaceHierarchy(mesh_hierarchy, *args, **kwargs):
    from firedrake.logging import warning, RED
    warning(
        RED %
        "VectorFunctionSpaceHierarchy is obsolete. Just build a FunctionSpace on the relevant mesh"
    )

    return tuple(
        firedrake.VectorFunctionSpace(mesh, *args, **kwargs)
        for mesh in mesh_hierarchy)
Ejemplo n.º 17
0
def test_firedrake_to_numpy_mixed_function():
    # Functions in DG0 have nodes at centers of finite element cells
    mesh = firedrake.UnitIntervalMesh(10)
    vec_dim = 4
    V = firedrake.VectorFunctionSpace(mesh, "DG", 0, dim=vec_dim)
    x = firedrake.SpatialCoordinate(mesh)
    test_input = firedrake.interpolate(firedrake.as_vector(vec_dim * (x[0], )),
                                       V)
    expected = numpy.linspace(0.05, 0.95, num=10)
    expected = numpy.reshape(numpy.tile(expected, (4, 1)).T, V.dim())
    assert numpy.allclose(to_numpy(test_input), expected)
Ejemplo n.º 18
0
def siahorizontalvelocity(mesh):
    hbase = surfaceelevation(mesh)
    if mesh._base_mesh.cell_dimension() == 2:
        if mesh._base_mesh.ufl_cell() == fd.quadrilateral:
            Vvectorbase = fd.VectorFunctionSpace(mesh._base_mesh, 'DQ', 0)
            VvectorR = fd.VectorFunctionSpace(mesh,
                                              'DQ',
                                              0,
                                              vfamily='R',
                                              vdegree=0,
                                              dim=2)
        else:
            Vvectorbase = fd.VectorFunctionSpace(mesh._base_mesh, 'DP', 0)
            VvectorR = fd.VectorFunctionSpace(mesh,
                                              'DP',
                                              0,
                                              vfamily='R',
                                              vdegree=0,
                                              dim=2)
        gradhbase = fd.project(fd.grad(hbase), Vvectorbase)
        Vvector = fd.VectorFunctionSpace(mesh, 'DQ', 0, dim=2)
    elif mesh._base_mesh.cell_dimension() == 1:
        Vvectorbase = fd.FunctionSpace(mesh._base_mesh, 'DP', 0)
        gradhbase = fd.project(hbase.dx(0), Vvectorbase)
        VvectorR = fd.FunctionSpace(mesh, 'DP', 0, vfamily='R', vdegree=0)
        Vvector = fd.FunctionSpace(mesh, 'DQ', 0)
    else:
        raise ValueError('base mesh of extruded input mesh must be 1D or 2D')
    gradh = fd.Function(VvectorR)
    gradh.dat.data[:] = gradhbase.dat.data_ro[:]
    h = extend(mesh, hbase)
    DQ0 = fd.FunctionSpace(mesh, 'DQ', 0)
    h0 = fd.project(h, DQ0)
    x = fd.SpatialCoordinate(mesh)
    z0 = fd.project(x[mesh._base_mesh.cell_dimension()], DQ0)
    # FIXME following only valid in flat bed case
    uvsia = -Gamma * (h0**(n + 1) -
                      (h0 - z0)**(n + 1)) * abs(gradh)**(n - 1) * gradh
    uv = fd.Function(Vvector).interpolate(uvsia)
    uv.rename('velocitySIA')
    return uv
Ejemplo n.º 19
0
def test_damage_transport():
    nx, ny = 32, 32
    Lx, Ly = 20e3, 20e3
    mesh = firedrake.RectangleMesh(nx, ny, Lx, Ly)
    x, y = firedrake.SpatialCoordinate(mesh)

    V = firedrake.VectorFunctionSpace(mesh, "CG", 2)
    Q = firedrake.FunctionSpace(mesh, "CG", 2)

    u0 = 100.0
    h0, dh = 500.0, 100.0
    T = 268.0

    ρ = ρ_I * (1 - ρ_I / ρ_W)
    Z = icepack.rate_factor(T) * (ρ * g * h0 / 4)**n
    q = 1 - (1 - (dh / h0) * (x / Lx))**(n + 1)
    du = Z * q * Lx * (h0 / dh) / (n + 1)

    u = interpolate(as_vector((u0 + du, 0)), V)
    h = interpolate(h0 - dh * x / Lx, Q)
    A = firedrake.Constant(icepack.rate_factor(T))

    S = firedrake.TensorFunctionSpace(mesh, "DG", 1)
    ε = firedrake.project(sym(grad(u)), S)
    M = firedrake.project(membrane_stress(strain_rate=ε, fluidity=A), S)

    degree = 1
    Δ = firedrake.FunctionSpace(mesh, "DG", degree)
    D_inflow = firedrake.Constant(0.0)
    D = firedrake.Function(Δ)

    damage_model = icepack.models.DamageTransport()
    damage_solver = icepack.solvers.DamageSolver(damage_model)

    final_time = Lx / u0
    max_speed = u.at((Lx - 1.0, Ly / 2), tolerance=1e-10)[0]
    δx = Lx / nx
    timestep = δx / max_speed / (2 * degree + 1)
    num_steps = int(final_time / timestep)
    dt = final_time / num_steps

    for step in range(num_steps):
        D = damage_solver.solve(
            dt,
            damage=D,
            velocity=u,
            strain_rate=ε,
            membrane_stress=M,
            damage_inflow=D_inflow,
        )

    Dmax = D.dat.data_ro[:].max()
    assert 0 < Dmax < 1
Ejemplo n.º 20
0
def test_plot_vector_field():
    nx, ny = 32, 32
    mesh = firedrake.UnitSquareMesh(nx, ny)
    V = firedrake.VectorFunctionSpace(mesh, family='CG', degree=1)

    x, y = firedrake.SpatialCoordinate(mesh)
    u = interpolate(as_vector((x + 0.01, x * y * (1 - y) * (y - 0.5))), V)

    arrows = icepack.plot.quiver(u)
    assert arrows is not None

    streamlines = icepack.plot.streamplot(u, density=1 / nx, precision=1 / nx)
    assert streamlines is not None
Ejemplo n.º 21
0
    def add_vector_field_to(self,
                            geo_map,
                            vector_field,
                            mode=None,
                            levels=None,
                            scale=None,
                            cmap=None,
                            name=None):
        """
        Add a vector field to a folium map.

        Parameters
        ----------
        geo_map : folium.Map
            Map to which the mesh plot should be added.
        vector_field: firedrake.Function
            A firedrake Function representing the vector field.
        mode: str, optional
            Plot to be generated, either contourf, contour or quiver.
            If not provided, contourf is used.
        levels: int or list of numbers, optional
            In contourf or contour mode: values of the contour lines.
            In quiver mode: number of ticks to be added to the color bar.
            If integer, it will determine the number of equispaced values to be used between
            the minimum and maximum entry of the scalar field.
            If list, it will determine the values to be used.
            If not provided, 10 levels are used by default.
        scale: number, optional
            This is only applicable for quiver mode: scaling to be applied before drawing arrows.
            If not provided, no scaling will be applied.
        cmap: str, optional
            matplotlib color map to be used.
            If not provided, the jet colormap is used.
        name: str, optional
            Name of the field, to be used in the creation of the color bar.
            If not provided, the name "vector field" will be used.
        """

        mesh = vector_field.function_space().mesh()
        vector_function_space = firedrake.VectorFunctionSpace(mesh, "CG", 1)
        vertices = mesh.coordinates.dat.data_ro
        cells = mesh.coordinates.cell_node_map().values
        vector_field_values = firedrake.interpolate(
            vector_field,
            vector_function_space).vector().array().reshape(-1, 2)

        return BaseSolutionPlotter.add_vector_field_to(self, geo_map, vertices,
                                                       cells,
                                                       vector_field_values,
                                                       mode, levels, scale,
                                                       cmap, name)
Ejemplo n.º 22
0
def test_ice_shelf_prognostic_solver(solver_type):
    ρ = ρ_I * (1 - ρ_I / ρ_W)

    Lx, Ly = 20.0e3, 20.0e3
    h0 = 500.0
    u0 = 100.0
    T = 254.15

    model = icepack.models.IceShelf(mass_transport=solver_type())
    opts = {'dirichlet_ids': [1], 'side_wall_ids': [3, 4], 'tol': 1e-12}

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

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

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

        q = (n + 1) * (ρ * g * h0 * u0 / 4)**n * icepack.rate_factor(T)
        ux = (u0**(n + 1) + q * x)**(1 / (n + 1))

        h = interpolate(h0 * u0 / ux, Q)
        h_initial = h.copy(deepcopy=True)

        A = firedrake.Constant(icepack.rate_factor(T))
        a = firedrake.Constant(0)

        u_guess = interpolate(firedrake.as_vector((ux, 0)), V)
        u = model.diagnostic_solve(u0=u_guess, h=h, A=A, **opts)

        final_time, dt = 1.0, 1.0 / 12
        num_timesteps = int(final_time / dt)

        for k in range(num_timesteps):
            h = model.prognostic_solve(dt, h0=h, a=a, u=u, h_inflow=h_initial)
            u = model.diagnostic_solve(u0=u, h=h, A=A, **opts)

        error.append(norm(h - h_initial) / norm(h_initial))
        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.05
Ejemplo n.º 23
0
    def __init__(self, mesh_m, viscosity):
        super().__init__()
        self.mesh_m = mesh_m
        self.failed_to_solve = False  # when self.solver.solve() fail

        # Setup problem, Taylor-Hood finite elements
        self.V = fd.VectorFunctionSpace(self.mesh_m, "CG", 2) \
            * fd.FunctionSpace(self.mesh_m, "CG", 1)

        # Preallocate solution variables for state equation
        self.solution = fd.Function(self.V, name="State")
        self.testfunction = fd.TestFunction(self.V)

        # Define viscosity parameter
        self.viscosity = viscosity

        # Weak form of incompressible Navier-Stokes equations
        z = self.solution
        u, p = fd.split(z)
        test = self.testfunction
        v, q = fd.split(test)
        nu = self.viscosity  # shorten notation
        self.F = nu*fd.inner(fd.grad(u), fd.grad(v))*fd.dx - p*fd.div(v)*fd.dx\
            + fd.inner(fd.dot(fd.grad(u), u), v)*fd.dx + fd.div(u)*q*fd.dx

        # Dirichlet Boundary conditions
        X = fd.SpatialCoordinate(self.mesh_m)
        dim = self.mesh_m.topological_dimension()
        if dim == 2:
            uin = 4 * fd.as_vector([(1 - X[1]) * X[1], 0])
        elif dim == 3:
            rsq = X[0]**2 + X[1]**2  # squared radius = 0.5**2 = 1/4
            uin = fd.as_vector([0, 0, 1 - 4 * rsq])
        else:
            raise NotImplementedError
        self.bcs = [
            fd.DirichletBC(self.V.sub(0), 0., [12, 13]),
            fd.DirichletBC(self.V.sub(0), uin, [10])
        ]

        # PDE-solver parameters
        self.nsp = None
        self.params = {
            "snes_max_it": 10,
            "mat_type": "aij",
            "pc_type": "lu",
            "pc_factor_mat_solver_type": "superlu_dist",
            # "snes_monitor": None, "ksp_monitor": None,
        }
Ejemplo n.º 24
0
def test_vertical_velocity():

    Lx, Ly = 20e3, 20e3
    nx, ny = 48, 48

    mesh2d = firedrake.RectangleMesh(nx, ny, Lx, Ly)
    mesh = firedrake.ExtrudedMesh(mesh2d, layers=1)
    Q = firedrake.FunctionSpace(mesh,
                                family="CG",
                                degree=2,
                                vfamily="DG",
                                vdegree=0)
    Q3D = firedrake.FunctionSpace(mesh,
                                  family="DG",
                                  degree=2,
                                  vfamily="GL",
                                  vdegree=6)
    V = firedrake.VectorFunctionSpace(mesh,
                                      dim=2,
                                      family="CG",
                                      degree=2,
                                      vfamily="GL",
                                      vdegree=5)
    # note we should call the families in the vertical velocity solver.

    x, y, ζ = firedrake.SpatialCoordinate(mesh)

    u_inflow = 1.0
    v_inflow = 2.0
    mu = 0.003
    mv = 0.001

    b = firedrake.interpolate(firedrake.Constant(0.0), Q)
    s = firedrake.interpolate(firedrake.Constant(1000.0), Q)
    h = firedrake.interpolate(s - b, Q)
    u = firedrake.interpolate(
        firedrake.as_vector((mu * x + u_inflow, mv * y + v_inflow)), V)

    m = -0.01

    def analytic_vertical_velocity(h, ζ, mu, mv, m, Q3D):
        return firedrake.interpolate(
            firedrake.Constant(m) - (firedrake.Constant(mu + mv) * h * ζ), Q3D)

    w = firedrake.interpolate(
        icepack.utilities.vertical_velocity(u, h, m=m) * h, Q3D)
    w_analytic = analytic_vertical_velocity(h, ζ, mu, mv, m, Q3D)

    assert np.mean(np.abs(w.dat.data - w_analytic.dat.data)) < 10e-9
Ejemplo n.º 25
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 = [], []
    model = icepack.models.IceShelf()
    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)
        solver = icepack.solvers.FlowSolver(
            model, prognostic_solver_type=solver_type
        )

        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 = solver.prognostic_solve(
                δt,
                thickness=h,
                velocity=u,
                accumulation=a,
                thickness_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
Ejemplo n.º 26
0
def test_shallow_ice_prognostic_solve():
    R = Constant(500e3)
    num_refinements = 4
    mesh = firedrake.UnitDiskMesh(num_refinements)
    mesh.coordinates.dat.data[:] *= float(R)
    T = Constant(254.15)
    A = icepack.rate_factor(T)

    Q = firedrake.FunctionSpace(mesh, "CG", 2)
    V = firedrake.VectorFunctionSpace(mesh, "CG", 2)

    x, y = firedrake.SpatialCoordinate(mesh)
    r = firedrake.sqrt(x**2 + y**2)

    β = Constant(0.5)
    h_divide = Constant(4e3)
    h_expr = h_divide * firedrake.max_value(0, 1 - (r / (β * R))**2)
    h_0 = interpolate(h_expr, Q)
    h = h_0.copy(deepcopy=True)
    u = firedrake.Function(V)

    b = Constant(0.0)
    s = interpolate(b + h, Q)
    a = Constant(0.0)

    model = icepack.models.ShallowIce()
    solver = icepack.solvers.FlowSolver(model)

    final_time = 100.0
    dt = 1.0
    num_steps = int(final_time / dt)

    for step in range(num_steps):
        u = solver.diagnostic_solve(velocity=u,
                                    thickness=h,
                                    surface=s,
                                    fluidity=A)

        h = solver.prognostic_solve(dt,
                                    thickness=h,
                                    velocity=u,
                                    accumulation=a)

        h.interpolate(firedrake.max_value(0, h))
        s.assign(b + h)

    error = abs(assemble(h * dx) / assemble(h_0 * dx) - 1)
    assert error < 1 / 2**(num_refinements + 1)
Ejemplo n.º 27
0
def test_eigenvalues():
    nx, ny = 32, 32
    mesh = firedrake.UnitSquareMesh(nx, ny)
    x, y = firedrake.SpatialCoordinate(mesh)

    V = firedrake.VectorFunctionSpace(mesh, family='CG', degree=2)
    u = interpolate(as_vector((x, 0)), V)

    Q = firedrake.FunctionSpace(mesh, family='DG', degree=2)
    ε = sym(grad(u))
    Λ1, Λ2 = eigenvalues(ε)
    λ1 = firedrake.project(Λ1, Q)
    λ2 = firedrake.project(Λ2, Q)

    assert norm(λ1 - Constant(1)) < norm(u) / (nx * ny)
    assert norm(λ2) < norm(u) / (nx * ny)
Ejemplo n.º 28
0
def interpolate(f, Q):
    r"""Interpolate an expression or a gridded data set to a function space

    Parameters
    ----------
    f : rasterio dataset or tuple of rasterio datasets
        The gridded data set for scalar fields or the tuple of gridded data
        sets for each component
    Q : firedrake.FunctionSpace
        The function space where the result will live

    Returns
    -------
    firedrake.Function
        A finite element function defined on `Q` with the same nodal values
        as the data `f`
    """
    if isinstance(f, (ufl.core.expr.Expr, firedrake.Function)):
        return firedrake.interpolate(f, Q)

    mesh = Q.mesh()
    element = Q.ufl_element()
    if len(element.sub_elements()) > 0:
        element = element.sub_elements()[0]

    V = firedrake.VectorFunctionSpace(mesh, element)
    X = firedrake.interpolate(mesh.coordinates, V).dat.data_ro
    num_points = X.shape[0]

    q = firedrake.Function(Q)

    if isinstance(f, rasterio.DatasetReader):
        q.dat.data[:] = np.fromiter(f.sample(X, indexes=1),
                                    dtype=np.float64,
                                    count=num_points)
    elif (isinstance(f, tuple)
          and all(isinstance(fi, rasterio.DatasetReader) for fi in f)):
        for i, fi in enumerate(f):
            q.dat.data[:, i] = np.fromiter(fi.sample(X, indexes=1),
                                           dtype=np.float64,
                                           count=num_points)
    else:
        raise ValueError('Argument must be a rasterio data set or a tuple of '
                         'data sets!')

    return q
Ejemplo n.º 29
0
def random_field_generator(function_space,
                           minval=0,
                           maxval=1,
                           var=1e-2,
                           len_scale=1,
                           len_low=0,
                           seed=20170519):
    mesh = function_space.mesh()
    dim = mesh.geometric_dimension()

    model = TPLStable(dim=dim, var=var, len_scale=len_scale, len_low=len_low)
    # model = Exponential(dim=dim, var=var, len_scale=len_scale)  # FIXME: Diego, the exponential model, instead of TPLStable, resulted in some chemical equilibrium errors (returning to previous at the moment)

    srf = SRF(model, seed=seed)

    ndofs = function_space.dim()
    size = int(ndofs**(1 / dim))

    xyz = [range(size) for _ in range(dim)]

    data = srf(xyz, mesh_type="structured")

    # The min and max values of x,y,z in the mesh
    xyz_min = [mesh.coordinates.dat.data[:, i].min() for i in range(dim)]
    xyz_max = [mesh.coordinates.dat.data[:, i].max() for i in range(dim)]

    xyz = [np.linspace(xyz_min[i], xyz_max[i], size) for i in range(dim)]

    datainterp = RegularGridInterpolator(xyz, data)

    # Now make the VectorFunctionSpace corresponding to V.
    W = fire.VectorFunctionSpace(mesh, function_space.ufl_element())

    # Next, interpolate the coordinates onto the nodes of W.
    X = fire.interpolate(mesh.coordinates, W)

    # Make an output function.
    k = fire.Function(function_space, name="Permeability")

    # Use the external data function to interpolate the values of f.
    kdata = np.array([datainterp(xyz) for xyz in X.dat.data_ro])

    # k.dat.data[:] = mydata(X.dat.data_ro)
    k.dat.data[:] = rescale_field(kdata, minval, maxval)[:, 0]

    return k
Ejemplo n.º 30
0
def test_diagnostic_solver_convergence(solver_type):
    # Create an ice shelf model
    model = icepack.models.IceShelf()
    opts = {
        "dirichlet_ids": [1],
        "side_wall_ids": [3, 4],
        "diagnostic_solver_type": solver_type,
    }

    # Solve the ice shelf model for successively higher mesh resolution
    for degree in range(1, 4):
        delta_x, error = [], []
        for N in range(16, 97 - 32 * (degree - 1), 4):
            mesh = firedrake.RectangleMesh(N, N, Lx, Ly)
            x, y = firedrake.SpatialCoordinate(mesh)

            V = firedrake.VectorFunctionSpace(mesh, "CG", degree)
            Q = firedrake.FunctionSpace(mesh, "CG", degree)

            u_exact = interpolate(as_vector((exact_u(x), 0)), V)
            u_guess = interpolate(u_exact + as_vector((perturb_u(x, y), 0)), V)

            h = interpolate(h0 - dh * x / Lx, Q)
            A = interpolate(firedrake.Constant(icepack.rate_factor(T)), Q)

            solver = icepack.solvers.FlowSolver(model, **opts)
            u = solver.diagnostic_solve(
                velocity=u_guess,
                thickness=h,
                fluidity=A,
                strain_rate_min=firedrake.Constant(0.0),
            )
            error.append(norm(u_exact - u) / norm(u_exact))
            delta_x.append(Lx / N)

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

        # Fit the error curve and check that the convergence rate is what we
        # expect
        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(f"log(error) ~= {slope:g} * log(dx) + {intercept:g}")
        assert slope > degree + 0.8