Пример #1
0
    def __init__(self,
                 F,
                 u,
                 bcs=None,
                 J=None,
                 Jp=None,
                 form_compiler_parameters=None):
        """
        :param F: the nonlinear form
        :param u: the :class:`.Function` to solve for
        :param bcs: the boundary conditions (optional)
        :param J: the Jacobian J = dF/du (optional)
        :param Jp: a form used for preconditioning the linear system,
                 optional, if not supplied then the Jacobian itself
                 will be used.
        :param dict form_compiler_parameters: parameters to pass to the form
            compiler (optional)
        """
        from firedrake import solving
        from firedrake import function

        # Store input UFL forms and solution Function
        self.F = F
        self.Jp = Jp
        self.u = u
        self.bcs = solving._extract_bcs(bcs)

        # Argument checking
        if not isinstance(self.F, ufl.Form):
            raise TypeError("Provided residual is a '%s', not a Form" %
                            type(self.F).__name__)
        if len(self.F.arguments()) != 1:
            raise ValueError("Provided residual is not a linear form")
        if not isinstance(self.u, function.Function):
            raise TypeError("Provided solution is a '%s', not a Function" %
                            type(self.u).__name__)

        # Use the user-provided Jacobian. If none is provided, derive
        # the Jacobian from the residual.
        self.J = J or ufl_expr.derivative(F, u)

        if not isinstance(self.J, ufl.Form):
            raise TypeError("Provided Jacobian is a '%s', not a Form" %
                            type(self.J).__name__)
        if len(self.J.arguments()) != 2:
            raise ValueError("Provided Jacobian is not a bilinear form")
        if self.Jp is not None and not isinstance(self.Jp, ufl.Form):
            raise TypeError("Provided preconditioner is a '%s', not a Form" %
                            type(self.Jp).__name__)
        if self.Jp is not None and len(self.Jp.arguments()) != 2:
            raise ValueError("Provided preconditioner is not a bilinear form")

        # Store form compiler parameters
        self.form_compiler_parameters = form_compiler_parameters
        self._constant_jacobian = False
Пример #2
0
    def __init__(self, F, u, bcs=None, J=None,
                 Jp=None,
                 form_compiler_parameters=None,
                 nest=None):
        """
        :param F: the nonlinear form
        :param u: the :class:`.Function` to solve for
        :param bcs: the boundary conditions (optional)
        :param J: the Jacobian J = dF/du (optional)
        :param Jp: a form used for preconditioning the linear system,
                 optional, if not supplied then the Jacobian itself
                 will be used.
        :param dict form_compiler_parameters: parameters to pass to the form
            compiler (optional)
        :param nest: indicate if matrices on mixed spaces should be
               built as monolithic operators (suitable for direct
               solves), or as nested blocks (suitable for fieldsplit
               preconditioning).  If not provided, uses the default
               given by ``parameters["matnest"]``.
        """
        from firedrake import solving
        from firedrake import function

        # Store input UFL forms and solution Function
        self.F = F
        self.Jp = Jp
        self.u = u
        self.bcs = solving._extract_bcs(bcs)

        # Argument checking
        if not isinstance(self.F, ufl.Form):
            raise TypeError("Provided residual is a '%s', not a Form" % type(self.F).__name__)
        if len(self.F.arguments()) != 1:
            raise ValueError("Provided residual is not a linear form")
        if not isinstance(self.u, function.Function):
            raise TypeError("Provided solution is a '%s', not a Function" % type(self.u).__name__)

        # Use the user-provided Jacobian. If none is provided, derive
        # the Jacobian from the residual.
        self.J = J or ufl_expr.derivative(F, u)

        if not isinstance(self.J, ufl.Form):
            raise TypeError("Provided Jacobian is a '%s', not a Form" % type(self.J).__name__)
        if len(self.J.arguments()) != 2:
            raise ValueError("Provided Jacobian is not a bilinear form")
        if self.Jp is not None and not isinstance(self.Jp, ufl.Form):
            raise TypeError("Provided preconditioner is a '%s', not a Form" % type(self.Jp).__name__)
        if self.Jp is not None and len(self.Jp.arguments()) != 2:
            raise ValueError("Provided preconditioner is not a bilinear form")

        self._nest = nest
        # Store form compiler parameters
        self.form_compiler_parameters = form_compiler_parameters
        self._constant_jacobian = False
Пример #3
0
    def __init__(self, *args, bcs=None, J=None, Jp=None, method="topological", V=None, is_linear=False, Jp_eq_J=False):
        from firedrake.variational_solver import check_pde_args, is_form_consistent
        if isinstance(args[0], ufl.classes.Equation):
            # initial construction from equation
            eq = args[0]
            u = args[1]
            sub_domain = args[2]
            if V is None:
                V = eq.lhs.arguments()[0].function_space()
            bcs = solving._extract_bcs(bcs)
            # Jp_eq_J is progressively evaluated as the tree is constructed
            self.Jp_eq_J = Jp is None and all([bc.Jp_eq_J for bc in bcs])

            # linear
            if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form):
                J = eq.lhs
                Jp = Jp or J
                if eq.rhs == 0:
                    F = ufl_expr.action(J, u)
                else:
                    if not isinstance(eq.rhs, (ufl.Form, slate.slate.TensorBase)):
                        raise TypeError("Provided BC RHS is a '%s', not a Form or Slate Tensor" % type(eq.rhs).__name__)
                    if len(eq.rhs.arguments()) != 1:
                        raise ValueError("Provided BC RHS is not a linear form")
                    F = ufl_expr.action(J, u) - eq.rhs
                self.is_linear = True
            # nonlinear
            else:
                if eq.rhs != 0:
                    raise TypeError("RHS of a nonlinear form equation has to be 0")
                F = eq.lhs
                J = J or ufl_expr.derivative(F, u)
                Jp = Jp or J
                self.is_linear = False
            # Check form style consistency
            is_form_consistent(self.is_linear, bcs)
            # Argument checking
            check_pde_args(F, J, Jp)
            # EquationBCSplit objects for `F`, `J`, and `Jp`
            self._F = EquationBCSplit(F, u, sub_domain, bcs=[bc if isinstance(bc, DirichletBC) else bc._F for bc in bcs], method=method, V=V)
            self._J = EquationBCSplit(J, u, sub_domain, bcs=[bc if isinstance(bc, DirichletBC) else bc._J for bc in bcs], method=method, V=V)
            self._Jp = EquationBCSplit(Jp, u, sub_domain, bcs=[bc if isinstance(bc, DirichletBC) else bc._Jp for bc in bcs], method=method, V=V)
        elif all(isinstance(args[i], EquationBCSplit) for i in range(3)):
            # reconstruction for splitting `solving_utils.split`
            self.Jp_eq_J = Jp_eq_J
            self.is_linear = is_linear
            self._F = args[0]
            self._J = args[1]
            self._Jp = args[2]
        else:
            raise TypeError("Wrong EquationBC arguments")
Пример #4
0
    def __init__(self, *args, bcs=None, J=None, Jp=None, method="topological", V=None, is_linear=False, Jp_eq_J=False):
        from firedrake.variational_solver import check_pde_args, is_form_consistent
        if isinstance(args[0], ufl.classes.Equation):
            # initial construction from equation
            eq = args[0]
            u = args[1]
            sub_domain = args[2]
            if V is None:
                V = eq.lhs.arguments()[0].function_space()
            bcs = solving._extract_bcs(bcs)
            # Jp_eq_J is progressively evaluated as the tree is constructed
            self.Jp_eq_J = Jp is None and all([bc.Jp_eq_J for bc in bcs])

            # linear
            if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form):
                J = eq.lhs
                Jp = Jp or J
                if eq.rhs == 0:
                    F = ufl_expr.action(J, u)
                else:
                    if not isinstance(eq.rhs, (ufl.Form, slate.slate.TensorBase)):
                        raise TypeError("Provided BC RHS is a '%s', not a Form or Slate Tensor" % type(eq.rhs).__name__)
                    if len(eq.rhs.arguments()) != 1:
                        raise ValueError("Provided BC RHS is not a linear form")
                    F = ufl_expr.action(J, u) - eq.rhs
                self.is_linear = True
            # nonlinear
            else:
                if eq.rhs != 0:
                    raise TypeError("RHS of a nonlinear form equation has to be 0")
                F = eq.lhs
                J = J or ufl_expr.derivative(F, u)
                Jp = Jp or J
                self.is_linear = False
            # Check form style consistency
            is_form_consistent(self.is_linear, bcs)
            # Argument checking
            check_pde_args(F, J, Jp)
            # EquationBCSplit objects for `F`, `J`, and `Jp`
            self._F = EquationBCSplit(F, u, sub_domain, bcs=[bc if isinstance(bc, DirichletBC) else bc._F for bc in bcs], method=method, V=V)
            self._J = EquationBCSplit(J, u, sub_domain, bcs=[bc if isinstance(bc, DirichletBC) else bc._J for bc in bcs], method=method, V=V)
            self._Jp = EquationBCSplit(Jp, u, sub_domain, bcs=[bc if isinstance(bc, DirichletBC) else bc._Jp for bc in bcs], method=method, V=V)
        elif all(isinstance(args[i], EquationBCSplit) for i in range(3)):
            # reconstruction for splitting `solving_utils.split`
            self.Jp_eq_J = Jp_eq_J
            self.is_linear = is_linear
            self._F = args[0]
            self._J = args[1]
            self._Jp = args[2]
        else:
            raise TypeError("Wrong EquationBC arguments")
Пример #5
0
    def __init__(self, F, u, bcs=None, J=None,
                 Jp=None,
                 form_compiler_parameters=None):
        """
        :param F: the nonlinear form
        :param u: the :class:`.Function` to solve for
        :param bcs: the boundary conditions (optional)
        :param J: the Jacobian J = dF/du (optional)
        :param Jp: a form used for preconditioning the linear system,
                 optional, if not supplied then the Jacobian itself
                 will be used.
        :param dict form_compiler_parameters: parameters to pass to the form
            compiler (optional)
        """
        from firedrake import solving
        from firedrake import function

        # Store input UFL forms and solution Function
        self.F = F
        self.Jp = Jp
        self.u = u
        self.bcs = solving._extract_bcs(bcs)

        # Argument checking
        if not isinstance(self.F, ufl.Form):
            raise TypeError("Provided residual is a '%s', not a Form" % type(self.F).__name__)
        if len(self.F.arguments()) != 1:
            raise ValueError("Provided residual is not a linear form")
        if not isinstance(self.u, function.Function):
            raise TypeError("Provided solution is a '%s', not a Function" % type(self.u).__name__)

        # Use the user-provided Jacobian. If none is provided, derive
        # the Jacobian from the residual.
        self.J = J or ufl_expr.derivative(F, u)

        if not isinstance(self.J, ufl.Form):
            raise TypeError("Provided Jacobian is a '%s', not a Form" % type(self.J).__name__)
        if len(self.J.arguments()) != 2:
            raise ValueError("Provided Jacobian is not a bilinear form")
        if self.Jp is not None and not isinstance(self.Jp, ufl.Form):
            raise TypeError("Provided preconditioner is a '%s', not a Form" % type(self.Jp).__name__)
        if self.Jp is not None and len(self.Jp.arguments()) != 2:
            raise ValueError("Provided preconditioner is not a bilinear form")

        # Store form compiler parameters
        self.form_compiler_parameters = form_compiler_parameters
        self._constant_jacobian = False
Пример #6
0
    def __init__(self,
                 F,
                 u,
                 bcs=None,
                 J=None,
                 Jp=None,
                 form_compiler_parameters=None,
                 is_linear=False):
        r"""
        :param F: the nonlinear form
        :param u: the :class:`.Function` to solve for
        :param bcs: the boundary conditions (optional)
        :param J: the Jacobian J = dF/du (optional)
        :param Jp: a form used for preconditioning the linear system,
                 optional, if not supplied then the Jacobian itself
                 will be used.
        :param dict form_compiler_parameters: parameters to pass to the form
            compiler (optional)
        :is_linear: internally used to check if all domain/bc forms
            are given either in 'A == b' style or in 'F == 0' style.
        """
        from firedrake import solving
        from firedrake import function

        self.bcs = solving._extract_bcs(bcs)
        # Check form style consistency
        self.is_linear = is_linear
        is_form_consistent(self.is_linear, self.bcs)
        self.Jp_eq_J = Jp is None

        self.u = u
        self.F = F
        self.Jp = Jp
        if not isinstance(self.u, function.Function):
            raise TypeError("Provided solution is a '%s', not a Function" %
                            type(self.u).__name__)
        # Use the user-provided Jacobian. If none is provided, derive
        # the Jacobian from the residual.
        self.J = J or ufl_expr.derivative(F, u)

        # Argument checking
        check_pde_args(self.F, self.J, self.Jp)

        # Store form compiler parameters
        self.form_compiler_parameters = form_compiler_parameters
        self._constant_jacobian = False
Пример #7
0
    def __init__(self,
                 F,
                 u,
                 bcs=None,
                 J=None,
                 Jp=None,
                 form_compiler_parameters=None,
                 nest=None):
        """
        :param F: the nonlinear form
        :param u: the :class:`.Function` to solve for
        :param bcs: the boundary conditions (optional)
        :param J: the Jacobian J = dF/du (optional)
        :param Jp: a form used for preconditioning the linear system,
                 optional, if not supplied then the Jacobian itself
                 will be used.
        :param dict form_compiler_parameters: parameters to pass to the form
            compiler (optional)
        :param nest: indicate if matrices on mixed spaces should be
               built as monolithic operators (suitable for direct
               solves), or as nested blocks (suitable for fieldsplit
               preconditioning).  If not provided, uses the default
               given by ``parameters["matnest"]``.
        """
        from firedrake import solving

        # Extract and check arguments
        u = solving._extract_u(u)
        bcs = solving._extract_bcs(bcs)

        # Store input UFL forms and solution Function
        self.F = F
        # Use the user-provided Jacobian. If none is provided, derive
        # the Jacobian from the residual.
        self.J = J or ufl_expr.derivative(F, u)
        self.Jp = Jp
        self.u = u
        self.bcs = bcs

        self._nest = nest
        # Store form compiler parameters
        self.form_compiler_parameters = form_compiler_parameters
        self._constant_jacobian = False
    def __init__(self, F, u, bcs=None, J=None,
                 Jp=None,
                 form_compiler_parameters=None,
                 is_linear=False):
        r"""
        :param F: the nonlinear form
        :param u: the :class:`.Function` to solve for
        :param bcs: the boundary conditions (optional)
        :param J: the Jacobian J = dF/du (optional)
        :param Jp: a form used for preconditioning the linear system,
                 optional, if not supplied then the Jacobian itself
                 will be used.
        :param dict form_compiler_parameters: parameters to pass to the form
            compiler (optional)
        :is_linear: internally used to check if all domain/bc forms
            are given either in 'A == b' style or in 'F == 0' style.
        """
        from firedrake import solving
        from firedrake import function

        self.bcs = solving._extract_bcs(bcs)
        # Check form style consistency
        self.is_linear = is_linear
        is_form_consistent(self.is_linear, self.bcs)
        self.Jp_eq_J = Jp is None

        self.u = u
        self.F = F
        self.Jp = Jp
        if not isinstance(self.u, function.Function):
            raise TypeError("Provided solution is a '%s', not a Function" % type(self.u).__name__)
        # Use the user-provided Jacobian. If none is provided, derive
        # the Jacobian from the residual.
        self.J = J or ufl_expr.derivative(F, u)

        # Argument checking
        check_pde_args(self.F, self.J, self.Jp)

        # Store form compiler parameters
        self.form_compiler_parameters = form_compiler_parameters
        self._constant_jacobian = False
Пример #9
0
    def __init__(self, F, u, bcs=None, J=None,
                 Jp=None,
                 form_compiler_parameters=None,
                 nest=None):
        """
        :param F: the nonlinear form
        :param u: the :class:`.Function` to solve for
        :param bcs: the boundary conditions (optional)
        :param J: the Jacobian J = dF/du (optional)
        :param Jp: a form used for preconditioning the linear system,
                 optional, if not supplied then the Jacobian itself
                 will be used.
        :param dict form_compiler_parameters: parameters to pass to the form
            compiler (optional)
        :param nest: indicate if matrices on mixed spaces should be
               built as monolithic operators (suitable for direct
               solves), or as nested blocks (suitable for fieldsplit
               preconditioning).  If not provided, uses the default
               given by ``parameters["matnest"]``.
        """
        from firedrake import solving

        # Extract and check arguments
        u = solving._extract_u(u)
        bcs = solving._extract_bcs(bcs)

        # Store input UFL forms and solution Function
        self.F = F
        # Use the user-provided Jacobian. If none is provided, derive
        # the Jacobian from the residual.
        self.J = J or ufl_expr.derivative(F, u)
        self.Jp = Jp
        self.u = u
        self.bcs = bcs

        self._nest = nest
        # Store form compiler parameters
        self.form_compiler_parameters = form_compiler_parameters
        self._constant_jacobian = False
Пример #10
0
    def __init__(self,
                 F,
                 u,
                 bcs=None,
                 J=None,
                 Jp=None,
                 form_compiler_parameters=None,
                 nest=None):
        """
        :param F: the nonlinear form
        :param u: the :class:`.Function` to solve for
        :param bcs: the boundary conditions (optional)
        :param J: the Jacobian J = dF/du (optional)
        :param Jp: a form used for preconditioning the linear system,
                 optional, if not supplied then the Jacobian itself
                 will be used.
        :param dict form_compiler_parameters: parameters to pass to the form
            compiler (optional)
        :param nest: indicate if matrices on mixed spaces should be
               built as monolithic operators (suitable for direct
               solves), or as nested blocks (suitable for fieldsplit
               preconditioning).  If not provided, uses the default
               given by ``parameters["matnest"]``.
        """
        from firedrake import solving
        from firedrake import function

        # Store input UFL forms and solution Function
        self.F = F
        self.Jp = Jp
        self.u = u
        self.bcs = solving._extract_bcs(bcs)

        # Argument checking
        if not isinstance(self.F, ufl.Form):
            raise TypeError("Provided residual is a '%s', not a Form" %
                            type(self.F).__name__)
        if len(self.F.arguments()) != 1:
            raise ValueError("Provided residual is not a linear form")
        if not isinstance(self.u, function.Function):
            raise TypeError("Provided solution is a '%s', not a Function" %
                            type(self.u).__name__)

        # Use the user-provided Jacobian. If none is provided, derive
        # the Jacobian from the residual.
        self.J = J or ufl_expr.derivative(F, u)

        if not isinstance(self.J, ufl.Form):
            raise TypeError("Provided Jacobian is a '%s', not a Form" %
                            type(self.J).__name__)
        if len(self.J.arguments()) != 2:
            raise ValueError("Provided Jacobian is not a bilinear form")
        if self.Jp is not None and not isinstance(self.Jp, ufl.Form):
            raise TypeError("Provided preconditioner is a '%s', not a Form" %
                            type(self.Jp).__name__)
        if self.Jp is not None and len(self.Jp.arguments()) != 2:
            raise ValueError("Provided preconditioner is not a bilinear form")

        self._nest = nest
        # Store form compiler parameters
        self.form_compiler_parameters = form_compiler_parameters
        self._constant_jacobian = False
Пример #11
0
    def __init__(
        self,
        F,
        u,
        udot,
        tspan,
        time=None,
        bcs=None,
        J=None,
        Jp=None,
        form_compiler_parameters=None,
        is_linear=False,
    ):
        r"""
        :param F: the nonlinear form
        :param u: the :class:`.Function` to solve for
        :param udot: the :class:`.Function` for time derivative
        :param tspan: the tuple for start time and end time
        :param time: the :class:`.Constant` for time-dependent weak forms
        :param bcs: the boundary conditions (optional)
        :param J: the Jacobian J = sigma*dF/dudot + dF/du (optional)
        :param Jp: a form used for preconditioning the linear system,
                 optional, if not supplied then the Jacobian itself
                 will be used.
        :param dict form_compiler_parameters: parameters to pass to the form
            compiler (optional)
        :is_linear: internally used to check if all domain/bc forms
            are given either in 'A == b' style or in 'F == 0' style.
        """
        from firedrake import solving
        from firedrake import function, Constant

        self.bcs = solving._extract_bcs(bcs)
        # Check form style consistency
        self.is_linear = is_linear
        is_form_consistent(self.is_linear, self.bcs)
        self.Jp_eq_J = Jp is None

        self.u = u
        self.udot = udot
        self.tspan = tspan
        self.F = F
        self.Jp = Jp
        if not isinstance(self.u, function.Function):
            raise TypeError(
                "Provided solution is a '%s', not a Function" % type(self.u).__name__
            )
        if not isinstance(self.udot, function.Function):
            raise TypeError(
                "Provided time derivative is a '%s', not a Function"
                % type(self.udot).__name__
            )

        # current value of time that may be used in weak form
        self.time = time or Constant(0.0)
        # timeshift value provided by the solver
        self.shift = Constant(1.0)

        # Use the user-provided Jacobian. If none is provided, derive
        # the Jacobian from the residual.
        self.J = J or self.shift * ufl_expr.derivative(F, udot) + ufl_expr.derivative(
            F, u
        )

        # Argument checking
        check_pde_args(self.F, self.J, self.Jp)

        # Store form compiler parameters
        self.form_compiler_parameters = form_compiler_parameters
        self._constant_jacobian = False