Example #1
0
def test_subdomains(compile_args):
    cell = ufl.triangle
    element = ufl.FiniteElement("Lagrange", cell, 1)
    u, v = ufl.TrialFunction(element), ufl.TestFunction(element)
    a0 = ufl.inner(u, v) * ufl.dx + ufl.inner(u, v) * ufl.dx(2)
    a1 = ufl.inner(u, v) * ufl.dx(2) + ufl.inner(u, v) * ufl.dx
    a2 = ufl.inner(u, v) * ufl.dx(2) + ufl.inner(u, v) * ufl.dx(1)
    a3 = ufl.inner(u, v) * ufl.ds(210) + ufl.inner(u, v) * ufl.ds(0)
    forms = [a0, a1, a2, a3]
    compiled_forms, module, code = ffcx.codegeneration.jit.compile_forms(
        forms,
        parameters={'scalar_type': 'double'},
        cffi_extra_compile_args=compile_args)

    for f, compiled_f in zip(forms, compiled_forms):
        assert compiled_f.rank == len(f.arguments())

    form0 = compiled_forms[0]
    ids = form0.integral_ids(module.lib.cell)
    assert ids[0] == -1 and ids[1] == 2

    form1 = compiled_forms[1]
    ids = form1.integral_ids(module.lib.cell)
    assert ids[0] == -1 and ids[1] == 2

    form2 = compiled_forms[2]
    ids = form2.integral_ids(module.lib.cell)
    assert ids[0] == 1 and ids[1] == 2

    form3 = compiled_forms[3]
    assert form3.num_integrals(module.lib.cell) == 0

    ids = form3.integral_ids(module.lib.exterior_facet)
    assert ids[0] == 0 and ids[1] == 210
Example #2
0
def test_assemble_manifold():
    """Test assembly of poisson problem on a mesh with topological dimension 1
    but embedded in 2D (gdim=2).
    """
    points = numpy.array([[0.0, 0.0], [0.2, 0.0], [0.4, 0.0], [0.6, 0.0],
                          [0.8, 0.0], [1.0, 0.0]],
                         dtype=numpy.float64)
    cells = numpy.array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]],
                        dtype=numpy.int32)
    cell = ufl.Cell("interval", geometric_dimension=points.shape[1])
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 1))
    mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)
    assert mesh.geometry.dim == 2
    assert mesh.topology.dim == 1

    U = dolfinx.FunctionSpace(mesh, ("P", 1))

    u, v = ufl.TrialFunction(U), ufl.TestFunction(U)
    w = dolfinx.Function(U)

    a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx(mesh)
    L = ufl.inner(1.0, v) * ufl.dx(mesh)

    bcdofs = dolfinx.fem.locate_dofs_geometrical(
        U, lambda x: numpy.isclose(x[0], 0.0))
    bcs = [dolfinx.DirichletBC(w, bcdofs)]
    A = dolfinx.fem.assemble_matrix(a, bcs)
    A.assemble()

    b = dolfinx.fem.assemble_vector(L)
    dolfinx.fem.apply_lifting(b, [a], [bcs])
    dolfinx.fem.set_bc(b, bcs)

    assert numpy.isclose(b.norm(), 0.41231)
    assert numpy.isclose(A.norm(), 25.0199)
Example #3
0
def run_scalar_test(mesh, V, degree):
    """ Manufactured Poisson problem, solving u = x[1]**p, where p is the
    degree of the Lagrange function space.

    """
    u, v = TrialFunction(V), TestFunction(V)
    a = inner(grad(u), grad(v)) * dx

    # Get quadrature degree for bilinear form integrand (ignores effect of non-affine map)
    a = inner(grad(u), grad(v)) * dx(metadata={"quadrature_degree": -1})
    a.integrals()[0].metadata(
    )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(a)
    a = form(a)

    # Source term
    x = SpatialCoordinate(mesh)
    u_exact = x[1]**degree
    f = -div(grad(u_exact))

    # Set quadrature degree for linear form integrand (ignores effect of non-affine map)
    L = inner(f, v) * dx(metadata={"quadrature_degree": -1})
    L.integrals()[0].metadata(
    )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(L)
    L = form(L)

    u_bc = Function(V)
    u_bc.interpolate(lambda x: x[1]**degree)

    # Create Dirichlet boundary condition
    facetdim = mesh.topology.dim - 1
    mesh.topology.create_connectivity(facetdim, mesh.topology.dim)
    bndry_facets = np.where(
        np.array(compute_boundary_facets(mesh.topology)) == 1)[0]
    bdofs = locate_dofs_topological(V, facetdim, bndry_facets)
    bc = dirichletbc(u_bc, bdofs)

    b = assemble_vector(L)
    apply_lifting(b, [a], bcs=[[bc]])
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    set_bc(b, [bc])

    a = form(a)
    A = assemble_matrix(a, bcs=[bc])
    A.assemble()

    # Create LU linear solver
    solver = PETSc.KSP().create(MPI.COMM_WORLD)
    solver.setType(PETSc.KSP.Type.PREONLY)
    solver.getPC().setType(PETSc.PC.Type.LU)
    solver.setOperators(A)

    uh = Function(V)
    solver.solve(b, uh.vector)
    uh.x.scatter_forward()

    M = (u_exact - uh)**2 * dx
    M = form(M)
    error = mesh.comm.allreduce(assemble_scalar(M), op=MPI.SUM)
    assert np.absolute(error) < 1.0e-14
Example #4
0
def forms(arguments, coefficients):
    v, u = arguments
    c, f = coefficients
    n = FacetNormal(triangle)
    a = u * v * dx
    L = f * v * dx
    b = u * v * dx(0) + inner(c * grad(u), grad(v)) * \
        dx(1) + dot(n, grad(u)) * v * ds + f * v * dx
    return (a, L, b)
Example #5
0
def forms(arguments, coefficients):
    v, u = arguments
    c, f = coefficients
    n = FacetNormal(triangle)
    a = u * v * dx
    L = f * v * dx
    b = u * v * dx(0) + inner(c * grad(u), grad(v)) * \
        dx(1) + dot(n, grad(u)) * v * ds + f * v * dx
    return (a, L, b)
Example #6
0
def test_assemble_functional():
    mesh = dolfin.generation.UnitSquareMesh(dolfin.MPI.comm_world, 12, 12)
    M = 1.0 * dx(domain=mesh)
    value = dolfin.fem.assemble(M)
    assert value == pytest.approx(1.0, 1e-12)
    x = dolfin.SpatialCoordinate(mesh)
    M = x[0] * dx(domain=mesh)
    value = dolfin.fem.assemble(M)
    assert value == pytest.approx(0.5, 1e-12)
Example #7
0
def test_assemble_functional():
    mesh = dolfin.generation.UnitSquareMesh(dolfin.MPI.comm_world, 12, 12)

    M = dolfin.Constant(1.0) * dx(domain=mesh)
    value = dolfin.fem.assemble(M)
    assert value == pytest.approx(1.0, 1e-12)

    f = dolfin.function.expression.Expression("x[0]", degree=1)
    M = f * dx(domain=mesh)
    value = dolfin.fem.assemble(M)
    assert value == pytest.approx(0.5, 1e-12)
Example #8
0
def test_assemble_functional_dx(mode):
    mesh = create_unit_square(MPI.COMM_WORLD, 12, 12, ghost_mode=mode)
    M = form(1.0 * dx(domain=mesh))
    value = assemble_scalar(M)
    value = mesh.comm.allreduce(value, op=MPI.SUM)
    assert value == pytest.approx(1.0, 1e-12)
    x = ufl.SpatialCoordinate(mesh)
    M = form(x[0] * dx(domain=mesh))
    value = assemble_scalar(M)
    value = mesh.comm.allreduce(value, op=MPI.SUM)
    assert value == pytest.approx(0.5, 1e-12)
Example #9
0
def test_assemble_functional():
    mesh = dolfinx.generation.UnitSquareMesh(dolfinx.MPI.comm_world, 12, 12)
    M = 1.0 * dx(domain=mesh)
    value = dolfinx.fem.assemble_scalar(M)
    value = dolfinx.MPI.sum(mesh.mpi_comm(), value)
    assert value == pytest.approx(1.0, 1e-12)
    x = SpatialCoordinate(mesh)
    M = x[0] * dx(domain=mesh)
    value = dolfinx.fem.assemble_scalar(M)
    value = dolfinx.MPI.sum(mesh.mpi_comm(), value)
    assert value == pytest.approx(0.5, 1e-12)
Example #10
0
def test_assemble_functional_dx(mode):
    mesh = UnitSquareMesh(MPI.COMM_WORLD, 12, 12, ghost_mode=mode)
    M = 1.0 * dx(domain=mesh)
    value = dolfinx.fem.assemble_scalar(M)
    value = mesh.mpi_comm().allreduce(value, op=MPI.SUM)
    assert value == pytest.approx(1.0, 1e-12)
    x = ufl.SpatialCoordinate(mesh)
    M = x[0] * dx(domain=mesh)
    value = dolfinx.fem.assemble_scalar(M)
    value = mesh.mpi_comm().allreduce(value, op=MPI.SUM)
    assert value == pytest.approx(0.5, 1e-12)
Example #11
0
def test_expression_assemble(V1, vV1, squaremesh_5):

    u1, u2 = dolfinx.Function(V1), dolfinx.Function(vV1)

    dx = ufl.dx(squaremesh_5)

    u1.vector.set(3.0)
    u2.vector.set(2.0)
    u1.vector.ghostUpdate()
    u2.vector.ghostUpdate()

    # check assembled shapes

    assert numpy.shape(dolfiny.expression.assemble(1.0, dx)) == ()
    assert numpy.shape(dolfiny.expression.assemble(ufl.grad(u1), dx)) == (2,)
    assert numpy.shape(dolfiny.expression.assemble(ufl.grad(u2), dx)) == (2, 2)

    # check assembled values

    assert numpy.isclose(dolfiny.expression.assemble(1.0, dx), 1.0)
    assert numpy.isclose(dolfiny.expression.assemble(u1, dx), 3.0)
    assert numpy.isclose(dolfiny.expression.assemble(u2, dx), 2.0).all()
    assert numpy.isclose(dolfiny.expression.assemble(u1 * u2, dx), 6.0).all()

    assert numpy.isclose(dolfiny.expression.assemble(ufl.grad(u1), dx), 0.0).all()
    assert numpy.isclose(dolfiny.expression.assemble(ufl.grad(u2), dx), 0.0).all()
Example #12
0
def test_additivity(mode):
    mesh = create_unit_square(MPI.COMM_WORLD, 12, 12, ghost_mode=mode)
    V = FunctionSpace(mesh, ("Lagrange", 1))

    f1 = Function(V)
    f2 = Function(V)
    f3 = Function(V)
    f1.x.array[:] = 1.0
    f2.x.array[:] = 2.0
    f3.x.array[:] = 3.0
    j1 = ufl.inner(f1, f1) * ufl.dx(mesh)
    j2 = ufl.inner(f2, f2) * ufl.ds(mesh)
    j3 = ufl.inner(ufl.avg(f3), ufl.avg(f3)) * ufl.dS(mesh)

    # Assemble each scalar form separately
    J1 = mesh.comm.allreduce(assemble_scalar(form(j1)), op=MPI.SUM)
    J2 = mesh.comm.allreduce(assemble_scalar(form(j2)), op=MPI.SUM)
    J3 = mesh.comm.allreduce(assemble_scalar(form(j3)), op=MPI.SUM)

    # Sum forms and assemble the result
    J12 = mesh.comm.allreduce(assemble_scalar(form(j1 + j2)), op=MPI.SUM)
    J13 = mesh.comm.allreduce(assemble_scalar(form(j1 + j3)), op=MPI.SUM)
    J23 = mesh.comm.allreduce(assemble_scalar(form(j2 + j3)), op=MPI.SUM)
    J123 = mesh.comm.allreduce(assemble_scalar(form(j1 + j2 + j3)), op=MPI.SUM)

    # Compare assembled values
    assert (J1 + J2) == pytest.approx(J12)
    assert (J1 + J3) == pytest.approx(J13)
    assert (J2 + J3) == pytest.approx(J23)
    assert (J1 + J2 + J3) == pytest.approx(J123)
Example #13
0
def test_expression_linearise(V1, V2, squaremesh_5):

    u1, u10 = dolfinx.Function(V1), dolfinx.Function(V1)
    u2, u20 = dolfinx.Function(V2), dolfinx.Function(V2)

    dx = ufl.dx(squaremesh_5)

    # Test linearisation of expressions at u0

    assert dolfiny.expression.linearise(1 * u1, u1, u0=u10) == \
        u10 + (u1 + (-1) * u10)
    assert dolfiny.expression.linearise(2 * u1 + u2, u1, u0=u10) == \
        (u2 + 2 * u10) + (2 * u1 + (-1) * (2 * u10))
    assert dolfiny.expression.linearise(u1**2 + u2, u1, u0=u10) == \
        (u10 * (2 * u1) + (-1) * (u10 * 2 * u10)) + (u10**2 + u2)

    assert dolfiny.expression.linearise(u1**2 + u2**2, [u1, u2], u0=[u10, u20]) == \
        (u10 * (2 * u1) + u20 * (2 * u2) + (-1) * (u10 * (2 * u10) + u20 * (2 * u20))) + (u10**2 + u20**2)
    assert dolfiny.expression.linearise([u1**2, u2], u1, u0=u10) == \
        [(u10 * (2 * u1) + (-1) * (u10 * 2 * u10)) + u10**2, u2]
    assert dolfiny.expression.linearise([u1**2 + u2, u2], [u1, u2], u0=[u10, u20]) == \
        [(u10 * (2 * u1) + u2 + (-1) * (u10 * (2 * u10) + u20)) + (u10**2 + u20), (u2 + (-1) * u20) + u20]

    # Test linearisation of forms at u0

    assert dolfiny.expression.linearise(1 * u1 * dx, u1, u0=u10) == \
        u10 * dx + (u1 * dx + (-1) * u10 * dx)
    assert dolfiny.expression.linearise([u1**2 * dx, u2 * dx], u1, u0=u10) == \
        [u10**2 * dx + u10 * (2 * u1) * dx + (-1) * (u10 * 2 * u10) * dx, u2 * dx]
Example #14
0
def test_gmsh_input_quad(order):
    pygmsh = pytest.importorskip("pygmsh")

    # Parameterize test if gmsh gets wider support
    R = 1
    res = 0.2 if order == 2 else 0.2
    algorithm = 2 if order == 2 else 5
    element = "quad{0:d}".format(int((order + 1)**2))

    geo = pygmsh.opencascade.Geometry()
    geo.add_raw_code("Mesh.ElementOrder={0:d};".format(order))
    geo.add_ball([0, 0, 0], R, char_length=res)
    geo.add_raw_code("Recombine Surface {1};")
    geo.add_raw_code("Mesh.Algorithm = {0:d};".format(algorithm))

    msh = pygmsh.generate_mesh(geo, verbose=True, dim=2)

    if order > 2:
        # Quads order > 3 have a gmsh specific ordering, and has to be permuted.
        msh_to_dolfin = np.array([0, 3, 11, 10, 1, 2, 6, 7, 4, 9, 12, 15, 5, 8, 13, 14])
        cells = np.zeros(msh.cells_dict[element].shape)
        for i in range(len(cells)):
            for j in range(len(msh_to_dolfin)):
                cells[i, j] = msh.cells_dict[element][i, msh_to_dolfin[j]]
    else:
        # XDMF does not support higher order quads
        cells = permute_cell_ordering(msh.cells_dict[element], permutation_vtk_to_dolfin(
            CellType.quadrilateral, msh.cells_dict[element].shape[1]))

    mesh = Mesh(MPI.comm_world, CellType.quadrilateral, msh.points, cells,
                [], GhostMode.none)
    surface = assemble_scalar(1 * dx(mesh))

    assert MPI.sum(mesh.mpi_comm(), surface) == pytest.approx(4 * np.pi * R * R, rel=1e-5)
def test_additivity(mode):
    mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 12, 12, ghost_mode=mode)
    V = dolfinx.FunctionSpace(mesh, ("CG", 1))

    f1 = dolfinx.Function(V)
    f2 = dolfinx.Function(V)
    f3 = dolfinx.Function(V)
    with f1.vector.localForm() as f1_local:
        f1_local.set(1.0)
    with f2.vector.localForm() as f2_local:
        f2_local.set(2.0)
    with f3.vector.localForm() as f3_local:
        f3_local.set(3.0)
    j1 = ufl.inner(f1, f1) * ufl.dx(mesh)
    j2 = ufl.inner(f2, f2) * ufl.ds(mesh)
    j3 = ufl.inner(ufl.avg(f3), ufl.avg(f3)) * ufl.dS(mesh)

    # Assemble each scalar form separately
    J1 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j1), op=MPI.SUM)
    J2 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j2), op=MPI.SUM)
    J3 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j3), op=MPI.SUM)

    # Sum forms and assemble the result
    J12 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j1 + j2), op=MPI.SUM)
    J13 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j1 + j3), op=MPI.SUM)
    J23 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j2 + j3), op=MPI.SUM)
    J123 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j1 + j2 + j3), op=MPI.SUM)

    # Compare assembled values
    assert (J1 + J2) == pytest.approx(J12)
    assert (J1 + J3) == pytest.approx(J13)
    assert (J2 + J3) == pytest.approx(J23)
    assert (J1 + J2 + J3) == pytest.approx(J123)
Example #16
0
def test_custom_quadrature(compile_args):
    ve = ufl.VectorElement("P", "triangle", 1)
    mesh = ufl.Mesh(ve)

    e = ufl.FiniteElement("P", mesh.ufl_cell(), 2)
    V = ufl.FunctionSpace(mesh, e)
    u, v = ufl.TrialFunction(V), ufl.TestFunction(V)

    points = [[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [0.5, 0.5], [0.0, 0.5], [0.5, 0.0]]
    weights = [1 / 12] * 6
    a = u * v * ufl.dx(metadata={"quadrature_rule": "custom",
                                 "quadrature_points": points, "quadrature_weights": weights})

    forms = [a]
    compiled_forms, module = ffcx.codegeneration.jit.compile_forms(forms, cffi_extra_compile_args=compile_args)

    ffi = cffi.FFI()
    form = compiled_forms[0][0]
    default_integral = form.create_cell_integral(-1)

    A = np.zeros((6, 6), dtype=np.float64)
    w = np.array([], dtype=np.float64)
    c = np.array([], dtype=np.float64)

    coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64)
    default_integral.tabulate_tensor(
        ffi.cast("double *", A.ctypes.data),
        ffi.cast("double *", w.ctypes.data),
        ffi.cast("double *", c.ctypes.data),
        ffi.cast("double *", coords.ctypes.data), ffi.NULL, ffi.NULL, 0)

    # Check that A is diagonal
    assert np.count_nonzero(A - np.diag(np.diagonal(A))) == 0
Example #17
0
def test_expression_evaluate(V1, V2, squaremesh_5):

    u1, v1 = ufl.TrialFunction(V1), ufl.TestFunction(V1)
    u2, v2 = ufl.TrialFunction(V2), ufl.TestFunction(V2)

    dx = ufl.dx(squaremesh_5)

    # Test evaluation of expressions

    assert dolfiny.expression.evaluate(1 * u1, u1, u2) == 1 * u2
    assert dolfiny.expression.evaluate(2 * u1 + u2, u1, u2) == 2 * u2 + 1 * u2
    assert dolfiny.expression.evaluate(u1**2 + u2, u1, u2) == u2**2 + 1 * u2

    assert dolfiny.expression.evaluate(u1 + u2, [u1, u2], [v1, v2]) == v1 + v2
    assert dolfiny.expression.evaluate([u1, u2], u1, v1) == [v1, u2]
    assert dolfiny.expression.evaluate([u1, u2], [u1, u2], [v1, v2]) == [v1, v2]

    # Test evaluation of forms

    assert dolfiny.expression.evaluate(1 * u1 * dx, u1, u2) == 1 * u2 * dx
    assert dolfiny.expression.evaluate(2 * u1 * dx + u2 * dx, u1, u2) == 2 * u2 * dx + 1 * u2 * dx
    assert dolfiny.expression.evaluate(u1**2 * dx + u2 * dx, u1, u2) == u2**2 * dx + 1 * u2 * dx

    assert dolfiny.expression.evaluate(u1 * dx + u2 * dx, [u1, u2], [v1, v2]) == v1 * dx + v2 * dx
    assert dolfiny.expression.evaluate([u1 * dx, u2 * dx], u1, v1) == [v1 * dx, u2 * dx]
    assert dolfiny.expression.evaluate([u1 * dx, u2 * dx], [u1, u2], [v1, v2]) == [v1 * dx, v2 * dx]
    def __init__(self, mesh, k: int, omega, c, c0, lumped):
        P = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), k)
        self.V = FunctionSpace(mesh, P)
        self.u, self.v = Function(self.V), Function(self.V)
        self.g1 = Function(self.V)
        self.g2 = Function(self.V)
        self.omega = omega
        self.c = c
        self.c0 = c0

        n = FacetNormal(mesh)

        # Pieces for plane wave incident field
        x = ufl.geometry.SpatialCoordinate(mesh)
        cos_wave = ufl.cos(self.omega / self.c0 * x[0])
        sin_wave = ufl.sin(self.omega / self.c0 * x[0])

        plane_wave = self.g1 * cos_wave + self.g2 * sin_wave

        dv, p = TrialFunction(self.V), TestFunction(self.V)
        self.L1 = - inner(grad(self.u), grad(p)) * dx(degree=k) \
            - (1 / self.c) * inner(self.v, p) * ds \
            - (1 / self.c**2) * (-self.omega**2) * inner(plane_wave, p) * dx \
            - inner(grad(plane_wave), grad(p)) * dx \
            + inner(dot(grad(plane_wave), n), p) * ds

        # Vector to be re-used for assembly
        self.b = None

        # TODO: precompile/pre-process Form L

        self.lumped = lumped
        if self.lumped:
            a = (1 / self.c**2) * p * dx(degree=k)
            self.M = dolfinx.fem.assemble_vector(a)
            self.M.ghostUpdate(addv=PETSc.InsertMode.ADD,
                               mode=PETSc.ScatterMode.REVERSE)
        else:
            a = (1 / self.c**2) * inner(dv, p) * dx(degree=k)
            M = dolfinx.fem.assemble_matrix(a)
            M.assemble()
            self.solver = PETSc.KSP().create(mesh.mpi_comm())
            opts = PETSc.Options()
            opts["ksp_type"] = "cg"
            opts["ksp_rtol"] = 1.0e-8
            self.solver.setFromOptions()
            self.solver.setOperators(M)
def test_fourth_order_quad(L, H, Z):
    """Test by comparing integration of z+x*y against sympy/scipy integration
    of a quad element. Z>0 implies curved element.

      *---------*   20-21-22-23-24-41--42--43--44
      |         |   |           |              |
      |         |   15 16 17 18 19 37  38  39  40
      |         |   |           |              |
      |         |   10 11 12 13 14 33  34  35  36
      |         |   |           |              |
      |         |   5  6  7  8  9  29  30  31  32
      |         |   |           |              |
      *---------*   0--1--2--3--4--25--26--27--28

    """
    points = np.array([[0, 0, 0], [L / 4, 0, 0], [L / 2, 0, 0],               # 0 1 2
                       [3 * L / 4, 0, 0], [L, 0, 0],                          # 3 4
                       [0, H / 4, -Z / 3], [L / 4, H / 4, -Z / 3], [L / 2, H / 4, -Z / 3],   # 5 6 7
                       [3 * L / 4, H / 4, -Z / 3], [L, H / 4, -Z / 3],                  # 8 9
                       [0, H / 2, 0], [L / 4, H / 2, 0], [L / 2, H / 2, 0],   # 10 11 12
                       [3 * L / 4, H / 2, 0], [L, H / 2, 0],                  # 13 14
                       [0, (3 / 4) * H, 0], [L / 4, (3 / 4) * H, 0],          # 15 16
                       [L / 2, (3 / 4) * H, 0], [3 * L / 4, (3 / 4) * H, 0],  # 17 18
                       [L, (3 / 4) * H, 0], [0, H, Z], [L / 4, H, Z],         # 19 20 21
                       [L / 2, H, Z], [3 * L / 4, H, Z], [L, H, Z],           # 22 23 24
                       [(5 / 4) * L, 0, 0], [(6 / 4) * L, 0, 0],              # 25 26
                       [(7 / 4) * L, 0, 0], [2 * L, 0, 0],                    # 27 28
                       [(5 / 4) * L, H / 4, -Z / 3], [(6 / 4) * L, H / 4, -Z / 3],      # 29 30
                       [(7 / 4) * L, H / 4, -Z / 3], [2 * L, H / 4, -Z / 3],            # 31 32
                       [(5 / 4) * L, H / 2, 0], [(6 / 4) * L, H / 2, 0],      # 33 34
                       [(7 / 4) * L, H / 2, 0], [2 * L, H / 2, 0],            # 35 36
                       [(5 / 4) * L, 3 / 4 * H, 0],                           # 37
                       [(6 / 4) * L, 3 / 4 * H, 0],                           # 38
                       [(7 / 4) * L, 3 / 4 * H, 0], [2 * L, 3 / 4 * H, 0],    # 39 40
                       [(5 / 4) * L, H, Z], [(6 / 4) * L, H, Z],              # 41 42
                       [(7 / 4) * L, H, Z], [2 * L, H, Z]])                   # 43 44

    # VTK ordering
    cells = np.array([[0, 4, 24, 20, 1, 2, 3, 9, 14, 19, 21, 22, 23, 5, 10, 15, 6, 7, 8, 11, 12, 13, 16, 17, 18],
                      [4, 28, 44, 24, 25, 26, 27, 32, 36, 40, 41, 42, 43, 9, 14, 19,
                       29, 30, 31, 33, 34, 35, 37, 38, 39]])
    cells = cells[:, perm_vtk(CellType.quadrilateral, cells.shape[1])]
    cell = ufl.Cell("quadrilateral", geometric_dimension=points.shape[1])
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 4))
    mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)

    def e2(x):
        return x[2] + x[0] * x[1]

    V = FunctionSpace(mesh, ("CG", 4))
    u = Function(V)
    u.interpolate(e2)

    intu = assemble_scalar(u * dx(mesh))
    intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM)

    nodes = [0, 5, 10, 15, 20]
    ref = sympy_scipy(points, nodes, 2 * L, H)
    assert ref == pytest.approx(intu, rel=1e-5)
Example #20
0
def test_ufl_block_extraction(V1, V2, squaremesh_5):
    mesh = squaremesh_5
    u1, v1 = ufl.TrialFunction(V1), ufl.TestFunction(V1)
    u2, v2 = ufl.TrialFunction(V2), ufl.TestFunction(V2)

    a = u1 * v1 * ufl.dx(mesh) + ufl.grad(u1 * v2)[0] * ufl.dx(mesh)

    ablocks = dolfiny.function.extract_blocks(a, [v1, v2], [u1, u2])

    assert ablocks[1][1].empty()
    assert ablocks[0][1].empty()

    L = ufl.grad(v2)[0] * ufl.dx(mesh)
    Lblocks = dolfiny.function.extract_blocks(L, [v1, v2])

    assert Lblocks[0].empty()
    assert Lblocks[1] == L
Example #21
0
def translate_cellvolume(terminal, mt, ctx):
    integrand, degree = one_times(ufl.dx(domain=terminal.ufl_domain()))
    interface = CellVolumeKernelInterface(ctx, mt.restriction)

    config = {name: getattr(ctx, name)
              for name in ["ufl_cell", "precision", "index_cache"]}
    config.update(interface=interface, quadrature_degree=degree)
    expr, = compile_ufl(integrand, point_sum=True, **config)
    return expr
Example #22
0
def test_block(V1, V2, squaremesh_5, nest):
    mesh = squaremesh_5

    u0 = dolfinx.Function(V1, name="u0")
    u1 = dolfinx.Function(V2, name="u1")

    v0 = ufl.TestFunction(V1)
    v1 = ufl.TestFunction(V2)

    Phi = (ufl.sin(u0) - 0.5)**2 * ufl.dx(mesh) + (4.0 * u0 -
                                                   u1)**2 * ufl.dx(mesh)

    F0 = ufl.derivative(Phi, u0, v0)
    F1 = ufl.derivative(Phi, u1, v1)

    F = [F0, F1]
    u = [u0, u1]

    opts = PETSc.Options("block")

    opts.setValue('snes_type', 'newtontr')
    opts.setValue('snes_rtol', 1.0e-08)
    opts.setValue('snes_max_it', 12)

    if nest:
        opts.setValue('ksp_type', 'cg')
        opts.setValue('pc_type', 'fieldsplit')
        opts.setValue('fieldsplit_pc_type', 'lu')
        opts.setValue('ksp_rtol', 1.0e-10)
    else:
        opts.setValue('ksp_type', 'preonly')
        opts.setValue('pc_type', 'lu')
        opts.setValue('pc_factor_mat_solver_type', 'mumps')

    problem = dolfiny.snesblockproblem.SNESBlockProblem(F,
                                                        u,
                                                        nest=nest,
                                                        prefix="block")
    sol = problem.solve()

    assert problem.snes.getConvergedReason() > 0
    assert np.isclose((sol[0].vector - np.arcsin(0.5)).norm(), 0.0)
    assert np.isclose((sol[1].vector - 4.0 * np.arcsin(0.5)).norm(), 0.0)
Example #23
0
def test_xdmf_input_tri(datadir):
    with XDMFFile(MPI.COMM_WORLD,
                  os.path.join(datadir, "mesh.xdmf"),
                  "r",
                  encoding=XDMFFile.Encoding.ASCII) as xdmf:
        mesh = xdmf.read_mesh(name="Grid")
    surface = assemble_scalar(1 * dx(mesh))
    assert mesh.mpi_comm().allreduce(surface,
                                     op=MPI.SUM) == pytest.approx(4 * np.pi,
                                                                  rel=1e-4)
Example #24
0
def test_expression_derivative(V1, V2, squaremesh_5):

    u1, du1, v1 = dolfinx.fem.Function(V1), ufl.TrialFunction(
        V1), ufl.TestFunction(V1)
    u2, du2, v2 = dolfinx.fem.Function(V2), ufl.TrialFunction(
        V2), ufl.TestFunction(V2)

    dx = ufl.dx(squaremesh_5)

    # Test derivative of expressions

    assert dolfiny.expression.derivative(1 * u1, u1, du1) == 1 * du1
    assert dolfiny.expression.derivative(2 * u1 + u2, u1, du1) == 2 * du1
    assert dolfiny.expression.derivative(u1**2 + u2, u1, du1) == du1 * 2 * u1

    assert dolfiny.expression.derivative(u1 + u2, [u1, u2],
                                         [v1, v2]) == v1 + v2
    assert dolfiny.expression.derivative([u1, u2], u1, v1) == [v1, 0]
    assert dolfiny.expression.derivative([u1, u2], [u1, u2],
                                         [v1, v2]) == [v1, v2]

    # Test derivative of forms

    assert dolfiny.expression.derivative(1 * u1 * dx, u1, du1) == 1 * du1 * dx
    assert dolfiny.expression.derivative(2 * u1 * dx + u2 * dx, u1,
                                         du1) == 2 * du1 * dx
    assert dolfiny.expression.derivative(u1**2 * dx + u2 * dx, u1,
                                         du2) == du2 * 2 * u1 * dx

    assert dolfiny.expression.derivative(u1 * dx + u2 * dx, [u1, u2],
                                         [v1, v2]) == v1 * dx + v2 * dx
    assert dolfiny.expression.derivative([u1 * dx, u2 * dx], u1,
                                         v1) == [v1 * dx,
                                                 ufl.Form([])]
    assert dolfiny.expression.derivative([u1 * dx, u2 * dx], [u1, u2],
                                         [v1, v2]) == [v1 * dx, v2 * dx]

    # Test derivative of expressions at u0

    u10, u20 = dolfinx.fem.Function(V1), dolfinx.fem.Function(V2)

    assert dolfiny.expression.derivative(1 * u1, u1, du1, u0=u10) == 1 * du1
    assert dolfiny.expression.derivative(2 * u1 + u2, u1, du1,
                                         u0=u10) == 2 * du1
    assert dolfiny.expression.derivative(u1**2 + u2, u1, du1,
                                         u0=u10) == du1 * 2 * u10

    assert dolfiny.expression.derivative(
        u1**2 + u2**2, [u1, u2], [v1, v2],
        [u10, u20]) == v1 * 2 * u10 + v2 * 2 * u20
    assert dolfiny.expression.derivative([u1**2, u2], u1, v1,
                                         u0=u10) == [v1 * 2 * u10, 0]
    assert dolfiny.expression.derivative(
        [u1**2 + u2, u2], [u1, u2], [v1, v2],
        [u10, u20]) == [v1 * 2 * u10 + v2, v2]
Example #25
0
def xtest_third_order_tri():
    #  *---*---*---*   3--11--10--2
    #  | \         |   | \        |
    #  *   *   *   *   8   7  15  13
    #  |     \     |   |    \     |
    #  *  *    *   *   9  14  6   12
    #  |         \ |   |        \ |
    #  *---*---*---*   0--4---5---1
    for H in (1.0, 2.0):
        for Z in (0.0, 0.5):
            L = 1
            points = np.array([
                [0, 0, 0],
                [L, 0, 0],
                [L, H, Z],
                [0, H, Z],  # 0, 1, 2, 3
                [L / 3, 0, 0],
                [2 * L / 3, 0, 0],  # 4, 5
                [2 * L / 3, H / 3, 0],
                [L / 3, 2 * H / 3, 0],  # 6, 7
                [0, 2 * H / 3, 0],
                [0, H / 3, 0],  # 8, 9
                [2 * L / 3, H, Z],
                [L / 3, H, Z],  # 10, 11
                [L, H / 3, 0],
                [L, 2 * H / 3, 0],  # 12, 13
                [L / 3, H / 3, 0],  # 14
                [2 * L / 3, 2 * H / 3, 0]
            ])  # 15
            cells = np.array([[0, 1, 3, 4, 5, 6, 7, 8, 9, 14],
                              [1, 2, 3, 12, 13, 10, 11, 7, 6, 15]])
            cells = permute_cell_ordering(
                cells,
                permutation_vtk_to_dolfin(CellType.triangle, cells.shape[1]))
            mesh = Mesh(MPI.COMM_WORLD,
                        CellType.triangle,
                        points,
                        cells, [],
                        degree=3)

            def e2(x):
                return x[2] + x[0] * x[1]

            degree = mesh.geometry.dofmap_layout().degree()
            # Interpolate function
            V = FunctionSpace(mesh, ("CG", degree))
            u = Function(V)
            u.interpolate(e2)

            intu = assemble_scalar(u * dx(metadata={"quadrature_degree": 40}))
            intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM)

            nodes = [0, 9, 8, 3]
            ref = sympy_scipy(points, nodes, L, H)
            assert ref == pytest.approx(intu, rel=1e-6)
def test_gmsh_input_3d(order, cell_type):
    try:
        import gmsh
    except ImportError:
        pytest.skip()
    if cell_type == CellType.hexahedron and order > 2:
        pytest.xfail("GMSH permutation for order > 2 hexahedra not implemented in DOLFINx.")

    res = 0.2

    gmsh.initialize()
    if cell_type == CellType.hexahedron:
        gmsh.option.setNumber("Mesh.RecombinationAlgorithm", 2)
        gmsh.option.setNumber("Mesh.RecombineAll", 2)
    gmsh.option.setNumber("Mesh.CharacteristicLengthMin", res)
    gmsh.option.setNumber("Mesh.CharacteristicLengthMax", res)

    circle = gmsh.model.occ.addDisk(0, 0, 0, 1, 1)

    if cell_type == CellType.hexahedron:
        gmsh.model.occ.extrude([(2, circle)], 0, 0, 1, numElements=[5], recombine=True)
    else:
        gmsh.model.occ.extrude([(2, circle)], 0, 0, 1, numElements=[5])
    gmsh.model.occ.synchronize()

    gmsh.model.mesh.generate(3)
    gmsh.model.mesh.setOrder(order)

    idx, points, _ = gmsh.model.mesh.getNodes()
    points = points.reshape(-1, 3)
    idx -= 1
    srt = np.argsort(idx)
    assert np.all(idx[srt] == np.arange(len(idx)))
    x = points[srt]

    element_types, element_tags, node_tags = gmsh.model.mesh.getElements(dim=3)
    name, dim, order, num_nodes, local_coords, num_first_order_nodes = gmsh.model.mesh.getElementProperties(
        element_types[0])

    cells = node_tags[0].reshape(-1, num_nodes) - 1
    if cell_type == CellType.tetrahedron:
        gmsh_cell_id = MPI.COMM_WORLD.bcast(gmsh.model.mesh.getElementType("tetrahedron", order), root=0)
    elif cell_type == CellType.hexahedron:
        gmsh_cell_id = MPI.COMM_WORLD.bcast(gmsh.model.mesh.getElementType("hexahedron", order), root=0)
    gmsh.finalize()

    # Permute the mesh topology from GMSH ordering to DOLFINx ordering
    domain = ufl_mesh_from_gmsh(gmsh_cell_id, 3)
    cells = cells[:, perm_gmsh(cell_type, cells.shape[1])]

    mesh = create_mesh(MPI.COMM_WORLD, cells, x, domain)

    volume = assemble_scalar(form(1 * dx(mesh)))

    assert mesh.comm.allreduce(volume, op=MPI.SUM) == pytest.approx(np.pi, rel=10 ** (-1 - order))
Example #27
0
    def cellvolume(restriction):
        from ufl import dx
        integrand, degree = ufl_utils.one_times(dx(domain=domain))
        integrand = ufl_utils.replace_coordinates(integrand, coordinate_coefficient)
        interface = CellVolumeKernelInterface(kernel_config["interface"], restriction)

        config = {k: v for k, v in kernel_config.items()
                  if k in ["ufl_cell", "precision", "index_cache"]}
        config.update(interface=interface, quadrature_degree=degree)
        expr, = fem.compile_ufl(integrand, point_sum=True, **config)
        return expr
Example #28
0
def test_subdomains(compile_args):
    cell = ufl.triangle
    element = ufl.FiniteElement("Lagrange", cell, 1)
    u, v = ufl.TrialFunction(element), ufl.TestFunction(element)
    a0 = ufl.inner(u, v) * ufl.dx + ufl.inner(u, v) * ufl.dx(2)
    a1 = ufl.inner(u, v) * ufl.dx(2) + ufl.inner(u, v) * ufl.dx
    a2 = ufl.inner(u, v) * ufl.dx(2) + ufl.inner(u, v) * ufl.dx(1)
    a3 = ufl.inner(u, v) * ufl.ds(210) + ufl.inner(u, v) * ufl.ds(0)
    forms = [a0, a1, a2, a3]
    compiled_forms, module = ffcx.codegeneration.jit.compile_forms(
        forms,
        parameters={'scalar_type': 'double'},
        cffi_extra_compile_args=compile_args)

    for f, compiled_f in zip(forms, compiled_forms):
        assert compiled_f.rank == len(f.arguments())

    ffi = cffi.FFI()

    form0 = compiled_forms[0][0]
    ids = np.zeros(form0.num_cell_integrals, dtype=np.int32)
    form0.get_cell_integral_ids(ffi.cast('int *', ids.ctypes.data))
    assert ids[0] == -1 and ids[1] == 2

    form1 = compiled_forms[1][0]
    ids = np.zeros(form1.num_cell_integrals, dtype=np.int32)
    form1.get_cell_integral_ids(ffi.cast('int *', ids.ctypes.data))
    assert ids[0] == -1 and ids[1] == 2

    form2 = compiled_forms[2][0]
    ids = np.zeros(form2.num_cell_integrals, dtype=np.int32)
    form2.get_cell_integral_ids(ffi.cast('int *', ids.ctypes.data))
    assert ids[0] == 1 and ids[1] == 2

    form3 = compiled_forms[3][0]
    ids = np.zeros(form3.num_cell_integrals, dtype=np.int32)
    form3.get_cell_integral_ids(ffi.cast('int *', ids.ctypes.data))
    assert len(ids) == 0
    ids = np.zeros(form3.num_exterior_facet_integrals, dtype=np.int32)
    form3.get_exterior_facet_integral_ids(ffi.cast('int *', ids.ctypes.data))
    assert ids[0] == 0 and ids[1] == 210
Example #29
0
def test_third_order_quad(L, H, Z):
    """Test by comparing integration of z+x*y against sympy/scipy integration
    of a quad element. Z>0 implies curved element.

      *---------*   3--8--9--2-22-23-17
      |         |   |        |       |
      |         |   11 14 15 7 26 27 21
      |         |   |        |       |
      |         |   10 12 13 6 24 25 20
      |         |   |        |       |
      *---------*   0--4--5--1-18-19-16

    """
    points = np.array([[0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z],        # 0  1 2 3
                       [L / 3, 0, 0], [2 * L / 3, 0, 0],                  # 4  5
                       [L, H / 3, 0], [L, 2 * H / 3, 0],                  # 6  7
                       [L / 3, H, Z], [2 * L / 3, H, Z],                  # 8  9
                       [0, H / 3, 0], [0, 2 * H / 3, 0],                  # 10 11
                       [L / 3, H / 3, 0], [2 * L / 3, H / 3, 0],          # 12 13
                       [L / 3, 2 * H / 3, 0], [2 * L / 3, 2 * H / 3, 0],  # 14 15
                       [2 * L, 0, 0], [2 * L, H, Z],                      # 16 17
                       [4 * L / 3, 0, 0], [5 * L / 3, 0, 0],              # 18 19
                       [2 * L, H / 3, 0], [2 * L, 2 * H / 3, 0],          # 20 21
                       [4 * L / 3, H, Z], [5 * L / 3, H, Z],              # 22 23
                       [4 * L / 3, H / 3, 0], [5 * L / 3, H / 3, 0],           # 24 25
                       [4 * L / 3, 2 * H / 3, 0], [5 * L / 3, 2 * H / 3, 0]])  # 26 27

    # Change to multiple cells when matthews dof-maps work for quads
    cells = np.array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
                      [1, 16, 17, 2, 18, 19, 20, 21, 22, 23, 6, 7, 24, 25, 26, 27]])

    cells = permute_cell_ordering(cells, permutation_vtk_to_dolfin(CellType.quadrilateral, cells.shape[1]))
    mesh = Mesh(MPI.comm_world, CellType.quadrilateral, points, cells,
                [], GhostMode.none)

    def e2(x):
        return x[2] + x[0] * x[1]

    # Interpolate function
    V = FunctionSpace(mesh, ("CG", 3))
    u = Function(V)
    cmap = fem.create_coordinate_map(mesh.ufl_domain())

    mesh.geometry.coord_mapping = cmap

    u.interpolate(e2)

    intu = assemble_scalar(u * dx(mesh))
    intu = MPI.sum(mesh.mpi_comm(), intu)

    nodes = [0, 3, 10, 11]
    ref = sympy_scipy(points, nodes, 2 * L, H)
    assert ref == pytest.approx(intu, rel=1e-6)
Example #30
0
File: norms.py Project: dham/themis
def norm(v, norm_type="L2", degree=None):
    """Compute the norm of ``v``.

	:arg v: a ufl expression (:class:`~.ufl.classes.Expr`) to compute the norm of
	:arg norm_type: the type of norm to compute, see below for
		 options.

	Available norm types are:

	* L2

	   .. math::

		  ||v||_{L^2}^2 = \int (v, v) \mathrm{d}x

	* H1

	   .. math::

		  ||v||_{H^1}^2 = \int (v, v) + (\\nabla v, \\nabla v) \mathrm{d}x

	* Hdiv

	   .. math::

		  ||v||_{H_\mathrm{div}}^2 = \int (v, v) + (\\nabla\cdot v, \\nabla \cdot v) \mathrm{d}x

	* Hcurl

	   .. math::

		  ||v||_{H_\mathrm{curl}}^2 = \int (v, v) + (\\nabla \wedge v, \\nabla \wedge v) \mathrm{d}x
	"""

    if not degree == None:
        dxn = dx(2 * degree + 1)
    else:
        dxn = dx
    typ = norm_type.lower()
    if typ == 'l2':
        form = inner(v, v) * dxn
    elif typ == 'h1':
        form = inner(v, v) * dxn + inner(grad(v), grad(v)) * dxn
    elif typ == "hdiv":
        form = inner(v, v) * dxn + div(v) * div(v) * dxn
    elif typ == "hcurl":
        form = inner(v, v) * dxn + inner(curl(v), curl(v)) * dxn
    else:
        raise RuntimeError("Unknown norm type '%s'" % norm_type)

    normform = ZeroForm(form)
    return sqrt(normform.assembleform())
Example #31
0
def test_monolithic(V1, V2, squaremesh_5):
    mesh = squaremesh_5

    Wel = ufl.MixedElement([V1.ufl_element(), V2.ufl_element()])
    W = dolfinx.FunctionSpace(mesh, Wel)

    u = dolfinx.Function(W)
    u0, u1 = ufl.split(u)

    v = ufl.TestFunction(W)
    v0, v1 = ufl.split(v)

    Phi = (ufl.sin(u0) - 0.5)**2 * ufl.dx(mesh) + (4.0 * u0 -
                                                   u1)**2 * ufl.dx(mesh)

    F = ufl.derivative(Phi, u, v)

    opts = PETSc.Options("monolithic")

    opts.setValue('snes_type', 'newtonls')
    opts.setValue('snes_linesearch_type', 'basic')

    opts.setValue('snes_rtol', 1.0e-10)
    opts.setValue('snes_max_it', 20)

    opts.setValue('ksp_type', 'preonly')
    opts.setValue('pc_type', 'lu')
    opts.setValue('pc_factor_mat_solver_type', 'mumps')

    problem = dolfiny.snesblockproblem.SNESBlockProblem([F], [u],
                                                        prefix="monolithic")
    sol, = problem.solve()

    u0, u1 = sol.split()
    u0 = u0.collapse()
    u1 = u1.collapse()

    assert np.isclose((u0.vector - np.arcsin(0.5)).norm(), 0.0)
    assert np.isclose((u1.vector - 4.0 * np.arcsin(0.5)).norm(), 0.0)
Example #32
0
    def cellvolume(restriction):
        from ufl import dx
        integrand, degree = ufl_utils.one_times(dx(domain=domain))
        integrand = ufl_utils.replace_coordinates(integrand, coordinate_coefficient)

        interface = CellVolumeKernelInterface(kernel_config["interface"], restriction)
        quadrature_index = gem.Index(name='q')

        config = {k: v for k, v in kernel_config.items()
                  if k in ["ufl_cell", "precision", "index_cache"]}
        config.update(interface=interface,
                      quadrature_degree=degree,
                      point_index=quadrature_index)
        expr, = fem.compile_ufl(integrand, **config)
        if quadrature_index in expr.free_indices:
            expr = gem.IndexSum(expr, quadrature_index)
        return expr
Example #33
0
    def error_indicators(self):
        """
        Generate and return linear form defining error indicators
        """
        # Extract these to increase readability
        R_T = self._R_T
        R_dT = self._R_dT
        z = self._Ez_h
        z_h = self._z_h

        # Define linear form for computing error indicators
        v = self.module.TestFunction(self._DG0)
        eta_T = (v * inner(R_T, z - z_h) * dx(self.domain) +
                 avg(v)*(inner(R_dT('+'), (z - z_h)('+')) +
                         inner(R_dT('-'), (z - z_h)('-'))) * dS(self.domain) +
                 v * inner(R_dT, z - z_h) * ds(self.domain))

        return eta_T
Example #34
0
    def cell_residual(self):
        """
        Generate and return (bilinear, linear) forms defining linear
        variational problem for the strong cell residual
        """
        # Define trial and test functions for the cell residuals on
        # discontinuous version of primal trial space
        R_T = self.module.TrialFunction(self._dV)
        v = self.module.TestFunction(self._dV)

        # Extract original test function in the weak residual
        v_h = self.weak_residual.arguments()[0]

        # Define forms defining linear variational problem for cell
        # residual
        v_T = self._b_T * v
        a_R_T = inner(v_T, R_T) * dx(self.domain)
        L_R_T = replace(self.weak_residual, {v_h: v_T})

        return (a_R_T, L_R_T)
Example #35
0
    def facet_residual(self):
        """
        Generate and return (bilinear, linear) forms defining linear
        variational problem for the strong facet residual(s)
        """
        # Define trial and test functions for the facet residuals on
        # discontinuous version of primal trial space
        R_e = self.module.TrialFunction(self._dV)
        v = self.module.TestFunction(self._dV)

        # Extract original test function in the weak residual
        v_h = self.weak_residual.arguments()[0]

        # Define forms defining linear variational problem for facet
        # residual
        v_e = self._b_e*v
        a_R_dT = ((inner(v_e('+'), R_e('+')) + inner(v_e('-'), R_e('-')))*dS(self.domain)
                  + inner(v_e, R_e)*ds(self.domain))
        L_R_dT = (replace(self.weak_residual, {v_h: v_e})
                  - inner(v_e, self._R_T)*dx(self.domain))

        return (a_R_dT, L_R_dT)
Example #36
0
    def solve(self, problem):
        self.problem = problem
        doSave = problem.doSave
        save_this_step = False
        onlyVel = problem.saveOnlyVel
        dt = self.metadata['dt']

        nu = Constant(self.problem.nu)
        self.tc.init_watch('init', 'Initialization', True, count_to_percent=False)
        self.tc.init_watch('rhs', 'Assembled right hand side', True, count_to_percent=True)
        self.tc.init_watch('applybc1', 'Applied velocity BC 1st step', True, count_to_percent=True)
        self.tc.init_watch('applybc3', 'Applied velocity BC 3rd step', True, count_to_percent=True)
        self.tc.init_watch('applybcP', 'Applied pressure BC or othogonalized rhs', True, count_to_percent=True)
        self.tc.init_watch('assembleMatrices', 'Initial matrix assembly', False, count_to_percent=True)
        self.tc.init_watch('solve 1', 'Running solver on 1st step', True, count_to_percent=True)
        self.tc.init_watch('solve 2', 'Running solver on 2nd step', True, count_to_percent=True)
        self.tc.init_watch('solve 3', 'Running solver on 3rd step', True, count_to_percent=True)
        self.tc.init_watch('solve 4', 'Running solver on 4th step', True, count_to_percent=True)
        self.tc.init_watch('assembleA1', 'Assembled A1 matrix (without stabiliz.)', True, count_to_percent=True)
        self.tc.init_watch('assembleA1stab', 'Assembled A1 stabilization', True, count_to_percent=True)
        self.tc.init_watch('next', 'Next step assignments', True, count_to_percent=True)
        self.tc.init_watch('saveVel', 'Saved velocity', True)

        self.tc.start('init')

        # Define function spaces (P2-P1)
        mesh = self.problem.mesh
        self.V = VectorFunctionSpace(mesh, "Lagrange", 2)  # velocity
        self.Q = FunctionSpace(mesh, "Lagrange", 1)  # pressure
        self.PS = FunctionSpace(mesh, "Lagrange", 2)  # partial solution (must be same order as V)
        self.D = FunctionSpace(mesh, "Lagrange", 1)  # velocity divergence space

        problem.initialize(self.V, self.Q, self.PS, self.D)

        # Define trial and test functions
        u = TrialFunction(self.V)
        v = TestFunction(self.V)
        p = TrialFunction(self.Q)
        q = TestFunction(self.Q)

        n = FacetNormal(mesh)
        I = Identity(find_geometric_dimension(u))

        # Initial conditions: u0 velocity at previous time step u1 velocity two time steps back p0 previous pressure
        [u1, u0, p0] = self.problem.get_initial_conditions([{'type': 'v', 'time': -dt},
                                                            {'type': 'v', 'time': 0.0},
                                                            {'type': 'p', 'time': 0.0}])

        u_ = Function(self.V)  # current tentative velocity
        u_cor = Function(self.V)  # current corrected velocity
        p_ = Function(self.Q)  # current pressure or pressure help function from rotation scheme
        p_mod = Function(self.Q)  # current modified pressure from rotation scheme

        # Define coefficients
        k = Constant(self.metadata['dt'])
        f = Constant((0, 0, 0))

        # Define forms
        # step 1: Tentative velocity, solve to u_
        u_ext = 1.5 * u0 - 0.5 * u1  # extrapolation for convection term

        # Stabilisation
        h = CellSize(mesh)
        if self.args.cbc_tau:
            # used in Simula cbcflow project
            tau = Constant(self.stabCoef) * h / (sqrt(inner(u_ext, u_ext)) + h)
        else:
            # proposed in R. Codina: On stabilized finite element methods for linear systems of
            # convection-diffusion-reaction equations.
            tau = Constant(self.stabCoef) * k * h ** 2 / (
            2 * nu * k + k * h * sqrt(DOLFIN_EPS + inner(u_ext, u_ext)) + h ** 2)
            # DOLFIN_EPS is added because of FEniCS bug that inner(u_ext, u_ext) can be negative when u_ext = 0

        if self.use_full_SUPG:
            v1 = v + tau * 0.5 * dot(grad(v), u_ext)
            parameters['form_compiler']['quadrature_degree'] = 6
        else:
            v1 = v

        def nonlinearity(function):
            if self.args.ema:
                return 2 * inner(dot(sym(grad(function)), u_ext), v1) * dx + inner(div(function) * u_ext, v1) * dx
            else:
                return inner(dot(grad(function), u_ext), v1) * dx

        def diffusion(fce):
            if self.useLaplace:
                return nu * inner(grad(fce), grad(v1)) * dx
            else:
                form = inner(nu * 2 * sym(grad(fce)), sym(grad(v1))) * dx
                if self.bcv == 'CDN':
                    return form
                if self.bcv == 'LAP':
                    return form - inner(nu * dot(grad(fce).T, n), v1) * problem.get_outflow_measure_form()
                if self.bcv == 'DDN':
                    return form  # additional term must be added to non-constant part

        def pressure_rhs():
            if self.args.bc == 'outflow':
                return inner(p0, div(v1)) * dx
            else:
                return inner(p0, div(v1)) * dx - inner(p0 * n, v1) * problem.get_outflow_measure_form()

        a1_const = (1. / k) * inner(u, v1) * dx + diffusion(0.5 * u)
        a1_change = nonlinearity(0.5 * u)
        if self.bcv == 'DDN':
            # does not penalize influx for current step, only for the next one
            # this can lead to oscilation:
            # DDN correct next step, but then u_ext is OK so in next step DDN is not used, leading to new influx...
            # u and u_ext cannot be switched, min_value is nonlinear function
            a1_change += -0.5 * min_value(Constant(0.), inner(u_ext, n)) * inner(u,
                                                                                 v1) * problem.get_outflow_measure_form()
            # NT works only with uflacs compiler

        L1 = (1. / k) * inner(u0, v1) * dx - nonlinearity(0.5 * u0) - diffusion(0.5 * u0) + pressure_rhs()
        if self.bcv == 'DDN':
            L1 += 0.5 * min_value(0., inner(u_ext, n)) * inner(u0, v1) * problem.get_outflow_measure_form()

        # Non-consistent SUPG stabilisation
        if self.stabilize and not self.use_full_SUPG:
            # a1_stab = tau*inner(dot(grad(u), u_ext), dot(grad(v), u_ext))*dx
            a1_stab = 0.5 * tau * inner(dot(grad(u), u_ext), dot(grad(v), u_ext)) * dx(None, {'quadrature_degree': 6})
            # optional: to use Crank Nicolson in stabilisation term following change of RHS is needed:
            # L1 += -0.5*tau*inner(dot(grad(u0), u_ext), dot(grad(v), u_ext))*dx(None, {'quadrature_degree': 6})

        outflow_area = Constant(problem.outflow_area)
        need_outflow = Constant(0.0)
        if self.useRotationScheme:
            # Rotation scheme
            F2 = inner(grad(p), grad(q)) * dx + (1. / k) * q * div(u_) * dx
        else:
            # Projection, solve to p_
            if self.forceOutflow and problem.can_force_outflow:
                info('Forcing outflow.')
                F2 = inner(grad(p - p0), grad(q)) * dx + (1. / k) * q * div(u_) * dx
                for m in problem.get_outflow_measures():
                    F2 += (1. / k) * (1. / outflow_area) * need_outflow * q * m
            else:
                F2 = inner(grad(p - p0), grad(q)) * dx + (1. / k) * q * div(u_) * dx
        a2, L2 = system(F2)

        # step 3: Finalize, solve to u_
        if self.useRotationScheme:
            # Rotation scheme
            F3 = (1. / k) * inner(u - u_, v) * dx + inner(grad(p_), v) * dx
        else:
            F3 = (1. / k) * inner(u - u_, v) * dx + inner(grad(p_ - p0), v) * dx
        a3, L3 = system(F3)

        if self.useRotationScheme:
            # Rotation scheme: modify pressure
            F4 = (p - p0 - p_ + nu * div(u_)) * q * dx
            a4, L4 = system(F4)

        # Assemble matrices
        self.tc.start('assembleMatrices')
        A1_const = assemble(a1_const)  # must be here, so A1 stays one Python object during repeated assembly
        A1_change = A1_const.copy()  # copy to get matrix with same sparse structure (data will be overwritten)
        if self.stabilize and not self.use_full_SUPG:
            A1_stab = A1_const.copy()  # copy to get matrix with same sparse structure (data will be overwritten)
        A2 = assemble(a2)
        A3 = assemble(a3)
        if self.useRotationScheme:
            A4 = assemble(a4)
        self.tc.end('assembleMatrices')

        if self.solvers == 'direct':
            self.solver_vel_tent = LUSolver('mumps')
            self.solver_vel_cor = LUSolver('mumps')
            self.solver_p = LUSolver('mumps')
            if self.useRotationScheme:
                self.solver_rot = LUSolver('mumps')
        else:
            # NT 2016-1  KrylovSolver >> PETScKrylovSolver

            # not needed, chosen not to use hypre_parasails:
            # if self.prec_v == 'hypre_parasails':  # in FEniCS 1.6.0 inaccessible using KrylovSolver class
            #     self.solver_vel_tent = PETScKrylovSolver('gmres')   # PETSc4py object
            #     self.solver_vel_tent.ksp().getPC().setType('hypre')
            #     PETScOptions.set('pc_hypre_type', 'parasails')
            #     # this is global setting, but preconditioners for pressure solvers are set by their constructors
            # else:
            self.solver_vel_tent = PETScKrylovSolver('gmres', self.args.precV)  # nonsymetric > gmres
            # cannot use 'ilu' in parallel
            self.solver_vel_cor = PETScKrylovSolver('cg', self.args.precVC)
            self.solver_p = PETScKrylovSolver(self.args.solP, self.args.precP)  # almost (up to BC) symmetric > CG
            if self.useRotationScheme:
                self.solver_rot = PETScKrylovSolver('cg', 'hypre_amg')

        # setup Krylov solvers
        if self.solvers == 'krylov':
            # Get the nullspace if there are no pressure boundary conditions
            foo = Function(self.Q)  # auxiliary vector for setting pressure nullspace
            if self.args.bc == 'nullspace':
                null_vec = Vector(foo.vector())
                self.Q.dofmap().set(null_vec, 1.0)
                null_vec *= 1.0 / null_vec.norm('l2')
                self.null_space = VectorSpaceBasis([null_vec])
                as_backend_type(A2).set_nullspace(self.null_space)

            # apply global options for Krylov solvers
            solver_options = {'monitor_convergence': True, 'maximum_iterations': 10000, 'nonzero_initial_guess': True}
            # 'nonzero_initial_guess': True   with  solver.solve(A, u, b) means that
            # Solver will use anything stored in u as an initial guess
            for solver in [self.solver_vel_tent, self.solver_vel_cor, self.solver_rot, self.solver_p] if \
                    self.useRotationScheme else [self.solver_vel_tent, self.solver_vel_cor, self.solver_p]:
                for key, value in solver_options.items():
                    try:
                        solver.parameters[key] = value
                    except KeyError:
                        info('Invalid option %s for KrylovSolver' % key)
                        return 1

            if self.args.solP == 'richardson':
                self.solver_p.parameters['monitor_convergence'] = False

            self.solver_vel_tent.parameters['relative_tolerance'] = 10 ** (-self.args.prv1)
            self.solver_vel_tent.parameters['absolute_tolerance'] = 10 ** (-self.args.pav1)
            self.solver_vel_cor.parameters['relative_tolerance'] = 10E-12
            self.solver_vel_cor.parameters['absolute_tolerance'] = 10E-4
            self.solver_p.parameters['relative_tolerance'] = 10 ** (-self.args.prp)
            self.solver_p.parameters['absolute_tolerance'] = 10 ** (-self.args.pap)
            if self.useRotationScheme:
                self.solver_rot.parameters['relative_tolerance'] = 10E-10
                self.solver_rot.parameters['absolute_tolerance'] = 10E-10

            if self.args.Vrestart > 0:
                self.solver_vel_tent.parameters['gmres']['restart'] = self.args.Vrestart

            if self.args.solP == 'gmres' and self.args.Prestart > 0:
                self.solver_p.parameters['gmres']['restart'] = self.args.Prestart

        # boundary conditions
        bcu, bcp = problem.get_boundary_conditions(self.args.bc == 'outflow', self.V, self.Q)
        self.tc.end('init')
        # Time-stepping
        info("Running of Incremental pressure correction scheme n. 1")
        ttime = self.metadata['time']
        t = dt
        step = 1

        # debug function
        if problem.args.debug_rot:
            plot_cor_v = Function(self.V)

        while t < (ttime + dt / 2.0):
            self.problem.update_time(t, step)
            if self.MPI_rank == 0:
                problem.write_status_file(t)

            if doSave:
                save_this_step = problem.save_this_step

            # assemble matrix (it depends on solution)
            self.tc.start('assembleA1')
            assemble(a1_change, tensor=A1_change)  # assembling into existing matrix is faster than assembling new one
            A1 = A1_const.copy()  # we dont want to change A1_const
            A1.axpy(1, A1_change, True)
            self.tc.end('assembleA1')
            self.tc.start('assembleA1stab')
            if self.stabilize and not self.use_full_SUPG:
                assemble(a1_stab, tensor=A1_stab)  # assembling into existing matrix is faster than assembling new one
                A1.axpy(1, A1_stab, True)
            self.tc.end('assembleA1stab')

            # Compute tentative velocity step
            begin("Computing tentative velocity")
            self.tc.start('rhs')
            b = assemble(L1)
            self.tc.end('rhs')
            self.tc.start('applybc1')
            [bc.apply(A1, b) for bc in bcu]
            self.tc.end('applybc1')
            try:
                self.tc.start('solve 1')
                self.solver_vel_tent.solve(A1, u_.vector(), b)
                self.tc.end('solve 1')
                if save_this_step:
                    self.tc.start('saveVel')
                    problem.save_vel(True, u_)
                    self.tc.end('saveVel')
                if save_this_step and not onlyVel:
                    problem.save_div(True, u_)
                problem.compute_err(True, u_, t)
                problem.compute_div(True, u_)
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            end()

            if self.useRotationScheme:
                begin("Computing tentative pressure")
            else:
                begin("Computing pressure")
            if self.forceOutflow and problem.can_force_outflow:
                out = problem.compute_outflow(u_)
                info('Tentative outflow: %f' % out)
                n_o = -problem.last_inflow - out
                info('Needed outflow: %f' % n_o)
                need_outflow.assign(n_o)
            self.tc.start('rhs')
            b = assemble(L2)
            self.tc.end('rhs')
            self.tc.start('applybcP')
            [bc.apply(A2, b) for bc in bcp]
            if self.args.bc == 'nullspace':
                self.null_space.orthogonalize(b)
            self.tc.end('applybcP')
            try:
                self.tc.start('solve 2')
                self.solver_p.solve(A2, p_.vector(), b)
                self.tc.end('solve 2')
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            if self.useRotationScheme:
                foo = Function(self.Q)
                foo.assign(p_ + p0)
                if save_this_step and not onlyVel:
                    problem.averaging_pressure(foo)
                    problem.save_pressure(True, foo)
            else:
                foo = Function(self.Q)
                foo.assign(p_)  # we do not want to change p_ by averaging
                if save_this_step and not onlyVel:
                    problem.averaging_pressure(foo)
                    problem.save_pressure(False, foo)
            end()

            begin("Computing corrected velocity")
            self.tc.start('rhs')
            b = assemble(L3)
            self.tc.end('rhs')
            if not self.args.B:
                self.tc.start('applybc3')
                [bc.apply(A3, b) for bc in bcu]
                self.tc.end('applybc3')
            try:
                self.tc.start('solve 3')
                self.solver_vel_cor.solve(A3, u_cor.vector(), b)
                self.tc.end('solve 3')
                problem.compute_err(False, u_cor, t)
                problem.compute_div(False, u_cor)
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            if save_this_step:
                self.tc.start('saveVel')
                problem.save_vel(False, u_cor)
                self.tc.end('saveVel')
            if save_this_step and not onlyVel:
                problem.save_div(False, u_cor)
            end()

            if self.useRotationScheme:
                begin("Rotation scheme pressure correction")
                self.tc.start('rhs')
                b = assemble(L4)
                self.tc.end('rhs')
                try:
                    self.tc.start('solve 4')
                    self.solver_rot.solve(A4, p_mod.vector(), b)
                    self.tc.end('solve 4')
                except RuntimeError as inst:
                    problem.report_fail(t)
                    return 1
                if save_this_step and not onlyVel:
                    problem.averaging_pressure(p_mod)
                    problem.save_pressure(False, p_mod)
                end()

                if problem.args.debug_rot:
                    # save applied pressure correction (expressed as a term added to RHS of next tentative vel. step)
                    # see comment next to argument definition
                    plot_cor_v.assign(project(k * grad(nu * div(u_)), self.V))
                    problem.fileDict['grad_cor']['file'].write(plot_cor_v, t)

            # compute functionals (e. g. forces)
            problem.compute_functionals(u_cor, p_mod if self.useRotationScheme else p_, t, step)

            # Move to next time step
            self.tc.start('next')
            u1.assign(u0)
            u0.assign(u_cor)
            u_.assign(u_cor)  # use corrected velocity as initial guess in first step

            if self.useRotationScheme:
                p0.assign(p_mod)
            else:
                p0.assign(p_)

            t = round(t + dt, 6)  # round time step to 0.000001
            step += 1
            self.tc.end('next')

        info("Finished: Incremental pressure correction scheme n. 1")
        problem.report()
        return 0
Example #37
0
def mass_cg(cell, degree):
    m = Mesh(VectorElement('Q', cell, 1))
    V = FunctionSpace(m, FiniteElement('Q', cell, degree, variant='spectral'))
    u = TrialFunction(V)
    v = TestFunction(V)
    return u*v*dx(rule=gll_quadrature_rule(cell, degree))
Example #38
0
def norm(v, norm_type="L2", mesh=None):
    """
    Return the norm of a given vector or function.

    *Arguments*
        v
            a :py:class:`Vector <dolfin.cpp.Vector>` or
            a :py:class:`Function <dolfin.functions.function.Function>`.
        norm_type
            see below for alternatives.
        mesh
            optional :py:class:`Mesh <dolfin.cpp.Mesh>` on
            which to compute the norm.

    If the norm type is not specified, the standard :math:`L^2` -norm
    is computed. Possible norm types include:

    *Vectors*

    ================   =================  ================
    Norm               Usage
    ================   =================  ================
    :math:`l^2`        norm(x, 'l2')      Default
    :math:`l^1`        norm(x, 'l1')
    :math:`l^\infty`   norm(x, 'linf')
    ================   =================  ================

    *Functions*

    ================  =================  =================================
    Norm              Usage              Includes the :math:`L^2` -term
    ================  =================  =================================
    :math:`L^2`       norm(v, 'L2')      Yes
    :math:`H^1`       norm(v, 'H1')      Yes
    :math:`H^1_0`     norm(v, 'H10')     No
    :math:`H` (div)   norm(v, 'Hdiv')    Yes
    :math:`H` (div)   norm(v, 'Hdiv0')   No
    :math:`H` (curl)  norm(v, 'Hcurl')   Yes
    :math:`H` (curl)  norm(v, 'Hcurl0')  No
    ================  =================  =================================

    *Examples of usage*

    .. code-block:: python

        v = Function(V)
        x = v.vector()

        print norm(x, 'linf')   # print the infinity norm of vector x

        n = norm(v)             # compute L^2 norm of v
        print norm(v, 'Hdiv')   # print H(div) norm of v
        n = norm(v, 'H1', mesh) # compute H^1 norm of v on given mesh

    """

    if not isinstance(v, (GenericVector, GenericFunction)):
        raise TypeError, "expected a GenericVector or GenericFunction"

    # Check arguments
    if not isinstance(norm_type, str):
        cpp.dolfin_error("norms.py",
                         "compute norm",
                         "Norm type must be a string, not " + str(type(norm_type)))
    if mesh is not None and not isinstance(mesh, Mesh):
        cpp.dolfin_error("norms.py",
                         "compute norm",
                         "Expecting a Mesh, not " + str(type(mesh)))

    # Select norm type
    if isinstance(v, GenericVector):
        return v.norm(norm_type.lower())

    elif (isinstance(v, Coefficient) and isinstance(v, GenericFunction)):
        if norm_type.lower() == "l2":
            M = inner(v, v)*dx()
        elif norm_type.lower() == "h1":
            M = inner(v, v)*dx() + inner(grad(v), grad(v))*dx()
        elif norm_type.lower() == "h10":
            M = inner(grad(v), grad(v))*dx()
        elif norm_type.lower() == "hdiv":
            M = inner(v, v)*dx() + div(v)*div(v)*dx()
        elif norm_type.lower() == "hdiv0":
            M = div(v)*div(v)*dx()
        elif norm_type.lower() == "hcurl":
            M = inner(v, v)*dx() + inner(curl(v), curl(v))*dx()
        elif norm_type.lower() == "hcurl0":
            M = inner(curl(v), curl(v))*dx()
        else:
            cpp.dolfin_error("norms.py",
                             "compute norm",
                             "Unknown norm type (\"%s\") for functions" % str(norm_type))
    else:
        cpp.dolfin_error("norms.py",
                         "compute norm",
                         "Unknown object type. Must be a vector or a function")

    # Get mesh
    if isinstance(v, Function) and mesh is None:
        mesh = v.function_space().mesh()

    # Assemble value
    r = assemble(M, mesh=mesh, form_compiler_parameters={"representation": "quadrature"})

    # Check value
    if r < 0.0:
        cpp.dolfin_error("norms.py",
                         "compute norm",
                         "Square of norm is negative, might be a round-off error")
    elif r == 0.0:
        return 0.0
    else:
        return sqrt(r)
Example #39
0
def project(v, V, bcs=None, mesh=None,
            solver_parameters=None,
            form_compiler_parameters=None,
            name=None):
    """Project an :class:`.Expression` or :class:`.Function` into a :class:`.FunctionSpace`

    :arg v: the :class:`.Expression`, :class:`ufl.Expr` or
         :class:`.Function` to project
    :arg V: the :class:`.FunctionSpace` or :class:`.Function` to project into
    :arg bcs: boundary conditions to apply in the projection
    :arg mesh: the mesh to project into
    :arg solver_parameters: parameters to pass to the solver used when
         projecting.
    :arg form_compiler_parameters: parameters to the form compiler
    :arg name: name of the resulting :class:`.Function`

    If ``V`` is a :class:`.Function` then ``v`` is projected into
    ``V`` and ``V`` is returned. If `V` is a :class:`.FunctionSpace`
    then ``v`` is projected into a new :class:`.Function` and that
    :class:`.Function` is returned.

    The ``bcs``, ``mesh`` and ``form_compiler_parameters`` are
    currently ignored."""
    from firedrake import function

    if isinstance(V, functionspace.FunctionSpaceBase):
        ret = function.Function(V, name=name)
    elif isinstance(V, function.Function):
        ret = V
        V = V.function_space()
    else:
        raise RuntimeError(
            'Can only project into functions and function spaces, not %r'
            % type(V))

    if isinstance(v, expression.Expression):
        shape = v.value_shape()
        # Build a function space that supports PointEvaluation so that
        # we can interpolate into it.
        if isinstance(V.ufl_element().degree(), tuple):
            deg = max(V.ufl_element().degree())
        else:
            deg = V.ufl_element().degree()

        if v.rank() == 0:
            fs = functionspace.FunctionSpace(V.mesh(), 'DG', deg+1)
        elif v.rank() == 1:
            fs = functionspace.VectorFunctionSpace(V.mesh(), 'DG',
                                                   deg+1,
                                                   dim=shape[0])
        else:
            fs = functionspace.TensorFunctionSpace(V.mesh(), 'DG',
                                                   deg+1,
                                                   shape=shape)
        f = function.Function(fs)
        f.interpolate(v)
        v = f
    elif isinstance(v, function.Function):
        if v.function_space().mesh() != ret.function_space().mesh():
            raise RuntimeError("Can't project between mismatching meshes")
    elif not isinstance(v, ufl.core.expr.Expr):
        raise RuntimeError("Can't only project from expressions and functions, not %r" % type(v))

    if v.ufl_shape != ret.ufl_shape:
        raise RuntimeError('Shape mismatch between source %s and target function spaces %s in project' %
                           (v.ufl_shape, ret.ufl_shape))

    p = ufl_expr.TestFunction(V)
    q = ufl_expr.TrialFunction(V)
    a = ufl.inner(p, q) * ufl.dx(domain=V.mesh())
    L = ufl.inner(p, v) * ufl.dx(domain=V.mesh())

    # Default to 1e-8 relative tolerance
    if solver_parameters is None:
        solver_parameters = {'ksp_type': 'cg', 'ksp_rtol': 1e-8}
    else:
        solver_parameters.setdefault('ksp_type', 'cg')
        solver_parameters.setdefault('ksp_rtol', 1e-8)

    _solve(a == L, ret, bcs=bcs,
           solver_parameters=solver_parameters,
           form_compiler_parameters=form_compiler_parameters)
    return ret
Example #40
0
def laplace(cell, degree):
    m = Mesh(VectorElement('Q', cell, 1))
    V = FunctionSpace(m, FiniteElement('Q', cell, degree, variant='spectral'))
    u = TrialFunction(V)
    v = TestFunction(V)
    return dot(grad(u), grad(v))*dx(rule=gll_quadrature_rule(cell, degree))
Example #41
0
def norm(v, norm_type="L2", mesh=None):
    r"""
    Return the norm of a given vector or function.

    *Arguments*
        v
            a :py:class:`Vector <dolfin.cpp.Vector>` or
            a :py:class:`Function <dolfin.functions.function.Function>`.
        norm_type
            see below for alternatives.
        mesh
            optional :py:class:`Mesh <dolfin.cpp.Mesh>` on
            which to compute the norm.

    If the norm type is not specified, the standard :math:`L^2` -norm
    is computed. Possible norm types include:

    *Vectors*

    ================   =================  ================
    Norm               Usage
    ================   =================  ================
    :math:`l^2`        norm(x, 'l2')      Default
    :math:`l^1`        norm(x, 'l1')
    :math:`l^\infty`   norm(x, 'linf')
    ================   =================  ================

    *Functions*

    ================  =================  =================================
    Norm              Usage              Includes the :math:`L^2` -term
    ================  =================  =================================
    :math:`L^2`       norm(v, 'L2')      Yes
    :math:`H^1`       norm(v, 'H1')      Yes
    :math:`H^1_0`     norm(v, 'H10')     No
    :math:`H` (div)   norm(v, 'Hdiv')    Yes
    :math:`H` (div)   norm(v, 'Hdiv0')   No
    :math:`H` (curl)  norm(v, 'Hcurl')   Yes
    :math:`H` (curl)  norm(v, 'Hcurl0')  No
    ================  =================  =================================

    *Examples of usage*

    .. code-block:: python

        v = Function(V)
        x = v.vector()

        print norm(x, 'linf')   # print the infinity norm of vector x

        n = norm(v)             # compute L^2 norm of v
        print norm(v, 'Hdiv')   # print H(div) norm of v
        n = norm(v, 'H1', mesh) # compute H^1 norm of v on given mesh

    """

    # if not isinstance(v, (GenericVector, GenericFunction)):
    #     cpp.dolfin_error("norms.py",
    #                      "compute norm",
    #                      "expected a GenericVector or GenericFunction")

    # Check arguments
    # if not isinstance(norm_type, string_types):
    #     cpp.dolfin_error("norms.py",
    #                      "compute norm",
    #                      "Norm type must be a string, not " +
    #                      str(type(norm_type)))
    # if mesh is not None and not isinstance(mesh, cpp.Mesh):
    #     cpp.dolfin_error("norms.py",
    #                      "compute norm",
    #                      "Expecting a Mesh, not " + str(type(mesh)))

    # Get mesh from function
    if isinstance(v, cpp.function.Function) and mesh is None:
        mesh = v.function_space().mesh()
    elif isinstance(v, MultiMeshFunction) and mesh is None:
        mesh = v.function_space().multimesh()

    # Define integration measure and domain
    if isinstance(v, MultiMeshFunction):
        dc = ufl.dx(mesh) + ufl.dC(mesh)
        assemble_func = functools.partial(assemble_multimesh, form_compiler_parameters={"representation": "quadrature"})
    else:
        dc = ufl.dx(mesh)
        assemble_func = assemble
    # Select norm type
    if isinstance(v, cpp.la.GenericVector):
        return v.norm(norm_type.lower())

    elif isinstance(v, ufl.Coefficient):
        if norm_type.lower() == "l2":
            M = v**2 * dc
        elif norm_type.lower() == "h1":
            M = (v**2 + grad(v)**2) * dc
        elif norm_type.lower() == "h10":
            M = grad(v)**2 * dc
        elif norm_type.lower() == "hdiv":
            M = (v**2 + div(v)**2) * dc
        elif norm_type.lower() == "hdiv0":
            M = div(v)**2 * dc
        elif norm_type.lower() == "hcurl":
            M = (v**2 + curl(v)**2) * dc
        elif norm_type.lower() == "hcurl0":
            M = curl(v)**2 * dc
        else:
            raise ValueError("Unknown norm type {}".format(str(norm_type)))
    else:
        raise TypeError("Do not know how to compute norm of {}".format(str(v)))

    # Assemble value and return
    return sqrt(assemble_func(M))
Example #42
0
def project(v, V=None, bcs=None, mesh=None,
            solver_type="cg",
            preconditioner_type="default",
            form_compiler_parameters=None):
    """
    Return projection of given expression *v* onto the finite element space *V*.

    *Arguments*
        v
            a :py:class:`Function <dolfin.functions.function.Function>` or
            an :py:class:`Expression <dolfin.functions.expression.Expression>`
        bcs
            Optional argument :py:class:`list of BoundaryCondition
            <dolfin.fem.bcs.BoundaryCondition>`
        V
            Optional argument :py:class:`FunctionSpace
            <dolfin.functions.functionspace.FunctionSpace>`
        mesh
            Optional argument :py:class:`mesh <dolfin.cpp.Mesh>`.
        solver_type
            see :py:func:`solve <dolfin.fem.solving.solve>` for options.
        preconditioner_type
            see :py:func:`solve <dolfin.fem.solving.solve>` for options.
        form_compiler_parameters
            see :py:class:`Parameters <dolfin.cpp.Parameters>` for more
            information.

    *Example of usage*

        .. code-block:: python

            v = Expression("sin(pi*x[0])")
            V = FunctionSpace(mesh, "Lagrange", 1)
            Pv = project(v, V)

        This is useful for post-processing functions or expressions
        which are not readily handled by visualization tools (such as
        for example discontinuous functions).

    """

    # If trying to project an Expression
    if V is None and isinstance(v, Expression):
        if mesh is not None and isinstance(mesh, cpp.Mesh):
            V = FunctionSpaceBase(mesh, v.ufl_element())
        else:
            raise TypeError, "expected a mesh when projecting an Expression"

    # Try extracting function space if not specified
    if V is None:
        V = _extract_function_space(v, mesh)

    # Check arguments
    if not isinstance(V, FunctionSpaceBase):
        cpp.dolfin_error("projection.py",
                         "compute projection",
                         "Illegal function space for projection, not a FunctionSpace: " + str(v))

    # Define variational problem for projection
    w = TestFunction(V)
    Pv = TrialFunction(V)
    a = ufl.inner(w, Pv)*ufl.dx()
    L = ufl.inner(w, v)*ufl.dx()

    # Assemble linear system
    A, b = assemble_system(a, L, bcs=bcs,
                           form_compiler_parameters=form_compiler_parameters)

    # Solve linear system for projection
    Pv = Function(V)
    cpp.la_solve(A, Pv.vector(), b, solver_type, preconditioner_type)

    return Pv
Example #43
0
    def solve(self, problem):
        self.problem = problem
        doSave = problem.doSave
        save_this_step = False
        onlyVel = problem.saveOnlyVel
        dt = self.metadata['dt']

        nu = Constant(self.problem.nu)
        # TODO check proper use of watches
        self.tc.init_watch('init', 'Initialization', True, count_to_percent=False)
        self.tc.init_watch('rhs', 'Assembled right hand side', True, count_to_percent=True)
        self.tc.init_watch('updateBC', 'Updated velocity BC', True, count_to_percent=True)
        self.tc.init_watch('applybc1', 'Applied velocity BC 1st step', True, count_to_percent=True)
        self.tc.init_watch('applybc3', 'Applied velocity BC 3rd step', True, count_to_percent=True)
        self.tc.init_watch('applybcP', 'Applied pressure BC or othogonalized rhs', True, count_to_percent=True)
        self.tc.init_watch('assembleMatrices', 'Initial matrix assembly', False, count_to_percent=True)
        self.tc.init_watch('solve 1', 'Running solver on 1st step', True, count_to_percent=True)
        self.tc.init_watch('solve 2', 'Running solver on 2nd step', True, count_to_percent=True)
        self.tc.init_watch('solve 3', 'Running solver on 3rd step', True, count_to_percent=True)
        self.tc.init_watch('solve 4', 'Running solver on 4th step', True, count_to_percent=True)
        self.tc.init_watch('assembleA1', 'Assembled A1 matrix (without stabiliz.)', True, count_to_percent=True)
        self.tc.init_watch('assembleA1stab', 'Assembled A1 stabilization', True, count_to_percent=True)
        self.tc.init_watch('next', 'Next step assignments', True, count_to_percent=True)
        self.tc.init_watch('saveVel', 'Saved velocity', True)

        self.tc.start('init')

        # Define function spaces (P2-P1)
        mesh = self.problem.mesh
        self.V = VectorFunctionSpace(mesh, "Lagrange", 2)  # velocity
        self.Q = FunctionSpace(mesh, "Lagrange", 1)  # pressure
        self.PS = FunctionSpace(mesh, "Lagrange", 2)  # partial solution (must be same order as V)
        self.D = FunctionSpace(mesh, "Lagrange", 1)   # velocity divergence space
        if self.bc == 'lagrange':
            L = FunctionSpace(mesh, "R", 0)
            QL = self.Q*L

        problem.initialize(self.V, self.Q, self.PS, self.D)

        # Define trial and test functions
        u = TrialFunction(self.V)
        v = TestFunction(self.V)
        if self.bc == 'lagrange':
            (pQL, rQL) = TrialFunction(QL)
            (qQL, lQL) = TestFunction(QL)
        else:
            p = TrialFunction(self.Q)
            q = TestFunction(self.Q)

        n = FacetNormal(mesh)
        I = Identity(u.geometric_dimension())

        # Initial conditions: u0 velocity at previous time step u1 velocity two time steps back p0 previous pressure
        [u1, u0, p0] = self.problem.get_initial_conditions([{'type': 'v', 'time': -dt},
                                                          {'type': 'v', 'time': 0.0},
                                                          {'type': 'p', 'time': 0.0}])

        if doSave:
            problem.save_vel(False, u0, 0.0)
            problem.save_vel(True, u0, 0.0)

        u_ = Function(self.V)         # current tentative velocity
        u_cor = Function(self.V)         # current corrected velocity
        if self.bc == 'lagrange':
            p_QL = Function(QL)    # current pressure or pressure help function from rotation scheme
            pQ = Function(self.Q)     # auxiliary function for conversion between QL.sub(0) and Q
        else:
            p_ = Function(self.Q)         # current pressure or pressure help function from rotation scheme
        p_mod = Function(self.Q)      # current modified pressure from rotation scheme

        # Define coefficients
        k = Constant(self.metadata['dt'])
        f = Constant((0, 0, 0))

        # Define forms
        # step 1: Tentative velocity, solve to u_
        u_ext = 1.5*u0 - 0.5*u1  # extrapolation for convection term

        # Stabilisation
        h = CellSize(mesh)
        # CBC delta:
        if self.cbcDelta:
            delta = Constant(self.stabCoef)*h/(sqrt(inner(u_ext, u_ext))+h)
        else:
            delta = Constant(self.stabCoef)*h**2/(2*nu*k + k*h*inner(u_ext, u_ext)+h**2)

        if self.use_full_SUPG:
            v1 = v + delta*0.5*k*dot(grad(v), u_ext)
            parameters['form_compiler']['quadrature_degree'] = 6
        else:
            v1 = v

        def nonlinearity(function):
            if self.use_ema:
               return 2*inner(dot(sym(grad(function)), u_ext), v1) * dx + inner(div(function)*u_ext, v1) * dx
                # return 2*inner(dot(sym(grad(function)), u_ext), v) * dx + inner(div(u_ext)*function, v) * dx
                # QQ implement this way?
            else:
                return inner(dot(grad(function), u_ext), v1) * dx

        def diffusion(fce):
            if self.useLaplace:
                return nu*inner(grad(fce), grad(v1)) * dx
            else:
                form = inner(nu * 2 * sym(grad(fce)), sym(grad(v1))) * dx
                if self.bcv == 'CDN':
                    # IMP will work only if p=0 on output, or we must add term
                    # inner(p0*n, v)*problem.get_outflow_measure_form() to avoid boundary layer
                    return form
                if self.bcv == 'LAP':
                    return form - inner(nu*dot(grad(fce).T, n), v1)  * problem.get_outflow_measure_form()
                if self.bcv == 'DDN':
                    # IMP will work only if p=0 on output, or we must add term
                    # inner(p0*n, v)*problem.get_outflow_measure_form() to avoid boundary layer
                    return form  # additional term must be added to non-constant part

        def pressure_rhs():
            if self.useLaplace or self.bcv == 'LAP':
                return inner(p0, div(v1)) * dx - inner(p0*n, v1) * problem.get_outflow_measure_form()
                # NT term inner(inner(p, n), v) is 0 when p=0 on outflow
            else:
                return inner(p0, div(v1)) * dx

        a1_const = (1./k)*inner(u, v1)*dx + diffusion(0.5*u)
        a1_change = nonlinearity(0.5*u)
        if self.bcv == 'DDN':
            # IMP Problem: Does not penalize influx for current step, only for the next one
            # IMP this can lead to oscilation: DDN correct next step, but then u_ext is OK so in next step DDN is not used, leading to new influx...
            # u and u_ext cannot be switched, min_value is nonlinear function
            a1_change += -0.5*min_value(Constant(0.), inner(u_ext, n))*inner(u, v1)*problem.get_outflow_measure_form()
            # IMP works only with uflacs compiler

        L1 = (1./k)*inner(u0, v1)*dx - nonlinearity(0.5*u0) - diffusion(0.5*u0) + pressure_rhs()
        if self.bcv == 'DDN':
            L1 += 0.5*min_value(0., inner(u_ext, n))*inner(u0, v1)*problem.get_outflow_measure_form()

        # Non-consistent SUPG stabilisation
        if self.stabilize and not self.use_full_SUPG:
            # a1_stab = delta*inner(dot(grad(u), u_ext), dot(grad(v), u_ext))*dx
            a1_stab = 0.5*delta*inner(dot(grad(u), u_ext), dot(grad(v), u_ext))*dx(None, {'quadrature_degree': 6})
            # NT optional: use Crank Nicolson in stabilisation term: change RHS
            # L1 += -0.5*delta*inner(dot(grad(u0), u_ext), dot(grad(v), u_ext))*dx(None, {'quadrature_degree': 6})

        outflow_area = Constant(problem.outflow_area)
        need_outflow = Constant(0.0)
        if self.useRotationScheme:
            # Rotation scheme
            if self.bc == 'lagrange':
                F2 = inner(grad(pQL), grad(qQL))*dx + (1./k)*qQL*div(u_)*dx + pQL*lQL*dx + qQL*rQL*dx
            else:
                F2 = inner(grad(p), grad(q))*dx + (1./k)*q*div(u_)*dx
        else:
            # Projection, solve to p_
            if self.bc == 'lagrange':
                F2 = inner(grad(pQL - p0), grad(qQL))*dx + (1./k)*qQL*div(u_)*dx + pQL*lQL*dx + qQL*rQL*dx
            else:
                if self.forceOutflow and problem.can_force_outflow:
                    info('Forcing outflow.')
                    F2 = inner(grad(p - p0), grad(q))*dx + (1./k)*q*div(u_)*dx
                    for m in problem.get_outflow_measures():
                        F2 += (1./k)*(1./outflow_area)*need_outflow*q*m
                else:
                    F2 = inner(grad(p - p0), grad(q))*dx + (1./k)*q*div(u_)*dx
        a2, L2 = system(F2)

        # step 3: Finalize, solve to u_
        if self.useRotationScheme:
            # Rotation scheme
            if self.bc == 'lagrange':
                F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_QL.sub(0)), v)*dx
            else:
                F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_), v)*dx
        else:
            if self.bc == 'lagrange':
                F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_QL.sub(0) - p0), v)*dx
            else:
                F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_ - p0), v)*dx
        a3, L3 = system(F3)

        if self.useRotationScheme:
            # Rotation scheme: modify pressure
            if self.bc == 'lagrange':
                pr = TrialFunction(self.Q)
                qr = TestFunction(self.Q)
                F4 = (pr - p0 - p_QL.sub(0) + nu*div(u_))*qr*dx
            else:
                F4 = (p - p0 - p_ + nu*div(u_))*q*dx
            # TODO zkusit, jestli to nebude rychlejsi? nepocitat soustavu, ale p.assign(...), nutno project(div(u),Q) coz je pocitani podobne soustavy
            # TODO zkusit v project zadat solver_type='lu' >> primy resic by mel byt efektivnejsi
            a4, L4 = system(F4)

        # Assemble matrices
        self.tc.start('assembleMatrices')
        A1_const = assemble(a1_const)  # need to be here, so A1 stays one Python object during repeated assembly
        A1_change = A1_const.copy()  # copy to get matrix with same sparse structure (data will be overwriten)
        if self.stabilize and not self.use_full_SUPG:
            A1_stab = A1_const.copy()  # copy to get matrix with same sparse structure (data will be overwriten)
        A2 = assemble(a2)
        A3 = assemble(a3)
        if self.useRotationScheme:
            A4 = assemble(a4)
        self.tc.end('assembleMatrices')

        if self.solvers == 'direct':
            self.solver_vel_tent = LUSolver('mumps')
            self.solver_vel_cor = LUSolver('mumps')
            self.solver_p = LUSolver('umfpack')
            if self.useRotationScheme:
                self.solver_rot = LUSolver('umfpack')
        else:
            # NT not needed, chosen not to use hypre_parasails
            # if self.prec_v == 'hypre_parasails':  # in FEniCS 1.6.0 inaccessible using KrylovSolver class
            #     self.solver_vel_tent = PETScKrylovSolver('gmres')   # PETSc4py object
            #     self.solver_vel_tent.ksp().getPC().setType('hypre')
            #     PETScOptions.set('pc_hypre_type', 'parasails')
            #     # this is global setting, but preconditioners for pressure solvers are set by their constructors
            # else:
            self.solver_vel_tent = KrylovSolver('gmres', self.prec_v)   # nonsymetric > gmres
            # IMP cannot use 'ilu' in parallel (choose different default option)
            self.solver_vel_cor = KrylovSolver('cg', 'hypre_amg')   # nonsymetric > gmres
            self.solver_p = KrylovSolver('cg', self.prec_p)          # symmetric > CG
            if self.useRotationScheme:
                self.solver_rot = KrylovSolver('cg', self.prec_p)

        solver_options = {'monitor_convergence': True, 'maximum_iterations': 1000, 'nonzero_initial_guess': True}
        # 'nonzero_initial_guess': True   with  solver.solbe(A, u, b) means that
        # Solver will use anything stored in u as an initial guess

        # Get the nullspace if there are no pressure boundary conditions
        foo = Function(self.Q)     # auxiliary vector for setting pressure nullspace
        if self.bc in ['nullspace', 'nullspace_s']:
            null_vec = Vector(foo.vector())
            self.Q.dofmap().set(null_vec, 1.0)
            null_vec *= 1.0/null_vec.norm('l2')
            self.null_space = VectorSpaceBasis([null_vec])
            if self.bc == 'nullspace':
                as_backend_type(A2).set_nullspace(self.null_space)

        # apply global options for Krylov solvers
        self.solver_vel_tent.parameters['relative_tolerance'] = 10 ** (-self.precision_rel_v_tent)
        self.solver_vel_tent.parameters['absolute_tolerance'] = 10 ** (-self.precision_abs_v_tent)
        self.solver_vel_cor.parameters['relative_tolerance'] = 10E-12
        self.solver_vel_cor.parameters['absolute_tolerance'] = 10E-4
        self.solver_p.parameters['relative_tolerance'] = 10**(-self.precision_p)
        self.solver_p.parameters['absolute_tolerance'] = 10E-10
        if self.useRotationScheme:
            self.solver_rot.parameters['relative_tolerance'] = 10**(-self.precision_p)
            self.solver_rot.parameters['absolute_tolerance'] = 10E-10

        if self.solvers == 'krylov':
            for solver in [self.solver_vel_tent, self.solver_vel_cor, self.solver_p, self.solver_rot] if \
                    self.useRotationScheme else [self.solver_vel_tent, self.solver_vel_cor, self.solver_p]:
                for key, value in solver_options.items():
                    try:
                        solver.parameters[key] = value
                    except KeyError:
                        info('Invalid option %s for KrylovSolver' % key)
                        return 1
                solver.parameters['preconditioner']['structure'] = 'same'
                # matrices A2-A4 do not change, so we can reuse preconditioners

        self.solver_vel_tent.parameters['preconditioner']['structure'] = 'same_nonzero_pattern'
        # matrix A1 changes every time step, so change of preconditioner must be allowed

        if self.bc == 'lagrange':
            fa = FunctionAssigner(self.Q, QL.sub(0))

        # boundary conditions
        bcu, bcp = problem.get_boundary_conditions(self.bc == 'outflow', self.V, self.Q)
        self.tc.end('init')
        # Time-stepping
        info("Running of Incremental pressure correction scheme n. 1")
        ttime = self.metadata['time']
        t = dt
        step = 1
        while t < (ttime + dt/2.0):
            info("t = %f" % t)
            self.problem.update_time(t, step)
            if self.MPI_rank == 0:
                problem.write_status_file(t)

            if doSave:
                save_this_step = problem.save_this_step

            # DDN debug
            # u_ext_in = assemble(inner(u_ext, n)*problem.get_outflow_measure_form())
            # DDN_triggered = assemble(min_value(Constant(0.), inner(u_ext, n))*problem.get_outflow_measure_form())
            # print('DDN: u_ext*n dSout = ', u_ext_in)
            # print('DDN: negative part of u_ext*n dSout = ', DDN_triggered)

            # assemble matrix (it depends on solution)
            self.tc.start('assembleA1')
            assemble(a1_change, tensor=A1_change)  # assembling into existing matrix is faster than assembling new one
            A1 = A1_const.copy()  # we dont want to change A1_const
            A1.axpy(1, A1_change, True)
            self.tc.end('assembleA1')
            self.tc.start('assembleA1stab')
            if self.stabilize and not self.use_full_SUPG:
                assemble(a1_stab, tensor=A1_stab)  # assembling into existing matrix is faster than assembling new one
                A1.axpy(1, A1_stab, True)
            self.tc.end('assembleA1stab')

            # Compute tentative velocity step
            begin("Computing tentative velocity")
            self.tc.start('rhs')
            b = assemble(L1)
            self.tc.end('rhs')
            self.tc.start('applybc1')
            [bc.apply(A1, b) for bc in bcu]
            self.tc.end('applybc1')
            try:
                self.tc.start('solve 1')
                self.solver_vel_tent.solve(A1, u_.vector(), b)
                self.tc.end('solve 1')
                if save_this_step:
                    self.tc.start('saveVel')
                    problem.save_vel(True, u_, t)
                    self.tc.end('saveVel')
                if save_this_step and not onlyVel:
                    problem.save_div(True, u_)
                problem.compute_err(True, u_, t)
                problem.compute_div(True, u_)
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            end()

            # DDN debug
            # u_ext_in = assemble(inner(u_, n)*problem.get_outflow_measure_form())
            # DDN_triggered = assemble(min_value(Constant(0.), inner(u_, n))*problem.get_outflow_measure_form())
            # print('DDN: u_tent*n dSout = ', u_ext_in)
            # print('DDN: negative part of u_tent*n dSout = ', DDN_triggered)

            if self.useRotationScheme:
                begin("Computing tentative pressure")
            else:
                begin("Computing pressure")
            if self.forceOutflow and problem.can_force_outflow:
                out = problem.compute_outflow(u_)
                info('Tentative outflow: %f' % out)
                n_o = -problem.last_inflow-out
                info('Needed outflow: %f' % n_o)
                need_outflow.assign(n_o)
            self.tc.start('rhs')
            b = assemble(L2)
            self.tc.end('rhs')
            self.tc.start('applybcP')
            [bc.apply(A2, b) for bc in bcp]
            if self.bc in ['nullspace', 'nullspace_s']:
                self.null_space.orthogonalize(b)
            self.tc.end('applybcP')
            try:
                self.tc.start('solve 2')
                if self.bc == 'lagrange':
                    self.solver_p.solve(A2, p_QL.vector(), b)
                else:
                    self.solver_p.solve(A2, p_.vector(), b)
                self.tc.end('solve 2')
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            if self.useRotationScheme:
                foo = Function(self.Q)
                if self.bc == 'lagrange':
                    fa.assign(pQ, p_QL.sub(0))
                    foo.assign(pQ + p0)
                else:
                    foo.assign(p_+p0)
                problem.averaging_pressure(foo)
                if save_this_step and not onlyVel:
                    problem.save_pressure(True, foo)
            else:
                if self.bc == 'lagrange':
                    fa.assign(pQ, p_QL.sub(0))
                    problem.averaging_pressure(pQ)
                    if save_this_step and not onlyVel:
                        problem.save_pressure(False, pQ)
                else:
                    # we do not want to change p=0 on outflow, it conflicts with do-nothing conditions
                    foo = Function(self.Q)
                    foo.assign(p_)
                    problem.averaging_pressure(foo)
                    if save_this_step and not onlyVel:
                        problem.save_pressure(False, foo)
            end()

            begin("Computing corrected velocity")
            self.tc.start('rhs')
            b = assemble(L3)
            self.tc.end('rhs')
            if not self.B:
                self.tc.start('applybc3')
                [bc.apply(A3, b) for bc in bcu]
                self.tc.end('applybc3')
            try:
                self.tc.start('solve 3')
                self.solver_vel_cor.solve(A3, u_cor.vector(), b)
                self.tc.end('solve 3')
                problem.compute_err(False, u_cor, t)
                problem.compute_div(False, u_cor)
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            if save_this_step:
                self.tc.start('saveVel')
                problem.save_vel(False, u_cor, t)
                self.tc.end('saveVel')
            if save_this_step and not onlyVel:
                problem.save_div(False, u_cor)
            end()

            # DDN debug
            # u_ext_in = assemble(inner(u_cor, n)*problem.get_outflow_measure_form())
            # DDN_triggered = assemble(min_value(Constant(0.), inner(u_cor, n))*problem.get_outflow_measure_form())
            # print('DDN: u_cor*n dSout = ', u_ext_in)
            # print('DDN: negative part of u_cor*n dSout = ', DDN_triggered)

            if self.useRotationScheme:
                begin("Rotation scheme pressure correction")
                self.tc.start('rhs')
                b = assemble(L4)
                self.tc.end('rhs')
                try:
                    self.tc.start('solve 4')
                    self.solver_rot.solve(A4, p_mod.vector(), b)
                    self.tc.end('solve 4')
                except RuntimeError as inst:
                    problem.report_fail(t)
                    return 1
                problem.averaging_pressure(p_mod)
                if save_this_step and not onlyVel:
                    problem.save_pressure(False, p_mod)
                end()

            # compute functionals (e. g. forces)
            problem.compute_functionals(u_cor,
                                        p_mod if self.useRotationScheme else (pQ if self.bc == 'lagrange' else p_), t)

            # Move to next time step
            self.tc.start('next')
            u1.assign(u0)
            u0.assign(u_cor)
            u_.assign(u_cor)  # use corretced velocity as initial guess in first step

            if self.useRotationScheme:
                p0.assign(p_mod)
            else:
                if self.bc == 'lagrange':
                    p0.assign(pQ)
                else:
                    p0.assign(p_)

            t = round(t + dt, 6)  # round time step to 0.000001
            step += 1
            self.tc.end('next')

        info("Finished: Incremental pressure correction scheme n. 1")
        problem.report()
        return 0