def systems_and_preconditioners(mesh, X, z, order=1):
    # Create a real analogue of our vector space for the wrapper preconditioner.
    dirichlet = 'top|right|bottom|left'
    X_real = ng.H1(mesh, order=order, dirichlet=dirichlet, complex=False)

    # Test and trial functions for the original space.
    u, v = X.TnT()

    # Real trial and test functions.
    ur, vr = X_real.TnT()

    # Create a real analogue of the bilinear form a.
    a_real = ng.BilinearForm(X_real)
    a_real += ng.SymbolicBFI(ng.grad(ur) * ng.grad(vr))
    a_real.Assemble()

    # Initialize petsc prior to conswtructing preconditioners.
    petsc.Initialize()

    # Create a bilinear form and a preconditioner for each z.
    zbas = []
    precs = []
    for k in range(len(z)):
        #  Create a bilinear form for the given z-value.
        zba = ng.BilinearForm(X)
        zba += ng.SymbolicBFI(z[k] * u * v - ng.grad(u) * ng.grad(v))

        # Create a preconditioner for the given z-value.
        mat_convert = petsc.PETScMatrix(a_real.mat, freedofs=X_real.FreeDofs())
        real_pc = petsc.PETSc2NGsPrecond(mat=mat_convert,
                                         name="real_pc",
                                         petsc_options={"pc_type": "gamg"})

        prec = WrapperPrec(real_pc)

        # Assemble the given bilinear form.
        zba.Assemble()

        # Tack the bilinear forms and preconditioners onto their respective lists.
        zbas += [zba]
        precs += [prec]

    return zbas, precs
Exemplo n.º 2
0
def SolveProblem(order=order, refines=refines):
    # load mesh from file
    for i in range(refines):
        t0 = timeit.time()
        mesh = MakeStructured2DMesh(quads=False, nx=8 * 2**i, ny=8 * 2**i)
        t1 = timeit.time()

        # C0-HDG FESpaces
        VT = H1(mesh, order=order + 1, dirichlet=".*")
        if bc == "clamped":  # clamped bc
            VF = TangentialFacetFESpace(mesh, order=order - 1,
                                        dirichlet=".*")  # with bdry condition
        else:
            VF = TangentialFacetFESpace(mesh,
                                        order=order - 1)  # no bdry condition
        V = FESpace([VT, VF])

        gfu = GridFunction(V)
        (xi, uhat), (zeta, vhat) = V.TnT()

        n = specialcf.normal(2)
        h = specialcf.mesh_size

        def tang(v):
            return v - (v * n) * n

        u = CoefficientFunction((grad(xi)[1], -grad(xi)[0]))
        v = CoefficientFunction((grad(zeta)[1], -grad(zeta)[0]))
        hess_zeta = zeta.Operator("hesse")
        # gradient by row
        gradv = CoefficientFunction(
            ((hess_zeta[1], hess_zeta[3]), (-hess_zeta[0], -hess_zeta[1])),
            dims=(2, 2))
        hess_xi = xi.Operator("hesse")
        gradu = CoefficientFunction(
            ((hess_xi[1], hess_xi[3]), (-hess_xi[0], -hess_xi[1])),
            dims=(2, 2))

        f = LinearForm(V)
        f += zeta * dx

        a = BilinearForm(V, condense=True, symmetric=True)
        lap = tau * u * v
        bilap = InnerProduct(gradu, gradv)
        bilap_BND = -(gradu * n * tang(v - vhat) + gradv * n * tang(u - uhat) -
                      4 * (order + 1)**2 / h * tang(u - uhat) * tang(v - vhat))

        ir = IntegrationRule(SEGM, 2 * order - 1)

        a += (lap + bilap) * dx
        a += bilap_BND * dx(element_boundary=True, intrules={SEGM: ir})

        ########### ASP 1: C0--> HDiv
        ########### ASP 1: C0--> HDiv
        ########### ASP 1: C0--> HDiv
        # two grid (Hdiv-HDG)
        VT1 = HDiv(mesh, order=order, hodivfree=True, dirichlet='.*')
        V1 = FESpace([VT1, VF])
        (u1, uhat1), (v1, vhat1) = V1.TnT()

        # Mapping HDiv--> H1
        mixmass = BilinearForm(trialspace=V1, testspace=V)
        # tangential part
        mixmass += u1 * v * dx

        # construct Pi-hat
        xiT, zetaT = VT.TnT()
        uT = CoefficientFunction((grad(xiT)[1], -grad(xiT)[0]))
        vT = CoefficientFunction((grad(zetaT)[1], -grad(zetaT)[0]))
        uhatT, vhatT = VF.TnT()

        # tangential part
        massfX = BilinearForm(VT, symmetric=True)
        massfX += uT * vT * dx

        massfY = BilinearForm(trialspace=VT, testspace=VF)
        massfY += -tang(uT) * tang(vhatT) * dx(element_boundary=True)

        massfZ = BilinearForm(VF)
        massfZ += tang(uhatT) * tang(vhatT) * dx(element_boundary=True)

        ############### DOFS splits for PROJECTOR
        embU = Embedding(V.ndof, V.Range(0))
        embV = Embedding(V.ndof, V.Range(1))

        a1 = BilinearForm(V1, condense=True)
        lap1 = tau * u1 * v1
        gradu1 = Grad(u1)
        gradv1 = Grad(v1)
        bilap1 = InnerProduct(gradu1, gradv1)

        jmp_u1 = tang(u1 - uhat1)
        jmp_v1 = tang(v1 - vhat1)
        bilap_BND1 = -(gradu1 * n * jmp_v1 + gradv1 * n * jmp_u1 - 4 *
                       (order + 1)**2 / h * jmp_u1 * jmp_v1)
        a1 += (lap1 + bilap1) * dx
        a1 += bilap_BND1 * dx(element_boundary=True, intrules={SEGM: ir})

        ########### ASP 2: HDiv--> H1
        ########### FIXME: weakly impose bdry condition
        if bc == "clamped":
            V0 = VectorH1(mesh, dirichlet=".*")
        else:
            V0 = VectorH1(mesh,
                          dirichletx="left|right",
                          dirichlety="top|bottom")
        u0, v0 = V0.TnT()
        a0 = BilinearForm(V0)
        a0 += (InnerProduct(Grad(u0), Grad(v0)) + tau * u0 * v0) * dx

        # Projection operator H1--> M
        mixmass0 = BilinearForm(trialspace=V0, testspace=V1)
        # tangential part
        mixmass0 += tang(u0) * tang(vhat1) * dx(element_boundary=True)
        mixmass0 += (u0 * n) * (v1 * n) * dx(element_boundary=True)

        massf0 = BilinearForm(V1)
        # tangential part
        massf0 += tang(uhat1) * tang(vhat1) * dx(element_boundary=True)
        massf0 += (u1 * n) * (v1 * n) * dx(element_boundary=True)

        def edgePatchBlocks(mesh, fes):
            blocks = []
            freedofs = fes.FreeDofs(True)
            for e in mesh.edges:
                edofs = set()
                # get ALL dofs connected to the edge
                for el in mesh[e].elements:
                    edofs |= set(d for d in fes.GetDofNrs(el) if freedofs[d])
                blocks.append(edofs)
            return blocks

        eBlocks = edgePatchBlocks(mesh, V1)

        class SymmetricGS(BaseMatrix):
            def __init__(self, smoother):
                super(SymmetricGS, self).__init__()
                self.smoother = smoother

            def Mult(self, x, y):
                y[:] = 0.0
                self.smoother.Smooth(y, x)
                self.smoother.SmoothBack(y, x)

            def Height(self):
                return self.smoother.height

            def Width(self):
                return self.smoother.height

        with TaskManager():
            f.Assemble()
            a.Assemble()
            ######## ASP 1
            mixmass.Assemble()
            massfX.Assemble()
            massfY.Assemble()
            massfZ.Assemble()
            ####### RK: PROJECTION (sparse cholesky factorization)
            imX = massfX.mat.Inverse(VT.FreeDofs(True),
                                     inverse="sparsecholesky")

            imZ = massfZ.mat.CreateSmoother(VF.FreeDofs(True))
            m_inv = embU @ imX @ embU.T + embV @ imZ @embV.T \
                    - embV @ imZ @ massfY.mat @ imX @ embU.T
            m_invT = embU @ imX @ embU.T + embV @ imZ @embV.T \
                    - embU @ imX @ massfY.mat.T @ imZ @ embV.T

            E = m_inv @ mixmass.mat
            ET = mixmass.mat.T @ m_invT

            a1.Assemble()
            ## ASP 2
            bjac = a1.mat.CreateBlockSmoother(eBlocks)
            bgs = SymmetricGS(bjac)

            mixmass0.Assemble()
            massf0.Assemble()
            m_inv0 = massf0.mat.CreateSmoother(V1.FreeDofs(True))

            a0.Assemble()
            pm0 = ngs_petsc.PETScMatrix(a0.mat, V0.FreeDofs())
            inva0 = ngs_petsc.PETSc2NGsPrecond(
                pm0, petsc_options={"pc_type": "hypre"})
            E0 = m_inv0 @ mixmass0.mat
            # ASP for rd system
            pc_a1 = bgs + E0 @ inva0 @ E0.T

            # Direct solver for rd system
            pc_a2 = a1.mat.Inverse(V1.FreeDofs(True), inverse="sparsecholesky")

            pre1 = E @ pc_a1 @ ET
            pre2 = E @ pc_a2 @ ET

            inv1 = CGSolver(a.mat,
                            pre1,
                            maxsteps=5000,
                            precision=1e-10,
                            printrates=True)
            inv2 = CGSolver(a.mat,
                            pre2,
                            maxsteps=5000,
                            precision=1e-10,
                            printrates=True)

            f.vec.data += a.harmonic_extension_trans * f.vec
            # solver
            gfu.vec.data = inv1 * f.vec
            gfu.vec.data = inv2 * f.vec
            gfu.vec.data += a.harmonic_extension * gfu.vec
            gfu.vec.data += a.inner_solve * f.vec
            print("bc:%s tau0:%.0e tau1 %.0e   ASP:%i  EXA: %i" %
                  (bc, tau0, tau1, inv1.GetSteps(), inv2.GetSteps()))
Exemplo n.º 3
0
def SolveProblem(order=order, refines=refines, condense=True, symmetric=False):
    for i in range(refines):
        t0 = timeit.time()
        mesh = MakeStructured3DMesh(hexes=False,
                                    nx=8 * 2**i,
                                    ny=8 * 2**i,
                                    nz=8 * 2**i)
        t1 = timeit.time()
        print("\nElasped:%.2e MESHING " % (t1 - t0))

        # Div-HDG spaces
        V = HDiv(mesh, order=order, dirichlet=".*")
        if freeBC == True:
            M = TangentialFacetFESpace(mesh,
                                       order=order,
                                       highest_order_dc=True)
            # aux H1 space
            V0 = VectorH1(mesh,
                          order=1,
                          dirichlety="left|right",
                          dirichletx="front|back",
                          dirichletz="top|bottom")
        else:  # dir bc
            M = TangentialFacetFESpace(mesh,
                                       order=order,
                                       highest_order_dc=True,
                                       dirichlet=".*")
            # aux H1 space
            V0 = VectorH1(mesh, order=1, dirichlet=".*")

        fes = FESpace([V, M])
        gfu = GridFunction(fes)
        (u, uhat), (v, vhat) = fes.TnT()
        (u0, v0) = V0.TnT()

        # gradients
        gradv, gradu = Grad(v), Grad(u)

        # RHS (constant)
        f = LinearForm(fes)
        f += (v[0] + v[1] + v[2]) * dx

        # normal direction and mesh size
        n = specialcf.normal(mesh.dim)
        h = specialcf.mesh_size
        # stability parameter
        #alpha = 8*order**2/h
        alpha = 8 * order**2 / h

        # tangential component
        def tang(v):
            return v - (v * n) * n

        ########### HDG operator ah
        a = BilinearForm(fes, symmetric=True, condense=True)
        # volume term
        a += (D * InnerProduct(gradu, gradv) + tau * u * v) * dx
        # bdry terms
        a += D * (-gradu * n * tang(v - vhat) - gradv * n * tang(u - uhat) +
                  alpha * tang(u - uhat) * tang(v - vhat)) * dx(
                      element_boundary=True)

        ######## face path blocks for smoother
        def facePatchBlocks(mesh, fes):
            blocks = []
            freedofs = fes.FreeDofs(True)
            for e in mesh.faces:
                edofs = set()
                # get ALL dofs connected to the face
                for el in mesh[e].elements:
                    edofs |= set(d for d in fes.GetDofNrs(el) if freedofs[d])
                blocks.append(edofs)
            return blocks

        def faceBlocks(mesh, fes):
            blocks = []
            freedofs = fes.FreeDofs(True)
            for e in mesh.faces:
                edofs = set(d for d in fes.GetDofNrs(e) if freedofs[d])
                blocks.append(edofs)
            return blocks

        ######## THIS IS MOST TIME CONSUMING PART
        fBlocks = facePatchBlocks(mesh, fes)
        fBlocks0 = faceBlocks(mesh, fes)
        t0 = timeit.time()
        # number of DOFS
        ntotal = fes.ndof
        nglobal = sum(fes.FreeDofs(True))
        print("Elasped:%.2e BLOCKING  Total DOFs: %.2e Global DOFs: %.2e " %
              (t0 - t1, ntotal, nglobal))

        class SymmetricGS(BaseMatrix):
            def __init__(self, smoother):
                super(SymmetricGS, self).__init__()
                self.smoother = smoother

            def Mult(self, x, y):
                y[:] = 0.0
                self.smoother.Smooth(y, x)
                self.smoother.SmoothBack(y, x)

            def Height(self):
                return self.smoother.height

            def Width(self):
                return self.smoother.height

        ########### ASP operator ah0
        a0 = BilinearForm(V0, symmetric=True)
        a0 += (D * InnerProduct(Grad(u0), Grad(v0)) + tau * u0 * v0) * dx

        # Projection operator V0--> fes
        # We set up a mixed mass matrix for V0 -> fes and then solving with the mass matrix in M
        mixmass = BilinearForm(trialspace=V0, testspace=fes)
        # tangential part
        mixmass += tang(u0) * tang(vhat) * dx(element_boundary=True)
        # normal part
        mixmass += (u0 * n) * (v * n) * dx(element_boundary=True)

        massf = BilinearForm(fes)
        massf += tang(uhat) * tang(vhat) * dx(element_boundary=True)
        massf += (u * n) * (v * n) * dx(element_boundary=True)

        with TaskManager():
            f.Assemble()
            a.Assemble()
            t1 = timeit.time()
            print("Elasped:%.2e ASSEMBLE " % (t1 - t0))
            ######### smoother (use edge blocks)
            # smoother
            jac = a.mat.CreateSmoother(fes.FreeDofs(True))
            bjac = a.mat.CreateBlockSmoother(fBlocks)

            ######## ASP
            a0.Assemble()
            pm = ngs_petsc.PETScMatrix(a0.mat, V0.FreeDofs())
            inva0 = ngs_petsc.PETSc2NGsPrecond(
                pm, petsc_options={"pc_type": "hypre"})
            massf.Assemble()
            mixmass.Assemble()
            # massf is block-diagonal in 3D!!!!!!!!!
            m_inv = massf.mat.CreateBlockSmoother(fBlocks0)

            E = m_inv @ mixmass.mat
            ET = mixmass.mat.T @ m_inv
            pre_twogrid = E @ inva0 @ ET

            # jacobi smoother
            pre1 = jac + pre_twogrid
            # block gs smoother
            pre2 = SymmetricGS(bjac) + pre_twogrid
            t2 = timeit.time()
            print("Elasped:%.2e PREC " % (t2 - t1))

            inv1 = CGSolver(a.mat,
                            pre1,
                            maxsteps=10000,
                            precision=1e-10,
                            printrates=True)
            inv2 = CGSolver(a.mat,
                            pre2,
                            maxsteps=10000,
                            precision=1e-10,
                            printrates=True)

            f.vec.data += a.harmonic_extension_trans * f.vec
            # solver
            gfu.vec.data = inv1 * f.vec
            gfu.vec.data = inv2 * f.vec
            gfu.vec.data += a.harmonic_extension * gfu.vec
            gfu.vec.data += a.inner_solve * f.vec
            t3 = timeit.time()
            print("Elasped:%.2e SOLVE " % (t3 - t2))
            print("JAC:%i  BGS: %i" % (inv1.GetSteps(), inv2.GetSteps()))

            print("*****************************************************")
            print("*****************************************************")
            print("*****************************************************")
Exemplo n.º 4
0
## The scalar preconditioner
us, vs = H1s.TnT()
h1s_blf = BilinearForm(H1s)
h1s_blf += beta * grad(us) * grad(vs) * dx

# Using NGsAMG
if use_ngs_amg:
    pc_h1s = Preconditioner(h1s_blf, "ngs_amg.h1_scal")

h1s_blf.Assemble()

# Using GAMG algebraic multigrid from PETSc
if not use_ngs_amg:
    pm_scal = ngs_petsc.PETScMatrix(h1s_blf.mat, H1s.FreeDofs())
    pc_h1s = ngs_petsc.PETSc2NGsPrecond(pm_scal,
                                        petsc_options={"pc_type": "gamg"})

pc_grad = G @ pc_h1s @ G.T

H1v = VectorH1(mesh, order=1, dirichlet="outer")

## On monday, we saw fast embedding via Dual shapes
## (see fast_embed.py)
from fast_embed import FastEmbed

E = FastEmbed(HC, H1v)

# Again, this is a C2C operation, because it takes a vector-valued
# H1 function (!) nad returns an HCurl function (!)
if mpi_world.size > 1:
    E = ParallelMatrix(E,
Exemplo n.º 5
0
E = hcm_inv @ mixmass.mat

## H1 scalar problem
h1scal_blf = BilinearForm(H1s)
h1scal_blf += beta * grad(us) * grad(vs) * dx
h1scal_blf.Assemble()

h1smat = petsc.PETScMatrix(h1scal_blf.mat, H1s.FreeDofs())
# pc_h1s = h1scal_blf.mat.Inverse(H1s.FreeDofs())
# pc_h1s = petsc.KSP(h1smat, "h1spc", petsc_options={ "ksp_type" : "cg",
#                                                     #"ksp_monitor" : "",
#                                                     #"ksp_converged_reason" : "",
#                                                     "pc_type" : "gamg"})
pc_h1s = petsc.PETSc2NGsPrecond(h1smat,
                                "h1spc",
                                petsc_options={"pc_type": "gamg"})

## H1 vector problem
h1v_blf = BilinearForm(H1v)
h1v_blf += alpha * InnerProduct(grad(uv), grad(vv)) * dx
h1v_blf.Assemble()

h1vmat = petsc.PETScMatrix(h1v_blf.mat, H1v.FreeDofs())
# h1v_blf.mat.Inverse(H1v.FreeDofs())
# pc_h1v = petsc.KSP(h1vmat, "h1vpc", petsc_options = { "ksp_converged_reason" : "",
#                                                       "pc_type" : "gamg"})
pc_h1v = petsc.PETSc2NGsPrecond(h1vmat,
                                name="h1vpc",
                                petsc_options={"pc_type": "gamg"})
Exemplo n.º 6
0
# ngs_pc = petsc.NGs2PETScPrecond(mat=mat_wrap, pc=c)
#ksp.SetPC(ngs_pc)
#ksp.Finalize()

t = -time()
gfu.vec.data = ksp * f.vec
t += time()

quit()

mat_convert = petsc.PETScMatrix(a.mat, freedofs=V.FreeDofs())
# mat_convert.SetNearNullSpace(kvecs)
petsc_pc = petsc.PETSc2NGsPrecond(mat=mat_convert,
                                  name="reverse_someksp",
                                  petsc_options={
                                      "pc_type": "ml",
                                      "pc_monitor": "",
                                      "pc_view": ""
                                  })
t2 = -time()
solvers.CG(mat=a.mat,
           rhs=f.vec,
           sol=gfu.vec,
           pre=petsc_pc,
           tol=1e-8,
           printrates=comm.rank == 0)
t2 += time()

ksp_res = ksp.results
if comm.rank == 0:
    print('ndof ', V.ndofglobal)