Пример #1
0
    def get_error(wh, mms=mms_data):
        # We look at the H1 error for velocity
        u3, u1, p = mms.solution
        u3h, u1h, ph = wh

        # X = ph.function_space()
        # bcs = DirichletBC(X, Constant(0), 'on_boundary').get_boundary_values().keys()
        # print np.linalg.norm(ph.vector().get_local()[bcs], np.inf)

        # Passing the HsNorm from preconditioner so that we don't compute
        # eigenvalues twice
        try:
            Hs = mms.normals.pop()
        except IndexError:
            Hs = HsNorm(ph.function_space(), s=-0.5)
        # e*H*e ie (e, e)_H
        e = interpolate(p, ph.function_space()).vector()
        e.axpy(-1, ph.vector())

        e = np.sqrt(e.inner(Hs*e))

        # On big meshes constructing the error for interpolation space
        # is expensive so wi reduce order then
        degree_rise = 1 if u3h.function_space().dim() < 2E6 else 0
        # NOTE: the error is interpolated to P2 disc, or P1 disc
        return (H1_norm(u3, u3h, degree_rise=degree_rise),
                H1_norm(u1, u1h),  
                e,
                L2_norm(p, ph))
Пример #2
0
def cannonical_inner_product(W, mms, params, AA):
    '''Inner product of alpha*H1 x beta*H1 x H-0.5'''
    V3, V1, Q = W
    # Extact Vi norms from system
    V3_inner = AA[0][0]
    V1_inner = AA[1][1]

    Q_inner = matrix_fromHs(HsNorm(Q, s=-0.5))

    B = block_diag_mat([V3_inner, V1_inner, Q_inner])

    return B
Пример #3
0
    def norm(u, uh, s=s):
        V = uh.function_space()
        # I compute it as (u-uh).Hs*(u-uh)
        Hs = matrix_fromHs(HsNorm(V, s))

        e = interpolate(u, V).vector()
        e.axpy(-1, uh.vector())  # u - uh
        # Alloc for matvec
        Hs_e = e.copy()
        Hs.mult(e, Hs_e)

        return sqrt(e.inner(Hs_e))
Пример #4
0
def cannonical_riesz_map(W, mms, params, AA):
    '''Riesz map wrt. inner product of alpha*H1 x beta*H1 x H-0.5'''
    V3, V1, Q = W
    # Extact Vi norms from system
    V3_inner = AA[0][0]
    V1_inner = AA[1][1]

    Q_inner = HsNorm(Q, s=-0.5)

    mms.normals.append(Q_inner)
    
    B = block_diag_mat([AMG(V3_inner), AMG(V1_inner), Q_inner**-1])

    return B
Пример #5
0
def cannonical_riesz_map_AMG(W, mms, params):
    '''AMG inverse'''
    V1, V, Q = W
    kappa = Constant(params.kappa)

    # Outer, H1_0
    u, v = TrialFunction(V1), TestFunction(V1)

    outer_mesh = V1.mesh()

    subdomains = mms.subdomains[0]  #
    facet_f = MeshFunction('size_t', outer_mesh,
                           outer_mesh.topology().dim() - 1, 0)
    [
        subd.mark(facet_f, i)
        for i, subd in enumerate(map(CompiledSubDomain, subdomains), 1)
    ]

    bcs = [
        DirichletBC(V1, Constant(0), facet_f, i)
        for i in range(1, 1 + len(subdomains))
    ]

    V1_norm, _ = assemble_system(
        inner(grad(u), grad(v)) * dx,
        inner(Constant(0), v) * dx, bcs)

    # Inner
    u, v = TrialFunction(V), TestFunction(V)

    V_norm = assemble(inner(grad(u), grad(v)) * dx + inner(u, v) * dx)

    # Multiplier on the boundary
    # Fractional part
    Hs = HsNorm(Q, s=[(1, -0.5), (params.eps, 0.0)])
    Hs = Hs**-1
    # L2 part
    # epsilon = Constant(params.eps)
    # p, q = TrialFunction(Q), TestFunction(Q)
    # m = epsilon*inner(p, q)*dx
    # M = assemble(m)

    # Q_norm = mat_add(Hs, M)

    # return block_diag_mat([V1_norm, V_norm, Q_norm])

    return block_diag_mat([AMG(V1_norm), AMG(V_norm), Hs])
Пример #6
0
def cannonical_inner_product(W, mms, params):
    '''H1 x H1 x H^{-1/2} cap L^2'''
    V1, V, Q = W
    kappa = Constant(params.kappa)

    # Outer, H1_0
    u, v = TrialFunction(V1), TestFunction(V1)

    outer_mesh = V1.mesh()

    subdomains = mms.subdomains[0]  #
    facet_f = MeshFunction('size_t', outer_mesh,
                           outer_mesh.topology().dim() - 1, 0)
    [
        subd.mark(facet_f, i)
        for i, subd in enumerate(map(CompiledSubDomain, subdomains), 1)
    ]

    bcs = [
        DirichletBC(V1, Constant(0), facet_f, i)
        for i in range(1, 1 + len(subdomains))
    ]

    V1_norm, _ = assemble_system(
        inner(grad(u), grad(v)) * dx,
        inner(Constant(0), v) * dx, bcs)

    # Inner
    u, v = TrialFunction(V), TestFunction(V)

    V_norm = assemble(inner(grad(u), grad(v)) * dx + inner(u, v) * dx)

    # Multiplier on the boundary
    # Fractional part
    Hs = matrix_fromHs(HsNorm(Q, s=-0.5))

    # L2 part
    epsilon = Constant(params.eps)
    p, q = TrialFunction(Q), TestFunction(Q)
    m = epsilon * inner(p, q) * dx
    M = assemble(m)

    Q_norm = mat_add(Hs, M)

    return block_diag_mat([V1_norm, V_norm, Q_norm])
Пример #7
0
    def get_error(wh,
                  subdomains=subdomains,
                  ifaces=ifaces,
                  exact=exact,
                  normals=mms_data.normals[0]):
        sigmah, uh, ph = wh
        print 'Mean ph', assemble(ph * dx)
        sigma_exact, u_exact, p_exact, I_exact = exact

        # Compute Hs norm on finer space
        Q = ph.function_space()
        Q = FunctionSpace(Q.mesh(), 'CG', 1)
        Hs = matrix_fromHs(HsNorm(Q, s=0.5))
        # Use interpolated
        ph = interpolate(ph, Q)

        return (broken_norm(Hdiv_norm, subdomains[:])(sigma_exact[:], sigmah),
                broken_norm(L2_norm, subdomains[:])(u_exact[:],
                                                    uh), L2_norm(p_exact, ph))
Пример #8
0
    def get_error(wh, mms=mms_data):
        # We look at the H1 error for velocity
        u3, u1, p = mms.solution
        u3h, u1h, ph = wh

        # On a finer mesh
        Q = FunctionSpace(ph.function_space().mesh(), 'CG', 3)
        Hs = HsNorm(Q, s=-0.5)

        # A U = M U Lambda
        # Hs = M * U * Lambda^{-0.5} * (M*U).T

        # e*H*e ie (e, e)_H
        e = interpolate(p, Q).vector()
        e.axpy(-1, interpolate(ph, Q).vector())

        e = np.sqrt(e.inner(Hs * e))
        # On big meshes constructing the error for interpolation space
        # is expensive so wi reduce order then
        degree_rise = 1 if u3h.function_space().dim() < 2E6 else 0
        # NOTE: the error is interpolated to P2 disc, or P1 disc
        return (H1_norm(u3, u3h, degree_rise=degree_rise), H1_norm(u1, u1h), e,
                L2_norm(p, ph))
Пример #9
0
def setup_preconditioner(W, which, eps=None):
    '''
    This is a block diagonal preconditioner based on 
    
        H1 x H-0.5 or (H1 \cap H0.5) x L2
    '''
    from block.algebraic.petsc import AMG
    from block.algebraic.petsc import LumpedInvDiag
    from hsmg.hseig import HsNorm
    
    V, Q = W

    if which == 0:
        print 'Using H1 x H-0.5 preconditioner'
        # H1
        u, v = TrialFunction(V), TestFunction(V)
        b00 = inner(grad(u), grad(v))*dx + inner(u, v)*dx
        # Inverted by BoomerAMG
        B00 = AMG(ii_assemble(b00))
        # The Q norm via spectral
        B11 = inverse(HsNorm(Q, s=-0.5))  # The norm is inverted exactly
    else:
        print 'Using (H1 \cap H0.5) x L2 preconditioner'
        bdry = Q.mesh()
        dxGamma = dx(domain=bdry)
        # Cap space
        u, v = TrialFunction(V), TestFunction(V)
        Tu, Tv = Trace(u, bdry), Trace(v, bdry)
        b00 = inner(grad(u), grad(v))*dx + inner(u, v)*dx + inner(Tu, Tv)*dxGamma
        # Inverted by BoomrAMG
        B00 = AMG(ii_convert(ii_assemble(b00)))

        # We don't have to work so hard for multiplier
        p, q = TrialFunction(Q), TestFunction(Q)
        B11 = LumpedInvDiag(ii_assemble(inner(p, q)*dx))

    return block_diag_mat([B00, B11])
Пример #10
0
def cannonical_riesz_map_AMG(W, mms, params, AA):
    '''Approx Riesz map w.r.t to Hdiv x L2 x H^s'''
    V, Q, Y = W
    kappa1 = Constant(params.kappa)

    # Hdiv norm with piecewise conductivities
    mesh = V.mesh()
    cell_f = MeshFunction('size_t', mesh, mesh.topology().dim(), 0)
    # Mark
    [
        CompiledSubDomain(subd, tol=1E-10).mark(cell_f, tag)
        for tag, subd in enumerate(mms.subdomains[2])
    ]
    # 0 is outside and that is where we have kappa
    sigma, tau = TrialFunction(V), TestFunction(V)
    dX = Measure('dx', subdomain_data=cell_f)

    V_norm = assemble((1. / kappa1) * inner(sigma, tau) * dX(0) +
                      inner(sigma, tau) * dX(1) +
                      inner(div(sigma), div(tau)) * dX)

    p, q = TrialFunction(Q), TestFunction(Q)
    Q_norm = assemble(inner(p, q) * dx)

    # Multiplier on the boundary
    epsilon = Constant(params.eps)
    # Fractional part
    Hs = HsNorm(Y, s=[(1, 0.5), (1. / params.eps, 0.)])  # Weight
    Hs = Hs**-1
    # L2 part
    #p, q = TrialFunction(Y), TestFunction(Y)
    #m = (1./epsilon)*inner(p, q)*dx
    #M = assemble(m)

    #Y_norm = mat_add(Hs, M)

    return block_diag_mat([HypreAMS(A=V_norm, V=V), LU(Q_norm), Hs])
Пример #11
0
def cannonical_inner_product(W, mms, params):
    '''Inner product of Hdiv x L2 x H^s'''
    V, Q, Y = W
    kappa1 = Constant(params.kappa)

    # Hdiv norm with piecewise conductivities
    mesh = V.mesh()
    cell_f = MeshFunction('size_t', mesh, mesh.topology().dim(), 0)
    # Mark
    [
        CompiledSubDomain(subd, tol=1E-10).mark(cell_f, tag)
        for tag, subd in enumerate(mms.subdomains[2])
    ]
    # 0 is outside and that is where we have kappa
    sigma, tau = TrialFunction(V), TestFunction(V)
    dX = Measure('dx', subdomain_data=cell_f)

    V_norm = assemble((1. / kappa1) * inner(sigma, tau) * dX(0) +
                      inner(sigma, tau) * dX(1) +
                      inner(div(sigma), div(tau)) * dX)

    p, q = TrialFunction(Q), TestFunction(Q)
    Q_norm = assemble(inner(p, q) * dx)

    # Multiplier on the boundary
    epsilon = Constant(params.eps)
    # Fractional part
    Hs = matrix_fromHs(HsNorm(Y, s=0.5))  # Weight

    # L2 part
    p, q = TrialFunction(Y), TestFunction(Y)
    m = (1. / epsilon) * inner(p, q) * dx
    M = assemble(m)

    Y_norm = mat_add(Hs, M)

    return block_diag_mat([V_norm, Q_norm, Y_norm])
Пример #12
0
def nonlinear_babuska(N, u_exact, p_exact):
    '''MMS for the problem'''
    mesh = UnitSquareMesh(N, N)
    bmesh = BoundaryMesh(mesh, 'exterior')

    V = FunctionSpace(mesh, 'CG', 1)
    Q = FunctionSpace(bmesh, 'CG', 1)
    W = (V, Q)

    up = ii_Function(W)
    u, p = up  # Split

    v, q = list(map(TestFunction, W))
    Tu, Tv = (Trace(x, bmesh) for x in (u, v))

    dxGamma = Measure('dx', domain=bmesh)

    # Nonlinearity
    nl = lambda u: (Constant(2) + u)**2

    f_exact = -div(nl(u) * grad(u))
    g_exact = u

    f = interpolate(Expression(f_exact, subs={u: u_exact}, degree=1), V)
    h = interpolate(Expression(g_exact, subs={u: u_exact}, degree=4), Q)

    # The nonlinear functional
    F = [
        inner(nl(u) * grad(u), grad(v)) * dx + inner(p, Tv) * dxGamma -
        inner(f, v) * dx,
        inner(Tu, q) * dxGamma - inner(h, q) * dxGamma
    ]

    dF = block_jacobian(F, up)

    # Setup H1 x H-0.5 preconditioner only once
    B0 = ii_derivative(inner(grad(u), grad(v)) * dx + inner(u, v) * dx, u)
    # The Q norm via spectral
    B1 = inverse(HsNorm(Q, s=-0.5))  # The norm is inverted exactly
    # Preconditioner
    B = block_diag_mat([AMG(ii_assemble(B0)), B1])

    # Newton
    eps = 1.0
    tol = 1.0E-10
    niter = 0.
    maxiter = 25

    OptDB = PETSc.Options()
    # Since later b gets very small making relative too much work
    OptDB.setValue('ksp_atol', 1E-6)
    OptDB.setValue('ksp_monitor_true_residual', None)

    dup = ii_Function(W)
    x_vec = as_backend_type(dup.vector()).vec()

    n_kspiters = []
    while eps > tol and niter < maxiter:
        niter += 1.

        A, b = (ii_assemble(x) for x in (dF, F))

        ksp = PETSc.KSP().create()
        ksp.setType('minres')
        ksp.setNormType(PETSc.KSP.NormType.NORM_PRECONDITIONED)

        ksp.setOperators(ii_PETScOperator(A))
        ksp.setPC(ii_PETScPreconditioner(B, ksp))

        ksp.setFromOptions()

        ksp.solve(as_petsc_nest(b), x_vec)
        niters = ksp.getIterationNumber() + 1

        n_kspiters.append(niters)

        eps = sqrt(sum(x.norm('l2')**2 for x in dup.vectors()))

        print('\t%d |du| = %g | niters %d' % (niter, eps, niters))

        # FIXME: Update
        for i in range(len(W)):
            up[i].vector().axpy(-1, dup[i].vector())

    return up, n_kspiters