Exemplo n.º 1
0
def get_aspect_ratios2d(mesh, python=False):
    """
    Computes the aspect ratio of each cell in a 2D triangular mesh

    :arg mesh: the input mesh to do computations on
    :kwarg python: compute the measure using Python?

    :rtype: firedrake.function.Function aspect_ratios with
        aspect ratio data
    """
    P0 = firedrake.FunctionSpace(mesh, "DG", 0)
    if python:
        P0_ten = firedrake.TensorFunctionSpace(mesh, "DG", 0)
        J = firedrake.interpolate(ufl.Jacobian(mesh), P0_ten)
        edge1 = ufl.as_vector([J[0, 0], J[1, 0]])
        edge2 = ufl.as_vector([J[0, 1], J[1, 1]])
        edge3 = edge1 - edge2
        a = ufl.sqrt(ufl.dot(edge1, edge1))
        b = ufl.sqrt(ufl.dot(edge2, edge2))
        c = ufl.sqrt(ufl.dot(edge3, edge3))
        aspect_ratios = firedrake.interpolate(
            a * b * c / ((a + b - c) * (b + c - a) * (c + a - b)), P0
        )
    else:
        coords = mesh.coordinates
        aspect_ratios = firedrake.Function(P0)
        op2.par_loop(
            get_pyop2_kernel("get_aspect_ratio", 2),
            mesh.cell_set,
            aspect_ratios.dat(op2.WRITE, aspect_ratios.cell_node_map()),
            coords.dat(op2.READ, coords.cell_node_map()),
        )
    return aspect_ratios
Exemplo n.º 2
0
def solve_something(mesh):
    V = fd.FunctionSpace(mesh, "CG", 1)
    u = fd.Function(V)
    v = fd.TestFunction(V)

    x, y = fd.SpatialCoordinate(mesh)
    # f = fd.sin(x) * fd.sin(y) + x**2 + y**2
    # uex = x**4 * y**4
    uex = fd.sin(x) * fd.sin(y)  #*(x*y)**3
    # def source(xs, ys):
    #     return 1/((x-xs)**2+(y-ys)**2 + 0.1)
    # uex = source(0, 0)
    uex = uex - fd.assemble(uex * fd.dx) / fd.assemble(1 * fd.dx(domain=mesh))
    # f = fd.conditional(fd.ge(abs(x)-abs(y), 0), 1, 0)
    from firedrake import inner, grad, dx, ds, div, sym
    eps = fd.Constant(0.0)
    f = uex - div(grad(uex)) + eps * div(grad(div(grad(uex))))
    n = fd.FacetNormal(mesh)
    g = inner(grad(uex), n)
    g1 = inner(grad(div(grad(uex))), n)
    g2 = div(grad(uex))
    # F = 0.1 * inner(u, v) * dx + inner(grad(u), grad(v)) * dx + inner(grad(grad(u)), grad(grad(v))) * dx - f * v * dx - g * v * ds
    F = inner(u, v) * dx + inner(grad(u),
                                 grad(v)) * dx - f * v * dx - g * v * ds
    F += eps * inner(div(grad(u)), div(grad(v))) * dx
    F += eps * g1 * v * ds
    F -= eps * g2 * inner(grad(v), n) * ds
    # f = -div(grad(uex))
    # F = inner(grad(u), grad(v)) * dx - f * v * dx

    # bc = fd.DirichletBC(V, uex, "on_boundary")
    bc = None
    fd.solve(F == 0,
             u,
             bcs=bc,
             solver_parameters={
                 "ksp_type": "cg",
                 "ksp_atol": 1e-13,
                 "ksp_rtol": 1e-13,
                 "ksp_dtol": 1e-13,
                 "ksp_stol": 1e-13,
                 "pc_type": "jacobi",
                 "pc_factor_mat_solver_type": "mumps",
                 "snes_type": "ksponly",
                 "ksp_converged_reason": None
             })
    print("||u-uex||             =", fd.norm(u - uex))
    print("||grad(u-uex)||       =", fd.norm(grad(u - uex)))
    print("||grad(grad(u-uex))|| =", fd.norm(grad(grad(u - uex))))
    err = fd.Function(
        fd.TensorFunctionSpace(mesh, "DG",
                               V.ufl_element().degree() - 2)).interpolate(
                                   grad(grad(u - uex)))
    # err = fd.Function(fd.FunctionSpace(mesh, "DG", V.ufl_element().degree())).interpolate(u-uex)
    fd.File(outdir + "sln.pvd").write(u)
    fd.File(outdir + "err.pvd").write(err)
Exemplo n.º 3
0
def TensorFunctionSpaceHierarchy(mesh_hierarchy, *args, **kwargs):
    from firedrake.logging import warning, RED
    warning(
        RED %
        "TensorFunctionSpaceHierarchy is obsolete. Just build a FunctionSpace on the relevant mesh"
    )

    return tuple(
        firedrake.TensorFunctionSpace(mesh, *args, **kwargs)
        for mesh in mesh_hierarchy)
    def __init__(self, mesh, permittivity_dict, k0L, **kvargs):
        super().__init__(mesh, k0L, **kvargs)
        self.II = fd.as_matrix(((1, 0), (0, 1)))
        self.permittivity = fd.Function(
            fd.TensorFunctionSpace(self.mesh, "DG", 0))

        for (subd_id, epsilon_tensor) in permittivity_dict.items():
            epsilon = fd.as_matrix(epsilon_tensor)
            self.permittivity.interpolate(
                epsilon, self.mesh.measure_set("cell", subd_id))
Exemplo n.º 5
0
def stresses(mesh, icemodel, u):
    Q1 = fd.FunctionSpace(mesh, 'Q', 1)
    TQ1 = fd.TensorFunctionSpace(mesh, 'Q', 1)
    Du = fd.Function(TQ1).interpolate(0.5 * (fd.grad(u) + fd.grad(u).T))
    Du2 = fd.Function(Q1).interpolate(0.5 * fd.inner(Du, Du) +
                                      icemodel.eps * icemodel.Dtyp**2.0)
    nu = fd.Function(Q1).interpolate(0.5 * Bn * Du2**(-1.0 / n))
    nu.rename('effective viscosity')
    tau = fd.Function(TQ1).interpolate(2.0 * nu * Du)
    tau.rename('tau')
    return tau, nu
Exemplo n.º 6
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
Exemplo n.º 7
0
    def __init__(self, c, bound, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.c = c
        self.T = self.Q.T
        r_mesh = self.T.ufl_domain()
        self.lam_space = fd.TensorFunctionSpace(r_mesh, "DG", 0)
        self.scalar_space = fd.FunctionSpace(r_mesh, "DG", 0)
        self.nuclear_norm = fd.Function(self.scalar_space)
        self.viol = fd.Function(self.scalar_space)
        self.lam = fd.Function(self.lam_space)
        self.gradS = fd.Function(self.lam_space)
        self.lam_c_grad_S = fd.Function(self.lam_space)
        self.argmin = fd.Function(self.lam_space)
        self.bound = fd.Function(self.scalar_space).interpolate(bound)

        self.iden = fd.Function(self.V_r)
        self.iden.interpolate(fd.SpatialCoordinate(r_mesh))
        self.S = self.T.copy(deepcopy=True)
        self.dim = r_mesh.topological_dimension()
Exemplo n.º 8
0
def test_metric_math(dim):
    """
    Check that the metric exponential and
    metric logarithm are indeed inverses.
    """
    mesh = uniform_mesh(dim, 1)
    P0_ten = firedrake.TensorFunctionSpace(mesh, "DG", 0)
    I = ufl.Identity(dim)
    M = firedrake.interpolate(2 * I, P0_ten)
    logM = metric_logarithm(M)
    expected = firedrake.interpolate(np.log(2) * I, P0_ten)
    assert np.allclose(logM.dat.data, expected.dat.data)
    M_ = metric_exponential(logM)
    assert np.allclose(M.dat.data, M_.dat.data)
    expM = metric_exponential(M)
    expected = firedrake.interpolate(np.exp(2) * I, P0_ten)
    assert np.allclose(expM.dat.data, expected.dat.data)
    M_ = metric_logarithm(expM)
    assert np.allclose(M.dat.data, M_.dat.data)
Exemplo n.º 9
0
def get_scaled_jacobians2d(mesh, python=False):
    """
    Computes the scaled Jacobian of each cell in a 2D triangular mesh

    :arg mesh: the input mesh to do computations on
    :kwarg python: compute the measure using Python?

    :rtype: firedrake.function.Function scaled_jacobians with scaled
        jacobian data.
    """
    P0 = firedrake.FunctionSpace(mesh, "DG", 0)
    if python:
        P0_ten = firedrake.TensorFunctionSpace(mesh, "DG", 0)
        J = firedrake.interpolate(ufl.Jacobian(mesh), P0_ten)
        edge1 = ufl.as_vector([J[0, 0], J[1, 0]])
        edge2 = ufl.as_vector([J[0, 1], J[1, 1]])
        edge3 = edge1 - edge2
        a = ufl.sqrt(ufl.dot(edge1, edge1))
        b = ufl.sqrt(ufl.dot(edge2, edge2))
        c = ufl.sqrt(ufl.dot(edge3, edge3))
        detJ = ufl.JacobianDeterminant(mesh)
        jacobian_sign = ufl.sign(detJ)
        max_product = ufl.Max(
            ufl.Max(ufl.Max(a * b, a * c), ufl.Max(b * c, b * a)), ufl.Max(c * a, c * b)
        )
        scaled_jacobians = firedrake.interpolate(detJ / max_product * jacobian_sign, P0)
    else:
        coords = mesh.coordinates
        scaled_jacobians = firedrake.Function(P0)
        op2.par_loop(
            get_pyop2_kernel("get_scaled_jacobian", 2),
            mesh.cell_set,
            scaled_jacobians.dat(op2.WRITE, scaled_jacobians.cell_node_map()),
            coords.dat(op2.READ, coords.cell_node_map()),
        )
    return scaled_jacobians
Exemplo n.º 10
0
    def initialize(self, pc):
        _, P = pc.getOperators()
        assert P.type == "python"
        context = P.getPythonContext()
        (self.J, self.bcs) = (context.a, context.row_bcs)

        test, trial = self.J.arguments()
        if test.function_space() != trial.function_space():
            raise NotImplementedError("test and trial spaces must be the same")

        Pk = test.function_space()
        element = Pk.ufl_element()
        shape = element.value_shape()
        mesh = Pk.ufl_domain()
        if len(shape) == 0:
            P1 = firedrake.FunctionSpace(mesh, "CG", 1)
        elif len(shape) == 2:
            P1 = firedrake.VectorFunctionSpace(mesh, "CG", 1, dim=shape[0])
        else:
            P1 = firedrake.TensorFunctionSpace(mesh,
                                               "CG",
                                               1,
                                               shape=shape,
                                               symmetry=element.symmetry())

        # TODO: A smarter low-order operator would also interpolate
        # any coefficients to the coarse space.
        mapper = ArgumentReplacer({
            test: firedrake.TestFunction(P1),
            trial: firedrake.TrialFunction(P1)
        })
        self.lo_J = map_integrands.map_integrand_dags(mapper, self.J)

        lo_bcs = []
        for bc in self.bcs:
            # Don't actually need the value, since it's only used for
            # killing parts of the restriction matrix.
            lo_bcs.append(
                firedrake.DirichletBC(P1,
                                      firedrake.zero(P1.shape),
                                      bc.sub_domain,
                                      method=bc.method))

        self.lo_bcs = tuple(lo_bcs)

        mat_type = PETSc.Options().getString(
            pc.getOptionsPrefix() + "lo_mat_type",
            firedrake.parameters["default_matrix_type"])
        self.lo_op = firedrake.assemble(self.lo_J,
                                        bcs=self.lo_bcs,
                                        mat_type=mat_type)
        self.lo_op.force_evaluation()
        A, P = pc.getOperators()
        nearnullsp = P.getNearNullSpace()
        if nearnullsp.handle != 0:
            # Actually have a near nullspace
            tmp = firedrake.Function(Pk)
            low = firedrake.Function(P1)
            vecs = []
            for vec in nearnullsp.getVecs():
                with tmp.dat.vec as v:
                    vec.copy(v)
                low.interpolate(tmp)
                with low.dat.vec_ro as v:
                    vecs.append(v.copy())
            nullsp = PETSc.NullSpace().create(vectors=vecs, comm=pc.comm)
            self.lo_op.petscmat.setNearNullSpace(nullsp)
        lo = PETSc.PC().create(comm=pc.comm)
        lo.incrementTabLevel(1, parent=pc)
        lo.setOperators(self.lo_op.petscmat, self.lo_op.petscmat)
        lo.setOptionsPrefix(pc.getOptionsPrefix() + "lo_")
        lo.setFromOptions()
        self.lo = lo
        self.restriction = restriction_matrix(Pk, P1, self.bcs, self.lo_bcs)

        self.work = self.lo_op.petscmat.createVecs()
        if len(self.bcs) > 0:
            bc_nodes = numpy.unique(
                numpy.concatenate([bc.nodes for bc in self.bcs]))
            bc_nodes = bc_nodes[bc_nodes < Pk.dof_dset.size]
            bc_iset = PETSc.IS().createBlock(numpy.prod(shape),
                                             bc_nodes,
                                             comm=PETSc.COMM_SELF)
            self.bc_indices = bc_iset.getIndices()
            bc_iset.destroy()
        else:
            self.bc_indices = numpy.empty(0, dtype=numpy.int32)
Exemplo n.º 11
0
    fd.triplot(mesh)
    plt.legend()
    plt.savefig("plots/darcy_rt.png")

# ----
# 3) Setting problem (FunctionSpace, Init.Condition, VariationalForms)
print('* setting problem')

# 3.1) # Define function space for system
if quad_mesh:
    RT = fd.FunctionSpace(mesh, "RTCF", order)
    DG = fd.FunctionSpace(mesh, "DQ", order - 1)

    # Others function space
    V = fd.VectorFunctionSpace(mesh, "DQ", order - 1)
    T = fd.TensorFunctionSpace(mesh, "DQ", order - 1)
else:
    RT = fd.FunctionSpace(mesh, "RT", order)
    DG = fd.FunctionSpace(mesh, "DG", order - 1)

    # Others function space
    V = fd.VectorFunctionSpace(mesh, "DG", order - 1)
    T = fd.TensorFunctionSpace(mesh, "DG", order - 1)

W = RT * DG

# test and trial functions on the subspaces of the mixed function spaces as
# follows: ::
u, p = fd.TrialFunctions(W)
v, q = fd.TestFunctions(W)
Exemplo n.º 12
0
def clement_interpolant(source, target_space=None, boundary_tag=None):
    r"""
    Compute the Clement interpolant of a :math:`\mathbb P0`
    source field, i.e. take the volume average over
    neighbouring cells at each vertex.

    :arg source: the :math:`\mathbb P0` source field
    :kwarg target_space: the :math:`\mathbb P1` space to
        interpolate into
    :boundary_tag: optional boundary tag to compute the
        Clement interpolant over.
    """
    V = source.function_space()
    assert V.ufl_element().family() == "Discontinuous Lagrange"
    assert V.ufl_element().degree() == 0
    rank = len(V.ufl_element().value_shape())
    mesh = V.mesh()
    dim = mesh.topological_dimension()
    P1 = firedrake.FunctionSpace(mesh, "CG", 1)
    dX = ufl.dx if boundary_tag is None else ufl.ds(boundary_tag)
    if target_space is None:
        if rank == 0:
            target_space = P1
        elif rank == 1:
            target_space = firedrake.VectorFunctionSpace(mesh, "CG", 1)
        elif rank == 2:
            target_space = firedrake.TensorFunctionSpace(mesh, "CG", 1)
        else:
            raise ValueError(f"Rank-{rank} tensors are not supported.")
    else:
        assert target_space.ufl_element().family() == "Lagrange"
        assert target_space.ufl_element().degree() == 1
    target = firedrake.Function(target_space)

    # Compute the patch volume at each vertex
    if boundary_tag is None:
        P0 = firedrake.FunctionSpace(mesh, "DG", 0)
        dx = ufl.dx(domain=mesh)
        volume = firedrake.assemble(firedrake.TestFunction(P0) * dx)
    else:
        volume = get_facet_areas(mesh)
    patch_volume = firedrake.Function(P1)
    kernel = "for (int i=0; i < p.dofs; i++) p[i] += v[0];"
    keys = {
        "v": (volume, op2.READ),
        "p": (patch_volume, op2.INC),
    }
    firedrake.par_loop(kernel, dX, keys)

    # Volume average
    keys = {
        "s": (source, op2.READ),
        "v": (volume, op2.READ),
        "t": (target, op2.INC),
    }
    if rank == 0:
        firedrake.par_loop(
            """
            for (int i=0; i < t.dofs; i++) {
              t[i] += s[0]*v[0];
            }
            """,
            dX,
            keys,
        )
    elif rank == 1:
        firedrake.par_loop(
            """
            int d = %d;
            for (int i=0; i < t.dofs; i++) {
              for (int j=0; j < d; j++) {
                t[i*d + j] += s[j]*v[0];
              }
            }
            """
            % dim,
            dX,
            keys,
        )
    elif rank == 2:
        firedrake.par_loop(
            """
            int d = %d;
            int Nd = d*d;
            for (int i=0; i < t.dofs; i++) {
              for (int j=0; j < d; j++) {
                for (int k=0; k < d; k++) {
                  t[i*Nd + j*d + k] += s[j*d + k]*v[0];
                }
              }
            }
            """
            % dim,
            dX,
            keys,
        )
    else:
        raise ValueError(f"Rank-{rank} tensors are not supported.")
    target.interpolate(target / patch_volume)
    if boundary_tag is not None:
        target.dat.data_with_halos[:] = np.nan_to_num(target.dat.data_with_halos)
    return target
Exemplo n.º 13
0
parser = argparse.ArgumentParser()
parser.add_argument('--mesh')
parser.add_argument('--input')
parser.add_argument('--output')
parser.add_argument('--damage', action='store_true')
parser.add_argument('--final-time', type=float)
parser.add_argument('--num-steps', type=int)
args = parser.parse_args()

# Load the mesh and create some function spaces
mesh = firedrake.Mesh(args.mesh)
Q = firedrake.FunctionSpace(mesh, family='CG', degree=2)
V = firedrake.VectorFunctionSpace(mesh, family='CG', degree=2)
Δ = firedrake.FunctionSpace(mesh, family='DG', degree=1)
S = firedrake.TensorFunctionSpace(mesh, family='DG', degree=1)

# Load the initial data from an HDF5 file if available
if args.input:
    h0 = firedrake.Function(Q)
    u0 = firedrake.Function(V)

    input_name = os.path.splitext(args.input)[0]
    with firedrake.DumbCheckpoint(input_name, mode=firedrake.FILE_READ) as chk:
        chk.load(h0, name='h')
        chk.load(u0, name='u')

# Otherwise, create some synthetic initial data symbolically
else:
    import numpy as np
    from numpy import pi as π