Esempio n. 1
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()))
Esempio n. 2
0
#
# 2D Poisson, high order, using AMG + BDDC
#

from ngsolve import *
import ngs_amg

from ngsolve.krylovspace import CGSolver

from amg_utils import *

comm = mpi_world

geo, mesh = gen_square(maxh=0.05, nref=0, comm=mpi_world)
V, a, f = setup_poisson(mesh, order=4, diri="right")
gfu = GridFunction(V)

# Here we use the BDDC precodnitioner, and tell it to plug the coarse level matrix into AMG.
pc_opts = {"ngs_amg_max_coarse_size": 5}
c = Preconditioner(a, "bddc", coarsetype="ngs_amg.h1_scal", **pc_opts)

with TaskManager():
    a.Assemble()
    f.Assemble()
    cb = None if comm.rank != 0 else lambda k, x: print(
        "it =", k, ", err =", x)
    cg = CGSolver(mat=a.mat, pre=c, callback=cb, maxsteps=100, tol=1e-12)
    cg.Solve(sol=gfu.vec, rhs=f.vec)
    print("nits", cg.iterations)
Esempio 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("*****************************************************")
Esempio n. 4
0
    ngmesh = unit_cube.GenerateMesh(maxh=0.1).Distribute(comm)
else:
    ngmesh = netgen.meshing.Mesh.Receive(comm)

for l in range(0):
    ngmesh.Refine()
mesh = Mesh(ngmesh)

fes = H1(mesh, order=1)
u, v = fes.TnT()
a = BilinearForm(grad(u) * grad(v) * dx + u * v * ds).Assemble()
f = LinearForm(x * v * dx).Assemble()
gfu = GridFunction(fes)
inv = CGSolver(a.mat,
               freedofs=fes.FreeDofs(),
               printing=False,
               maxsteps=400,
               tol=1e-8)
gfu.vec.data = inv * f.vec
masterprint("ngs-dot =", InnerProduct(gfu.vec, f.vec))

pardofs = fes.ParallelDofs()
globnums, nglob = pardofs.EnumerateGlobally()

locmat = a.mat.local_mat
val, col, ind = locmat.CSR()
ind = np.array(ind, dtype='int32')

apsc_loc = psc.Mat().createAIJ(size=(locmat.height, locmat.width),
                               csr=(ind, col, val),
                               comm=MPI.COMM_SELF)