def get_solvers(use_krylov_solvers, krylov_solvers, sys_comp, bcs, x_, Q, scalar_components, velocity_update_type, **NS_namespace): """Return linear solvers. We are solving for - tentative velocity - pressure correction and possibly: - scalars """ if use_krylov_solvers: ## tentative velocity solver ## u_sol = KrylovSolver('bicgstab', 'additive_schwarz') u_sol.parameters['preconditioner']['structure'] = 'same' u_sol.parameters.update(krylov_solvers) ## pressure solver ## if bcs['p'] == []: p_sol = KrylovSolver('cg', 'hypre_amg') else: p_sol = KrylovSolver('gmres', 'hypre_amg') p_sol.parameters['preconditioner']['structure'] = 'same' p_sol.parameters.update(krylov_solvers) if bcs['p'] == []: attach_pressure_nullspace(p_sol, x_, Q) sols = [u_sol, p_sol] ## scalar solver ## if len(scalar_components) > 0: c_sol = KrylovSolver('bicgstab', 'additive_schwarz') c_sol.parameters['preconditioner']['structure'] = 'same_nonzero_pattern' c_sol.parameters.update(krylov_solvers) sols.append(c_sol) else: sols.append(None) else: ## tentative velocity solver ## u_sol = LUSolver('mumps') u_sol.parameters['reuse_factorization'] = True ## pressure solver ## p_sol = LUSolver('mumps') p_sol.parameters['reuse_factorization'] = True if bcs['p'] == []: p_sol.normalize = True sols = [u_sol, p_sol] ## scalar solver ## if len(scalar_components) > 0: c_sol = LUSolver('mumps') sols.append(c_sol) else: sols.append(None) return sols
def setup(u_components, u, v, p, q, nu, nut_, les_model, LESsource, bcs, scalar_components, V, Q, x_, U_AB, A_cache, velocity_update_solver, u_, u_1, u_2, p_, assemble_matrix, GradFunction, DivFunction, **NS_namespace): """Preassemble mass and diffusion matrices. Set up and prepare all equations to be solved. Called once, before going into time loop. """ # Mass matrix M = assemble_matrix(inner(u, v) * dx) # Stiffness matrix (without viscosity coefficient) K = assemble_matrix(inner(grad(u), grad(v)) * dx) # Allocate stiffness matrix for LES that changes with time KT = None if les_model is None else (Matrix(M), inner(grad(u), grad(v))) # Pressure Laplacian. Either reuse K or assemble new Ap = assemble_matrix(inner(grad(q), grad(p)) * dx, bcs['p']) if les_model is None: if not Ap.id() == K.id(): # Compress matrix (creates new matrix) Bp = Matrix() Ap.compressed(Bp) Ap = Bp # Replace cached matrix with compressed version key = (inner(grad(q), grad(p)) * dx, tuple(bcs['p'])) A_cache[key] = (Ap, A_cache[key][1]) # Allocate coefficient matrix (needs reassembling) A = Matrix(M) # Allocate Function for holding and computing the velocity divergence on Q divu = DivFunction(u_, Q, name='divu', method=velocity_update_solver) # Allocate a dictionary of Functions for holding and computing pressure gradients gradp = { ui: GradFunction(p_, V, i=i, name='dpd' + ('x', 'y', 'z')[i], method=velocity_update_solver) for i, ui in enumerate(u_components) } # Create dictionary to be returned into global NS namespace d = dict(A=A, M=M, K=K, Ap=Ap, divu=divu, gradp=gradp) if bcs['p'] == []: attach_pressure_nullspace(Ap, x_, Q) # Allocate coefficient matrix and work vectors for scalars. Matrix differs from velocity in boundary conditions only if len(scalar_components) > 0: d.update(Ta=Matrix(M)) if len(scalar_components) > 1: # For more than one scalar we use the same linear algebra solver for all. # For this to work we need some additional tensors. The extra matrix # is required since different scalars may have different boundary conditions Tb = Matrix(M) bb = Vector(x_[scalar_components[0]]) bx = Vector(x_[scalar_components[0]]) d.update(Tb=Tb, bb=bb, bx=bx) # Setup for solving convection a_conv = inner(v, dot(u_1, nabla_grad(u))) * dx A_conv = assemble(inner(v, dot(u_2, nabla_grad(u))) * dx) # A scalar always uses the Standard convection form a_scalar = None if len(scalar_components) > 0: a_scalar = 0.5 * inner(v, dot(grad(u), U_AB)) * dx u_ab = None if les_model is None else as_vector( [Function(V) for i in range(len(u_components))]) LT = None if les_model is None else LESsource( (nu + nut_), u_ab, V, name='LTd') d.update(a_conv=a_conv, A_conv=A_conv, a_scalar=a_scalar, LT=LT, KT=KT, u_ab=u_ab) return d
def get_solvers(use_krylov_solvers, krylov_solvers, sys_comp, bcs, x_, Q, scalar_components, velocity_update_type, **NS_namespace): """Return linear solvers. We are solving for - tentative velocity - pressure correction - velocity update (unless lumping is switched on) and possibly: - scalars """ if use_krylov_solvers: ## tentative velocity solver ## u_sol = KrylovSolver('bicgstab', 'jacobi') if "structure" in u_sol.parameters['preconditioner']: u_sol.parameters['preconditioner']['structure'] = "same" else: u_sol.parameters['preconditioner']['reuse'] = True u_sol.parameters.update(krylov_solvers) ## velocity correction solver if velocity_update_type != "default": du_sol = None else: du_sol = KrylovSolver('bicgstab', 'jacobi') if "structure" in du_sol.parameters['preconditioner']: du_sol.parameters['preconditioner']['structure'] = "same" else: du_sol.parameters['preconditioner']['reuse'] = True du_sol.parameters.update(krylov_solvers) #du_sol.parameters['preconditioner']['ilu']['fill_level'] = 1 #PETScOptions.set("pc_hypre_euclid_print_statistics", True) ## pressure solver ## if bcs['p'] == []: p_sol = KrylovSolver('minres', 'hypre_amg') else: p_sol = KrylovSolver('gmres', 'hypre_amg') if "structure" in p_sol.parameters['preconditioner']: p_sol.parameters['preconditioner']['structure'] = "same" else: p_sol.parameters['preconditioner']['reuse'] = True p_sol.parameters.update(krylov_solvers) if bcs['p'] == []: attach_pressure_nullspace(p_sol, x_, Q) sols = [u_sol, p_sol, du_sol] ## scalar solver ## if len(scalar_components) > 0: #c_sol = KrylovSolver('bicgstab', 'hypre_euclid') c_sol = KrylovSolver('bicgstab', 'jacobi') if "structure" in c_sol.parameters['preconditioner']: c_sol.parameters['preconditioner']['structure'] = "same_nonzero_pattern" else: c_sol.parameters['preconditioner']['reuse'] = False c_sol.parameters['preconditioner']['same_nonzero_pattern'] = True c_sol.parameters.update(krylov_solvers) sols.append(c_sol) else: sols.append(None) else: ## tentative velocity solver ## u_sol = LUSolver() u_sol.parameters['reuse_factorization'] = True ## velocity correction ## if velocity_update_type != "default": du_sol = None else: du_sol = LUSolver() du_sol.parameters['reuse_factorization'] = True ## pressure solver ## p_sol = LUSolver() p_sol.parameters['reuse_factorization'] = True if bcs['p'] == []: p_sol.normalize = True sols = [u_sol, p_sol, du_sol] ## scalar solver ## if len(scalar_components) > 0: c_sol = LUSolver() sols.append(c_sol) else: sols.append(None) return sols
def setup(u_components, u, v, p, q, nu, nut_, les_model, LESsource, bcs, scalar_components, V, Q, x_, U_AB, A_cache, velocity_update_solver, u_, u_1, u_2, p_, assemble_matrix, GradFunction, DivFunction, **NS_namespace): """Preassemble mass and diffusion matrices. Set up and prepare all equations to be solved. Called once, before going into time loop. """ # Mass matrix M = assemble_matrix(inner(u, v)*dx) # Stiffness matrix (without viscosity coefficient) K = assemble_matrix(inner(grad(u), grad(v))*dx) # Allocate stiffness matrix for LES that changes with time KT = None if les_model is None else (Matrix(M), inner(grad(u), grad(v))) # Pressure Laplacian. Either reuse K or assemble new Ap = assemble_matrix(inner(grad(q), grad(p))*dx, bcs['p']) if les_model is None: if not Ap.id() == K.id(): # Compress matrix (creates new matrix) Bp = Matrix() Ap.compressed(Bp) Ap = Bp # Replace cached matrix with compressed version key = (inner(grad(q), grad(p))*dx, tuple(bcs['p'])) A_cache[key] = (Ap, A_cache[key][1]) # Allocate coefficient matrix (needs reassembling) A = Matrix(M) # Allocate Function for holding and computing the velocity divergence on Q divu = DivFunction(u_, Q, name='divu', method=velocity_update_solver) # Allocate a dictionary of Functions for holding and computing pressure gradients gradp = {ui: GradFunction(p_, V, i=i, name='dpd'+('x','y','z')[i], method=velocity_update_solver) for i, ui in enumerate(u_components)} # Create dictionary to be returned into global NS namespace d = dict(A=A, M=M, K=K, Ap=Ap, divu=divu, gradp=gradp) if bcs['p'] == []: attach_pressure_nullspace(Ap, x_, Q) # Allocate coefficient matrix and work vectors for scalars. Matrix differs from velocity in boundary conditions only if len(scalar_components) > 0: d.update(Ta=Matrix(M)) if len(scalar_components) > 1: # For more than one scalar we use the same linear algebra solver for all. # For this to work we need some additional tensors. The extra matrix # is required since different scalars may have different boundary conditions Tb = Matrix(M) bb = Vector(x_[scalar_components[0]]) bx = Vector(x_[scalar_components[0]]) d.update(Tb=Tb, bb=bb, bx=bx) # Setup for solving convection a_conv = inner(v, dot(u_1, nabla_grad(u)))*dx A_conv = assemble(inner(v, dot(u_2, nabla_grad(u)))*dx) # A scalar always uses the Standard convection form a_scalar = None if len(scalar_components) > 0: a_scalar = 0.5*inner(v, dot(grad(u), U_AB))*dx u_ab = None if les_model is None else as_vector([Function(V) for i in range(len(u_components))]) LT = None if les_model is None else LESsource((nu+nut_), u_ab, V, name='LTd') d.update(a_conv=a_conv, A_conv=A_conv, a_scalar=a_scalar, LT=LT, KT=KT, u_ab=u_ab) return d
def get_solvers(use_krylov_solvers, krylov_solvers, bcs, x_, Q, scalar_components, velocity_krylov_solver, pressure_krylov_solver, scalar_krylov_solver, **NS_namespace): """Return linear solvers. We are solving for - tentative velocity - pressure correction and possibly: - scalars """ if use_krylov_solvers: ## tentative velocity solver ## u_sol = KrylovSolver(velocity_krylov_solver['solver_type'], velocity_krylov_solver['preconditioner_type']) u_sol.parameters['preconditioner']['structure'] = 'same' u_sol.parameters.update(krylov_solvers) ## pressure solver ## #p_prec = PETScPreconditioner('hypre_amg') #p_prec.parameters['report'] = True #p_prec.parameters['hypre']['BoomerAMG']['agressive_coarsening_levels'] = 0 #p_prec.parameters['hypre']['BoomerAMG']['strong_threshold'] = 0.5 #PETScOptions.set('pc_hypre_boomeramg_truncfactor', 0) #PETScOptions.set('pc_hypre_boomeramg_agg_num_paths', 1) p_sol = KrylovSolver(pressure_krylov_solver['solver_type'], pressure_krylov_solver['preconditioner_type']) p_sol.parameters['preconditioner']['structure'] = 'same' #p_sol.parameters['profile'] = True p_sol.parameters.update(krylov_solvers) if bcs['p'] == []: attach_pressure_nullspace(p_sol, x_, Q) sols = [u_sol, p_sol] ## scalar solver ## if len(scalar_components) > 0: c_sol = KrylovSolver(scalar_krylov_solver['solver_type'], scalar_krylov_solver['preconditioner_type']) c_sol.parameters.update(krylov_solvers) c_sol.parameters['preconditioner']['structure'] = 'same_nonzero_pattern' sols.append(c_sol) else: sols.append(None) else: ## tentative velocity solver ## u_sol = LUSolver('mumps') u_sol.parameters['same_nonzero_pattern'] = True ## pressure solver ## p_sol = LUSolver('mumps') p_sol.parameters['reuse_factorization'] = True if bcs['p'] == []: p_sol.normalize = True sols = [u_sol, p_sol] ## scalar solver ## if len(scalar_components) > 0: c_sol = LUSolver('mumps') sols.append(c_sol) else: sols.append(None) return sols
def setup(u_components, u, v, p, q, nu, nut_, LESsource, bcs, scalar_components, V, Q, x_, u_, p_, q_1, q_2, velocity_update_solver, assemble_matrix, les_model, DivFunction, GradFunction, homogenize, **NS_namespace): """Set up all equations to be solved.""" # Mass matrix M = assemble_matrix(inner(u, v) * dx) # Stiffness matrix (without viscosity coefficient) K = assemble_matrix(inner(grad(u), grad(v)) * dx) # Allocate stiffness matrix for LES that changes with time KT = None if les_model is None else (Matrix(M), inner(grad(u), grad(v))) # Pressure Laplacian. Either reuse K or assemble new Ap = assemble_matrix(inner(grad(q), grad(p)) * dx, bcs['p']) if les_model is None: if not Ap.id() == K.id(): Bp = Matrix() Ap.compressed(Bp) Ap = Bp # Allocate coefficient matrix (needs reassembling) A = Matrix(M) # Allocate Function for holding and computing the velocity divergence on Q divu = DivFunction(u_, Q, name='divu', method=velocity_update_solver) # Allocate a dictionary of Functions for holding and computing pressure gradients gradp = { ui: GradFunction(p_, V, i=i, name='dpd' + ('x', 'y', 'z')[i], bcs=homogenize(bcs[ui]), method=velocity_update_solver) for i, ui in enumerate(u_components) } # Check first if we are starting from two equal velocities (u_1=u_2) initial_u1_norm = sum([q_1[ui].vector().norm('l2') for ui in u_components]) initial_u2_norm = sum([q_2[ui].vector().norm('l2') for ui in u_components]) # In that case use Euler on first iteration beta = Constant( 2.0) if abs(initial_u1_norm - initial_u2_norm) > DOLFIN_EPS_LARGE else Constant(3.0) # Create dictionary to be returned into global NS namespace d = dict(A=A, M=M, K=K, Ap=Ap, divu=divu, gradp=gradp, beta=beta) if bcs['p'] == []: attach_pressure_nullspace(Ap, x_, Q) # Allocate coefficient matrix and work vectors for scalars. Matrix differs from velocity in boundary conditions only if len(scalar_components) > 0: d.update(Ta=Matrix(M)) if len(scalar_components) > 1: # For more than one scalar we use the same linear algebra solver for all. # For this to work we need some additional tensors. The extra matrix # is required since different scalars may have different boundary conditions Tb = Matrix(M) bb = Vector(x_[scalar_components[0]]) bx = Vector(x_[scalar_components[0]]) d.update(Tb=Tb, bb=bb, bx=bx) # Setup for solving convection u_convecting = as_vector([Function(V) for i in range(len(u_components))]) a_conv = inner(v, dot(u_convecting, nabla_grad(u))) * dx # Faster version a_scalar = inner(v, dot(u_, nabla_grad(u))) * dx LT = None if les_model is None else LESsource( (nu + nut_), u_convecting, V, name='LTd') d.update(u_convecting=u_convecting, a_conv=a_conv, a_scalar=a_scalar, LT=LT, KT=KT) return d