def __init__(self, function_space, model_parameters):
        super(AllenCahnHeatModel, self).__init__()

        self._solution_function = fd.Function(function_space)
        self._solutiondot_function = fd.Function(function_space)
        test_function = fd.TestFunction(function_space)

        # Split mixed FE function into separate functions and put them into namedtuple
        FiniteElementFunction = namedtuple("FiniteElementFunction",
                                           ["phi", "T"])

        split_solution_function = FiniteElementFunction(
            *ufl.split(self._solution_function))
        split_solutiondot_function = FiniteElementFunction(
            *ufl.split(self._solutiondot_function))
        split_test_function = FiniteElementFunction(*ufl.split(test_function))

        finite_element_functions = (
            split_solution_function,
            split_solutiondot_function,
            split_test_function,
        )

        F_AC = get_allen_cahn_weak_form(*finite_element_functions,
                                        model_parameters)
        F_heat = get_heat_weak_form(*finite_element_functions,
                                    model_parameters)

        F = F_AC + F_heat

        self._residual = F
示例#2
0
def derivative(form, u, du=None, coefficient_derivatives=None):
    if du is None:
        # Get existing arguments from form and position the new one with the next argument number
        from ufl.algorithms import extract_arguments
        form_arguments = extract_arguments(form)

        number = max([-1] + [arg.number() for arg in form_arguments]) + 1

        if any(arg.part() is not None for arg in form_arguments):
            cpp.dolfin_error(
                "formmanipulation.py", "compute derivative of form",
                "Cannot automatically create third argument using parts, please supply one"
            )
        part = None

        if isinstance(u, Function):
            V = u.function_space()
            du = Argument(V, number, part)
        elif isinstance(u, (list, tuple)) and all(
                isinstance(w, Function) for w in u):
            V = MixedFunctionSpace([w.function_space() for w in u])
            du = ufl.split(Argument(V, number, part))
        else:
            cpp.dolfin_error(
                "formmanipulation.py", "compute derivative of form",
                "Cannot automatically create third argument, please supply one"
            )
    return ufl.derivative(form, u, du, coefficient_derivatives)
示例#3
0
def Arguments(V, number):
    """UFL value: Create an Argument in a mixed space, and return a
    tuple with the function components corresponding to the subelements.

    This is the overloaded PyDOLFIN variant.
    """
    return ufl.split(Argument(V, number))
示例#4
0
def TrialFunctions(V: functionspace.FunctionSpace):
    """Create a TrialFunction in a mixed space, and return a
    tuple with the function components corresponding to the
    subelements.

    """
    return ufl.split(TrialFunction(V))
示例#5
0
def derivative(form, u, du=None, coefficient_derivatives=None):
    if du is None:
        # Get existing arguments from form and position the new one with the next argument number
        from ufl.algorithms import extract_arguments
        form_arguments = extract_arguments(form)

        number = max([-1] + [arg.number() for arg in form_arguments]) + 1

        if any(arg.part() is not None for arg in form_arguments):
            cpp.dolfin_error("formmanipulation.py",
                             "compute derivative of form",
                             "Cannot automatically create third argument using parts, please supply one")
        part = None

        if isinstance(u, Function):
            V = u.function_space()
            du = Argument(V, number, part)
        elif isinstance(u, (list,tuple)) and all(isinstance(w, Function) for w in u):
            V = MixedFunctionSpace([w.function_space() for w in u])
            du = ufl.split(Argument(V, number, part))
        else:
            cpp.dolfin_error("formmanipulation.py",
                             "compute derivative of form",
                             "Cannot automatically create third argument, please supply one")
    return ufl.derivative(form, u, du, coefficient_derivatives)
示例#6
0
def TrialFunctions(V):
    """UFL value: Create a TrialFunction in a mixed space, and return a
    tuple with the function components corresponding to the subelements.

    This is the overloaded PyDOLFIN variant.
    """
    return ufl.split(TrialFunction(V))
示例#7
0
def Arguments(V, number):
    """UFL value: Create an Argument in a mixed space, and return a
    tuple with the function components corresponding to the subelements.

    This is the overloaded PyDOLFIN variant.
    """
    return ufl.split(Argument(V, number))
示例#8
0
def test_physically_mapped_facet():
    mesh = Mesh(VectorElement("P", triangle, 1))

    # set up variational problem
    U = FiniteElement("Morley", mesh.ufl_cell(), 2)
    V = FiniteElement("P", mesh.ufl_cell(), 1)
    R = FiniteElement("P", mesh.ufl_cell(), 1)
    Vv = VectorElement(BrokenElement(V))
    Qhat = VectorElement(BrokenElement(V[facet]))
    Vhat = VectorElement(V[facet])
    Z = FunctionSpace(mesh, MixedElement(U, Vv, Qhat, Vhat, R))

    z = Coefficient(Z)
    u, d, qhat, dhat, lam = split(z)

    s = FacetNormal(mesh)
    trans = as_matrix([[1, 0], [0, 1]])
    mat = trans*grad(grad(u))*trans + outer(d, d) * u
    J = (u**2*dx +
         u**3*dx +
         u**4*dx +
         inner(mat, mat)*dx +
         inner(grad(d), grad(d))*dx +
         dot(s, d)**2*ds)
    L_match = inner(qhat, dhat - d)
    L = J + inner(lam, inner(d, d)-1)*dx + (L_match('+') + L_match('-'))*dS + L_match*ds
    compile_form(L)
示例#9
0
def TrialFunctions(V):
    """UFL value: Create a TrialFunction in a mixed space, and return a
    tuple with the function components corresponding to the subelements.

    This is the overloaded PyDOLFIN variant.
    """
    return ufl.split(TrialFunction(V))
示例#10
0
def computeVelocityField(mesh):
    Xh = dl.VectorFunctionSpace(mesh,'Lagrange', 2)
    Wh = dl.FunctionSpace(mesh, 'Lagrange', 1)

    mixed_element = dl.MixedElement([Xh.ufl_element(), Wh.ufl_element()])
    XW = dl.FunctionSpace(mesh, mixed_element)

    
    Re = 1e2
    
    g = dl.Expression(('0.0','(x[0] < 1e-14) - (x[0] > 1 - 1e-14)'), element=Xh.ufl_element())
    bc1 = dl.DirichletBC(XW.sub(0), g, v_boundary)
    bc2 = dl.DirichletBC(XW.sub(1), dl.Constant(0), q_boundary, 'pointwise')
    bcs = [bc1, bc2]
    
    vq = dl.Function(XW)
    (v,q) = ufl.split(vq)
    (v_test, q_test) = dl.TestFunctions (XW)
    
    def strain(v):
        return ufl.sym(ufl.grad(v))
    
    F = ( (2./Re)*ufl.inner(strain(v),strain(v_test))+ ufl.inner (ufl.nabla_grad(v)*v, v_test)
           - (q * ufl.div(v_test)) + ( ufl.div(v) * q_test) ) * ufl.dx
           
    dl.solve(F == 0, vq, bcs, solver_parameters={"newton_solver":
                                         {"relative_tolerance":1e-4, "maximum_iterations":100,
                                          "linear_solver":"default"}})
        
    return v
示例#11
0
    def monolithic_solve():
        """Monolithic version"""
        E = P * P
        W = FunctionSpace(mesh, E)
        U = Function(W)
        dU = ufl.TrialFunction(W)
        u0, u1 = ufl.split(U)
        v0, v1 = ufl.TestFunctions(W)

        F = inner((u0**2 + 1) * ufl.grad(u0), ufl.grad(v0)) * dx \
            + inner((u1**2 + 1) * ufl.grad(u1), ufl.grad(v1)) * dx \
            - inner(f, v0) * ufl.dx - inner(g, v1) * dx
        J = derivative(F, U, dU)

        F, J = form(F), form(J)

        u0_bc = Function(V0)
        u0_bc.interpolate(bc_val_0)
        u1_bc = Function(V1)
        u1_bc.interpolate(bc_val_1)
        bdofsW0_V0 = locate_dofs_topological((W.sub(0), V0), facetdim,
                                             bndry_facets)
        bdofsW1_V1 = locate_dofs_topological((W.sub(1), V1), facetdim,
                                             bndry_facets)
        bcs = [
            dirichletbc(u0_bc, bdofsW0_V0, W.sub(0)),
            dirichletbc(u1_bc, bdofsW1_V1, W.sub(1))
        ]

        Jmat = create_matrix(J)
        Fvec = create_vector(F)

        snes = PETSc.SNES().create(MPI.COMM_WORLD)
        snes.setTolerances(rtol=1.0e-15, max_it=10)

        snes.getKSP().setType("preonly")
        snes.getKSP().getPC().setType("lu")

        problem = NonlinearPDE_SNESProblem(F, J, U, bcs)
        snes.setFunction(problem.F_mono, Fvec)
        snes.setJacobian(problem.J_mono, J=Jmat, P=None)

        U.sub(0).interpolate(initial_guess_u)
        U.sub(1).interpolate(initial_guess_p)

        x = create_vector(F)
        x.array = U.vector.array_r

        snes.solve(None, x)
        assert snes.getKSP().getConvergedReason() > 0
        assert snes.getConvergedReason() > 0
        return x.norm()
示例#12
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)
示例#13
0
    def computeVelocityField(self):
        """
        The steady-state Navier-Stokes equation for velocity v:
        -1/Re laplace v + nabla q + v dot nabla v = 0  in Omega
        nabla dot v = 0                                in Omega
        v = g                                          on partial Omega
        """
        Xh = dl.VectorFunctionSpace(self.mesh, 'Lagrange', self.eldeg)
        Wh = dl.FunctionSpace(self.mesh, 'Lagrange', 1)

        mixed_element = dl.MixedElement([Xh.ufl_element(), Wh.ufl_element()])
        XW = dl.FunctionSpace(self.mesh, mixed_element)

        Re = dl.Constant(self.Re)

        def v_boundary(x, on_boundary):
            return on_boundary

        def q_boundary(x, on_boundary):
            return x[0] < dl.DOLFIN_EPS and x[1] < dl.DOLFIN_EPS

        g = dl.Expression(('0.0', '(x[0] < 1e-14) - (x[0] > 1 - 1e-14)'),
                          element=Xh.ufl_element())
        bc1 = dl.DirichletBC(XW.sub(0), g, v_boundary)
        bc2 = dl.DirichletBC(XW.sub(1), dl.Constant(0), q_boundary,
                             'pointwise')
        bcs = [bc1, bc2]

        vq = dl.Function(XW)
        (v, q) = ufl.split(vq)
        (v_test, q_test) = dl.TestFunctions(XW)

        def strain(v):
            return ufl.sym(ufl.grad(v))

        F = ((2. / Re) * ufl.inner(strain(v), strain(v_test)) +
             ufl.inner(ufl.nabla_grad(v) * v, v_test) - (q * ufl.div(v_test)) +
             (ufl.div(v) * q_test)) * ufl.dx

        dl.solve(F == 0,
                 vq,
                 bcs,
                 solver_parameters={
                     "newton_solver": {
                         "relative_tolerance": 1e-4,
                         "maximum_iterations": 100,
                         "linear_solver": "default"
                     }
                 })

        return v
示例#14
0
def Arguments(V, number):
    """UFL value: Create an Argument in a mixed space, and return a
    tuple with the function components corresponding to the subelements.

    This is the overloaded PyDOLFIN variant.

    """
    if isinstance(V, MixedFunctionSpace):
        return [
            Argument(V.sub_space(i), number, i)
            for i in range(V.num_sub_spaces())
        ]
    else:
        return ufl.split(Argument(V, number))
示例#15
0
def derivative(form, u, du=None):
    if du is None:
        if isinstance(u, Function):
            V = u.function_space()
            du = Argument(V)
        elif isinstance(u, (list,tuple)) and all(isinstance(w, Function) for w in u):
            V = MixedFunctionSpace([w.function_space() for w in u])
            du = ufl.split(Argument(V))
        else:
            cpp.dolfin_error("formmanipulation.py",
                             "compute derivative of form",
                             "Cannot automatically create third argument, please supply one")

    return ufl.derivative(form, u, du)
def derivative(form, u, du=None):
    if du is None:
        if isinstance(u, Function):
            V = u.function_space()
            du = Argument(V)
        elif isinstance(u, (list, tuple)) and all(
                isinstance(w, Function) for w in u):
            V = MixedFunctionSpace([w.function_space() for w in u])
            du = ufl.split(Argument(V))
        else:
            cpp.dolfin_error(
                "formmanipulation.py", "compute derivative of form",
                "Cannot automatically create third argument, please supply one"
            )

    return ufl.derivative(form, u, du)
def monolithic_assembly(clock, reps, mesh, use_cpp_forms):
    P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2)
    P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    TH = P2_el * P1_el
    W = dolfinx.FunctionSpace(mesh, TH)
    num_dofs = W.dim

    U = dolfinx.Function(W)
    u, p = ufl.split(U)
    v, q = ufl.TestFunctions(W)

    g = ufl.as_vector([0.0, 0.0, -1.0])
    F = (
        ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx
        + ufl.inner(p, ufl.div(v)) * ufl.dx
        + ufl.inner(ufl.div(u), q) * ufl.dx
        - ufl.inner(g, v) * ufl.dx
    )
    J = ufl.derivative(F, U, ufl.TrialFunction(W))
    bcs = []

    # Get jitted forms for better performance
    if use_cpp_forms:
        F = dolfinx.fem.assemble._create_cpp_form(F)
        J = dolfinx.fem.assemble._create_cpp_form(J)

    b = dolfinx.fem.create_vector(F)
    A = dolfinx.fem.create_matrix(J)
    for i in range(reps):
        A.zeroEntries()
        with b.localForm() as b_local:
            b_local.set(0.0)

        with dolfinx.common.Timer("ZZZ Mat Monolithic") as tmr:
            dolfinx.fem.assemble_matrix(A, J, bcs)
            A.assemble()
            clock["mat"] += tmr.elapsed()[0]

        with dolfinx.common.Timer("ZZZ Vec Monolithic") as tmr:
            dolfinx.fem.assemble_vector(b, F)
            dolfinx.fem.apply_lifting(b, [J], bcs=[bcs], x0=[U.vector], scale=-1.0)
            b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
            dolfinx.fem.set_bc(b, bcs, x0=U.vector, scale=-1.0)
            b.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)
            clock["vec"] += tmr.elapsed()[0]

    return num_dofs, A, b
示例#18
0
def derivative(form, u, du=None, coefficient_derivatives=None):
    if du is None:
        # Get existing arguments from form and position the new one with the next argument number
        form_arguments = form.arguments()

        number = max([-1] + [arg.number() for arg in form_arguments]) + 1

        if any(arg.part() is not None for arg in form_arguments):
            cpp.dolfin_error(
                "formmanipulation.py", "compute derivative of form",
                "Cannot automatically create new Argument using "
                "parts, please supply one")
        part = None

        if isinstance(u, Function):
            V = u.function_space()
            du = Argument(V, number, part)

        elif isinstance(u, (list, tuple)) and all(
                isinstance(w, Function) for w in u):
            cpp.deprecation(
                "derivative of form w.r.t. a tuple of Coefficients", "1.7.0",
                "2.0.0", "Take derivative w.r.t. a single Coefficient on "
                "a mixed space instead.")

            # Get mesh
            mesh = u[0].function_space().mesh()
            if not all(mesh.id() == v.function_space().mesh().id() for v in u):
                cpp.dolfin_error(
                    "formmanipulation.py", "compute derivative of form",
                    "Don't know how to compute derivative with "
                    "respect to Coefficients on different meshes yet")

            # Build mixed element, space and argument
            element = ufl.MixedElement(
                [v.function_space().ufl_element() for v in u])
            V = FunctionSpace(mesh, element)
            du = ufl.split(Argument(V, number, part))

        else:
            cpp.dolfin_error("formmanipulation.py",
                             "compute derivative of form w.r.t. '%s'" % u,
                             "Supply Function as a Coefficient")

    return ufl.derivative(form, u, du, coefficient_derivatives)
示例#19
0
    def argument(self, o):
        from ufl import split
        from firedrake import MixedFunctionSpace, FunctionSpace
        V = o.function_space()
        if len(V) == 1:
            # Not on a mixed space, just return ourselves.
            return o

        if o in self._arg_cache:
            return self._arg_cache[o]

        V_is = V.split()
        indices = self.blocks[o.number()]

        try:
            indices = tuple(indices)
            nidx = len(indices)
        except TypeError:
            # Only one index provided.
            indices = (indices, )
            nidx = 1

        if nidx == 1:
            W = V_is[indices[0]]
            W = FunctionSpace(W.mesh(), W.ufl_element())
            a = (Argument(W, o.number(), part=o.part()), )
        else:
            W = MixedFunctionSpace([V_is[i] for i in indices])
            a = split(Argument(W, o.number(), part=o.part()))
        args = []
        for i in range(len(V_is)):
            if i in indices:
                c = indices.index(i)
                a_ = a[c]
                if len(a_.ufl_shape) == 0:
                    args += [a_]
                else:
                    args += [a_[j] for j in numpy.ndindex(a_.ufl_shape)]
            else:
                args += [
                    Zero()
                    for j in numpy.ndindex(V_is[i].ufl_element().value_shape())
                ]
        return self._arg_cache.setdefault(o, as_vector(args))
示例#20
0
    def argument(self, o):
        from ufl import split
        from firedrake import MixedFunctionSpace, FunctionSpace
        V = o.function_space()
        if len(V) == 1:
            # Not on a mixed space, just return ourselves.
            return o

        if o in self._arg_cache:
            return self._arg_cache[o]

        V_is = V.split()
        indices = self.blocks[o.number()]

        try:
            indices = tuple(indices)
            nidx = len(indices)
        except TypeError:
            # Only one index provided.
            indices = (indices, )
            nidx = 1

        if nidx == 1:
            W = V_is[indices[0]]
            W = FunctionSpace(W.mesh(), W.ufl_element())
            a = (Argument(W, o.number(), part=o.part()), )
        else:
            W = MixedFunctionSpace([V_is[i] for i in indices])
            a = split(Argument(W, o.number(), part=o.part()))
        args = []
        for i in range(len(V_is)):
            if i in indices:
                c = indices.index(i)
                a_ = a[c]
                if len(a_.ufl_shape) == 0:
                    args += [a_]
                else:
                    args += [a_[j] for j in numpy.ndindex(a_.ufl_shape)]
            else:
                args += [Zero()
                         for j in numpy.ndindex(
                         V_is[i].ufl_element().value_shape())]
        return self._arg_cache.setdefault(o, as_vector(args))
示例#21
0
def derivative(form, u, du=None, coefficient_derivatives=None):
    if du is None:
        # Get existing arguments from form and position the new one with the next argument number
        form_arguments = form.arguments()

        number = max([-1] + [arg.number() for arg in form_arguments]) + 1

        if any(arg.part() is not None for arg in form_arguments):
            cpp.dolfin_error("formmanipulation.py",
                             "compute derivative of form",
                             "Cannot automatically create new Argument using "
                             "parts, please supply one")
        part = None

        if isinstance(u, Function):
            V = u.function_space()
            du = Argument(V, number, part)

        elif isinstance(u, (list,tuple)) and all(isinstance(w, Function) for w in u):
            cpp.deprecation("derivative of form w.r.t. a tuple of Coefficients",
                            "1.7.0", "2.0.0",
                            "Take derivative w.r.t. a single Coefficient on "
                            "a mixed space instead.")

            # Get mesh
            mesh = u[0].function_space().mesh()
            if not all(mesh.id() == v.function_space().mesh().id() for v in u):
                cpp.dolfin_error("formmanipulation.py",
                                 "compute derivative of form",
                                 "Don't know how to compute derivative with "
                                 "respect to Coefficients on different meshes yet")

            # Build mixed element, space and argument
            element = ufl.MixedElement([v.function_space().ufl_element() for v in u])
            V = FunctionSpace(mesh, element)
            du = ufl.split(Argument(V, number, part))

        else:
            cpp.dolfin_error("formmanipulation.py",
                             "compute derivative of form w.r.t. '%s'" % u,
                             "Supply Function as a Coefficient")

    return ufl.derivative(form, u, du, coefficient_derivatives)
示例#22
0
#
# Harmonic map demo using one mixed function u to represent x and y.
# Author: Martin Alnes
# Date: 2009-04-09
#
from ufl import (Coefficient, FiniteElement, VectorElement, derivative, dot,
                 dx, grad, inner, split, triangle)

cell = triangle
X = VectorElement("Lagrange", cell, 1)
Y = FiniteElement("Lagrange", cell, 1)
M = X * Y

u = Coefficient(M)
x, y = split(u)

L = inner(grad(x), grad(x)) * dx + dot(x, x) * y * dx

F = derivative(L, u)
J = derivative(F, u)

forms = [L, F, J]
示例#23
0
def test_assembly_solve_taylor_hood_nl(mesh):
    """Assemble Stokes problem with Taylor-Hood elements and solve."""
    gdim = mesh.geometry.dim
    P2 = VectorFunctionSpace(mesh, ("Lagrange", 2))
    P1 = FunctionSpace(mesh, ("Lagrange", 1))

    def boundary0(x):
        """Define boundary x = 0"""
        return np.isclose(x[0], 0.0)

    def boundary1(x):
        """Define boundary x = 1"""
        return np.isclose(x[0], 1.0)

    def initial_guess_u(x):
        u_init = np.row_stack(
            (np.sin(x[0]) * np.sin(x[1]), np.cos(x[0]) * np.cos(x[1])))
        if gdim == 3:
            u_init = np.row_stack((u_init, np.cos(x[2])))
        return u_init

    def initial_guess_p(x):
        return -x[0]**2 - x[1]**3

    u_bc_0 = Function(P2)
    u_bc_0.interpolate(
        lambda x: np.row_stack(tuple(x[j] + float(j) for j in range(gdim))))

    u_bc_1 = Function(P2)
    u_bc_1.interpolate(
        lambda x: np.row_stack(tuple(np.sin(x[j]) for j in range(gdim))))

    facetdim = mesh.topology.dim - 1
    bndry_facets0 = locate_entities_boundary(mesh, facetdim, boundary0)
    bndry_facets1 = locate_entities_boundary(mesh, facetdim, boundary1)

    bdofs0 = locate_dofs_topological(P2, facetdim, bndry_facets0)
    bdofs1 = locate_dofs_topological(P2, facetdim, bndry_facets1)

    bcs = [dirichletbc(u_bc_0, bdofs0), dirichletbc(u_bc_1, bdofs1)]

    u, p = Function(P2), Function(P1)
    du, dp = ufl.TrialFunction(P2), ufl.TrialFunction(P1)
    v, q = ufl.TestFunction(P2), ufl.TestFunction(P1)

    F = [
        inner(ufl.grad(u), ufl.grad(v)) * dx + inner(p, ufl.div(v)) * dx,
        inner(ufl.div(u), q) * dx
    ]
    J = [[derivative(F[0], u, du),
          derivative(F[0], p, dp)],
         [derivative(F[1], u, du),
          derivative(F[1], p, dp)]]
    P = [[J[0][0], None], [None, inner(dp, q) * dx]]

    F, J, P = form(F), form(J), form(P)

    # -- Blocked and monolithic

    Jmat0 = create_matrix_block(J)
    Pmat0 = create_matrix_block(P)
    Fvec0 = create_vector_block(F)

    snes = PETSc.SNES().create(MPI.COMM_WORLD)
    snes.setTolerances(rtol=1.0e-15, max_it=10)
    snes.getKSP().setType("minres")
    snes.getKSP().getPC().setType("lu")

    problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs, P=P)
    snes.setFunction(problem.F_block, Fvec0)
    snes.setJacobian(problem.J_block, J=Jmat0, P=Pmat0)

    u.interpolate(initial_guess_u)
    p.interpolate(initial_guess_p)

    x0 = create_vector_block(F)
    with u.vector.localForm() as _u, p.vector.localForm() as _p:
        scatter_local_vectors(x0, [_u.array_r, _p.array_r],
                              [(u.function_space.dofmap.index_map,
                                u.function_space.dofmap.index_map_bs),
                               (p.function_space.dofmap.index_map,
                                p.function_space.dofmap.index_map_bs)])
    x0.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                   mode=PETSc.ScatterMode.FORWARD)

    snes.solve(None, x0)

    assert snes.getConvergedReason() > 0

    # -- Blocked and nested

    Jmat1 = create_matrix_nest(J)
    Pmat1 = create_matrix_nest(P)
    Fvec1 = create_vector_nest(F)

    snes = PETSc.SNES().create(MPI.COMM_WORLD)
    snes.setTolerances(rtol=1.0e-15, max_it=10)

    nested_IS = Jmat1.getNestISs()

    snes.getKSP().setType("minres")
    snes.getKSP().setTolerances(rtol=1e-12)
    snes.getKSP().getPC().setType("fieldsplit")
    snes.getKSP().getPC().setFieldSplitIS(["u", nested_IS[0][0]],
                                          ["p", nested_IS[1][1]])

    ksp_u, ksp_p = snes.getKSP().getPC().getFieldSplitSubKSP()
    ksp_u.setType("preonly")
    ksp_u.getPC().setType('lu')
    ksp_p.setType("preonly")
    ksp_p.getPC().setType('lu')

    problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs, P=P)
    snes.setFunction(problem.F_nest, Fvec1)
    snes.setJacobian(problem.J_nest, J=Jmat1, P=Pmat1)

    u.interpolate(initial_guess_u)
    p.interpolate(initial_guess_p)

    x1 = create_vector_nest(F)
    for x1_soln_pair in zip(x1.getNestSubVecs(), (u, p)):
        x1_sub, soln_sub = x1_soln_pair
        soln_sub.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                                    mode=PETSc.ScatterMode.FORWARD)
        soln_sub.vector.copy(result=x1_sub)
        x1_sub.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                           mode=PETSc.ScatterMode.FORWARD)

    x1.set(0.0)
    snes.solve(None, x1)

    assert snes.getConvergedReason() > 0
    assert nest_matrix_norm(Jmat1) == pytest.approx(Jmat0.norm(), 1.0e-12)
    assert Fvec1.norm() == pytest.approx(Fvec0.norm(), 1.0e-12)
    assert x1.norm() == pytest.approx(x0.norm(), 1.0e-12)

    # -- Monolithic

    P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2)
    P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    TH = P2_el * P1_el
    W = FunctionSpace(mesh, TH)
    U = Function(W)
    dU = ufl.TrialFunction(W)
    u, p = ufl.split(U)
    du, dp = ufl.split(dU)
    v, q = ufl.TestFunctions(W)

    F = inner(ufl.grad(u), ufl.grad(v)) * dx + inner(p, ufl.div(v)) * dx \
        + inner(ufl.div(u), q) * dx
    J = derivative(F, U, dU)
    P = inner(ufl.grad(du), ufl.grad(v)) * dx + inner(dp, q) * dx

    F, J, P = form(F), form(J), form(P)

    bdofsW0_P2_0 = locate_dofs_topological((W.sub(0), P2), facetdim,
                                           bndry_facets0)
    bdofsW0_P2_1 = locate_dofs_topological((W.sub(0), P2), facetdim,
                                           bndry_facets1)

    bcs = [
        dirichletbc(u_bc_0, bdofsW0_P2_0, W.sub(0)),
        dirichletbc(u_bc_1, bdofsW0_P2_1, W.sub(0))
    ]

    Jmat2 = create_matrix(J)
    Pmat2 = create_matrix(P)
    Fvec2 = create_vector(F)

    snes = PETSc.SNES().create(MPI.COMM_WORLD)
    snes.setTolerances(rtol=1.0e-15, max_it=10)
    snes.getKSP().setType("minres")
    snes.getKSP().getPC().setType("lu")

    problem = NonlinearPDE_SNESProblem(F, J, U, bcs, P=P)
    snes.setFunction(problem.F_mono, Fvec2)
    snes.setJacobian(problem.J_mono, J=Jmat2, P=Pmat2)

    U.sub(0).interpolate(initial_guess_u)
    U.sub(1).interpolate(initial_guess_p)

    x2 = create_vector(F)
    x2.array = U.vector.array_r

    snes.solve(None, x2)

    assert snes.getConvergedReason() > 0
    assert Jmat2.norm() == pytest.approx(Jmat0.norm(), 1.0e-12)
    assert Fvec2.norm() == pytest.approx(Fvec0.norm(), 1.0e-12)
    assert x2.norm() == pytest.approx(x0.norm(), 1.0e-12)
示例#24
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('solve',
                           'Running nonlinear solver',
                           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')

        mesh = self.problem.mesh

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

        # to assign solution in space W.sub(0) to Function(V) we need FunctionAssigner (cannot be assigned directly)
        fa = FunctionAssigner(self.V, self.W.sub(0))
        velSp = Function(self.V)

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

        # Define unknown and test function(s) NS
        v, q = TestFunctions(self.W)
        w = Function(self.W)
        dw = TrialFunction(self.W)
        u, p = split(w)

        # Define fields
        n = FacetNormal(mesh)
        I = Identity(u.geometric_dimension())
        theta = 0.5  # Crank-Nicholson
        k = Constant(self.metadata['dt'])

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

        if doSave:
            problem.save_vel(False, u0)

        # boundary conditions
        bcu, bcp = problem.get_boundary_conditions(False, self.W.sub(0),
                                                   self.W.sub(1))

        # Define steady part of the equation
        def T(u):
            return -p * I + 2.0 * nu * sym(grad(u))

        def F(u, v, q):
            return (inner(T(u), grad(v)) - q * div(u)) * dx + inner(
                grad(u) * u, v) * dx

        # Define variational forms
        F_ns = (inner(
            (u - u0), v) / k) * dx + (1.0 - theta) * F(u0, v, q) + theta * F(
                u, v, q)
        J_ns = derivative(F_ns, w, dw)
        # J_ns = derivative(F_ns, w)  # did not work

        # NS_problem = NonlinearVariationalProblem(F_ns, w, bcu, J_ns, form_compiler_parameters=ffc_options)
        NS_problem = NonlinearVariationalProblem(F_ns, w, bcu, J_ns)
        # (var. formulation, unknown, Dir. BC, jacobian, optional)
        NS_solver = NonlinearVariationalSolver(NS_problem)

        prm = NS_solver.parameters
        prm['newton_solver']['absolute_tolerance'] = 1E-08
        prm['newton_solver']['relative_tolerance'] = 1E-08
        # prm['newton_solver']['maximum_iterations'] = 45
        # prm['newton_solver']['relaxation_parameter'] = 1.0
        prm['newton_solver']['linear_solver'] = 'mumps'
        # prm['newton_solver']['lu_solver']['same_nonzero_pattern'] = True

        info(NS_solver.parameters, True)

        self.tc.end('init')

        # Time-stepping
        info("Running of direct method")
        ttime = self.metadata['time']
        t = dt
        step = 1
        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

            # Compute
            begin("Solving NS ....")
            try:
                self.tc.start('solve')
                NS_solver.solve()
                self.tc.end('solve')
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            end()

            # Extract solutions:
            (u, p) = w.split()
            fa.assign(velSp, u)
            # we are assigning twice (now and inside save_vel), but it works with one method save_vel for direct and
            #   projection (we could split save_vel to save one assign)

            if save_this_step:
                self.tc.start('saveVel')
                problem.save_vel(False, velSp)
                self.tc.end('saveVel')
            if save_this_step and not onlyVel:
                problem.save_div(False, u)
            problem.compute_err(False, u, t)
            problem.compute_div(False, u)

            # foo = Function(self.Q)
            # foo.assign(p)
            # problem.averaging_pressure(foo)
            # if save_this_step and not onlyVel:
            #     problem.save_pressure(False, foo)

            if save_this_step and not onlyVel:
                problem.save_pressure(False, p)

            # compute functionals (e. g. forces)
            problem.compute_functionals(u, p, t, step)

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

        info("Finished: direct method")
        problem.report()
        return 0
示例#25
0
# ```
#
# For the test functions, {py:func}`TestFunctions<function
# ufl.argument.TestFunctions>` (note the 's' at the end) is used to
# define the scalar test functions `q` and `v`. Some mixed objects
# of the {py:class}`Function<dolfinx.fem.function.Function>` class on
# `ME` are defined to represent $u = (c_{n+1}, \mu_{n+1})$ and
# $u0 = (c_{n}, \mu_{n})$, and these are then split into
# sub-functions:

# +
u = Function(ME)  # current solution
u0 = Function(ME)  # solution from previous converged step

# Split mixed functions
c, mu = ufl.split(u)
c0, mu0 = ufl.split(u0)
# -

# The line `c, mu = ufl.split(u)` permits direct access to the
# components of a mixed function. Note that `c` and `mu` are references
# for components of `u`, and not copies.
#
# ```{index} single: interpolating functions; (in Cahn-Hilliard demo)
# ```
#
# The initial conditions are interpolated into a finite element space:

# +
# Zero u
u.x.array[:] = 0.0
示例#26
0
def test_matrix_assembly_block_nl():
    """Test assembly of block matrices and vectors into (a) monolithic
    blocked structures, PETSc Nest structures, and monolithic structures
    in the nonlinear setting
    """
    mesh = create_unit_square(MPI.COMM_WORLD, 4, 8)
    p0, p1 = 1, 2
    P0 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p0)
    P1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p1)
    V0 = FunctionSpace(mesh, P0)
    V1 = FunctionSpace(mesh, P1)

    def initial_guess_u(x):
        return np.sin(x[0]) * np.sin(x[1])

    def initial_guess_p(x):
        return -x[0]**2 - x[1]**3

    def bc_value(x):
        return np.cos(x[0]) * np.cos(x[1])

    facetdim = mesh.topology.dim - 1
    bndry_facets = locate_entities_boundary(
        mesh, facetdim,
        lambda x: np.logical_or(np.isclose(x[0], 0.0), np.isclose(x[0], 1.0)))

    u_bc = Function(V1)
    u_bc.interpolate(bc_value)
    bdofs = locate_dofs_topological(V1, facetdim, bndry_facets)
    bc = dirichletbc(u_bc, bdofs)

    # Define variational problem
    du, dp = ufl.TrialFunction(V0), ufl.TrialFunction(V1)
    u, p = Function(V0), Function(V1)
    v, q = ufl.TestFunction(V0), ufl.TestFunction(V1)

    u.interpolate(initial_guess_u)
    p.interpolate(initial_guess_p)

    f = 1.0
    g = -3.0

    F0 = inner(u, v) * dx + inner(p, v) * dx - inner(f, v) * dx
    F1 = inner(u, q) * dx + inner(p, q) * dx - inner(g, q) * dx

    a_block = form([[derivative(F0, u, du),
                     derivative(F0, p, dp)],
                    [derivative(F1, u, du),
                     derivative(F1, p, dp)]])
    L_block = form([F0, F1])

    # Monolithic blocked
    x0 = create_vector_block(L_block)
    scatter_local_vectors(x0, [u.vector.array_r, p.vector.array_r],
                          [(u.function_space.dofmap.index_map,
                            u.function_space.dofmap.index_map_bs),
                           (p.function_space.dofmap.index_map,
                            p.function_space.dofmap.index_map_bs)])
    x0.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                   mode=PETSc.ScatterMode.FORWARD)

    # Ghosts are updated inside assemble_vector_block
    A0 = assemble_matrix_block(a_block, bcs=[bc])
    b0 = assemble_vector_block(L_block, a_block, bcs=[bc], x0=x0, scale=-1.0)
    A0.assemble()
    assert A0.getType() != "nest"
    Anorm0 = A0.norm()
    bnorm0 = b0.norm()

    # Nested (MatNest)
    x1 = create_vector_nest(L_block)
    for x1_soln_pair in zip(x1.getNestSubVecs(), (u, p)):
        x1_sub, soln_sub = x1_soln_pair
        soln_sub.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                                    mode=PETSc.ScatterMode.FORWARD)
        soln_sub.vector.copy(result=x1_sub)
        x1_sub.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                           mode=PETSc.ScatterMode.FORWARD)

    A1 = assemble_matrix_nest(a_block, bcs=[bc])
    b1 = assemble_vector_nest(L_block)
    apply_lifting_nest(b1, a_block, bcs=[bc], x0=x1, scale=-1.0)
    for b_sub in b1.getNestSubVecs():
        b_sub.ghostUpdate(addv=PETSc.InsertMode.ADD,
                          mode=PETSc.ScatterMode.REVERSE)
    bcs0 = bcs_by_block([L.function_spaces[0] for L in L_block], [bc])

    set_bc_nest(b1, bcs0, x1, scale=-1.0)
    A1.assemble()

    assert A1.getType() == "nest"
    assert nest_matrix_norm(A1) == pytest.approx(Anorm0, 1.0e-12)
    assert b1.norm() == pytest.approx(bnorm0, 1.0e-12)

    # Monolithic version
    E = P0 * P1
    W = FunctionSpace(mesh, E)
    dU = ufl.TrialFunction(W)
    U = Function(W)
    u0, u1 = ufl.split(U)
    v0, v1 = ufl.TestFunctions(W)

    U.sub(0).interpolate(initial_guess_u)
    U.sub(1).interpolate(initial_guess_p)

    F = inner(u0, v0) * dx + inner(u1, v0) * dx + inner(u0, v1) * dx + inner(u1, v1) * dx \
        - inner(f, v0) * ufl.dx - inner(g, v1) * dx
    J = derivative(F, U, dU)
    F, J = form(F), form(J)

    bdofsW_V1 = locate_dofs_topological((W.sub(1), V1), facetdim, bndry_facets)

    bc = dirichletbc(u_bc, bdofsW_V1, W.sub(1))
    A2 = assemble_matrix(J, bcs=[bc])
    A2.assemble()
    b2 = assemble_vector(F)
    apply_lifting(b2, [J], bcs=[[bc]], x0=[U.vector], scale=-1.0)
    b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    set_bc(b2, [bc], x0=U.vector, scale=-1.0)
    assert A2.getType() != "nest"
    assert A2.norm() == pytest.approx(Anorm0, 1.0e-12)
    assert b2.norm() == pytest.approx(bnorm0, 1.0e-12)
示例#27
0
文件: prior.py 项目: cpempire/GOOED
    def __init__(self,
                 Vh,
                 gamma,
                 delta,
                 mean=None,
                 rel_tol=1e-12,
                 max_iter=100):
        """
        Construct the prior model.
        Input:

        - :code:`Vh`:              the finite element space for the parameter
        - :code:`gamma` and :code:`delta`: the coefficient in the PDE
        - :code:`Theta`:           the SPD tensor for anisotropic diffusion of the PDE
        - :code:`mean`:            the prior mean
        """
        assert delta != 0., "Intrinsic Gaussian Prior are not supported"
        self.Vh = Vh

        trial = dl.TrialFunction(Vh)
        test = dl.TestFunction(Vh)

        varfL = ufl.inner(ufl.grad(trial), ufl.grad(test)) * ufl.dx
        varfM = ufl.inner(trial, test) * ufl.dx

        self.M = dl.assemble(varfM)
        self.R = dl.assemble(gamma * varfL + delta * varfM)

        self.Rsolver = PETScKrylovSolver(self.Vh.mesh().mpi_comm(), "cg",
                                         amg_method())
        self.Rsolver.set_operator(self.R)
        self.Rsolver.parameters["maximum_iterations"] = max_iter
        self.Rsolver.parameters["relative_tolerance"] = rel_tol
        self.Rsolver.parameters["error_on_nonconvergence"] = True
        self.Rsolver.parameters["nonzero_initial_guess"] = False

        self.Msolver = PETScKrylovSolver(self.Vh.mesh().mpi_comm(), "cg",
                                         "jacobi")
        self.Msolver.set_operator(self.M)
        self.Msolver.parameters["maximum_iterations"] = max_iter
        self.Msolver.parameters["relative_tolerance"] = rel_tol
        self.Msolver.parameters["error_on_nonconvergence"] = True
        self.Msolver.parameters["nonzero_initial_guess"] = False

        ndim = Vh.mesh().geometry().dim()
        old_qr = dl.parameters["form_compiler"]["quadrature_degree"]
        dl.parameters["form_compiler"]["quadrature_degree"] = -1
        qdegree = 2 * Vh._ufl_element.degree()
        metadata = {"quadrature_degree": qdegree}

        representation_old = dl.parameters["form_compiler"]["representation"]
        dl.parameters["form_compiler"]["representation"] = "quadrature"

        element = ufl.VectorElement("Quadrature",
                                    Vh.mesh().ufl_cell(),
                                    qdegree,
                                    dim=(ndim + 1),
                                    quad_scheme="default")
        Qh = dl.FunctionSpace(Vh.mesh(), element)

        ph = dl.TrialFunction(Qh)
        qh = dl.TestFunction(Qh)

        pph = ufl.split(ph)

        Mqh = dl.assemble(ufl.inner(ph, qh) * ufl.dx(metadata=metadata))
        ones = dl.Vector(self.R.mpi_comm())
        Mqh.init_vector(ones, 0)
        ones.set_local(
            np.ones(ones.get_local().shape, dtype=ones.get_local().dtype))
        dMqh = Mqh * ones
        dMqh.set_local(ones.get_local() / np.sqrt(dMqh.get_local()))
        Mqh.zero()
        Mqh.set_diagonal(dMqh)

        sqrtdelta = math.sqrt(delta)
        sqrtgamma = math.sqrt(gamma)
        varfGG = sqrtdelta * pph[0] * test * ufl.dx(metadata=metadata)
        for i in range(ndim):
            varfGG = varfGG + sqrtgamma * pph[i + 1] * test.dx(i) * ufl.dx(
                metadata=metadata)

        GG = dl.assemble(varfGG)
        self.sqrtR = MatMatMult(GG, Mqh)

        dl.parameters["form_compiler"]["quadrature_degree"] = old_qr
        dl.parameters["form_compiler"]["representation"] = representation_old

        self.mean = mean

        if self.mean is None:
            self.mean = dl.Vector(self.R.mpi_comm())
            self.init_vector(self.mean, 0)
示例#28
0
def galerkin_method(mesh):
	# Mesh and function spaces
	h = mesh.hmin()

	V = VectorElement("Lagrange", triangle, 1)
	P = FiniteElement("Lagrange", triangle, 1)
	VP = MixedElement([V,P])
	W = FunctionSpace(mesh, VP)

	# Define Boundaries and Boundary Condictions
	inflow = 'near(x[0],0)'
	outflow = 'near(x[0], 2.2)'
	walls = 'near(x[1], 0) || near(x[1], 0.41)'
	cylinder = 'on_boundary && x[0]>0.1 && x[0]<0.3 && x[1]>0.1 && x[1]<0.3'

	#inflow_profile = Expression(('4.0*1.5*x[1]*(0.41 - x[1])*sin(3.1415*t/8) / pow(0.41, 4)', '0'), t=0.0, degree=4)
	inflow_profile2 = Expression(('4.0*x[1]*(0.41 - x[1])*1.5*sin(3.14*t/8) / pow(0.41, 2)', '0'), t=0.0, degree=2)

	bcu_inflow = DirichletBC(W.sub(0), inflow_profile2, inflow)
	bcu_walls = DirichletBC(W.sub(0), Constant((0, 0)), walls)
	bcu_cylinder = DirichletBC(W.sub(0), Constant((0, 0)), cylinder)
	bcp_outflow = DirichletBC(W.sub(1), Constant(0), outflow)
	bcs = [bcu_inflow, bcu_walls, bcu_cylinder, bcp_outflow]

	#Trial and test functions
	vp = TrialFunction(W)
	u, p = ufl.split(vp)
	#u, p = TrialFunctions(W)
	w, q = TestFunctions(W)

	#Functions
	v0 = Constant((0.,0.))
	vp1 = Function(W)
	u1, p1 = vp1.split()
	un = interpolate(v0, W.sub(0).collapse())

	#Stress tensor
	def epsilon(v):
		return sym(nabla_grad(v))

	def sigma(v,p,nu):
		return 2*nu*epsilon(v)-p*Identity(len(v))

	#Parameters
	dt = 0.2*h/10.
	idt = 1./dt
	t_end = 0.8
	nu = 1/1000
	f = Constant((0.,0.))
	n = FacetNormal(mesh)
	rho = 1.
	print('dt: ', dt)
	print('\n\nNum iteracoes: ', int(t_end/dt))

	#Standard Galerkin
	F = (1.0/dt)*inner(u-un,w)*dx + inner(dot(u1,nabla_grad(u)),w)*dx + inner(sigma(u,p,nu),epsilon(w))*dx + q*div(u)*dx - inner(f,w)*dx + inner(p*n,w)*ds - nu*inner(w,grad(u).T*n)*ds

	##########STABILIZATION#############
	h = 2.0*Circumradius(mesh)
	unorm = sqrt(dot(u1, u1))

	#Residuo momento
	R = (1.0/dt)*(u-un)+dot(u1,nabla_grad(u))-div(sigma(u,p,nu)) + nabla_grad(p)

	#PSPG
	tau_pspg = (h*h)/2.
	F_pspg = tau_pspg*inner(R,nabla_grad(q))*dx

	#SUPG
	tau_supg = ((2.0*idt)**2 + (2.0*u/h)**2 + 9.0*(4.0*nu/h**2)**2 )**(-0.5)
	F_supg = tau_supg*inner(R,dot(u1,nabla_grad(w)))*dx

	#LSIC
	tau_lsic = 0.5*unorm*h
	F_lsic = inner(div(u),div(w))*tau_lsic*dx

	F_est = F + F_pspg + F_supg + F_lsic
	#F_est = F + F_pspg + F_supg

	# define Jacobian
	F1 = action(F_est,vp1)
	J = derivative(F1, vp1,vp)

	#solution parameters
	tolr = 'relative_tolerance'
	tola = 'absolute_tolerance'
	ln = 'linear_solver'
	ns = 'newton_solver'
	prec = 'preconditioner'
	ks = 'krylov_solver'
	mi = 'maximum_iterations'
	enon = 'error_on_nonconvergence'

	linear = {tolr: 1.0E-8, tola: 1.0E-6, mi: 10000, enon: False}
	nonlinear = {tolr: 1.0E-4, tola: 1.0E-4, ln:'gmres', mi:20, ln:'gmres', prec:'ilu', enon: False, ks: linear}
	par = {ns: nonlinear}

	# Time-stepping
	t = 0

	inicio = time.time()
	while t < t_end:
		inflow_profile2.t = t*10
		print ("t = ", t)
		# Compute
		#begin("Solving ....")
		solve(F1 == 0, vp1, bcs=bcs, J=J, solver_parameters = par)
		#end()
		# Extract solutions:
		(u1, p1) = vp1.split(True)
		
		# Move to next time step
		un.assign(u1)
		t += dt
	fim = time.time()

	tempo = fim-inicio

	return u1, p1, tempo
示例#29
0
def test_matrix_assembly_block():
    """Test assembly of block matrices and vectors into (a) monolithic
    blocked structures, PETSc Nest structures, and monolithic structures
    in the nonlinear setting
    """
    mesh = dolfinx.generation.UnitSquareMesh(dolfinx.MPI.comm_world, 4, 8)

    p0, p1 = 1, 2
    P0 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p0)
    P1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p1)

    V0 = dolfinx.function.FunctionSpace(mesh, P0)
    V1 = dolfinx.function.FunctionSpace(mesh, P1)

    def boundary(x):
        return numpy.logical_or(x[0] < 1.0e-6, x[0] > 1.0 - 1.0e-6)

    def initial_guess_u(x):
        return numpy.sin(x[0]) * numpy.sin(x[1])

    def initial_guess_p(x):
        return -x[0]**2 - x[1]**3

    def bc_value(x):
        return numpy.cos(x[0]) * numpy.cos(x[1])

    facetdim = mesh.topology.dim - 1
    mf = dolfinx.MeshFunction("size_t", mesh, facetdim, 0)
    mf.mark(boundary, 1)
    bndry_facets = numpy.where(mf.values == 1)[0]

    u_bc = dolfinx.function.Function(V1)
    u_bc.interpolate(bc_value)
    bdofs = dolfinx.fem.locate_dofs_topological(V1, facetdim, bndry_facets)
    bc = dolfinx.fem.dirichletbc.DirichletBC(u_bc, bdofs)

    # Define variational problem
    du, dp = ufl.TrialFunction(V0), ufl.TrialFunction(V1)
    u, p = dolfinx.function.Function(V0), dolfinx.function.Function(V1)
    v, q = ufl.TestFunction(V0), ufl.TestFunction(V1)

    u.interpolate(initial_guess_u)
    p.interpolate(initial_guess_p)

    f = 1.0
    g = -3.0

    F0 = inner(u, v) * dx + inner(p, v) * dx - inner(f, v) * dx
    F1 = inner(u, q) * dx + inner(p, q) * dx - inner(g, q) * dx

    a_block = [[derivative(F0, u, du),
                derivative(F0, p, dp)],
               [derivative(F1, u, du),
                derivative(F1, p, dp)]]
    L_block = [F0, F1]

    # Monolithic blocked
    x0 = dolfinx.fem.create_vector_block(L_block)
    dolfinx.cpp.la.scatter_local_vectors(
        x0, [u.vector.array_r, p.vector.array_r],
        [u.function_space.dofmap.index_map, p.function_space.dofmap.index_map])
    x0.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                   mode=PETSc.ScatterMode.FORWARD)

    # Ghosts are updated inside assemble_vector_block
    A0 = dolfinx.fem.assemble_matrix_block(a_block, [bc])
    b0 = dolfinx.fem.assemble_vector_block(L_block,
                                           a_block, [bc],
                                           x0=x0,
                                           scale=-1.0)
    A0.assemble()
    assert A0.getType() != "nest"
    Anorm0 = A0.norm()
    bnorm0 = b0.norm()

    # Nested (MatNest)
    x1 = dolfinx.fem.create_vector_nest(L_block)
    for x1_soln_pair in zip(x1.getNestSubVecs(), (u, p)):
        x1_sub, soln_sub = x1_soln_pair
        soln_sub.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                                    mode=PETSc.ScatterMode.FORWARD)
        soln_sub.vector.copy(result=x1_sub)
        x1_sub.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                           mode=PETSc.ScatterMode.FORWARD)

    A1 = dolfinx.fem.assemble_matrix_nest(a_block, [bc])
    b1 = dolfinx.fem.assemble_vector_nest(L_block)
    dolfinx.fem.apply_lifting_nest(b1, a_block, [bc], x1, scale=-1.0)
    for b_sub in b1.getNestSubVecs():
        b_sub.ghostUpdate(addv=PETSc.InsertMode.ADD,
                          mode=PETSc.ScatterMode.REVERSE)
    bcs0 = dolfinx.cpp.fem.bcs_rows(
        dolfinx.fem.assemble._create_cpp_form(L_block), [bc])
    dolfinx.fem.set_bc_nest(b1, bcs0, x1, scale=-1.0)
    A1.assemble()

    assert A1.getType() == "nest"
    assert nest_matrix_norm(A1) == pytest.approx(Anorm0, 1.0e-12)
    assert b1.norm() == pytest.approx(bnorm0, 1.0e-12)

    # Monolithic version
    E = P0 * P1
    W = dolfinx.function.FunctionSpace(mesh, E)
    dU = ufl.TrialFunction(W)
    U = dolfinx.function.Function(W)
    u0, u1 = ufl.split(U)
    v0, v1 = ufl.TestFunctions(W)

    U.interpolate(lambda x: numpy.row_stack(
        (initial_guess_u(x), initial_guess_p(x))))

    F = inner(u0, v0) * dx + inner(u1, v0) * dx + inner(u0, v1) * dx + inner(u1, v1) * dx \
        - inner(f, v0) * ufl.dx - inner(g, v1) * dx
    J = derivative(F, U, dU)

    bdofsW_V1 = dolfinx.fem.locate_dofs_topological((W.sub(1), V1), facetdim,
                                                    bndry_facets)

    bc = dolfinx.fem.dirichletbc.DirichletBC(u_bc, bdofsW_V1, W.sub(1))
    A2 = dolfinx.fem.assemble_matrix(J, [bc])
    A2.assemble()
    b2 = dolfinx.fem.assemble_vector(F)
    dolfinx.fem.apply_lifting(b2, [J], bcs=[[bc]], x0=[U.vector], scale=-1.0)
    b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    dolfinx.fem.set_bc(b2, [bc], x0=U.vector, scale=-1.0)
    assert A2.getType() != "nest"
    assert A2.norm() == pytest.approx(Anorm0, 1.0e-12)
    assert b2.norm() == pytest.approx(bnorm0, 1.0e-12)
示例#30
0
I = Identity(3)  # the identity matrix
F = I + grad(u)  # the deformation gradient
F = variable(F)
J = variable(det(F))  # dF
mat = GuccioneMaterial(e1=fibers[0],
                       e2=fibers[1],
                       e3=fibers[2],
                       kappa=1e3,
                       Tactive=0.0)
psi = mat.strain_energy(F)  #guccione hyperelastic material energy function

# Postprocecing velocity
v = Function(W)
#(v0, v1, v2) = ufl.split(v)
#(v0, v1, v2, v3) = ufl.split(v)
(v0, v1, v2, v3, v4, v5) = ufl.split(v)

# Reaction (not working yet)
epsilon = 0.1
c = Function(P.sub(1).collapse())
c_n = Function(P.sub(1).collapse())
s = TestFunction(P.sub(1).collapse())

#BCs for reaction
bc_react_epi = DirichletBC(P.sub(1), Constant(1), boundary_markers, 40)
bc_react_endo = DirichletBC(P.sub(1), Constant(0), boundary_markers, 30)
bcs_react = [bc_react_epi, bc_react_endo]

#Define storage file
u_file = XDMFFile("contraction/u.xdmf")
p0_file = XDMFFile("results_" + str(N) + "/p0.xdmf")
示例#31
0
def test_assembly_solve_block():
    """Solve a two-field nonlinear diffusion like problem with block matrix
    approaches and test that solution is the same.
    """
    mesh = dolfinx.generation.UnitSquareMesh(dolfinx.MPI.comm_world, 12, 11)
    p = 1
    P = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p)
    V0 = dolfinx.function.FunctionSpace(mesh, P)
    V1 = V0.clone()

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

    def bc_val_1(x):
        return numpy.sin(x[0]) * numpy.cos(x[1])

    def initial_guess_u(x):
        return numpy.sin(x[0]) * numpy.sin(x[1])

    def initial_guess_p(x):
        return -x[0]**2 - x[1]**3

    def boundary(x):
        return numpy.logical_or(x[0] < 1.0e-6, x[0] > 1.0 - 1.0e-6)

    facetdim = mesh.topology.dim - 1
    mf = dolfinx.MeshFunction("size_t", mesh, facetdim, 0)
    mf.mark(boundary, 1)
    bndry_facets = numpy.where(mf.values == 1)[0]

    u_bc0 = dolfinx.function.Function(V0)
    u_bc0.interpolate(bc_val_0)
    u_bc1 = dolfinx.function.Function(V1)
    u_bc1.interpolate(bc_val_1)

    bdofs0 = dolfinx.fem.locate_dofs_topological(V0, facetdim, bndry_facets)
    bdofs1 = dolfinx.fem.locate_dofs_topological(V1, facetdim, bndry_facets)

    bcs = [
        dolfinx.fem.dirichletbc.DirichletBC(u_bc0, bdofs0),
        dolfinx.fem.dirichletbc.DirichletBC(u_bc1, bdofs1)
    ]

    # Block and Nest variational problem
    u, p = dolfinx.function.Function(V0), dolfinx.function.Function(V1)
    du, dp = ufl.TrialFunction(V0), ufl.TrialFunction(V1)
    v, q = ufl.TestFunction(V0), ufl.TestFunction(V1)

    f = 1.0
    g = -3.0

    F = [
        inner((u**2 + 1) * ufl.grad(u), ufl.grad(v)) * dx - inner(f, v) * dx,
        inner((p**2 + 1) * ufl.grad(p), ufl.grad(q)) * dx - inner(g, q) * dx
    ]

    J = [[derivative(F[0], u, du),
          derivative(F[0], p, dp)],
         [derivative(F[1], u, du),
          derivative(F[1], p, dp)]]

    # -- Blocked version
    Jmat0 = dolfinx.fem.create_matrix_block(J)
    Fvec0 = dolfinx.fem.create_vector_block(F)

    snes = PETSc.SNES().create(dolfinx.MPI.comm_world)
    snes.setTolerances(rtol=1.0e-15, max_it=10)

    snes.getKSP().setType("preonly")
    snes.getKSP().getPC().setType("lu")
    snes.getKSP().getPC().setFactorSolverType("mumps")

    problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs)
    snes.setFunction(problem.F_block, Fvec0)
    snes.setJacobian(problem.J_block, J=Jmat0, P=None)

    u.interpolate(initial_guess_u)
    p.interpolate(initial_guess_p)

    x0 = dolfinx.fem.create_vector_block(F)
    dolfinx.cpp.la.scatter_local_vectors(
        x0, [u.vector.array_r, p.vector.array_r],
        [u.function_space.dofmap.index_map, p.function_space.dofmap.index_map])
    x0.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                   mode=PETSc.ScatterMode.FORWARD)

    snes.solve(None, x0)

    assert snes.getKSP().getConvergedReason() > 0
    assert snes.getConvergedReason() > 0

    J0norm = Jmat0.norm()
    F0norm = Fvec0.norm()
    x0norm = x0.norm()

    # -- Nested (MatNest)
    Jmat1 = dolfinx.fem.create_matrix_nest(J)
    Fvec1 = dolfinx.fem.create_vector_nest(F)

    snes = PETSc.SNES().create(dolfinx.MPI.comm_world)
    snes.setTolerances(rtol=1.0e-15, max_it=10)

    nested_IS = Jmat1.getNestISs()

    snes.getKSP().setType("fgmres")
    snes.getKSP().setTolerances(rtol=1e-12)
    snes.getKSP().getPC().setType("fieldsplit")
    snes.getKSP().getPC().setFieldSplitIS(["u", nested_IS[0][0]],
                                          ["p", nested_IS[1][1]])

    ksp_u, ksp_p = snes.getKSP().getPC().getFieldSplitSubKSP()
    ksp_u.setType("preonly")
    ksp_u.getPC().setType('lu')
    ksp_u.getPC().setFactorSolverType('mumps')
    ksp_p.setType("preonly")
    ksp_p.getPC().setType('lu')
    ksp_p.getPC().setFactorSolverType('mumps')

    problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs)
    snes.setFunction(problem.F_nest, Fvec1)
    snes.setJacobian(problem.J_nest, J=Jmat1, P=None)

    u.interpolate(initial_guess_u)
    p.interpolate(initial_guess_p)

    x1 = dolfinx.fem.create_vector_nest(F)
    for x1_soln_pair in zip(x1.getNestSubVecs(), (u, p)):
        x1_sub, soln_sub = x1_soln_pair
        soln_sub.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                                    mode=PETSc.ScatterMode.FORWARD)
        soln_sub.vector.copy(result=x1_sub)
        x1_sub.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                           mode=PETSc.ScatterMode.FORWARD)

    snes.solve(None, x1)

    assert snes.getKSP().getConvergedReason() > 0
    assert snes.getConvergedReason() > 0
    assert x1.getType() == "nest"
    assert Jmat1.getType() == "nest"
    assert Fvec1.getType() == "nest"

    J1norm = nest_matrix_norm(Jmat1)
    F1norm = Fvec1.norm()
    x1norm = x1.norm()

    assert J1norm == pytest.approx(J0norm, 1.0e-12)
    assert F1norm == pytest.approx(F0norm, 1.0e-12)
    assert x1norm == pytest.approx(x0norm, 1.0e-12)

    # -- Monolithic version
    E = P * P
    W = dolfinx.function.FunctionSpace(mesh, E)
    U = dolfinx.function.Function(W)
    dU = ufl.TrialFunction(W)
    u0, u1 = ufl.split(U)
    v0, v1 = ufl.TestFunctions(W)

    F = inner((u0**2 + 1) * ufl.grad(u0), ufl.grad(v0)) * dx \
        + inner((u1**2 + 1) * ufl.grad(u1), ufl.grad(v1)) * dx \
        - inner(f, v0) * ufl.dx - inner(g, v1) * dx
    J = derivative(F, U, dU)

    u0_bc = dolfinx.function.Function(V0)
    u0_bc.interpolate(bc_val_0)
    u1_bc = dolfinx.function.Function(V1)
    u1_bc.interpolate(bc_val_1)

    bdofsW0_V0 = dolfinx.fem.locate_dofs_topological((W.sub(0), V0), facetdim,
                                                     bndry_facets)
    bdofsW1_V1 = dolfinx.fem.locate_dofs_topological((W.sub(1), V1), facetdim,
                                                     bndry_facets)

    bcs = [
        dolfinx.fem.dirichletbc.DirichletBC(u0_bc, bdofsW0_V0, W.sub(0)),
        dolfinx.fem.dirichletbc.DirichletBC(u1_bc, bdofsW1_V1, W.sub(1))
    ]

    Jmat2 = dolfinx.fem.create_matrix(J)
    Fvec2 = dolfinx.fem.create_vector(F)

    snes = PETSc.SNES().create(dolfinx.MPI.comm_world)
    snes.setTolerances(rtol=1.0e-15, max_it=10)

    snes.getKSP().setType("preonly")
    snes.getKSP().getPC().setType("lu")
    snes.getKSP().getPC().setFactorSolverType("mumps")

    problem = NonlinearPDE_SNESProblem(F, J, U, bcs)
    snes.setFunction(problem.F_mono, Fvec2)
    snes.setJacobian(problem.J_mono, J=Jmat2, P=None)

    U.interpolate(lambda x: numpy.row_stack(
        (initial_guess_u(x), initial_guess_p(x))))

    x2 = dolfinx.fem.create_vector(F)
    x2.array = U.vector.array_r

    snes.solve(None, x2)

    assert snes.getKSP().getConvergedReason() > 0
    assert snes.getConvergedReason() > 0

    J2norm = Jmat2.norm()
    F2norm = Fvec2.norm()
    x2norm = x2.norm()

    assert J2norm == pytest.approx(J0norm, 1.0e-12)
    assert F2norm == pytest.approx(F0norm, 1.0e-12)
    assert x2norm == pytest.approx(x0norm, 1.0e-12)
示例#32
0
#
# For the test functions,
# :py:func:`TestFunctions<function ufl.argument.TestFunctions>` (note
# the 's' at the end) is used to define the scalar test functions ``q``
# and ``v``.
# Some mixed objects of the
# :py:class:`Function<dolfinx.fem.function.Function>` class on ``ME``
# are defined to represent :math:`u = (c_{n+1}, \mu_{n+1})` and :math:`u0
# = (c_{n}, \mu_{n})`, and these are then split into sub-functions::

# Define functions
u = Function(ME)  # current solution
u0 = Function(ME)  # solution from previous converged step

# Split mixed functions
c, mu = split(u)
c0, mu0 = split(u0)

# The line ``c, mu = split(u)`` permits direct access to the components of
# a mixed function. Note that ``c`` and ``mu`` are references for
# components of ``u``, and not copies.
#
# .. index::
#    single: interpolating functions; (in Cahn-Hilliard demo)
#
# The initial conditions are interpolated into a finite element space::

# Zero u
with u.vector.localForm() as x_local:
    x_local.set(0.0)
示例#33
0
# Contraction parameters
I = Identity(3)  # the identity matrix
F = I + grad(u)  # the deformation gradient
F = variable(F)
J = variable(det(F))  # dF
mat = GuccioneMaterial(e1=fibers[0],
                       e2=fibers[1],
                       e3=fibers[2],
                       kappa=1e3,
                       Tactive=0.0)
psi = mat.strain_energy(F)  #guccione hyperelastic material energy function

# Postprocecing velocity
v = Function(W)
(v0, v1, v2) = ufl.split(v)

#Define storage file
u_file = XDMFFile("contraction/u.xdmf")
p0_file = XDMFFile("results_for_K[2]/p0_K" + str(j) + ".xdmf")
p1_file = XDMFFile("results_for_K[2]/p1_K" + str(j) + ".xdmf")
p2_file = XDMFFile("results_for_K[2]/p2_K" + str(j) + ".xdmf")
v0_file = XDMFFile("results_for_K[2]/v0_K" + str(j) + ".xdmf")
v1_file = XDMFFile("results_for_K[2]/v1_K" + str(j) + ".xdmf")
v2_file = XDMFFile("results_for_K[2]/v2_K" + str(j) + ".xdmf")
append = False

# Solve
steps = 20
dt = 1 / steps
t = 0.0
示例#34
0
# For the test functions,
# :py:func:`TestFunctions<dolfin.functions.function.TestFunctions>` (note
# the 's' at the end) is used to define the scalar test functions ``q``
# and ``v``. The
# :py:class:`TrialFunction<dolfin.functions.function.TrialFunction>`
# ``du`` has dimension two. Some mixed objects of the
# :py:class:`Function<dolfin.functions.function.Function>` class on ``ME``
# are defined to represent :math:`u = (c_{n+1}, \mu_{n+1})` and :math:`u0
# = (c_{n}, \mu_{n})`, and these are then split into sub-functions::

# Define functions
u = Function(ME)  # current solution
u0 = Function(ME)  # solution from previous converged step

# Split mixed functions
dc, dmu = split(du)
c, mu = split(u)
c0, mu0 = split(u0)

# The line ``c, mu = split(u)`` permits direct access to the components of
# a mixed function. Note that ``c`` and ``mu`` are references for
# components of ``u``, and not copies.
#
# .. index::
#    single: interpolating functions; (in Cahn-Hilliard demo)
#
# Initial conditions are created by using the evaluate method
# then interpolated into a finite element space::


def u_init(values, x):
示例#35
0
t_end = 0.4

print('dt: ', dt)
print('\n\nNum iteracoes: ', int(t_end / dt))

###############FLUID PROBLEM################

#Fluid parameters
mu_f = 0.04  #Fluid dynamic viscosity
rho_f = 1.06  #Fluid density
nu_f = Constant(mu_f / rho_f)  #Fluid kinematic viscosity
f = Constant((0., 0., 0.))  #Fluid body forces

#Trial and test functions
vp = TrialFunction(W)
v, p = ufl.split(vp)  #v = fluid velocity, p = pressure : Trial Functions!
w, q = TestFunctions(
    W
)  #w = velocity test function (momentum) , q = pressure test function (continuity)

#Functions
v0 = Constant((0., 0., 0.))  #Initial velocity
vp1 = Function(W)  #solution function for rigid problem
v1, p1 = vp1.split(
)  #solution for velocity (v1) e pressure(p1) separeted rigid problem

vn = interpolate(v0,
                 W.sub(0).collapse()
                 )  #Defining initial velocity for previously time step (i=0).

示例#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('solve', 'Running nonlinear solver', 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')

        mesh = self.problem.mesh

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

        # to assign solution in space W.sub(0) to Function(V) we need FunctionAssigner (cannot be assigned directly)
        fa = FunctionAssigner(self.V, self.W.sub(0))
        velSp = Function(self.V)

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

        # Define unknown and test function(s) NS
        v, q = TestFunctions(self.W)
        w = Function(self.W)
        dw = TrialFunction(self.W)
        u, p = split(w)

        # Define fields
        n = FacetNormal(mesh)
        I = Identity(u.geometric_dimension())
        theta = 0.5  # Crank-Nicholson
        k = Constant(self.metadata['dt'])

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

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

        # boundary conditions
        bcu, bcp = problem.get_boundary_conditions(self.bc == 'outflow', self.W.sub(0), self.W.sub(1))
        # NT bcp is not used

        # Define steady part of the equation
        def T(u):
            return -p * I + 2.0 * nu * sym(grad(u))

        def F(u, v, q):
            return (inner(T(u), grad(v)) - q * div(u)) * dx + inner(grad(u) * u, v) * dx

        # Define variational forms
        F_ns = (inner((u - u0), v) / k) * dx + (1.0 - theta) * F(u0, v, q) + theta * F(u, v, q)
        J_ns = derivative(F_ns, w, dw)
        # J_ns = derivative(F_ns, w)  # did not work

        # NS_problem = NonlinearVariationalProblem(F_ns, w, bcu, J_ns, form_compiler_parameters=ffc_options)
        NS_problem = NonlinearVariationalProblem(F_ns, w, bcu, J_ns)
        # (var. formulation, unknown, Dir. BC, jacobian, optional)
        NS_solver = NonlinearVariationalSolver(NS_problem)

        prm = NS_solver.parameters
        prm['newton_solver']['absolute_tolerance'] = 1E-08
        prm['newton_solver']['relative_tolerance'] = 1E-08
        # prm['newton_solver']['maximum_iterations'] = 45
        # prm['newton_solver']['relaxation_parameter'] = 1.0
        prm['newton_solver']['linear_solver'] = 'mumps'

        info(NS_solver.parameters, True)

        self.tc.end('init')

        # Time-stepping
        info("Running of direct method")
        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

            # Compute
            begin("Solving NS ....")
            try:
                self.tc.start('solve')
                NS_solver.solve()
                self.tc.end('solve')
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            end()

            # Extract solutions:
            (u, p) = w.split()
            fa.assign(velSp, u)
            # we are assigning twice (now and inside save_vel), but it works with one method save_vel for direct and
            #   projection (we could split save_vel to save one assign)

            if save_this_step:
                self.tc.start('saveVel')
                problem.save_vel(False, velSp, t)
                self.tc.end('saveVel')
            if save_this_step and not onlyVel:
                problem.save_div(False, u)
            problem.compute_err(False, u, t)
            problem.compute_div(False, u)

            # foo = Function(self.Q)
            # foo.assign(p)
            # problem.averaging_pressure(foo)
            # if save_this_step and not onlyVel:
            #     problem.save_pressure(False, foo)

            if save_this_step and not onlyVel:
                problem.save_pressure(False, p)

            # compute functionals (e. g. forces)
            problem.compute_functionals(u, p, t)

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

        info("Finished: direct method")
        problem.report()
        return 0
示例#37
0
def galerkin_method(mesh):
    # Mesh and function spaces
    h = mesh.hmin()

    V = VectorElement("Lagrange", triangle, 1)
    P = FiniteElement("Lagrange", triangle, 1)
    VP = MixedElement([V, P])
    W = FunctionSpace(mesh, VP)

    # Define Boundaries and Boundary Condictions
    upperedge = 'near(x[1], 1)'
    noslip = 'near(x[1], 0) || near(x[0], 1) || near(x[0], 0)'

    bcu_noslip = DirichletBC(W.sub(0), Constant((0.0, 0.0)), noslip)
    bcu_top = DirichletBC(W.sub(0), Constant((1.0, 0.0)), upperedge)
    bcs = [bcu_noslip, bcu_top]

    #Trial and test functions
    vp = TrialFunction(W)
    u, p = ufl.split(vp)
    w, q = TestFunctions(W)

    #Functions
    v0 = Constant((0., 0.))
    vp1 = Function(W)
    u1, p1 = vp1.split()
    un = interpolate(v0, W.sub(0).collapse())

    #Stress tensor
    def epsilon(v):
        return sym(nabla_grad(v))

    def sigma(v, p, nu):
        return 2 * nu * epsilon(v) - p * Identity(len(v))

    #Parameters
    dt = 0.2 * h / 1.
    idt = 1. / dt
    t_end = 2.5
    nu = 1 / 1000
    f = Constant((0., 0.))
    n = FacetNormal(mesh)
    rho = 1.

    #Standard Galerkin
    F = (1.0 / dt) * inner(u - un, w) * dx + inner(dot(
        u1, nabla_grad(u)), w) * dx + inner(sigma(u, p, nu), epsilon(
            w)) * dx + q * div(u) * dx - inner(f, w) * dx + inner(
                p * n, w) * ds - nu * inner(w,
                                            grad(u).T * n) * ds

    ##########STABILIZATION#############
    h = 2.0 * Circumradius(mesh)
    unorm = sqrt(dot(u1, u1))

    #Residuo momento
    R = (1.0 / dt) * (u - un) + dot(u1, nabla_grad(u)) - div(sigma(
        u, p, nu)) + nabla_grad(p)

    #PSPG
    tau_pspg = (h * h) / 2.
    F_pspg = tau_pspg * inner(R, nabla_grad(q)) * dx

    #SUPG
    tau_supg = ((2.0 * idt)**2 + (2.0 * u / h)**2 + 9.0 *
                (4.0 * nu / h**2)**2)**(-0.5)
    F_supg = tau_supg * inner(R, dot(u1, nabla_grad(w))) * dx

    #LSIC
    tau_lsic = 0.5 * unorm * h
    F_lsic = inner(div(u), div(w)) * tau_lsic * dx

    F_est = F + F_pspg + F_supg + F_lsic
    #F_est = F + F_pspg + F_supg

    # define Jacobian
    F1 = action(F_est, vp1)
    J = derivative(F1, vp1, vp)

    #solution parameters
    tolr = 'relative_tolerance'
    tola = 'absolute_tolerance'
    ln = 'linear_solver'
    ns = 'newton_solver'
    prec = 'preconditioner'
    ks = 'krylov_solver'
    mi = 'maximum_iterations'
    enon = 'error_on_nonconvergence'

    linear = {tolr: 1.0E-6, tola: 1.0E-6, mi: 1000, enon: False}
    nonlinear = {
        tolr: 1.0E-5,
        tola: 1.0E-5,
        ln: 'gmres',
        mi: 3,
        ln: 'gmres',
        prec: 'ilu',
        enon: False,
        ks: linear
    }
    par = {ns: nonlinear}

    # Time-stepping
    t = 0
    # Create files for storing solution
    #ufile = File("Driven_cavity/velocity"+str(n_cells)+".pvd")
    #pfile = File("Driven_cavity/pressure"+str(n_cells)+".pvd")

    inicio = time.time()
    while t < t_end:
        print("t = ", t)
        # Compute
        #begin("Solving ....")
        solve(F1 == 0, vp1, bcs=bcs, J=J, solver_parameters=par)
        #end()
        # Extract solutions:
        (u1, p1) = vp1.split(True)
        # Plot
        #plot(v)
        # Save to file
        #ufile << u1
        #pfile << p1
        # Move to next time step
        un.assign(u1)
        t += dt
        #print('velocity no final: ', np.array(v.vector[0]).mean())
    fim = time.time()

    tempo = fim - inicio

    return u1, p1, tempo