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
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
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")
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")
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
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
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
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, 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
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