예제 #1
0
from dolfin import *
from fenicstools import divergence_matrix
from numpy import cos, pi

mesh = UnitSquareMesh(10, 10)
x = mesh.coordinates()
x[:] = (x - 0.5) * 2
x[:] = 0.5*(cos(pi*(x-1.) / 2.) + 1.)

CG = VectorFunctionSpace(mesh, 'CG', 1)
u = interpolate(Expression(("sin(2*pi*x[0])", "cos(3*pi*x[1])")), CG)

C = divergence_matrix(mesh)
DG = FunctionSpace(mesh, 'DG', 0)
cc = Function(DG)
cc.vector()[:] = C * u.vector()
plot(cc, title='Gauss div')
plot(div(u), title="Projection")

divu_dg = project(div(u), DG)

plot(divu_dg - cc, title="Difference between FV and FEM")

예제 #2
0
def setup(low_memory_version, u_components, u, v, p, q, velocity_degree,
          bcs, scalar_components, V, Q, x_, dim, mesh,
          constrained_domain, velocity_update_type, **NS_namespace):
    """Preassemble mass and diffusion matrices. 
    
    Set up and prepare all equations to be solved. Called once, before 
    going into time loop.
    
    """    
    P = None
    Rx = None        
    if not low_memory_version:
        # Constant pressure gradient matrix
        P = dict((ui, assemble(v*p.dx(i)*dx)) for i, ui in enumerate(u_components))

        # Constant velocity divergence matrix
        if V == Q:
            Rx = P
        else:
            Rx = dict((ui, assemble(q*u.dx(i)*dx)) for i, ui in  enumerate(u_components))

    # Mass matrix
    M = assemble(inner(u, v)*dx)                    

    # Stiffness matrix (without viscosity coefficient)
    K = assemble(inner(grad(u), grad(v))*dx)        
    
    # Pressure Laplacian. Either reuse K or assemble new
    if V == Q and bcs['p'] == []:
        Ap = K
        
    else:
        Bp = assemble(inner(grad(q), grad(p))*dx) 
        [bc.apply(Bp) for bc in bcs['p']]
        Ap = Matrix()
        Bp.compressed(Ap)

    # Allocate coefficient matrix (needs reassembling)
    A = Matrix(M)

    # Create dictionary to be returned into global NS namespace
    d = dict(P=P, Rx=Rx, A=A, M=M, K=K, Ap=Ap)

    # 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)    
    
    # Allocate for velocity update 
    if velocity_update_type.upper() == "GRADIENT_MATRIX":
        from fenicstools.WeightedGradient import weighted_gradient_matrix
        dP = weighted_gradient_matrix(mesh, range(dim), degree=velocity_degree, 
                                      constrained_domain=constrained_domain)
        dp = Function(V) 
        d.update(dP=dP, dp=dp)
        from fenicstools import divergence_matrix
        C = divergence_matrix(mesh)
        MA = assemble(q*TrialFunction(FunctionSpace(mesh, "DG", 0))*dx)
        d.update(C=C, MA=MA)
        
    elif velocity_update_type.upper() == "LUMPING":
        ones = Function(V)
        ones.vector()[:] = 1.
        ML = M * ones.vector()
        ML.set_local(1. / ML.array())
        d.update(ML=ML)
        
    else:
        Mu = Matrix(M) if len(scalar_components) > 0 else M # Copy if used by scalars
        [bc.apply(Mu) for bc in bcs['u0']]
        d.update(Mu=Mu)
    
    # Setup for solving convection
    u_ab = as_vector([Function(V) for i in range(len(u_components))])
    a_conv = 0.5*inner(v, dot(u_ab, nabla_grad(u)))*dx  # Faster version
    #a_conv = 0.5*inner(v, dot(U_AB, nabla_grad(u)))*dx
    a_scalar = a_conv    
    d.update(u_ab=u_ab, a_conv=a_conv, a_scalar=a_scalar)
    return d