Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
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
Example #6
0
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