This page was generated from unit-5a.3-petsc/PETSc_interface.ipynb.
5.3.2 NGSolve - PETSc interface¶
We use the ngs2petsc interface to map vectors and matrices between NGSolve and PETSc
[1]:
from ipyparallel import Cluster
c = await Cluster(engines="mpi").start_and_connect(n=4, activate=True)
Starting 4 engines with <class 'ipyparallel.cluster.launcher.MPIEngineSetLauncher'>
[2]:
%%px
from ngsolve import *
from netgen.occ import unit_square
comm = MPI.COMM_WORLD
ngmesh = unit_square.GenerateMesh(maxh=0.1, comm=comm)
for l in range(2):
ngmesh.Refine()
mesh = Mesh(ngmesh)
The Python-module ngsolve.ngs2petsc provides functionality to transfer vectors and matrices between NGSolve and Python.
Make sure that the ipyparallel server can import the module, e.g. by starting the cluster in the current directory.
[3]:
%%px
import ngsolve.ngs2petsc as n2p
import petsc4py.PETSc as psc
[4]:
%%px
fes = H1(mesh, order=1, dirichlet="left|bottom")
u,v = fes.TnT()
a = BilinearForm(grad(u)*grad(v)*dx+u*v*ds).Assemble()
f = LinearForm(x*v*dx).Assemble()
gfu = GridFunction(fes)
The function CreatePETScMatrix takes an NGSolve matrix, and creates a PETSc matrix from it. A VectorMapping object can map vectors between NGSolve and PETSc.
[5]:
%%px
psc_mat = n2p.CreatePETScMatrix(a.mat, fes.FreeDofs())
vecmap = n2p.VectorMapping (a.mat.row_pardofs, fes.FreeDofs())
[stderr:1] [4860d8c30022:61806] Read -1, expected 33824, errno = 1
[stderr:0] [4860d8c30022:61805] Read -1, expected 48864, errno = 1
[stderr:2] [4860d8c30022:61807] Read -1, expected 17328, errno = 1
Create PETSc-vectors fitting to the matrix
[6]:
%%px
psc_f, psc_u = psc_mat.createVecs()
setting up the parallel Krylov-space solver ….
[7]:
%%px
ksp = psc.KSP()
ksp.create()
ksp.setOperators(psc_mat)
ksp.setType(psc.KSP.Type.CG)
ksp.setNormType(psc.KSP.NormType.NORM_NATURAL)
ksp.getPC().setType("gamg")
ksp.setTolerances(rtol=1e-6, atol=0, divtol=1e16, max_it=400)
moving vectors between NGSolve and PETSc, and solve:
[8]:
%%px
vecmap.N2P(f.vec, psc_f)
ksp.solve(psc_f, psc_u)
vecmap.P2N(psc_u, gfu.vec);
[stderr:0] [4860d8c30022:61805] Read -1, expected 12480, errno = 1
[4860d8c30022:61805] Read -1, expected 49920, errno = 1
[stderr:1] [4860d8c30022:61806] Read -1, expected 9512, errno = 1
[4860d8c30022:61806] Read -1, expected 15980, errno = 1
[4860d8c30022:61806] Read -1, expected 63920, errno = 1
[4860d8c30022:61806] Read -1, expected 38048, errno = 1
[4860d8c30022:61806] Read -1, expected 5200, errno = 1
[4860d8c30022:61806] Read -1, expected 5672, errno = 1
[4860d8c30022:61806] Read -1, expected 5680, errno = 1
[stderr:2] [4860d8c30022:61807] Read -1, expected 11312, errno = 1
[4860d8c30022:61807] Read -1, expected 16740, errno = 1
[4860d8c30022:61807] Read -1, expected 45248, errno = 1
[4860d8c30022:61807] Read -1, expected 66960, errno = 1
[4860d8c30022:61807] Read -1, expected 4392, errno = 1
[4860d8c30022:61807] Read -1, expected 5640, errno = 1
[4860d8c30022:61807] Read -1, expected 8784, errno = 1
[4860d8c30022:61807] Read -1, expected 7664, errno = 1
[stderr:3] [4860d8c30022:61808] Read -1, expected 22316, errno = 1
[4860d8c30022:61808] Read -1, expected 89264, errno = 1
[4860d8c30022:61808] Read -1, expected 8032, errno = 1
[9]:
gfu = c[:]["gfu"]
from ngsolve.webgui import Draw
[10]:
Draw (gfu[0])
[10]:
BaseWebGuiScene
PETSc preconditioner for NGSolve¶
Next we create a PETSc preconditioner, and wrap it into an NGSolve preconditioner:
[11]:
%%px
a = BilinearForm(grad(u)*grad(v)*dx+u*v*ds)
# pre = Preconditioner(a, "petsc", pctype="gamg", levels=10)
pre = Preconditioner(a, "gamg")
a.Assemble();
[stderr:1] [4860d8c30022:61806] Read -1, expected 33824, errno = 1
[4860d8c30022:61806] Read -1, expected 9512, errno = 1
[4860d8c30022:61806] Read -1, expected 15980, errno = 1
[4860d8c30022:61806] Read -1, expected 38048, errno = 1
[4860d8c30022:61806] Read -1, expected 63920, errno = 1
[4860d8c30022:61806] Read -1, expected 5200, errno = 1
[4860d8c30022:61806] Read -1, expected 5672, errno = 1
[4860d8c30022:61806] Read -1, expected 5680, errno = 1
[stderr:2] [4860d8c30022:61807] Read -1, expected 17328, errno = 1
[4860d8c30022:61807] Read -1, expected 11312, errno = 1
[4860d8c30022:61807] Read -1, expected 16740, errno = 1
[4860d8c30022:61807] Read -1, expected 66960, errno = 1
[4860d8c30022:61807] Read -1, expected 45248, errno = 1
[4860d8c30022:61807] Read -1, expected 4392, errno = 1
[4860d8c30022:61807] Read -1, expected 8784, errno = 1
[4860d8c30022:61807] Read -1, expected 5640, errno = 1
[4860d8c30022:61807] Read -1, expected 7664, errno = 1
[stderr:3] [4860d8c30022:61808] Read -1, expected 22316, errno = 1
[4860d8c30022:61808] Read -1, expected 89264, errno = 1
[4860d8c30022:61808] Read -1, expected 8032, errno = 1
[stderr:0] [4860d8c30022:61805] Read -1, expected 48864, errno = 1
[4860d8c30022:61805] Read -1, expected 12480, errno = 1
[4860d8c30022:61805] Read -1, expected 49920, errno = 1
and use it in an NGSolve - CGSolver:
[12]:
%%px
from ngsolve.krylovspace import CGSolver
inv = CGSolver(a.mat, pre, printrates=comm.rank==0)
gfu.vec.data = inv * f.vec
[stdout:0] CG iteration 1, residual = 0.16127010686172552
CG iteration 2, residual = 0.03143032472771138
CG iteration 3, residual = 0.004236806109474593
CG iteration 4, residual = 0.000673560256142833
CG iteration 5, residual = 9.254951509649891e-05
CG iteration 6, residual = 1.1543042891878278e-05
CG iteration 7, residual = 1.6313785246668694e-06
CG iteration 8, residual = 2.0609628931866596e-07
CG iteration 9, residual = 2.8655513283220788e-08
CG iteration 10, residual = 4.197371013948971e-09
CG iteration 11, residual = 4.94864208996692e-10
CG iteration 12, residual = 6.073045380176665e-11
CG iteration 13, residual = 8.761255707217241e-12
CG iteration 14, residual = 1.1080633610630865e-12
CG iteration 15, residual = 1.4459025695516513e-13
[13]:
gfu = c[:]["gfu"]
Draw (gfu[0]);
[ ]:
[ ]: