Example #1
0
    ext_mesh = EmbeddedMesh(facet_f, 1)
    EV = FunctionSpace(ext_mesh, 'CG', 1)

    # The auxiliary problem would be speced at
    aux_mesh = SubMesh(mesh, cell_f, 1)
    facet_f = MeshFunction('size_t', aux_mesh, 1, 0)
    DomainBoundary().mark(facet_f, 1)
    left.mark(facet_f, 2)
    right.mark(facet_f, 2)

    # Extending from
    gamma_mesh = StraightLineMesh(np.array([0.5, 0]), np.array([0.5, 1]), 3*ny)
    V = FunctionSpace(gamma_mesh, 'CG', 1)

    E = harmonic_extension_operator(V, EV, auxiliary_facet_f=facet_f)

    v = interpolate(Constant(1), V).vector()
    q = Function(EV, E*v)
    File('foo.pvd') << q
    
    from xii.linalg.convert import collapse
    E_ = collapse(E)

    q = Function(EV, E_*v)
    File('foo_.pvd') << q


    

Example #2
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
Example #3
0
def setup_preconditioner(W, which, eps=None):
    '''
    Mirror the structure of preconditioner proposed in 
    
      Robust preconditioners for PDE-constrained optimization with limited
      observations; Mardal and Nielsen and Nordaas, BIT 2017

    or Schoeberl and Zulehner's
      
      Symmetric indefinite preconditioners for saddle point problems with 
      applications to PDE constrained optimization problems
    '''
    from block.algebraic.petsc import AMG
    from block.algebraic.petsc import LumpedInvDiag
    from xii.linalg.convert import collapse
    print 'WHICH is', which
    (Q, V, B) = W

    p, u, lmbda = map(TrialFunction, W)
    q, v, beta = map(TestFunction, W)

    bmesh = BoundaryMesh(Q.mesh(), 'exterior')
    Tu = Trace(u, bmesh)
    Tv = Trace(v, bmesh)

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

    # Nielsen
    if which == 0:
        b00 = Constant(eps)*inner(p, q)*dx
        B00 = LumpedInvDiag(ii_assemble(b00))
        
        M_bdry = ii_convert(ii_assemble(inner(Tu, Tv)*dxGamma))
        # H2 norm with H1 elements
        A = ii_assemble(inner(grad(v), grad(u))*dx + inner(v, u)*dx)
        # From dual to nodal
        M = LumpedInvDiag(ii_assemble(inner(u, v)*dx))
        # The whole matrix to be inverted is then (second term is H2 approx)
        B11 = collapse(M_bdry + eps*A*M*A)
        # 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))
    # SZ
    else:
        print 'X'
        # eps*L2
        b00 = Constant(eps)*inner(p, q)*dx
        B00 = LumpedInvDiag(ii_assemble(b00))

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

        # (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))
    
    return block_diag_mat([B00, B11, B22])
Example #4
0
def setup_preconditioner(W, which, eps=None):
    '''
    Mirror the structure of preconditioner proposed in 
    
      Robust preconditioners for PDE-constrained optimization with limited
      observations; Mardal and Nielsen and Nordaas, BIT 2017

    or Schoeberl and Zulehner's
      
      Symmetric indefinite preconditioners for saddle point problems with 
      applications to PDE constrained optimization problems
    '''
    from block.algebraic.petsc import AMG
    from block.algebraic.petsc import LumpedInvDiag
    from xii.linalg.convert import collapse
    print('WHICH is', which)
    (Q, V, B) = W

    p, u, lmbda = list(map(TrialFunction, W))
    q, v, beta = list(map(TestFunction, W))

    bmesh = BoundaryMesh(Q.mesh(), 'exterior')
    Tu = Trace(u, bmesh)
    Tv = Trace(v, bmesh)

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

    # Nielsen
    if which == 0:
        b00 = Constant(eps) * inner(p, q) * dx
        B00 = LumpedInvDiag(ii_assemble(b00))

        M_bdry = ii_convert(ii_assemble(inner(Tu, Tv) * dxGamma))
        # H2 norm with H1 elements
        A = ii_assemble(inner(grad(v), grad(u)) * dx + inner(v, u) * dx)
        # From dual to nodal
        M = LumpedInvDiag(ii_assemble(inner(u, v) * dx))
        # The whole matrix to be inverted is then (second term is H2 approx)
        B11 = collapse(M_bdry + eps * A * M * A)
        # 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))
    # SZ
    else:
        print('X')
        # eps*L2
        b00 = Constant(eps) * inner(p, q) * dx
        B00 = LumpedInvDiag(ii_assemble(b00))

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

        # (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))

    return block_diag_mat([B00, B11, B22])
Example #5
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 = map(TrialFunction, W)
    q, v, beta = 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 = 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 = 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.iteritems():
        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