Exemple #1
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)
Exemple #2
0
def test_n_min_ufl():
    """Tests that the sharp cutoff function does what it should when n is given by a ufl expression."""

    k = 10.0

    mesh = fd.UnitSquareMesh(10,10)

    V = fd.FunctionSpace(mesh,"CG",1)

    x = fd.SpatialCoordinate(mesh)
    
    n = 1.0 + fd.sin(30*x[0])
    
    prob = hh.HelmholtzProblem(k,V,n=n)

    n_min_val = 2.0
    
    prob.n_min(n_min_val)

    V_DG = fd.FunctionSpace(mesh,"DG",0)
    
    n_fn = fd.Function(V_DG)

    n_fn.interpolate(prob._n)
    
    assert (n_fn.dat.data_ro >= n_min_val).all()
Exemple #3
0
def test_n_min_pre_ufl():
    """Tests that the sharp cutoff function does what it should when n_pre is given by a UFL expression."""

    k = 10.0

    mesh = fd.UnitSquareMesh(10,10)

    V = fd.FunctionSpace(mesh,"CG",1)

    x = fd.SpatialCoordinate(mesh)
    
    n_pre = 1.0 + fd.sin(30*x[0])
    
    prob = hh.HelmholtzProblem(k,V,n_pre=n_pre,A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]]))

    n_min_val = 2.0
    
    prob.n_min(n_min_val,True)

    V_DG = fd.FunctionSpace(mesh,"DG",0)
    
    n_fn = fd.Function(V_DG)

    n_fn.interpolate(prob._n_pre)
    
    assert (n_fn.dat.data_ro >= n_min_val).all()
Exemple #4
0
def test_sharp_cutoff_ufl():
    """Tests that the sharp cutoff function does what it should when the
coefficient is given by a ufl expression."""

    k = 10.0

    mesh = fd.UnitSquareMesh(10,10)

    V = fd.FunctionSpace(mesh,"CG",1)

    x = fd.SpatialCoordinate(mesh)

    n = 1.0 + fd.sin(30*x[0])
    
    prob = hh.HelmholtzProblem(k,V,n=n)
    
    prob.sharp_cutoff(np.array([0.5,0.5]),0.5)

    V_DG = fd.FunctionSpace(mesh,"DG",0)
    
    n_fn = fd.Function(V_DG)

    n_fn.interpolate(prob._n)


    # This is a rudimentary test that it's 1 on the boundary
    # Yes, I kind of made this pass by changing the value to check until it did.
    # But I've confirmed that it's doing (roughly) the right thing visually, so I'm content
    
    assert n_fn.dat.data_ro[97] == 1.0
Exemple #5
0
def test_sharp_cutoff_pre_ufl():
    """Tests that the sharp cutoff function does what it should when the
    preconditioning coefficient is given by ufl."""

    k = 10.0

    mesh = fd.UnitSquareMesh(10,10)

    V = fd.FunctionSpace(mesh,"CG",1)

    x = fd.SpatialCoordinate(mesh)

    n_pre = 1.0 + fd.sin(30*x[0])

    prob = hh.HelmholtzProblem(k,V,n_pre=n_pre,A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]]))

    prob.sharp_cutoff(np.array([0.5,0.5]),0.5,True)

    V_DG = fd.FunctionSpace(mesh,"DG",0)

    n_fn = fd.Function(V_DG)

    n_fn.interpolate(prob._n_pre)

    # As above
    assert n_fn.dat.data_ro[97] == 1.0
Exemple #6
0
def test_sharp_cutoff():
    """Tests that the sharp cutoff function does what it should."""

    k = 10.0

    mesh = fd.UnitSquareMesh(10,10)

    V = fd.FunctionSpace(mesh,"CG",1)
    
    prob = hh.HelmholtzProblem(k,V,n=2.0)

    prob.sharp_cutoff(np.array([0.5,0.5]),0.5)

    V_DG = fd.FunctionSpace(mesh,"DG",0)
    
    n_fn = fd.Function(V_DG)

    n_fn.interpolate(prob._n)


    # This is a rudimentary test that it's 1 on the boundary and 2 elsewhere
    # Yes, I kind of made this pass by changing the value to check until it did.
    # But I've confirmed that it's doing (roughly) the right thing visually, so I'm content
    
    assert n_fn.dat.data_ro[97] == 1.0

    assert n_fn.dat.data_ro[95] == 2.0
Exemple #7
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
def test_scalar_field():
    Nx, Ny = 16, 16
    mesh2d = firedrake.UnitSquareMesh(Nx, Ny)
    mesh3d = firedrake.ExtrudedMesh(mesh2d, layers=1)
    x, y, z = firedrake.SpatialCoordinate(mesh3d)

    Q3D = firedrake.FunctionSpace(mesh3d,
                                  family='CG',
                                  degree=2,
                                  vfamily='GL',
                                  vdegree=5)
    q3d = firedrake.interpolate((x**2 + y**2) * (1 - z**4), Q3D)
    q_avg = depth_average(q3d)

    p3d = firedrake.interpolate(x**2 + y**2, Q3D)
    p_avg = depth_average(p3d, weight=1 - z**4)

    Q2D = firedrake.FunctionSpace(mesh2d, family='CG', degree=2)
    x, y = firedrake.SpatialCoordinate(mesh2d)
    q2d = firedrake.interpolate(4 * (x**2 + y**2) / 5, Q2D)

    assert q_avg.ufl_domain() is mesh2d
    assert norm(q_avg - q2d) / norm(q2d) < 1 / (Nx * Ny)**2
    assert norm(p_avg - q2d) / norm(q2d) < 1 / (Nx * Ny)**2

    Q0 = firedrake.FunctionSpace(mesh3d,
                                 family='CG',
                                 degree=2,
                                 vfamily='GL',
                                 vdegree=0)
    q_lift = lift3d(q_avg, Q0)
    assert norm(depth_average(q_lift) - q2d) / norm(q2d) < 1 / (Nx * Ny)**2
Exemple #9
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
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
Exemple #11
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
Exemple #12
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 = fda.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)
Exemple #13
0
def extend(mesh, f):
    if mesh._base_mesh.cell_dimension() == 2:
        if mesh._base_mesh.ufl_cell() == fd.quadrilateral:
            Q1R = fd.FunctionSpace(mesh, 'Q', 1, vfamily='R', vdegree=0)
        else:
            Q1R = fd.FunctionSpace(mesh, 'P', 1, vfamily='R', vdegree=0)
    elif mesh._base_mesh.cell_dimension() == 1:
        Q1R = fd.FunctionSpace(mesh, 'P', 1, vfamily='R', vdegree=0)
    else:
        raise ValueError('base mesh of extruded input mesh must be 1D or 2D')
    fextend = fd.Function(Q1R)
    fextend.dat.data[:] = f.dat.data_ro[:]
    return fextend
Exemple #14
0
def _build_space(mesh, el, space, deg):
    if el == "tria":
        V = fd.FunctionSpace(mesh, space, deg)
    elif el == "quad":
        if space == "spectral":
            element = fd.FiniteElement(
                "CG", mesh.ufl_cell(), degree=deg, variant="spectral"
            )
            V = fd.FunctionSpace(mesh, element)
        elif space == "S":
            V = fd.FunctionSpace(mesh, "S", deg)
        else:
            raise ValueError("Space not supported yet")
    return V
Exemple #15
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
Exemple #16
0
    def __init__(self, mesh_m):
        super().__init__()
        self.mesh_m = mesh_m

        # Setup problem
        self.V = fd.FunctionSpace(self.mesh_m, "CG", 1)

        # Preallocate solution variables for state and adjoint equations
        self.solution = fd.Function(self.V, name="State")

        # Weak form of Poisson problem
        u = self.solution
        v = fd.TestFunction(self.V)
        self.f = fd.Constant(4.)
        self.F = (fd.inner(fd.grad(u), fd.grad(v)) - self.f * v) * fd.dx
        self.bcs = fd.DirichletBC(self.V, 0., "on_boundary")

        # PDE-solver parameters
        self.params = {
            "ksp_type": "cg",
            "mat_type": "aij",
            "pc_type": "hypre",
            "pc_factor_mat_solver_package": "boomerang",
            "ksp_rtol": 1e-11,
            "ksp_atol": 1e-11,
            "ksp_stol": 1e-15,
        }

        stateproblem = fd.NonlinearVariationalProblem(self.F,
                                                      self.solution,
                                                      bcs=self.bcs)
        self.solver = fd.NonlinearVariationalSolver(
            stateproblem, solver_parameters=self.params)
Exemple #17
0
def test_plot_field():
    mesh = firedrake.UnitSquareMesh(32, 32)
    Q = firedrake.FunctionSpace(mesh, "CG", 1)
    x, y = firedrake.SpatialCoordinate(mesh)
    u = interpolate(x * y, Q)

    fig, axes = icepack.plot.subplots(nrows=2,
                                      ncols=2,
                                      sharex=True,
                                      sharey=True)

    filled_contours = icepack.plot.tricontourf(u, axes=axes[0, 0])
    assert filled_contours is not None
    colorbar = plt.colorbar(filled_contours, ax=axes[0, 0])
    assert colorbar is not None

    contours = icepack.plot.tricontour(u, axes=axes[0, 1])
    assert contours is not None

    colors_flat = icepack.plot.tripcolor(u, shading="flat", axes=axes[1, 0])
    assert colors_flat is not None

    colors_gouraud = icepack.plot.tripcolor(u,
                                            shading="gouraud",
                                            axes=axes[1, 1])
    assert colors_flat.get_array().shape != colors_gouraud.get_array().shape
def test_coeff_definition_no_error():
    """Test that a coeff with just too few many pieces is not caught."""
    k = 20.0
    mesh = fd.UnitSquareMesh(100, 100)
    V = fd.FunctionSpace(mesh, "CG", 1)

    num_pieces = 12
    noise_level = 0.1
    num_repeats = 10

    A_pre = fd.as_matrix(np.array([[1.0, 0.0], [0.0, 1.0]]))
    A_stoch = PiecewiseConstantCoeffGenerator(mesh, num_pieces, noise_level,
                                              A_pre, [2, 2])

    n_pre = 1.0
    n_stoch = PiecewiseConstantCoeffGenerator(mesh, num_pieces, noise_level,
                                              n_pre, [1])

    f = 1.0
    g = 1.0

    GMRES_its = nbex.nearby_preconditioning_experiment(V, k, A_pre, A_stoch,
                                                       n_pre, n_stoch, f, g,
                                                       num_repeats)

    # The code should not error.

    assert GMRES_its.shape != (0, )
def test_coeff_definition_error():
    """Test that a coeff with too many pieces is caught."""
    k = 20.0
    mesh = fd.UnitSquareMesh(100, 100)
    V = fd.FunctionSpace(mesh, "CG", 1)

    num_pieces = 13
    noise_level = 0.1
    num_repeats = 10

    A_pre = fd.as_matrix(np.array([[1.0, 0.0], [0.0, 1.0]]))
    A_stoch = PiecewiseConstantCoeffGenerator(mesh, num_pieces, noise_level,
                                              A_pre, [2, 2])

    n_pre = 1.0
    n_stoch = PiecewiseConstantCoeffGenerator(mesh, num_pieces, noise_level,
                                              n_pre, [1])

    f = 1.0
    g = 1.0

    GMRES_its = nbex.nearby_preconditioning_experiment(V, k, A_pre, A_stoch,
                                                       n_pre, n_stoch, f, g,
                                                       num_repeats)

    # The code should catch the error and print a warning message, and
    # exit, not recording any GMRES iterations.

    assert GMRES_its.shape == (0, )
Exemple #20
0
def coarsen_function_space(V, self, coefficient_mapping=None):
    if hasattr(V, "_coarse"):
        return V._coarse
    fine = V
    indices = []
    while True:
        if V.index is not None:
            indices.append(V.index)
        if V.component is not None:
            indices.append(V.component)
        if V.parent is not None:
            V = V.parent
        else:
            break

    mesh = self(V.mesh(), self)

    Vf = V
    V = firedrake.FunctionSpace(mesh, V.ufl_element())

    from firedrake.dmhooks import get_transfer_operators, push_transfer_operators
    transfer = get_transfer_operators(Vf.dm)
    push_transfer_operators(V.dm, *transfer)
    if len(V) > 1:
        for V_, Vc_ in zip(Vf, V):
            transfer = get_transfer_operators(V_.dm)
            push_transfer_operators(Vc_.dm, *transfer)

    for i in reversed(indices):
        V = V.sub(i)
    V._fine = fine
    fine._coarse = V

    return V
Exemple #21
0
def get_restriction_weights(coarse, fine):
    mesh = coarse.mesh()
    assert hasattr(mesh, "_shared_data_cache")
    cache = mesh._shared_data_cache["hierarchy_restriction_weights"]
    key = entity_dofs_key(coarse.finat_element.entity_dofs())
    try:
        return cache[key]
    except KeyError:
        # We hit each fine dof more than once since we loop
        # elementwise over the coarse cells.  So we need a count of
        # how many times we did this to weight the final contribution
        # appropriately.
        if not (coarse.ufl_element() == fine.ufl_element()):
            raise ValueError("Can't transfer between different spaces")
        if coarse.finat_element.entity_dofs(
        ) == coarse.finat_element.entity_closure_dofs():
            return cache.setdefault(key, None)
        ele = coarse.ufl_element()
        if isinstance(ele, ufl.VectorElement):
            ele = ele.sub_elements()[0]
            weights = firedrake.Function(
                firedrake.FunctionSpace(fine.mesh(), ele))
        else:
            weights = firedrake.Function(fine)
        c2f_map = coarse_to_fine_node_map(coarse, fine)
        kernel = get_count_kernel(c2f_map.arity)
        op2.par_loop(kernel, c2f_map.iterset,
                     weights.dat(op2.INC, c2f_map[op2.i[0]]))
        weights.assign(1 / weights)
        return cache.setdefault(key, weights)
Exemple #22
0
def coarsen(dm, comm):
    """Callback to coarsen a DM.

    :arg DM: The DM to coarsen.
    :arg comm: The communicator for the new DM (ignored)

    This transfers a coarse application context over to the coarsened
    DM (if found on the input DM).
    """
    from firedrake.mg.utils import get_level
    from firedrake.mg.ufl_utils import coarsen
    V = get_function_space(dm)
    if V is None:
        raise RuntimeError("No functionspace found on DM")
    hierarchy, level = get_level(V.mesh())
    if level < 1:
        raise RuntimeError("Cannot coarsen coarsest DM")
    if hasattr(V, "_coarse"):
        cdm = V._coarse.dm
    else:
        V._coarse = firedrake.FunctionSpace(hierarchy[level - 1], V.ufl_element())
        cdm = V._coarse.dm

    transfer = get_transfer_operators(dm)
    push_transfer_operators(cdm, *transfer)
    ctx = get_appctx(dm)
    if ctx is not None:
        push_appctx(cdm, coarsen(ctx))
        # Necessary for MG inside a fieldsplit in a SNES.
        cdm.setKSPComputeOperators(firedrake.solving_utils._SNESContext.compute_operators)
    V._coarse._fine = V
    return cdm
Exemple #23
0
    def __init__(self, mesh_m):
        super().__init__()

        # Setup problem
        V = fd.FunctionSpace(mesh_m, "CG", 1)

        # Weak form of Poisson problem
        u = fda.Function(V, name="State")
        v = fd.TestFunction(V)
        f = fda.Constant(4.)
        F = (fd.inner(fd.grad(u), fd.grad(v)) - f * v) * fd.dx
        bcs = fda.DirichletBC(V, 0., "on_boundary")

        # PDE-solver parameters
        params = {
            "ksp_type": "cg",
            "mat_type": "aij",
            "pc_type": "hypre",
            "pc_factor_mat_solver_package": "boomerang",
            "ksp_rtol": 1e-11,
            "ksp_atol": 1e-11,
            "ksp_stol": 1e-15,
        }

        self.solution = u
        problem = fda.NonlinearVariationalProblem(F, self.solution, bcs=bcs)
        self.solver = fda.NonlinearVariationalSolver(problem,
                                                     solver_parameters=params)
Exemple #24
0
    def __init__(self,
                 mesh,
                 element,
                 variational_form_residual,
                 dirichlet_boundary_conditions,
                 initial_values,
                 quadrature_degree=None,
                 time_dependent=True,
                 time_stencil_size=2,
                 output_directory_path="output/"):

        self.mesh = mesh

        self.element = element

        self.function_space = fe.FunctionSpace(mesh, element)

        self.quadrature_degree = quadrature_degree

        self.solutions = [
            fe.Function(self.function_space) for i in range(time_stencil_size)
        ]

        self.solution = self.solutions[0]

        self.backup_solution = fe.Function(self.solution)

        if time_dependent:

            assert (time_stencil_size > 1)

            self.time = fe.Constant(0.)

            self.timestep_size = fe.Constant(1.)

        else:

            self.time = None

            self.timestep_size = None

        self.output_directory_path = pathlib.Path(output_directory_path)

        self.solution_file = None

        self.plotvars = None

        self.initial_values = initial_values(sim=self)

        for solution in self.solutions:

            solution.assign(self.initial_values)

        self.variational_form_residual = variational_form_residual(
            sim=self, solution=self.solution)

        self.dirichlet_boundary_conditions = \
            dirichlet_boundary_conditions(sim = self)

        self.snes_iteration_count = 0
def create_form(form_string, family, degree, dimension, operation):
    from firedrake import dx, inner, grad
    import firedrake as f

    f.parameters['coffee']['optlevel'] = 'O3'
    f.parameters['pyop2_options']['opt_level'] = 'O3'
    f.parameters['pyop2_options']['simd_isa'] = 'avx'
    f.parameters["pyop2_options"]["lazy_evaluation"] = False

    m = f.UnitSquareMesh(2, 2, quadrilateral=True)
    if dimension == 3:
        m = f.ExtrudedMesh(m, 2)

    fs = f.FunctionSpace(m, family, degree)
    v = f.TestFunction(fs)
    if operation == "matrix":
        u = f.TrialFunction(fs)
    elif operation == "action":
        u = f.Function(fs)
    else:
        raise ValueError("Unknown operation: %s" % operation)

    if form_string == "u * v * dx":
        return u * v * dx
    elif form_string == "inner(grad(u), grad(v)) * dx":
        return inner(grad(u), grad(v)) * dx
Exemple #26
0
def test_ilu():
    """Tests that ILU functionality gives correct solution."""

    k = 10.0

    num_cells = utils.h_to_num_cells(k**-1.5,2)

    mesh = fd.UnitSquareMesh(num_cells,num_cells)

    V = fd.FunctionSpace(mesh,"CG",1)
    
    prob = hh.HelmholtzProblem(k,V)

    angle = 2.0 * np.pi/7.0

    d = [np.cos(angle),np.sin(angle)]
    
    prob.f_g_plane_wave(d)

    for fill_in in range(40):
    
        prob.use_ilu_gmres(fill_in)

        prob.solve()

        x = fd.SpatialCoordinate(mesh)

        # This error was found out by eye
        assert np.abs(fd.norms.errornorm(fd.exp(1j * k * fd.dot(fd.as_vector(d),x)),uh=prob.u_h,norm_type='H1')) < 0.5
Exemple #27
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
Exemple #28
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
Exemple #29
0
    def __init__(self,
                 *args,
                 rayleigh_number=7.e5,
                 prandtl_number=0.0216,
                 stefan_number=0.046,
                 liquidus_temperature=0.,
                 hotwall_temperature=1.,
                 initial_temperature=-0.1546,
                 cutoff_length=0.5,
                 element_degrees=(1, 2, 2),
                 mesh_dimensions=(20, 40),
                 **kwargs):

        if "solution" not in kwargs:

            mesh = fe.RectangleMesh(nx=mesh_dimensions[0],
                                    ny=mesh_dimensions[1],
                                    Lx=cutoff_length,
                                    Ly=1.)

            element = sapphire.simulations.navier_stokes_boussinesq.element(
                cell=mesh.ufl_cell(), degrees=element_degrees)

            kwargs["solution"] = fe.Function(fe.FunctionSpace(mesh, element))

        super().__init__(*args,
                         reynolds_number=1. / prandtl_number,
                         rayleigh_number=rayleigh_number,
                         prandtl_number=prandtl_number,
                         stefan_number=stefan_number,
                         liquidus_temperature=liquidus_temperature,
                         hotwall_temperature=hotwall_temperature,
                         initial_temperature=initial_temperature,
                         **kwargs)
Exemple #30
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