コード例 #1
0
    def _new_transfer_operator(self,
                               name,
                               key1,
                               key2,
                               engine,
                               use_matrix_free=True):
        '''
        fes1 : coarse grid
        fes2 : fine grid
        '''
        fes1 = self._fes_storage[key1]
        fes2 = self._fes_storage[key2]

        parallel = hasattr(fes1, 'GroupComm')
        if use_matrix_free:
            if key1 == key2:
                return mfem.IdentityOperator(fes1.GetTrueVSize())
            elif parallel:
                return mfem.TrueTransferOperator(fes1, fes2)
            else:

                P1 = None if fes1.Conforming(
                ) else fes1.GetConformingProlongation()
                if P1 is None:
                    P1 = mfem.IdentityOperator(fes1.GetTrueVSize())

                R2 = None if fes2.Conforming(
                ) else fes2.GetConformingRestriction()
                if R2 is None:
                    R2 = mfem.IdentityOperator(fes2.GetTrueVSize())

                Opr1 = mfem.TransferOperator(fes1, fes2)
                opr = mfem.TripleProductOperator(R2, Opr1, P1, False, False,
                                                 False)
                opr._linked_opr = (R2, Opr1, P1)
                return opr

        else:
            if parallel:
                PP = mfem.OperatorPtr(mfem.Operator.Hypre_ParCSR)

                fes2.GetTransferOperator(fes1, PP)
                PP.SetOperatorOwner(False)
                P = PP.Ptr()
                return P
            else:
                assert False, "Should not come here"
コード例 #2
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
コード例 #3
0
def genearate_smoother(engine, level, blk_opr):
    from petram.engine import ParallelEngine
    assert not isinstance(
        engine, ParallelEngine), "Parallel is not supported"

    engine.access_idx = 0
    P = None
    diags = []
    cols = [0]
    ess_tdofs = []
    A, _X, _RHS, _Ae,  _B,  _M, _dep_vars = engine.assembled_blocks
    widths = A.get_local_col_widths()

    use_complex_opr = A.complex and (A.shape[0] == blk_opr.NumRowBlocks())

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

        tmp_cols = []
        tmp_diags = []
        if engine.r_isFESvar(dep_var):
            ess_tdof = mfem.intArray(engine.ess_tdofs[dep_var])
            ess_tdofs.append(ess_tdofs)
            opr = A[offset, offset]

            if use_complex_opr:
                mat = blk_opr._linked_op[(offset, offset)]
                conv = mat.GetConvention()
                conv == 1 if mfem.ComplexOperator.HERMITIAN else -1
                mat1 = mat._real_operator
                mat2 = mat._imag_operator
            else:
                conv = 1
                if A.complex:
                    mat1 = blk_opr.GetBlock(offset*2, offset*2)
                    mat2 = blk_opr.GetBlock(offset*2 + 1, offset*2 + 1)
                else:
                    mat1 = blk_opr.GetBlock(offset, offset)

            if A.complex:
                dd = opr.diagonal()
                diag = mfem.Vector(list(dd.real))
                print("real", dd.real)
                rsmoother = mfem.OperatorChebyshevSmoother(mat1,
                                                           diag,
                                                           ess_tdof,
                                                           2)
                dd = opr.diagonal()*conv
                diag = mfem.Vector(list(dd.real))
                print("imag", dd.imag)
                ismoother = mfem.OperatorChebyshevSmoother(mat1,
                                                           diag,
                                                           ess_tdof,
                                                           2)
                tmp_cols.append(opr.shape[0])
                tmp_cols.append(opr.shape[0])
                tmp_diags.append(rsmoother)
                tmp_diags.append(ismoother)

            else:
                dd = opr.diagonal()
                diag = mfem.Vector(list(dd))
                smoother = mfem.OperatorChebyshevSmoother(mat1,
                                                          diag,
                                                          ess_tdof,
                                                          2)
                tmp_diags.append(smoother)
                tmp_cols.append(opr.shape[0])

        else:
            print("Non FESvar", dep_var, offset)
            tmp_cols.append(widths[offset])
            tmp_diags.append(mfem.IdentityOperator(widths[offset]))
            if A.complex:
                tmp_cols.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
            blockOffsets = mfem.intArray(tmp_cols)
            blockOffsets.PartialSum()
            smoother = mfem.BlockDiagonalPreconditioner(blockOffsets)
            smoother.SetDiagonalBlock(0, tmp_diags[0])
            smoother.SetDiagonalBlock(1, tmp_diags[1])
            smoother._smoother = tmp_diags
            cols.append(tmp_cols[1]*2)
            diags.append(smoother)
        else:
            cols.extend(tmp_cols)
            diags.extend(tmp_diags)

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

    P = mfem.BlockDiagonalPreconditioner(co)
    for i, d in enumerate(diags):
        P.SetDiagonalBlock(i,  d)
    P._diags = diags
    P._ess_tdofs = ess_tdofs
    return P
コード例 #4
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