def make_inv_mat(self, idx, inv):
        ro = np.hstack([0, np.cumsum(np.array(self.lsize)[idx])])
        row = mfem.intArray(list(ro))
        col = mfem.intArray(list(ro))
        mat = mfem.BlockOperator(row, col)

        for ii, i in enumerate(idx):
            mat.SetBlock(ii, ii, inv[i])
        return mat
Пример #2
0
    def get_global_blkmat_interleave(self):
        '''
        This routine ordered unkonws in the following order
           Re FFE1, Im FES1, ReFES2, Im FES2, ...
        If self.complex is False, it assembles a nomal block
        matrix FES1, FES2...
        '''
        roffsets, coffsets = self.get_local_partitioning(convert_real=True,
                                                         interleave=True)
        dprint1("offsets", roffsets, coffsets)
        ro = mfem.intArray(list(roffsets))
        co = mfem.intArray(list(coffsets))
        glcsr = mfem.BlockOperator(ro, co)

        ii = 0

        for i in range(self.shape[0]):
            jj = 0
            for j in range(self.shape[1]):
                if self[i, j] is not None:
                    if use_parallel:
                        if isinstance(self[i, j], chypre.CHypreMat):
                            gcsr = self[i, j]
                            cp = self[i, j].GetColPartArray()
                            rp = self[i, j].GetRowPartArray()
                            s = self[i, j].shape
                            #if (cp == rp).all() and s[0] == s[1]:
                            if gcsr[0] is not None:
                                csr = ToScipyCoo(gcsr[0]).tocsr()
                                gcsr[0] = ToHypreParCSR(csr, col_starts=cp)
                            if gcsr[1] is not None:
                                csr = ToScipyCoo(gcsr[1]).tocsr()
                                gcsr[1] = ToHypreParCSR(csr, col_starts=cp)
                                gcsrm = ToHypreParCSR(-csr, col_starts=cp)
                            dprint2(i, j, s, rp, cp)
                        else:
                            assert False, "unsupported block element " + str(
                                type(self[i, j]))
                    else:
                        if isinstance(self[i, j], ScipyCoo):
                            gcsr = self[i, j].get_mfem_sparsemat()
                            if gcsr[1] is not None:
                                gcsrm = mfem.SparseMatrix(gcsr[1])
                                gcsrm *= -1.
                        else:
                            assert False, "unsupported block element " + type(
                                self[i, j])
                    glcsr.SetBlock(ii, jj, gcsr[0])
                    if self.complex:
                        glcsr.SetBlock(ii + 1, jj + 1, gcsr[0])
                    if gcsr[1] is not None:
                        glcsr.SetBlock(ii + 1, jj, gcsr[1])
                        glcsr.SetBlock(ii, jj + 1, gcsrm)
                jj = jj + 2 if self.complex else jj + 1
            ii = ii + 2 if self.complex else ii + 1

        return glcsr
 def make_sub_matrix(self, src_mat, roffset, coffset, row_idx, col_idx):
     ro = mfem.intArray(list(roffset))
     co = mfem.intArray(list(coffset))
     mat = mfem.BlockOperator(ro, co)
     for ii, i in enumerate(row_idx):
         for jj, j in enumerate(col_idx):
             m = get_block(src_mat, i, j)
             if m is None: continue
             mat.SetBlock(ii, jj, m)
     return mat
Пример #4
0
true_s1 = xhat_space.TrueVSize()
true_s_test = test_space.TrueVSize()

true_offsets = mfem.intArray([0, true_s0, true_s0 + true_s1])
true_offsets_test = mfem.intArray([0, true_s_test])

x = mfem.BlockVector(true_offsets)
b = mfem.BlockVector(true_offsets)
x.Assign(0.0)
b.Assign(0.0)

# 10. Set up the 1x2 block Least Squares DPG operator, B = [B0 Bhat],
#     the normal equation operator, A = B^t Sinv B, and
#     the normal equation right-hand-size, b = B^t Sinv F.

B = mfem.BlockOperator(true_offsets_test, true_offsets)
B.SetBlock(0, 0, matB0)
B.SetBlock(0, 1, matBhat)

A = mfem.RAPOperator(B, matSinv, B)

trueF = F.ParallelAssemble()

SinvF = mfem.HypreParVector(test_space)
matSinv.Mult(trueF, SinvF)
B.MultTranspose(SinvF, b)

# 11. Set up a block-diagonal preconditioner for the 2x2 normal equation
#
#        [ S0^{-1}     0     ]
#        [   0     Shat^{-1} ]      Shat = (Bhat^T Sinv Bhat)
Пример #5
0
mVarf = mfem.ParBilinearForm(R_space)
bVarf = mfem.ParMixedBilinearForm(R_space, W_space)

mVarf.AddDomainIntegrator(mfem.VectorFEMassIntegrator(k))
mVarf.Assemble()
mVarf.Finalize()
M = mVarf.ParallelAssemble()

bVarf.AddDomainIntegrator(mfem.VectorFEDivergenceIntegrator())
bVarf.Assemble()
bVarf.Finalize()
B = bVarf.ParallelAssemble()
B *= -1
BT = B.Transpose()

darcyOp = mfem.BlockOperator(block_trueOffsets)
darcyOp.SetBlock(0, 0, M)
darcyOp.SetBlock(0, 1, BT)
darcyOp.SetBlock(1, 0, B)

#M2 = M.Transpose()
#M3 = M2.Transpose()
MinvBt = B.Transpose()
Md = mfem.HypreParVector(MPI.COMM_WORLD, M.GetGlobalNumRows(),
                         M.GetRowStarts())
M.GetDiag(Md)
MinvBt.InvScaleRows(Md)
S = mfem.hypre.ParMult(B, MinvBt)

invM = mfem.HypreDiagScale(M)
invS = mfem.HypreBoomerAMG(S)
Пример #6
0
    def get_global_blkmat_merged(self, symmetric=False):
        '''
        This routine ordered unkonws in the following order
           Re FFE1, Im FES1, ReFES2, Im FES2, ...
        matrix FES1, FES2...
        '''
        assert self.complex, "this format is complex only"

        roffsets, coffsets = self.get_local_partitioning()
        roffsets = np.sum(np.diff(roffsets).reshape(-1, 2), 1)
        coffsets = np.sum(np.diff(coffsets).reshape(-1, 2), 1)
        roffsets = np.hstack([0, np.cumsum(roffsets)])
        coffsets = np.hstack([0, np.cumsum(coffsets)])
        dprint1("Generating MFEM BlockMatrix: shape = " +
                str((len(roffsets) - 1, len(coffsets) - 1)))
        dprint1("Generating MFEM BlockMatrix: roffset/coffset = ", roffsets,
                coffsets)

        ro = mfem.intArray(list(roffsets))
        co = mfem.intArray(list(coffsets))
        glcsr = mfem.BlockOperator(ro, co)

        ii = 0

        for j in range(self.shape[1]):
            jfirst = True
            for i in range(self.shape[0]):
                if self[i, j] is not None:
                    if use_parallel:
                        if isinstance(self[i, j], chypre.CHypreMat):
                            gcsr = self[i, j]
                            cp = self[i, j].GetColPartArray()
                            rp = self[i, j].GetRowPartArray()
                            rsize_local = rp[1] - rp[0]

                            if jfirst:
                                csize_local = cp[1] - cp[0]
                                csize = allgather(csize_local)
                                cstarts = np.hstack([0, np.cumsum(csize)])
                                jfirst = False
                            s = self[i, j].shape
                            # if (cp == rp).all() and s[0] == s[1]:
                            '''
                            if gcsr[0] is not None:
                                csc = ToScipyCoo(gcsr[0]).tocsc()
                                csc1 = [csc[:,cstarts[k]:cstarts[k+1]] for k in range(len(cstarts)-1)]
                                if symmetric:
                                   csc1m = [-csc[:,cstarts[k]:cstarts[k+1]] for k in range(len(cstarts)-1)]
                            else:
                                csc1 = [None]*len(csize)
                                csc1m = [None]*len(csize)

                            if gcsr[1] is not None:
                                csc   = ToScipyCoo(gcsr[1]).tocsc()
                                if not symmetric:
                                    csc2  = [ csc[:,cstarts[k]:cstarts[k+1]] for k in range(len(cstarts)-1)]
                                csc2m = [-csc[:,cstarts[k]:cstarts[k+1]] for k in range(len(cstarts)-1)]
                            else:
                                csc2  = [None]*len(csize)
                                csc2m = [None]*len(csize)

                            if symmetric:
                                csr = scipy.sparse.bmat([sum(zip(csc1, csc2m), ()),
                                                         sum(zip(csc2m, csc1m),  ())]).tocsr()
                            else:
                                csr = scipy.sparse.bmat([sum(zip(csc1, csc2m), ()),
                                                         sum(zip(csc2, csc1),  ())]).tocsr()

                            cp2 = [(cp*2)[0], (cp*2)[1], np.sum(csize)*2]
                            #gcsr[1] = ToHypreParCSR(csr, col_starts =cp)
                            gcsr  = ToHypreParCSR(csr, col_starts =cp2)
                            '''
                            if gcsr[0] is None:
                                csr = scipy.sparse.csr_matrix(
                                    (rsize_local, cstarts[-1]),
                                    dtype=np.float64)
                                cp3 = [cp[0], cp[1], cstarts[-1]]
                                gcsa = ToHypreParCSR(csr, col_starts=cp3)
                            else:
                                gcsa = gcsr[0]

                            if gcsr[1] is None:
                                csr = scipy.sparse.csr_matrix(
                                    (rsize_local, cstarts[-1]),
                                    dtype=np.float64)
                                cp3 = [cp[0], cp[1], cstarts[-1]]
                                gcsb = ToHypreParCSR(csr, col_starts=cp3)
                            else:
                                gcsb = gcsr[1]

                        else:
                            assert False, "unsupported block element " + \
                                str(type(self[i, j]))
                    else:
                        if isinstance(self[i, j], ScipyCoo):
                            '''
                            if symmetric:
                                tmp  = scipy.sparse.bmat([[ self[i, j].real, -self[i, j].imag],
                                                          [-self[i, j].imag, -self[i, j].real]])
                            else:
                                tmp  = scipy.sparse.bmat([[self[i, j].real, -self[i, j].imag],
                                                          [self[i, j].imag,  self[i, j].real]])
                            '''
                            csra = self[i, j].real.tocsr()
                            csrb = self[i, j].imag.tocsr()
                            csra.eliminate_zeros()
                            csrb.eliminate_zeros()
                            gcsa = mfem.SparseMatrix(csra)
                            gcsb = mfem.SparseMatrix(csrb)
                        else:
                            assert False, "unsupported block element " + \
                                type(self[i, j])

                    Hermitian = False if symmetric else True
                    gcsr = mfem.ComplexOperator(gcsa, gcsb, False, False,
                                                Hermitian)
                    gcsr._real_operator = gcsa
                    gcsr._imag_operator = gcsb

                    glcsr.SetBlock(i, j, gcsr)

        return glcsr
Пример #7
0
def fill_prolongation_operator(engine, level, blk_opr):
    engine.access_idx = 0
    P = None
    diags = []

    A, _X, _RHS, _Ae,  _B,  _M, _dep_vars = engine.assembled_blocks
    use_complex_opr = A.complex and (A.shape[0] == blk_opr.NumRowBlocks())

    hights = A.get_local_row_heights()
    widths = A.get_local_col_widths()

    print(hights, widths)
    cols = [0]
    rows = [0]

    for dep_var in engine.r_dep_vars:
        offset = engine.r_dep_var_offset(dep_var)

        tmp_cols = []
        tmp_rows = []
        tmp_diags = []

        if use_complex_opr:
            mat = blk_opr._linked_op[(offset, offset)]
            conv = mat.GetConvention()
            conv == (1 if mfem.ComplexOperator.HERMITIAN else -1)
        else:
            conv = 1

        if engine.r_isFESvar(dep_var):
            h = engine.fespaces.get_hierarchy(dep_var)
            P = h.GetProlongationAtLevel(level)
            tmp_cols.append(P.Width())
            tmp_rows.append(P.Height())
            tmp_diags.append(P)
            if A.complex:
                tmp_cols.append(P.Width())
                tmp_rows.append(P.Height())
                if conv == -1:
                    oo2 = mfem.ScaleOperator(P, -1)
                    oo2._opr = P
                    tmp_diags.append(oo2)
                else:
                    tmp_diags.append(P)
        else:
            tmp_cols.append(widths[offset])
            tmp_rows.append(widths[offset])
            tmp_diags.append(mfem.IdentityOperator(widths[offset]))

            if A.complex:
                tmp_cols.append(widths[offset])
                tmp_rows.append(widths[offset])
                oo = mfem.IdentityOperator(widths[offset])
                if conv == -1:
                    oo2 = mfem.ScaleOperator(oo, -1)
                    oo2._opr = oo
                    tmp_diags.append(oo2)
                else:
                    tmp_diags.append(oo)
        if use_complex_opr:
            tmp_cols = [0] + tmp_cols
            tmp_rows = [0] + tmp_rows
            offset_c = mfem.intArray(tmp_cols)
            offset_r = mfem.intArray(tmp_rows)
            offset_c.PartialSum()
            offset_r.PartialSum()
            smoother = mfem.BlockOperator(offset_r, offset_c)
            smoother.SetDiagonalBlock(0, tmp_diags[0])
            smoother.SetDiagonalBlock(1, tmp_diags[1])
            smoother._smoother = tmp_diags
            cols.append(tmp_cols[1]*2)
            rows.append(tmp_rows[1]*2)
            diags.append(smoother)
        else:
            cols.extend(tmp_cols)
            rows.extend(tmp_rows)
            diags.extend(tmp_diags)

    ro = mfem.intArray(rows)
    co = mfem.intArray(cols)
    ro.PartialSum()
    co.PartialSum()

    P = mfem.BlockOperator(ro, co)
    for i, d in enumerate(diags):
        P.SetBlock(i, i, d)
    P._diags = diags
    return P
Пример #8
0
def fill_prolongation_operator(engine, level, XX, AA, ls_type, phys_real):
    engine.access_idx = 0
    P = None
    diags = []

    use_complex_opr = ls_type in ['blk_merged', 'blk_merged_s']

    widths = [XX.BlockSize(i) for i in range(XX.NumBlocks())]

    if not phys_real:
        if use_complex_opr:
            widths = [x // 2 for x in widths]
        else:
            widths = [widths[i * 2] for i in range(len(widths) // 2)]

    cols = [0]
    rows = [0]

    for dep_var in engine.r_dep_vars:
        offset = engine.r_dep_var_offset(dep_var)

        tmp_cols = []
        tmp_rows = []
        tmp_diags = []

        # if use_complex_opr:
        #    mat = AA._linked_op[(offset, offset)]
        #    conv = mat.GetConvention()
        #    conv = (1 if mfem.ComplexOperator.HERMITIAN else -1)
        # else:
        #    conv = 1

        if engine.r_isFESvar(dep_var):
            h = engine.fespaces.get_hierarchy(dep_var)
            P = h.GetProlongationAtLevel(level)
            tmp_cols.append(P.Width())
            tmp_rows.append(P.Height())
            tmp_diags.append(P)
            if not phys_real:
                tmp_cols.append(P.Width())
                tmp_rows.append(P.Height())
                # if conv == -1:
                #    oo2 = mfem.ScaledOperator(P, -1)
                #    oo2._opr = P
                #    tmp_diags.append(oo2)
                # else:
                tmp_diags.append(P)
        else:
            tmp_cols.append(widths[offset])
            tmp_rows.append(widths[offset])
            tmp_diags.append(mfem.IdentityOperator(widths[offset]))

            if not phys_real:
                tmp_cols.append(widths[offset])
                tmp_rows.append(widths[offset])
                oo = mfem.IdentityOperator(widths[offset])
                # if conv == -1:
                #    oo2 = mfem.ScaledOperator(oo, -1)
                #    oo2._opr = oo
                #    tmp_diags.append(oo2)
                # else:
                tmp_diags.append(oo)

        if use_complex_opr:
            tmp_cols = [0] + tmp_cols
            tmp_rows = [0] + tmp_rows
            offset_c = mfem.intArray(tmp_cols)
            offset_r = mfem.intArray(tmp_rows)
            offset_c.PartialSum()
            offset_r.PartialSum()
            smoother = mfem.BlockOperator(offset_r, offset_c)
            smoother.SetDiagonalBlock(0, tmp_diags[0])
            smoother.SetDiagonalBlock(1, tmp_diags[1])
            smoother._smoother = tmp_diags
            cols.append(tmp_cols[1] * 2)
            rows.append(tmp_rows[1] * 2)
            diags.append(smoother)
        else:
            cols.extend(tmp_cols)
            rows.extend(tmp_rows)
            diags.extend(tmp_diags)

    ro = mfem.intArray(rows)
    co = mfem.intArray(cols)
    ro.PartialSum()
    co.PartialSum()

    P = mfem.BlockOperator(ro, co)
    for i, d in enumerate(diags):
        P.SetBlock(i, i, d)
    P._diags = diags
    return P