def expand_linear_solver_parameters(linear_solver_parameters, default_linear_solver_parameters = {}): """ Return an expanded dictionary of linear solver parameters with all defaults explicitly specified. The optional default_linear_solver_parameters argument can be used to override global defaults. """ if not isinstance(linear_solver_parameters, dict): raise InvalidArgumentException("linear_solver_parameters must be a dictionary") if not isinstance(default_linear_solver_parameters, dict): raise InvalidArgumentException("default_linear_solver_parameters must be a dictionary") linear_solver_parameters = apply_default_parameters(linear_solver_parameters, default_linear_solver_parameters) linear_solver_parameters = apply_default_parameters(linear_solver_parameters, {"linear_solver":"default", "preconditioner":"default", "lu_solver":dolfin.parameters["lu_solver"].to_dict(), "krylov_solver":dolfin.parameters["krylov_solver"].to_dict() }) if linear_solver_parameters["linear_solver"] in ["default", "lu"] or dolfin.has_lu_solver_method(linear_solver_parameters["linear_solver"]): del(linear_solver_parameters["preconditioner"]) del(linear_solver_parameters["krylov_solver"]) else: del(linear_solver_parameters["lu_solver"]) return linear_solver_parameters
def LinearSolver(*args, **kwargs): """ Return a linear solver. Arguments: One of: 1. Arguments as accepted by the DOLFIN LinearSolver constructor. or: 2. A dictionary of linear solver parameters. """ if not len(args) == 1 or not len(kwargs) == 0 or not isinstance( args[0], dict): return _LinearSolver(*args, **kwargs) linear_solver_parameters = args[0] linear_solver = "lu" pc = None kp = {} lp = {} for key in linear_solver_parameters: if key == "linear_solver": linear_solver = linear_solver_parameters[key] elif key == "preconditioner": pc = linear_solver_parameters[key] elif key == "krylov_solver": kp = linear_solver_parameters[key] elif key == "lu_solver": lp = linear_solver_parameters[key] elif key in [ "print_matrix", "print_rhs", "reset_jacobian", "symmetric" ]: raise NotImplementedException( "Unsupported linear solver parameter: %s" % key) else: raise InvalidArgumentException( "Unexpected linear solver parameter: %s" % key) if linear_solver in ["default", "direct", "lu"]: is_lu = True linear_solver = "default" elif linear_solver == "iterative": is_lu = False linear_solver = "gmres" else: is_lu = dolfin.has_lu_solver_method(linear_solver) if is_lu: linear_solver = _LUSolver(linear_solver) linear_solver.parameters.update(lp) else: if pc is None: linear_solver = _KrylovSolver(linear_solver) else: linear_solver = _KrylovSolver(linear_solver, pc) linear_solver.parameters.update(kp) return linear_solver
def expanded_linear_solver_parameters(form, linear_solver_parameters, static, bcs, symmetric_bcs): if static: default = { "lu_solver": { "reuse_factorization": True, "same_nonzero_pattern": True }, "krylov_solver": { "preconditioner": { "structure": "same" } } } if (len(bcs) == 0 or symmetric_bcs) and is_self_adjoint_form(form): default["lu_solver"]["symmetric"] = True linear_solver_parameters = expand_linear_solver_parameters( linear_solver_parameters, default_linear_solver_parameters=default) else: default = { "lu_solver": { "reuse_factorization": False, "same_nonzero_pattern": False }, "krylov_solver": { "preconditioner": { "structure": "different_nonzero_pattern" } } } if (len(bcs) == 0 or symmetric_bcs) and is_self_adjoint_form(form): default["lu_solver"]["symmetric"] = True linear_solver_parameters = expand_linear_solver_parameters( linear_solver_parameters, default_linear_solver_parameters=default) static_parameters = False if linear_solver_parameters["linear_solver"] in [ "direct", "lu" ] or dolfin.has_lu_solver_method( linear_solver_parameters["linear_solver"]): static_parameters = linear_solver_parameters["lu_solver"]["reuse_factorization"] or \ linear_solver_parameters["lu_solver"]["same_nonzero_pattern"] else: static_parameters = not linear_solver_parameters[ "krylov_solver"]["preconditioner"][ "structure"] == "different_nonzero_pattern" if static_parameters: raise ParameterException( "Non-static solve supplied with static linear solver parameters" ) return linear_solver_parameters
def _set_solver(self,operator,op_name=None): """ Set the solver of an operator """ if type(operator) is df.PETScMatrix: if df.__version__<='1.6.0': solver = df.PETScLUSolver('mumps' if df.has_lu_solver_method('mumps') else 'default') solver.set_operator(operator) solver.parameters['reuse_factorization']=True else: solver = df.PETScLUSolver(self.mpi_comm,operator,'mumps' if df.has_lu_solver_method('mumps') else 'default') # solver.set_operator(operator) # solver.parameters['reuse_factorization']=True if op_name == 'K': solver.parameters['symmetric']=True else: import scipy.sparse.linalg as spsla solver = spsla.splu(operator.tocsc(copy=True)) return solver
def LinearSolver(*args, **kwargs): """ Return a linear solver. Arguments: One of: 1. Arguments as accepted by the DOLFIN LinearSolver constructor. or: 2. A dictionary of linear solver parameters. """ if not len(args) == 1 or not len(kwargs) == 0 or not isinstance(args[0], dict): return _LinearSolver(*args, **kwargs) linear_solver_parameters = args[0] linear_solver = "lu" pc = None kp = {} lp = {} for key in linear_solver_parameters: if key == "linear_solver": linear_solver = linear_solver_parameters[key] elif key == "preconditioner": pc = linear_solver_parameters[key] elif key == "krylov_solver": kp = linear_solver_parameters[key] elif key == "lu_solver": lp = linear_solver_parameters[key] elif key in ["print_matrix", "print_rhs", "reset_jacobian", "symmetric"]: raise NotImplementedException("Unsupported linear solver parameter: %s" % key) else: raise InvalidArgumentException("Unexpected linear solver parameter: %s" % key) if linear_solver in ["default", "direct", "lu"]: is_lu = True linear_solver = "default" elif linear_solver == "iterative": is_lu = False linear_solver = "gmres" else: is_lu = dolfin.has_lu_solver_method(linear_solver) if is_lu: linear_solver = _LUSolver(linear_solver) linear_solver.parameters.update(lp) else: if pc is None: linear_solver = _KrylovSolver(linear_solver) else: linear_solver = _KrylovSolver(linear_solver, pc) linear_solver.parameters.update(kp) return linear_solver
def get_default_factor_solver_package(comm): """Return first available factor solver package name. This is implemened using DOLFIN now.""" methods_parallel = ("mumps", "superlu_dist", "pastix") methods_sequential = ("mumps", "umfpack", "superlu", "superlu_dist", "pastix") if MPI.size(comm) > 1: methods = methods_parallel else: methods = methods_sequential for method in methods: if has_lu_solver_method(method): return method raise RuntimeError("Did not find any suitable direct sparse solver in PETSc")
def expanded_linear_solver_parameters(form, linear_solver_parameters, static, bcs, symmetric_bcs): if static: if dolfin_version() < (1, 3, 0): default = {"lu_solver":{"reuse_factorization":True, "same_nonzero_pattern":True}, "krylov_solver":{"preconditioner":{"reuse":True}}} else: default = {"lu_solver":{"reuse_factorization":True, "same_nonzero_pattern":True}, "krylov_solver":{"preconditioner":{"structure":"same"}}} if (len(bcs) == 0 or symmetric_bcs) and is_self_adjoint_form(form): if dolfin_version() < (1, 3, 0): default["lu_solver"]["symmetric_operator"] = True else: default["lu_solver"]["symmetric"] = True linear_solver_parameters = expand_linear_solver_parameters(linear_solver_parameters, default_linear_solver_parameters = default) else: if dolfin_version() < (1, 3, 0): default = {"lu_solver":{"reuse_factorization":False, "same_nonzero_pattern":False}, "krylov_solver":{"preconditioner":{"reuse":False}}} else: default = {"lu_solver":{"reuse_factorization":False, "same_nonzero_pattern":False}, "krylov_solver":{"preconditioner":{"structure":"different_nonzero_pattern"}}} if (len(bcs) == 0 or symmetric_bcs) and is_self_adjoint_form(form): if dolfin_version() < (1, 3, 0): default["lu_solver"]["symmetric_operator"] = True else: default["lu_solver"]["symmetric"] = True linear_solver_parameters = expand_linear_solver_parameters(linear_solver_parameters, default_linear_solver_parameters = default) static_parameters = False if linear_solver_parameters["linear_solver"] in ["direct", "lu"] or dolfin.has_lu_solver_method(linear_solver_parameters["linear_solver"]): static_parameters = linear_solver_parameters["lu_solver"]["reuse_factorization"] or \ linear_solver_parameters["lu_solver"]["same_nonzero_pattern"] else: if dolfin_version() < (1, 3, 0): static_parameters = linear_solver_parameters["krylov_solver"]["preconditioner"]["reuse"] else: static_parameters = not linear_solver_parameters["krylov_solver"]["preconditioner"]["structure"] == "different_nonzero_pattern" if static_parameters: raise ParameterException("Non-static solve supplied with static linear solver parameters") return linear_solver_parameters
def get_default_factor_solver_type(comm): """Return first available factor solver type name. This is implemened using DOLFIN now.""" methods_parallel = ("mumps", "superlu_dist", "pastix") methods_sequential = ("mumps", "umfpack", "superlu", "superlu_dist", "pastix") if isinstance(comm, PETSc.Comm): comm = comm.tompi4py() if MPI.size(comm) > 1: methods = methods_parallel else: methods = methods_sequential for method in methods: if has_lu_solver_method(method): return method raise RuntimeError("Did not find any suitable direct sparse solver in PETSc")
def __init__(self, *args, **kwargs): args, kwargs = copy.copy(args), copy.copy(kwargs) # Process arguments not to be passed to _extract_args if "initial_guess" in kwargs: if not kwargs["initial_guess"] is None and not isinstance(kwargs["initial_guess"], dolfin.Function): raise InvalidArgumentException("initial_guess must be a Function") initial_guess = kwargs["initial_guess"] del(kwargs["initial_guess"]) else: initial_guess = None if "adjoint_solver_parameters" in kwargs: if not kwargs["adjoint_solver_parameters"] is None and not isinstance(kwargs["adjoint_solver_parameters"], dict): raise InvalidArgumentException("adjoint_solver_parameters must be a dictionary") adjoint_solver_parameters = kwargs["adjoint_solver_parameters"] del(kwargs["adjoint_solver_parameters"]) else: adjoint_solver_parameters = None if "pre_assembly_parameters" in kwargs: pre_assembly_parameters = kwargs["pre_assembly_parameters"] del(kwargs["pre_assembly_parameters"]) else: pre_assembly_parameters = {} # Process remaining arguments if "form_compiler_parameters" in kwargs: raise NotImplementedException("form_compiler_parameters argument not supported") eq, x, bcs, J, tol, goal, form_parameters, solver_parameters = dolfin.fem.solving._extract_args(*args, **kwargs) # Relax requirements on equation syntax eq_lhs_rank = form_rank(eq.lhs) if eq_lhs_rank == 1: form = eq.lhs if not is_zero_rhs(eq.rhs): form -= eq.rhs if x in ufl.algorithms.extract_coefficients(form): if J is None: J = derivative(form, x) if x in ufl.algorithms.extract_coefficients(J): # Non-linear solve is_linear = False else: # Linear solve, rank 2 LHS cache_info("Detected that solve for %s is linear" % x.name()) form = replace(form, {x:dolfin.TrialFunction(x.function_space())}) eq = lhs(form) == rhs(form) eq_lhs_rank = form_rank(eq.lhs) assert(eq_lhs_rank == 2) is_linear = True else: # Linear solve, rank 1 LHS is_linear = True elif eq_lhs_rank == 2: form = eq.lhs if not is_zero_rhs(eq.rhs): form -= eq.rhs if not x in ufl.algorithms.extract_coefficients(form): # Linear solve, rank 2 LHS eq = lhs(form) == rhs(form) eq_lhs_rank = form_rank(eq.lhs) assert(eq_lhs_rank == 2) is_linear = True else: # ?? raise InvalidArgumentException("Invalid equation") # Initial guess sanity checking if is_linear: if not "krylov_solver" in solver_parameters: solver_parameters["krylov_solver"] = {} def initial_guess_enabled(): return solver_parameters["krylov_solver"].get("nonzero_initial_guess", False) def initial_guess_disabled(): return not solver_parameters["krylov_solver"].get("nonzero_initial_guess", True) def enable_initial_guess(): solver_parameters["krylov_solver"]["nonzero_initial_guess"] = True return if initial_guess is None: if initial_guess_enabled(): initial_guess = x elif eq_lhs_rank == 1: # Supplied an initial guess for a linear solve with a rank 1 LHS - # ignore it initial_guess = None elif "linear_solver" in solver_parameters and not solver_parameters["linear_solver"] in ["direct", "lu"] and not dolfin.has_lu_solver_method(solver_parameters["linear_solver"]): # Supplied an initial guess with a Krylov solver - check the # initial_guess solver parameter if initial_guess_disabled(): raise ParameterException("initial_guess cannot be set if nonzero_initial_guess solver parameter is False") enable_initial_guess() elif is_linear: # Supplied an initial guess for a linear solve with an LU solver - # ignore it initial_guess = None # Initialise EquationSolver.__init__(self, eq, x, bcs, solver_parameters = solver_parameters, adjoint_solver_parameters = adjoint_solver_parameters, pre_assembly_parameters = pre_assembly_parameters) self.__args = args self.__kwargs = kwargs self.__J = J self.__tol = tol self.__goal = goal self.__form_parameters = form_parameters self.__initial_guess = initial_guess # Assemble self.reassemble() return
# -*- coding: utf-8 -*- """ Checks that this version of FEniCS/DOLFIN was compiled with parallel HDF5 and a few extra preconditoners and solvers. """ import dolfin as df assert df.has_hdf5_parallel() assert df.has_krylov_solver_preconditioner('hypre_amg') assert df.has_krylov_solver_preconditioner('hypre_euclid') assert df.has_krylov_solver_preconditioner('hypre_parasails') assert df.has_lu_solver_method('mumps') assert df.has_petsc() assert df.has_petsc4py()
from dolfin import has_lu_solver_method lusolver = "superlu_dist" if has_lu_solver_method("superlu_dist") else "default" direct = dict( reuse = False, iterative = False, lusolver = lusolver, ) direct_reuse = dict( reuse = True, iterative = False, lusolver = lusolver, luparams = dict( symmetric = False, same_nonzero_pattern = True, reuse_factorization = True,), ) bicgstab = dict( reuse = False, iterative = True, lusolver = ("superlu_dist" if has_lu_solver_method("superlu_dist") else "default"), luparams = dict( symmetric = False, same_nonzero_pattern = True, reuse_factorization = False,), ks = "bicgstab", kp = "hypre_euclid", kparams = dict( maximum_iterations = 600,