xref: /petsc/src/binding/petsc4py/demo/legacy/poisson2d/poisson2d.py (revision 8a7d4057d9226490dba4e1a062f54f84e7d90861)
155a74a43SLisandro Dalcin# ------------------------------------------------------------------------
255a74a43SLisandro Dalcin#
355a74a43SLisandro Dalcin#  Poisson problem. This problem is modeled by the partial
455a74a43SLisandro Dalcin#  differential equation
555a74a43SLisandro Dalcin#
655a74a43SLisandro Dalcin#          -Laplacian(u) = 1,  0 < x,y < 1,
755a74a43SLisandro Dalcin#
855a74a43SLisandro Dalcin#  with boundary conditions
955a74a43SLisandro Dalcin#
1055a74a43SLisandro Dalcin#           u = 0  for  x = 0, x = 1, y = 0, y = 1
1155a74a43SLisandro Dalcin#
129690009eSJose E. Roman#  A finite difference approximation with the usual 5-point stencil
1355a74a43SLisandro Dalcin#  is used to discretize the boundary value problem to obtain a
1455a74a43SLisandro Dalcin#  nonlinear system of equations. The problem is solved in a 2D
1555a74a43SLisandro Dalcin#  rectangular domain, using distributed arrays (DAs) to partition
1655a74a43SLisandro Dalcin#  the parallel grid.
1755a74a43SLisandro Dalcin#
1855a74a43SLisandro Dalcin# ------------------------------------------------------------------------
1955a74a43SLisandro Dalcin
2055a74a43SLisandro Dalcintry: range = xrange
2155a74a43SLisandro Dalcinexcept: pass
2255a74a43SLisandro Dalcin
2355a74a43SLisandro Dalcinimport sys, petsc4py
2455a74a43SLisandro Dalcinpetsc4py.init(sys.argv)
2555a74a43SLisandro Dalcin
2655a74a43SLisandro Dalcinfrom petsc4py import PETSc
2755a74a43SLisandro Dalcin
2855a74a43SLisandro Dalcinclass Poisson2D(object):
2955a74a43SLisandro Dalcin
3055a74a43SLisandro Dalcin    def __init__(self, da):
3155a74a43SLisandro Dalcin        assert da.getDim() == 2
3255a74a43SLisandro Dalcin        self.da = da
3355a74a43SLisandro Dalcin        self.localX  = da.createLocalVec()
3455a74a43SLisandro Dalcin
3555a74a43SLisandro Dalcin    def formRHS(self, B):
3655a74a43SLisandro Dalcin        b = self.da.getVecArray(B)
3755a74a43SLisandro Dalcin        mx, my = self.da.getSizes()
3855a74a43SLisandro Dalcin        hx, hy = [1.0/m for m in [mx, my]]
3955a74a43SLisandro Dalcin        (xs, xe), (ys, ye) = self.da.getRanges()
4055a74a43SLisandro Dalcin        for j in range(ys, ye):
4155a74a43SLisandro Dalcin            for i in range(xs, xe):
4255a74a43SLisandro Dalcin                b[i, j] = 1*hx*hy
4355a74a43SLisandro Dalcin
4455a74a43SLisandro Dalcin    def mult(self, mat, X, Y):
4555a74a43SLisandro Dalcin        #
4655a74a43SLisandro Dalcin        self.da.globalToLocal(X, self.localX)
4755a74a43SLisandro Dalcin        x = self.da.getVecArray(self.localX)
4855a74a43SLisandro Dalcin        y = self.da.getVecArray(Y)
4955a74a43SLisandro Dalcin        #
5055a74a43SLisandro Dalcin        mx, my = self.da.getSizes()
5155a74a43SLisandro Dalcin        hx, hy = [1.0/m for m in [mx, my]]
5255a74a43SLisandro Dalcin        (xs, xe), (ys, ye) = self.da.getRanges()
5355a74a43SLisandro Dalcin        for j in range(ys, ye):
5455a74a43SLisandro Dalcin            for i in range(xs, xe):
5555a74a43SLisandro Dalcin                u = x[i, j] # center
5655a74a43SLisandro Dalcin                u_e = u_w = u_n = u_s = 0
5755a74a43SLisandro Dalcin                if i > 0:    u_w = x[i-1, j] # west
5855a74a43SLisandro Dalcin                if i < mx-1: u_e = x[i+1, j] # east
5955a74a43SLisandro Dalcin                if j > 0:    u_s = x[i, j-1] # south
6055a74a43SLisandro Dalcin                if j < ny-1: u_n = x[i, j+1] # north
6155a74a43SLisandro Dalcin                u_xx = (-u_e + 2*u - u_w)*hy/hx
6255a74a43SLisandro Dalcin                u_yy = (-u_n + 2*u - u_s)*hx/hy
6355a74a43SLisandro Dalcin                y[i, j] = u_xx + u_yy
6455a74a43SLisandro Dalcin
6555a74a43SLisandro DalcinOptDB = PETSc.Options()
6655a74a43SLisandro Dalcin
6755a74a43SLisandro Dalcinn  = OptDB.getInt('n', 16)
6855a74a43SLisandro Dalcinnx = OptDB.getInt('nx', n)
6955a74a43SLisandro Dalcinny = OptDB.getInt('ny', n)
7055a74a43SLisandro Dalcin
71*8e704042SBarry Smithda = PETSc.DMDA().create([nx, ny], stencil_width=1, setup=False)
72*8e704042SBarry Smithda.setFromOptions()
73*8e704042SBarry Smithda.setUp()
7455a74a43SLisandro Dalcinpde = Poisson2D(da)
7555a74a43SLisandro Dalcin
7655a74a43SLisandro Dalcinx = da.createGlobalVec()
7755a74a43SLisandro Dalcinb = da.createGlobalVec()
7855a74a43SLisandro Dalcin# A = da.createMat('python')
7955a74a43SLisandro DalcinA = PETSc.Mat().createPython(
8055a74a43SLisandro Dalcin    [x.getSizes(), b.getSizes()], comm=da.comm)
8155a74a43SLisandro DalcinA.setPythonContext(pde)
8255a74a43SLisandro DalcinA.setUp()
8355a74a43SLisandro Dalcin
8455a74a43SLisandro Dalcinksp = PETSc.KSP().create()
8555a74a43SLisandro Dalcinksp.setOperators(A)
8655a74a43SLisandro Dalcinksp.setType('cg')
8755a74a43SLisandro Dalcinpc = ksp.getPC()
8855a74a43SLisandro Dalcinpc.setType('none')
8955a74a43SLisandro Dalcinksp.setFromOptions()
9055a74a43SLisandro Dalcin
9155a74a43SLisandro Dalcinpde.formRHS(b)
9255a74a43SLisandro Dalcinksp.solve(b, x)
9355a74a43SLisandro Dalcin
9455a74a43SLisandro Dalcinu = da.createNaturalVec()
9555a74a43SLisandro Dalcinda.globalToNatural(x, u)
9655a74a43SLisandro Dalcin
9755a74a43SLisandro Dalcinif OptDB.getBool('plot', True):
9855a74a43SLisandro Dalcin    draw = PETSc.Viewer.DRAW(x.comm)
9955a74a43SLisandro Dalcin    OptDB['draw_pause'] = 1
10055a74a43SLisandro Dalcin    draw(x)
101