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