Ejemplo n.º 1
0
def apply_lifting(b: PETSc.Vec,
                  a: typing.List[typing.Union[Form, cpp.fem.Form]],
                  bcs: typing.List[typing.List[DirichletBC]],
                  x0: typing.Optional[typing.List[PETSc.Vec]] = [],
                  scale: float = 1.0) -> None:
    """Modify RHS vector b for lifting of Dirichlet boundary conditions.
    It modifies b such that:

        b <- b - scale * A_j (g_j - x0_j)

    where j is a block (nest) index. For a non-blocked problem j = 0.
    The boundary conditions bcs are on the trial spaces V_j. The forms
    in [a] must have the same test space as L (from which b was built),
    but the trial space may differ. If x0 is not supplied, then it is
    treated as zero.

    Ghost contributions are not accumulated (not sent to owner). Caller
    is responsible for calling VecGhostUpdateBegin/End.
    """
    with contextlib.ExitStack() as stack:
        x0 = [stack.enter_context(x.localForm()) for x in x0]
        x0_r = [x.array_r for x in x0]
        b_local = stack.enter_context(b.localForm())
        cpp.fem.apply_lifting(b_local.array_w, _create_cpp_form(a), bcs, x0_r,
                              scale)
Ejemplo n.º 2
0
    def F(self, snes: PETSc.SNES, x: PETSc.Vec, b: PETSc.Vec):
        """Assemble the residual F into the vector b.

        Parameters
        ==========
        snes: the snes object
        x: Vector containing the latest solution.
        b: Vector to assemble the residual into.
        """
        # We need to assign the vector to the function

        x.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                      mode=PETSc.ScatterMode.FORWARD)
        x.copy(self.u.vector)
        self.u.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                                  mode=PETSc.ScatterMode.FORWARD)

        # Zero the residual vector
        # import pdb; pdb.set_trace()
        with b.localForm() as b_local:
            b_local.set(0.0)
        assemble_vector(b, self.F_form)

        # Apply boundary conditions
        apply_lifting(b, [self.J_form], [self.bcs], [x], -1.0)
        b.ghostUpdate(addv=PETSc.InsertMode.ADD,
                      mode=PETSc.ScatterMode.REVERSE)
        set_bc(b, self.bcs, x, -1.0)
Ejemplo n.º 3
0
def assemble_vector(form: ufl.form.Form,
                    constraint: MultiPointConstraint,
                    b: _PETSc.Vec = None) -> _PETSc.Vec:
    """
    Assemble a linear form into vector b with corresponding multi point constraint

    Parameters
    ----------
    form
        The linear form
    constraint
        The multi point constraint
    b
        PETSc vector to assemble into (optional)

    Returns
    -------
    PETSc.Vec
        The assembled linear form
    """

    if b is None:
        b = _cpp.la.petsc.create_vector(
            constraint.function_space.dofmap.index_map,
            constraint.function_space.dofmap.index_map_bs)
    t = Timer("~MPC: Assemble vector (C++)")
    with b.localForm() as b_local:
        b_local.set(0.0)
        dolfinx_mpc.cpp.mpc.assemble_vector(b_local, form,
                                            constraint._cpp_object)
    t.stop()
    return b
Ejemplo n.º 4
0
def _(b: PETSc.Vec, L: typing.Union[Form, cpp.fem.Form]) -> PETSc.Vec:
    """Assemble linear form into an existing PETSc vector. The vector is not
    zeroed before assembly and it is not finalised, qi.e. ghost values are
    not accumulated on the owning processes.

    """
    with b.localForm() as b_local:
        cpp.fem.assemble_vector(b_local.array_w, _create_cpp_form(L))
    return b
Ejemplo n.º 5
0
def _(b: PETSc.Vec, L: FormMetaClass, coeffs=Coefficients(None,
                                                          None)) -> PETSc.Vec:
    """Assemble linear form into an existing PETSc vector. The vector is
    not zeroed before assembly and it is not finalised, i.e. ghost
    values are not accumulated on the owning processes.

    """
    c = (coeffs[0] if coeffs[0] is not None else pack_constants(L),
         coeffs[1] if coeffs[1] is not None else pack_coefficients(L))
    with b.localForm() as b_local:
        _cpp.fem.assemble_vector(b_local.array_w, L, c[0], c[1])
    return b
    def F(self, x: PETSc.Vec, F: PETSc.Vec):
        with F.localForm() as F_local:
            F_local.set(0.0)
        dolfinx_mpc.assemble_vector(self._L, self.mpc, b=F)

        # Apply boundary condition
        dolfinx_mpc.apply_lifting(F, [self._a],
                                  bcs=[self.bcs],
                                  constraint=self.mpc,
                                  x0=[x],
                                  scale=-1.0)
        F.ghostUpdate(addv=PETSc.InsertMode.ADD,
                      mode=PETSc.ScatterMode.REVERSE)
        dolfinx.fem.petsc.set_bc(F, self.bcs, x, -1.0)
Ejemplo n.º 7
0
def _(b: PETSc.Vec, L: typing.Union[Form, cpp.fem.Form]) -> PETSc.Vec:
    """Assemble linear form into an existing vector.

    The vector must already have the correct size and parallel layout
    and wll be zeroed. The returned vector is finalised, i.e. ghost
    values accumulated across MPI processes.

    """
    L_cpp = _create_cpp_form(L)
    with b.localForm() as b_local:
        b_local.set(0.0)
    cpp.fem.assemble_vector(b, L_cpp)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    return b
Ejemplo n.º 8
0
def apply_lifting(b: PETSc.Vec,
                  a: typing.List[FormMetaClass],
                  bcs: typing.List[typing.List[DirichletBCMetaClass]],
                  x0: typing.Optional[typing.List[PETSc.Vec]] = [],
                  scale: float = 1.0,
                  constants=None,
                  coeffs=None) -> None:
    """Apply the function :func:`dolfinx.fem.apply_lifting` to a PETSc Vector."""
    with contextlib.ExitStack() as stack:
        x0 = [stack.enter_context(x.localForm()) for x in x0]
        x0_r = [x.array_r for x in x0]
        b_local = stack.enter_context(b.localForm())
        assemble.apply_lifting(b_local.array_w, a, bcs, x0_r, scale, constants,
                               coeffs)
Ejemplo n.º 9
0
    def homogenize(self, vector: _PETSc.Vec) -> None:
        """
        For a vector, homogenize (set to zero) the vector components at
        the multi-point constraint slave DoF indices. This is particularly useful
        for nonlinear problems.

        Parameters
        ----------
        vector
            The input vector
        """
        with vector.localForm() as vector_local:
            self._cpp_object.homogenize(vector_local.array_w)
        vector.ghostUpdate(addv=_PETSc.InsertMode.INSERT, mode=_PETSc.ScatterMode.FORWARD)
Ejemplo n.º 10
0
    def backsubstitution(self, vector: _PETSc.Vec) -> None:
        """
        For a vector, impose the multi-point constraint by backsubstiution.
        This function is used after solving the reduced problem to obtain the values
        at the slave degrees of freedom

        Parameters
        ----------
        vector
            The input vector
        """
        # Unravel data from constraint
        with vector.localForm() as vector_local:
            self._cpp_object.backsubstitution(vector_local.array_w)
        vector.ghostUpdate(addv=_PETSc.InsertMode.INSERT, mode=_PETSc.ScatterMode.FORWARD)
Ejemplo n.º 11
0
 def F(self, x: PETSc.Vec, b: PETSc.Vec):
     """Assemble the residual F into the vector b.
     Parameters
     ----------
     x
         The vector containing the latest solution
     b
         Vector to assemble the residual into
     """
     # Reset the residual vector
     with b.localForm() as b_local:
         b_local.set(0.0)
     fem.assemble_vector(b, self._L)
     # Apply boundary condition
     fem.apply_lifting(b, [self._a], [self.bcs], [x], -1.0)
     b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
     fem.set_bc(b, self.bcs, x, -1.0)
Ejemplo n.º 12
0
def apply_lifting(b: _PETSc.Vec,
                  form: List[_fem.FormMetaClass],
                  bcs: List[List[_fem.DirichletBCMetaClass]],
                  constraint: MultiPointConstraint,
                  x0: List[_PETSc.Vec] = [],
                  scale: float = 1.0):
    """
    Apply lifting to vector b, i.e.

    .. math::
        b <- b - scale * K^T (A_j (g_j - x0_j))

    Parameters
    ----------
    b
        PETSc vector to assemble into
    form
        The linear form
    bcs
        List of Dirichlet boundary conditions
    constraint
        The multi point constraint
    x0
        List of vectors
    scale
        Scaling for lifting

    Returns
    -------
    PETSc.Vec
        The assembled linear form
    """
    t = Timer("~MPC: Apply lifting (C++)")
    with contextlib.ExitStack() as stack:
        x0 = [stack.enter_context(x.localForm()) for x in x0]
        x0_r = [x.array_r for x in x0]
        b_local = stack.enter_context(b.localForm())
        dolfinx_mpc.cpp.mpc.apply_lifting(b_local.array_w, form, bcs, x0_r,
                                          scale, constraint._cpp_object)
    t.stop()
Ejemplo n.º 13
0
def _(b: PETSc.Vec,
      L: FormMetaClass,
      constants=None,
      coeffs=None) -> PETSc.Vec:
    """Assemble linear form into an existing PETSc vector.

    Note:
        The vector is not zeroed before assembly and it is not
        finalised, i.e. ghost values are not accumulated on the owning
        processes.

    Args:
        b: Vector to assemble the contribution of the linear form into.
        L: A linear form to assemble into `b`.

    Returns:
        An assembled vector.

    """
    with b.localForm() as b_local:
        assemble.assemble_vector(b_local.array_w, L, constants, coeffs)
    return b