xref: /petsc/src/binding/petsc4py/demo/poisson2d/poisson2d.py (revision 5808f68492579297331054bd8ff190489c3b8c20)
1*5808f684SSatish Balay# ------------------------------------------------------------------------
2*5808f684SSatish Balay#
3*5808f684SSatish Balay#  Poisson problem. This problem is modeled by the partial
4*5808f684SSatish Balay#  differential equation
5*5808f684SSatish Balay#
6*5808f684SSatish Balay#          -Laplacian(u) = 1,  0 < x,y < 1,
7*5808f684SSatish Balay#
8*5808f684SSatish Balay#  with boundary conditions
9*5808f684SSatish Balay#
10*5808f684SSatish Balay#           u = 0  for  x = 0, x = 1, y = 0, y = 1
11*5808f684SSatish Balay#
12*5808f684SSatish Balay#  A finite difference approximation with the usual 7-point stencil
13*5808f684SSatish Balay#  is used to discretize the boundary value problem to obtain a
14*5808f684SSatish Balay#  nonlinear system of equations. The problem is solved in a 2D
15*5808f684SSatish Balay#  rectangular domain, using distributed arrays (DAs) to partition
16*5808f684SSatish Balay#  the parallel grid.
17*5808f684SSatish Balay#
18*5808f684SSatish Balay# ------------------------------------------------------------------------
19*5808f684SSatish Balay
20*5808f684SSatish Balaytry: range = xrange
21*5808f684SSatish Balayexcept: pass
22*5808f684SSatish Balay
23*5808f684SSatish Balayimport sys, petsc4py
24*5808f684SSatish Balaypetsc4py.init(sys.argv)
25*5808f684SSatish Balay
26*5808f684SSatish Balayfrom petsc4py import PETSc
27*5808f684SSatish Balay
28*5808f684SSatish Balayclass Poisson2D(object):
29*5808f684SSatish Balay
30*5808f684SSatish Balay    def __init__(self, da):
31*5808f684SSatish Balay        assert da.getDim() == 2
32*5808f684SSatish Balay        self.da = da
33*5808f684SSatish Balay        self.localX  = da.createLocalVec()
34*5808f684SSatish Balay
35*5808f684SSatish Balay    def formRHS(self, B):
36*5808f684SSatish Balay        b = self.da.getVecArray(B)
37*5808f684SSatish Balay        mx, my = self.da.getSizes()
38*5808f684SSatish Balay        hx, hy = [1.0/m for m in [mx, my]]
39*5808f684SSatish Balay        (xs, xe), (ys, ye) = self.da.getRanges()
40*5808f684SSatish Balay        for j in range(ys, ye):
41*5808f684SSatish Balay            for i in range(xs, xe):
42*5808f684SSatish Balay                b[i, j] = 1*hx*hy
43*5808f684SSatish Balay
44*5808f684SSatish Balay    def mult(self, mat, X, Y):
45*5808f684SSatish Balay        #
46*5808f684SSatish Balay        self.da.globalToLocal(X, self.localX)
47*5808f684SSatish Balay        x = self.da.getVecArray(self.localX)
48*5808f684SSatish Balay        y = self.da.getVecArray(Y)
49*5808f684SSatish Balay        #
50*5808f684SSatish Balay        mx, my = self.da.getSizes()
51*5808f684SSatish Balay        hx, hy = [1.0/m for m in [mx, my]]
52*5808f684SSatish Balay        (xs, xe), (ys, ye) = self.da.getRanges()
53*5808f684SSatish Balay        for j in range(ys, ye):
54*5808f684SSatish Balay            for i in range(xs, xe):
55*5808f684SSatish Balay                u = x[i, j] # center
56*5808f684SSatish Balay                u_e = u_w = u_n = u_s = 0
57*5808f684SSatish Balay                if i > 0:    u_w = x[i-1, j] # west
58*5808f684SSatish Balay                if i < mx-1: u_e = x[i+1, j] # east
59*5808f684SSatish Balay                if j > 0:    u_s = x[i, j-1] # south
60*5808f684SSatish Balay                if j < ny-1: u_n = x[i, j+1] # north
61*5808f684SSatish Balay                u_xx = (-u_e + 2*u - u_w)*hy/hx
62*5808f684SSatish Balay                u_yy = (-u_n + 2*u - u_s)*hx/hy
63*5808f684SSatish Balay                y[i, j] = u_xx + u_yy
64*5808f684SSatish Balay
65*5808f684SSatish BalayOptDB = PETSc.Options()
66*5808f684SSatish Balay
67*5808f684SSatish Balayn  = OptDB.getInt('n', 16)
68*5808f684SSatish Balaynx = OptDB.getInt('nx', n)
69*5808f684SSatish Balayny = OptDB.getInt('ny', n)
70*5808f684SSatish Balay
71*5808f684SSatish Balayda = PETSc.DMDA().create([nx, ny], stencil_width=1)
72*5808f684SSatish Balaypde = Poisson2D(da)
73*5808f684SSatish Balay
74*5808f684SSatish Balayx = da.createGlobalVec()
75*5808f684SSatish Balayb = da.createGlobalVec()
76*5808f684SSatish Balay# A = da.createMat('python')
77*5808f684SSatish BalayA = PETSc.Mat().createPython(
78*5808f684SSatish Balay    [x.getSizes(), b.getSizes()], comm=da.comm)
79*5808f684SSatish BalayA.setPythonContext(pde)
80*5808f684SSatish BalayA.setUp()
81*5808f684SSatish Balay
82*5808f684SSatish Balayksp = PETSc.KSP().create()
83*5808f684SSatish Balayksp.setOperators(A)
84*5808f684SSatish Balayksp.setType('cg')
85*5808f684SSatish Balaypc = ksp.getPC()
86*5808f684SSatish Balaypc.setType('none')
87*5808f684SSatish Balayksp.setFromOptions()
88*5808f684SSatish Balay
89*5808f684SSatish Balaypde.formRHS(b)
90*5808f684SSatish Balayksp.solve(b, x)
91*5808f684SSatish Balay
92*5808f684SSatish Balayu = da.createNaturalVec()
93*5808f684SSatish Balayda.globalToNatural(x, u)
94*5808f684SSatish Balay
95*5808f684SSatish Balayif OptDB.getBool('plot', True):
96*5808f684SSatish Balay    draw = PETSc.Viewer.DRAW(x.comm)
97*5808f684SSatish Balay    OptDB['draw_pause'] = 1
98*5808f684SSatish Balay    draw(x)
99