Ejemplo n.º 1
0
def setup_preconditioner(W, which, eps):
    '''
    This is a block diagonal preconditioner based on 
    
        Hdiv x L2 x (H0.5 \cap sqrt(eps)*L2) or ? 
    '''
    from block.algebraic.petsc import LU
    from block.algebraic.petsc import LumpedInvDiag
    from hsmg import HsNorm
    
    S, V, Q = W

    # Hdiv
    sigma, tau = TrialFunction(S), TestFunction(S)
    b00 = inner(div(sigma), div(tau))*dx + inner(sigma, tau)*dx
    # Inverted exactly
    B00 = LU(ii_assemble(b00))

    # L2
    u, v = TrialFunction(V), TestFunction(V)
    b11 = inner(u, v)*dx
    # Inverted by BoomerAMG
    B11 = LumpedInvDiag(ii_assemble(b11))

    # The Q norm via spectral
    B22 = inverse(HsNorm(Q, s=0.5) + eps*HsNorm(Q, s=0.0))# The norm is inverted exactly

    return block_diag_mat([B00, B11, B22])
Ejemplo n.º 2
0
def setup_preconditioner(W, which, eps):
    from block.algebraic.petsc import AMG
    from block.algebraic.petsc import LumpedInvDiag, LU
    from hsmg import HsNorm

    u1, ub, p1, u2, p2, lambda_ = map(TrialFunction, W)
    v1, vb, q1, v2, q2, beta_ = map(TestFunction, W)

    # Neither is super spectacular
    # Completely block diagonal preconditioner with H1 on the bubble space
    if which == 0:
        b00 = inner(grad(u1), grad(v1)) * dx + inner(u1, v1) * dx
        B00 = AMG(ii_assemble(b00))

        bbb = inner(grad(ub), grad(vb)) * dx + inner(ub, vb) * dx
        Bbb = LumpedInvDiag(ii_assemble(bbb))

        b11 = inner(p1, q1) * dx
        B11 = AMG(ii_assemble(b11))

        b22 = inner(div(u2), div(v2)) * dx + inner(u2, v2) * dx
        B22 = LU(ii_assemble(b22))

        b33 = inner(p2, q2) * dx
        B33 = LumpedInvDiag(ii_assemble(b33))

        B44 = inverse(HsNorm(W[-1], s=0.5))

        return block_diag_mat([B00, Bbb, B11, B22, B33, B44])

    # Monolithic for MINI velocity
    b = [[0, 0], [0, 0]]
    b[0][0] = inner(grad(u1), grad(v1)) * dx + inner(u1, v1) * dx
    b[0][1] = inner(grad(ub), grad(v1)) * dx + inner(ub, v1) * dx
    b[1][0] = inner(grad(u1), grad(vb)) * dx + inner(u1, vb) * dx
    b[1][1] = inner(grad(ub), grad(vb)) * dx + inner(ub, vb) * dx
    # Make into a monolithic matrix
    B00 = AMG(ii_convert(ii_assemble(b)))

    b11 = inner(p1, q1) * dx
    B11 = AMG(ii_assemble(b11))

    b22 = inner(div(u2), div(v2)) * dx + inner(u2, v2) * dx
    B22 = LU(ii_assemble(b22))

    b33 = inner(p2, q2) * dx
    B33 = LumpedInvDiag(ii_assemble(b33))

    B44 = inverse(HsNorm(W[-1], s=0.5))
    # So this is a 5x5 matrix
    BB = block_diag_mat([B00, B11, B22, B33, B44])
    # But the preconditioner has to be 6x6; reduce 6 to 6 by comcat
    # first two, rest stays same
    R = ReductionOperator([2, 3, 4, 5, 6], W)

    return (R.T) * BB * R
Ejemplo n.º 3
0
def setup_preconditioner(W, which, eps):
    '''
    This is a block diagonal preconditioner based on 
    
        H1 x H1 x (H-0.5 \cap \sqrt{eps-1}*L2) or ...
    '''
    # NOTE for eps large the fractional term is expected to dominte
    from block.algebraic.petsc import AMG
    from block.algebraic.petsc import LumpedInvDiag
    from hsmg import HsNorm

    V1, V2, Q = W

    if which == 0:
        # H1
        print '\tUsing H1 x H1 x (sqrt(1./%g)*L2 \cap H-0.5) preconditioner' % eps
        u1, v1 = TrialFunction(V1), TestFunction(V1)
        b00 = inner(grad(u1), grad(v1)) * dx + inner(u1, v1) * dx
        # Inverted by BoomerAMG
        B00 = AMG(ii_assemble(b00))

        u2, v2 = TrialFunction(V2), TestFunction(V2)
        b11 = inner(grad(u2), grad(v2)) * dx + inner(u2, v2) * dx
        # Inverted by BoomerAMG
        B11 = AMG(ii_assemble(b11))

        # The Q norm via spectral, the norm is inverted exactly
        B22 = inverse((HsNorm(Q, s=-0.5) + (eps**-1) * HsNorm(Q, s=0.0)))
    else:
        print '\tUsing (H1 \cap H0.5) x (H1 \cap H0.5) x sqrt(%g)*L2 preconditioner' % eps

        iface = Q.mesh()
        dxGamma = dx(domain=iface)
        # H1
        u1, v1 = TrialFunction(V1), TestFunction(V1)
        Tu1, Tv1 = Trace(u1, iface), Trace(v1, iface)

        b00 = inner(grad(u1), grad(v1)) * dx + inner(u1, v1) * dx + inner(
            Tu1, Tv1) * dxGamma
        # Inverted by BoomerAMG
        B00 = AMG(ii_convert(ii_assemble(b00)))

        u2, v2 = TrialFunction(V2), TestFunction(V2)
        Tu2, Tv2 = Trace(u2, iface), Trace(v2, iface)

        b11 = inner(grad(u2), grad(v2)) * dx + inner(u2, v2) * dx + inner(
            Tu2, Tv2) * dxGamma
        # Inverted by BoomerAMG
        B11 = AMG(ii_convert(ii_assemble(b11)))

        # The Q norm via spectral
        p, q = TrialFunction(Q), TestFunction(Q)
        b22 = Constant(1. / eps) * inner(p, q) * dxGamma
        B22 = LumpedInvDiag(ii_assemble(b22))

    return block_diag_mat([B00, B11, B22])
Ejemplo n.º 4
0
def setup_preconditioner(W, which, eps):
    '''The preconditioner'''
    from block.algebraic.petsc import AMG, LumpedInvDiag
    from block import block_transpose
    from hsmg import HsNorm

    u, ub, p, lambda_ = map(TrialFunction, W)
    v, vb, q, beta_ = map(TestFunction, W)

    # A block diagonal preconditioner
    if which == 0:
        b00 = inner(grad(u), grad(v)) * dx + inner(u, v) * dx
        B00 = AMG(ii_assemble(b00))

        b11 = inner(grad(ub), grad(vb)) * dx + inner(ub, vb) * dx
        B11 = LumpedInvDiag(ii_assemble(b11))

        b22 = inner(p, q) * dx
        B22 = AMG(ii_assemble(b22))

        M = W[-1]
        Mi = M.sub(0).collapse()
        B33 = inverse(VectorizedOperator(HsNorm(Mi, s=-0.5), M))

        return block_diag_mat([B00, B11, B22, B33])

    # Preconditioner monolithic in Stokes velocity
    b = [[0, 0], [0, 0]]
    b[0][0] = inner(grad(u), grad(v)) * dx + inner(u, v) * dx
    b[0][1] = inner(grad(ub), grad(v)) * dx + inner(ub, v) * dx
    b[1][0] = inner(grad(u), grad(vb)) * dx + inner(u, vb) * dx
    b[1][1] = inner(grad(ub), grad(vb)) * dx + inner(ub, vb) * dx
    # Make into a monolithic matrix
    B00 = AMG(ii_convert(ii_assemble(b)))

    b11 = inner(p, q) * dx
    B11 = AMG(ii_assemble(b11))

    M = W[-1]
    Mi = M.sub(0).collapse()
    B22 = inverse(VectorizedOperator(HsNorm(Mi, s=-0.5), M))
    # So this is a 3x3 matrix
    BB = block_diag_mat([B00, B11, B22])
    # But the preconditioner has to be 4x4
    R = ReductionOperator([2, 3, 4], W)

    return (R.T) * BB * R
Ejemplo n.º 5
0
def setup_preconditioner(W, p_constant):
    '''Just an idea H1 x H1 x (Hs \cap p_constant L2)'''
    from block.algebraic.petsc import AMG
    from hsmg import HsNorm

    u3, u, p = map(TrialFunction, W)
    v3, v, q = map(TestFunction, W)

    b00 = inner(grad(u3), grad(v3)) * dx + inner(u3, v3) * ds
    B00 = assemble(b00)

    b11 = inner(grad(u), grad(v)) * dx + inner(u, v) * ds
    B11 = assemble(b11)

    B22 = inverse(HsNorm(W[-1], s=-0.5) + p_constant * HsNorm(W[-1], s=0.0))

    return block_diag_mat([AMG(B00), AMG(B11), B22])
Ejemplo n.º 6
0
def setup_preconditioner(W, which, eps):
    '''
    TODO
    '''
    from block.algebraic.petsc import AMG
    from block.algebraic.petsc import LumpedInvDiag
    from hsmg import HsNorm

    V1, V2, Q = W

    gamma_mesh = Q.mesh()
    dxGamma = Measure('dx', domain=gamma_mesh)

    u1, u2 = map(TrialFunction, (V1, V2))
    v1, v2 = map(TestFunction, (V1, V2))

    Tu1, Tu2 = map(lambda x: Trace(x, gamma_mesh), (u1, u2))
    Tv1, Tv2 = map(lambda x: Trace(x, gamma_mesh), (v1, v2))

    if eps > 1:
        b00 = Constant(eps) * inner(grad(u1), grad(v1)) * dx + inner(u1,
                                                                     v1) * dx
        B00 = ii_assemble(b00)
    else:
        b00 = Constant(eps) * inner(grad(u1), grad(v1)) * dx + inner(
            u1, v1) * dx + inner(Tu1, Tv1) * dxGamma
        B00 = ii_convert(ii_assemble(b00))
    B00 = AMG(B00)

    b11 = inner(grad(u2), grad(v2)) * dx + inner(u2, v2) * dx
    # Inverted by BoomerAMG
    B11 = AMG(ii_assemble(b11))

    if eps > 1:
        B22 = inverse(HsNorm(Q, s=-0.5))
    else:
        B22 = inverse(HsNorm(Q, s=0.5))

    return block_diag_mat([B00, B11, B22])
Ejemplo n.º 7
0
def setup_preconditioner(W, which, eps=None):
    '''
    This is a block diagonal preconditioner based on H1 x H^{-0.5}
    '''
    from xii.linalg.matrix_utils import as_petsc
    from numpy import hstack
    from petsc4py import PETSc
    from hsmg import HsNorm

    assert len(eps) == 2
    mu_value, lmbda_value = eps

    V, Q = W

    # H1
    u, v = TrialFunction(V), TestFunction(V)
    b00 = inner(grad(u), grad(v)) * dx + inner(u, v) * dx
    A = as_backend_type(assemble(b00))

    # Attach rigid deformations to A
    # Functions
    Z = [
        interpolate(Constant((1, 0)), V),
        interpolate(Constant((0, 1)), V),
        interpolate(Expression(('x[1]', '-x[0]'), degree=1), V)
    ]
    # The basis
    Z = VectorSpaceBasis([z.vector() for z in Z])
    Z.orthonormalize()
    A.set_nullspace(Z)
    A.set_near_nullspace(Z)

    A = as_petsc(A)
    # Setup the preconditioner in petsc
    pc = PETSc.PC().create()
    pc.setType(PETSc.PC.Type.HYPRE)
    pc.setOperators(A)
    # Other options
    opts = PETSc.Options()
    opts.setValue('pc_hypre_boomeramg_cycle_type', 'V')
    opts.setValue('pc_hypre_boomeramg_relax_type_all', 'symmetric-SOR/Jacobi')
    opts.setValue('pc_hypre_boomeramg_coarsen_type', 'Falgout')
    pc.setFromOptions()

    # Wrap for cbc.block
    B00 = BlockPC(pc)
    # The Q norm via spectral
    Qi = Q.sub(0).collapse()
    B11 = inverse(VectorizedOperator(HsNorm(Qi, s=-0.5), Q))

    return block_diag_mat([B00, B11])
Ejemplo n.º 8
0
def setup_preconditioner(W, which, eps=None):
    '''
    This is a block diagonal preconditioner based on Hdiv x H0.5'''
    from block.algebraic.petsc import LU
    from hsmg import HsNorm

    S, Q = W

    sigma, tau = TrialFunction(S), TestFunction(S)
    # Hdiv
    b00 = inner(div(sigma), div(tau)) * dx + inner(sigma, tau) * dx
    B00 = LU(ii_assemble(b00))  # Exact
    # H0.5
    B11 = HsNorm(Q, s=0.5)**-1  # The norm is inverted exactly

    return block_diag_mat([B00, B11])
def setup_preconditioner(W, which, eps):
    '''The preconditioner'''
    from block.algebraic.petsc import AMG, LumpedInvDiag
    from hsmg import HsNorm

    u, p, lambda_ = map(TrialFunction, W)
    v, q, beta_ = map(TestFunction, W)

    b00 = inner(grad(u), grad(v)) * dx + inner(u, v) * dx
    B00 = AMG(ii_assemble(b00))

    b11 = inner(p, q) * dx
    B11 = AMG(ii_assemble(b11))

    M = W[-1]
    Mi = M.sub(0).collapse()
    B22 = inverse(VectorizedOperator(HsNorm(Mi, s=-0.5), M))

    return block_diag_mat([B00, B11, B22])
Ejemplo n.º 10
0
def setup_preconditioner(W, which, eps=None):
    '''
    This is a block diagonal preconditioner based on H1 x L2 x H^{-0.5}
    '''
    from block.algebraic.petsc import LumpedInvDiag
    from xii.linalg.matrix_utils import as_petsc
    from numpy import hstack
    from petsc4py import PETSc
    from hsmg import HsNorm

    V, Q, Y = W

    # H1
    u, v = TrialFunction(V), TestFunction(V)
    b00 = inner(grad(u), grad(v)) * dx + inner(u, v) * dx
    # NOTE: since interpolation is broken with MINI I don't interpolate
    # here the RM basis to attach the vectros to matrix
    A = assemble(b00)

    A = as_petsc(A)
    # Setup the preconditioner in petsc
    pc = PETSc.PC().create()
    pc.setType(PETSc.PC.Type.HYPRE)
    pc.setOperators(A)
    # Other options
    opts = PETSc.Options()
    opts.setValue('pc_hypre_boomeramg_cycle_type', 'V')
    opts.setValue('pc_hypre_boomeramg_relax_type_all', 'symmetric-SOR/Jacobi')
    opts.setValue('pc_hypre_boomeramg_coarsen_type', 'Falgout')
    pc.setFromOptions()
    # Wrap for cbc.block
    B00 = BlockPC(pc)

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

    # The Y norm via spectral
    Yi = Y.sub(0).collapse()
    B22 = inverse(VectorizedOperator(HsNorm(Yi, s=-0.5), Y))

    return block_diag_mat([B00, B11, B22])
Ejemplo n.º 11
0
def setup_preconditioner(W, which, eps):
    '''The preconditioner'''
    from block.algebraic.petsc import AMG
    from hsmg import HsNorm

    u, p, lambda_ = map(TrialFunction, W)
    v, q, beta_ = map(TestFunction, W)

    b00 = Constant(eps) * inner(grad(u), grad(v)) * dx + inner(u, v) * dx
    B00 = AMG(ii_assemble(b00))

    b11a = Constant(1. / eps) * inner(p, q) * dx

    b11b = inner(grad(p), grad(q)) * dx
    bcs = DirichletBC(W[1], Constant(0), 'on_boundary')
    B11b, _ = assemble_system(b11b, inner(Constant(0), q) * dx, bcs)

    B11 = AMG(ii_assemble(b11a)) + AMG(B11b)

    B22 = inverse((1. / eps) * HsNorm(W[-1], s=-0.5))

    return block_diag_mat([B00, B11, B22])
Ejemplo n.º 12
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 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])
def setup_preconditioner(W, which, eps):
    from block.algebraic.petsc import AMG
    from block.algebraic.petsc import LumpedInvDiag, LU
    from hsmg import HsNorm

    u1, p1, u2, p2, lambda_ = map(TrialFunction, W)
    v1, q1, v2, q2, beta_ = map(TestFunction, W)
    # This is not spectacular
    b00 = inner(grad(u1), grad(v1)) * dx + inner(u1, v1) * dx
    B00 = AMG(ii_assemble(b00))

    b11 = inner(p1, q1) * dx
    B11 = AMG(ii_assemble(b11))

    b22 = inner(div(u2), div(v2)) * dx + inner(u2, v2) * dx
    B22 = LU(ii_assemble(b22))

    b33 = inner(p2, q2) * dx
    B33 = LumpedInvDiag(ii_assemble(b33))

    B44 = inverse(HsNorm(W[-1], s=0.5))

    return block_diag_mat([B00, B11, B22, B33, B44])
Ejemplo n.º 14
0
from hsmg import HsNorm
import numpy as np

mesh = UnitSquareMesh(10, 10)
VV = FunctionSpace(mesh,
                   MixedElement([FiniteElement('Lagrange', triangle, 1)] * 3))
u, v = TrialFunction(VV), TestFunction(VV)
M = assemble(inner(u, v) * dx)

x = M.create_vec()
x.set_local(np.random.rand(x.local_size()))

y = M * x

V = FunctionSpace(mesh, 'CG', 1)
u, v = TrialFunction(V), TestFunction(V)
Mj = assemble(inner(u, v) * dx)
# Should match M
X = VectorizedOperator(Mj, VV)
y0 = X * x

print(x.norm('l2'), (y - y0).norm('linf'))

I = HsNorm(V, s=0.5)
II = VectorizedOperator(I, VV)

foo = II * x
x0 = inverse(II) * foo

print((x - x0).norm('linf'))
Ejemplo n.º 15
0
def solve_problem(ncells, eps, solver_params):
    '''Optim problem on [0, 1]^2'''
    # Made up
    f = Expression('x[0] + x[1]', degree=1)

    mesh = UnitSquareMesh(*(ncells, ) * 2)
    bmesh = BoundaryMesh(mesh, 'exterior')

    Q = FunctionSpace(mesh, 'DG', 0)
    V = FunctionSpace(mesh, 'CG', 1)
    B = FunctionSpace(mesh, 'CG', 1)
    W = [Q, V, B]

    p, u, lmbda = list(map(TrialFunction, W))
    q, v, beta = list(map(TestFunction, W))
    Tu = Trace(u, bmesh)
    Tv = Trace(v, bmesh)

    # The line integral
    dxGamma = Measure('dx', domain=bmesh)

    a = [[0] * len(W) for _ in range(len(W))]

    a[0][0] = Constant(eps) * inner(p, q) * dx
    a[0][2] = inner(q, lmbda) * dx
    # We put zero on the diagonal temporarily and then replace by
    # the fractional laplacian
    a[1][1] = 0
    a[1][2] = inner(grad(v), grad(lmbda)) * dx + inner(v, lmbda) * dx

    a[2][0] = inner(p, beta) * dx
    a[2][1] = inner(grad(u), grad(beta)) * dx + inner(u, beta) * dx

    L = [
        inner(Constant(0), q) * dx,
        inner(Constant(0), v) * dx,  # Same replacement idea here
        inner(Constant(0), beta) * dx
    ]
    # All but (1, 1) and 1 are final
    AA, bb = list(map(ii_assemble, (a, L)))

    # Now I want and operator which corresponds to (Tv, (-Delta^{0.5} T_u))_bdry
    TV = FunctionSpace(bmesh, 'CG', 1)
    T = PETScMatrix(trace_mat_no_restrict(V, TV))
    # The fractional laplacian nodal->dual
    fDelta = HsNorm(TV, s=0.5)
    # This should be it
    A11 = block_transpose(T) * fDelta * T
    # Now, while here we can also comute the rhs contribution
    # (Tv, (-Delta^{0.5}, f))
    f_vec = interpolate(f, V).vector()
    b1 = A11 * f_vec
    bb[1] = b1
    AA[1][1] = A11

    wh = ii_Function(W)
    # Direct solve
    if not solver_params:
        AAm, bbm = list(map(ii_convert, (AA, bb)))
        LUSolver('umfpack').solve(AAm, wh.vector(), bbm)
        return wh, -1

    # Magne like precond
    if False:
        # Preconditioner like in the L2 case but with L2 bdry replaced
        b00 = Constant(eps) * inner(p, q) * dx
        B00 = LumpedInvDiag(ii_assemble(b00))

        H1 = ii_assemble(inner(grad(v), grad(u)) * dx + inner(v, u) * dx)
        # From dual to nodal
        R = LumpedInvDiag(ii_assemble(inner(u, v) * dx))
        # The whole matrix to be inverted is then (second term is H2 approx)
        B11 = collapse(A11 + eps * H1 * R * H1)
        # And the inverse
        B11 = AMG(B11, parameters={'pc_hypre_boomeramg_cycle_type': 'W'})

        b22 = Constant(1. / eps) * inner(lmbda, beta) * dx
        B22 = LumpedInvDiag(ii_assemble(b22))
    # A bit like SZ
    else:
        b00 = Constant(eps) * inner(p, q) * dx
        B00 = LumpedInvDiag(ii_assemble(b00))

        # L2 \cap eps H1
        H1 = assemble(
            Constant(eps) * (inner(grad(v), grad(u)) * dx + inner(v, u) * dx))
        B11 = AMG(collapse(A11 + H1))

        # (1./eps)*L2 \cap 1./sqrt(eps)H1
        a = Constant(1./eps)*inner(beta, lmbda)*dx + \
            Constant(1./sqrt(eps))*(inner(grad(beta), grad(lmbda))*dx + inner(beta, lmbda)*dx)
        B22 = AMG(assemble(a))

    BB = block_diag_mat([B00, B11, B22])

    # Want the iterations to start from random (iterative)
    wh.block_vec().randomize()

    # Default is minres
    if '-ksp_type' not in solver_params: solver_params['-ksp_type'] = 'minres'

    opts = PETSc.Options()
    for key, value in solver_params.items():
        opts.setValue(key, None if value == 'none' else value)

    ksp = PETSc.KSP().create()
    ksp.setOperators(ii_PETScOperator(AA))
    ksp.setPC(ii_PETScPreconditioner(BB, ksp))

    ksp.setNormType(PETSc.KSP.NormType.NORM_PRECONDITIONED)
    ksp.setFromOptions()

    ksp.solve(as_petsc_nest(bb), wh.petsc_vec())

    niters = ksp.getIterationNumber()

    return wh, niters