xref: /petsc/src/binding/petsc4py/test/test_pc_py.py (revision 5808f68492579297331054bd8ff190489c3b8c20)
1*5808f684SSatish Balay# --------------------------------------------------------------------
2*5808f684SSatish Balay
3*5808f684SSatish Balayfrom petsc4py import PETSc
4*5808f684SSatish Balayimport unittest
5*5808f684SSatish Balayfrom sys import getrefcount
6*5808f684SSatish Balay
7*5808f684SSatish Balay# --------------------------------------------------------------------
8*5808f684SSatish Balay
9*5808f684SSatish Balayclass BaseMyPC(object):
10*5808f684SSatish Balay    def setup(self, pc):
11*5808f684SSatish Balay        pass
12*5808f684SSatish Balay    def reset(self, pc):
13*5808f684SSatish Balay        pass
14*5808f684SSatish Balay    def apply(self, pc, x, y):
15*5808f684SSatish Balay        raise NotImplementedError
16*5808f684SSatish Balay    def applyT(self, pc, x, y):
17*5808f684SSatish Balay        self.apply(pc, x, y)
18*5808f684SSatish Balay    def applyS(self, pc, x, y):
19*5808f684SSatish Balay        self.apply(pc, x, y)
20*5808f684SSatish Balay    def applySL(self, pc, x, y):
21*5808f684SSatish Balay        self.applyS(pc, x, y)
22*5808f684SSatish Balay    def applySR(self, pc, x, y):
23*5808f684SSatish Balay        self.applyS(pc, x, y)
24*5808f684SSatish Balay    def applyRich(self, pc, x, y, w, tols):
25*5808f684SSatish Balay        self.apply(pc, x, y)
26*5808f684SSatish Balay
27*5808f684SSatish Balayclass MyPCNone(BaseMyPC):
28*5808f684SSatish Balay    def apply(self, pc, x, y):
29*5808f684SSatish Balay        x.copy(y)
30*5808f684SSatish Balay
31*5808f684SSatish Balayclass MyPCJacobi(BaseMyPC):
32*5808f684SSatish Balay    def setup(self, pc):
33*5808f684SSatish Balay        A, P = pc.getOperators()
34*5808f684SSatish Balay        self.diag = P.getDiagonal()
35*5808f684SSatish Balay        self.diag.reciprocal()
36*5808f684SSatish Balay    def reset(self, pc):
37*5808f684SSatish Balay        self.diag.destroy()
38*5808f684SSatish Balay        del self.diag
39*5808f684SSatish Balay    def apply(self, pc, x, y):
40*5808f684SSatish Balay        y.pointwiseMult(self.diag, x)
41*5808f684SSatish Balay    def applyS(self, pc, x, y):
42*5808f684SSatish Balay        self.diag.copy(y)
43*5808f684SSatish Balay        y.sqrtabs()
44*5808f684SSatish Balay        y.pointwiseMult(y, x)
45*5808f684SSatish Balay
46*5808f684SSatish Balayclass PC_PYTHON_CLASS(object):
47*5808f684SSatish Balay
48*5808f684SSatish Balay    def __init__(self):
49*5808f684SSatish Balay        self.impl = None
50*5808f684SSatish Balay        self.log = {}
51*5808f684SSatish Balay    def _log(self, method, *args):
52*5808f684SSatish Balay        self.log.setdefault(method, 0)
53*5808f684SSatish Balay        self.log[method] += 1
54*5808f684SSatish Balay    def create(self, pc):
55*5808f684SSatish Balay        self._log('create', pc)
56*5808f684SSatish Balay    def destroy(self, pc):
57*5808f684SSatish Balay        self._log('destroy')
58*5808f684SSatish Balay        self.impl = None
59*5808f684SSatish Balay    def reset(self, pc):
60*5808f684SSatish Balay        self._log('reset', pc)
61*5808f684SSatish Balay    def view(self, pc, vw):
62*5808f684SSatish Balay        self._log('view', pc, vw)
63*5808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
64*5808f684SSatish Balay        assert isinstance(vw, PETSc.Viewer)
65*5808f684SSatish Balay        pass
66*5808f684SSatish Balay    def setFromOptions(self, pc):
67*5808f684SSatish Balay        self._log('setFromOptions', pc)
68*5808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
69*5808f684SSatish Balay        OptDB = PETSc.Options(pc)
70*5808f684SSatish Balay        impl =  OptDB.getString('impl','MyPCNone')
71*5808f684SSatish Balay        klass = globals()[impl]
72*5808f684SSatish Balay        self.impl = klass()
73*5808f684SSatish Balay    def setUp(self, pc):
74*5808f684SSatish Balay        self._log('setUp', pc)
75*5808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
76*5808f684SSatish Balay        self.impl.setup(pc)
77*5808f684SSatish Balay    def preSolve(self, pc, ksp, b, x):
78*5808f684SSatish Balay        self._log('preSolve', pc, ksp, b, x)
79*5808f684SSatish Balay    def postSolve(self, pc, ksp, b, x):
80*5808f684SSatish Balay        self._log('postSolve', pc, ksp, b, x)
81*5808f684SSatish Balay    def apply(self, pc, x, y):
82*5808f684SSatish Balay        self._log('apply', pc, x, y)
83*5808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
84*5808f684SSatish Balay        assert isinstance(x,  PETSc.Vec)
85*5808f684SSatish Balay        assert isinstance(y,  PETSc.Vec)
86*5808f684SSatish Balay        self.impl.apply(pc, x, y)
87*5808f684SSatish Balay    def applySymmetricLeft(self, pc, x, y):
88*5808f684SSatish Balay        self._log('applySymmetricLeft', pc, x, y)
89*5808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
90*5808f684SSatish Balay        assert isinstance(x,  PETSc.Vec)
91*5808f684SSatish Balay        assert isinstance(y,  PETSc.Vec)
92*5808f684SSatish Balay        self.impl.applySL(pc, x, y)
93*5808f684SSatish Balay    def applySymmetricRight(self, pc, x, y):
94*5808f684SSatish Balay        self._log('applySymmetricRight', pc, x, y)
95*5808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
96*5808f684SSatish Balay        assert isinstance(x,  PETSc.Vec)
97*5808f684SSatish Balay        assert isinstance(y,  PETSc.Vec)
98*5808f684SSatish Balay        self.impl.applySR(pc, x, y)
99*5808f684SSatish Balay    def applyTranspose(self, pc, x, y):
100*5808f684SSatish Balay        self._log('applyTranspose', pc, x, y)
101*5808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
102*5808f684SSatish Balay        assert isinstance(x,  PETSc.Vec)
103*5808f684SSatish Balay        assert isinstance(y,  PETSc.Vec)
104*5808f684SSatish Balay        self.impl.applyT(pc, x, y)
105*5808f684SSatish Balay
106*5808f684SSatish Balay    def applyRichardson(self, pc, x, y, w, tols):
107*5808f684SSatish Balay        self._log('applyRichardson', pc, x, y, w, tols)
108*5808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
109*5808f684SSatish Balay        assert isinstance(x,  PETSc.Vec)
110*5808f684SSatish Balay        assert isinstance(y,  PETSc.Vec)
111*5808f684SSatish Balay        assert isinstance(w,  PETSc.Vec)
112*5808f684SSatish Balay        assert isinstance(tols,  tuple)
113*5808f684SSatish Balay        assert len(tols) == 4
114*5808f684SSatish Balay        self.impl.applyRich(pc, x, y, w, tols)
115*5808f684SSatish Balay
116*5808f684SSatish Balay
117*5808f684SSatish Balayclass TestPCPYTHON(unittest.TestCase):
118*5808f684SSatish Balay
119*5808f684SSatish Balay    PC_TYPE = PETSc.PC.Type.PYTHON
120*5808f684SSatish Balay
121*5808f684SSatish Balay    PC_PREFIX = 'test-'
122*5808f684SSatish Balay
123*5808f684SSatish Balay    def setUp(self):
124*5808f684SSatish Balay        pc = self.pc = PETSc.PC()
125*5808f684SSatish Balay        pc.create(PETSc.COMM_SELF)
126*5808f684SSatish Balay        pc.setType(self.PC_TYPE)
127*5808f684SSatish Balay        module = __name__
128*5808f684SSatish Balay        factory = 'PC_PYTHON_CLASS'
129*5808f684SSatish Balay        self.pc.prefix = self.PC_PREFIX
130*5808f684SSatish Balay        OptDB = PETSc.Options(self.pc)
131*5808f684SSatish Balay        assert OptDB.prefix == self.pc.prefix
132*5808f684SSatish Balay        OptDB['pc_python_type'] = '%s.%s' % (module, factory)
133*5808f684SSatish Balay        self.pc.setFromOptions()
134*5808f684SSatish Balay        del OptDB['pc_python_type']
135*5808f684SSatish Balay        assert self._getCtx().log['create'] == 1
136*5808f684SSatish Balay        assert self._getCtx().log['setFromOptions'] == 1
137*5808f684SSatish Balay        ctx = self._getCtx()
138*5808f684SSatish Balay        self.assertEqual(getrefcount(ctx), 3)
139*5808f684SSatish Balay
140*5808f684SSatish Balay    def tearDown(self):
141*5808f684SSatish Balay        ctx = self._getCtx()
142*5808f684SSatish Balay        self.pc.destroy() # XXX
143*5808f684SSatish Balay        self.pc = None
144*5808f684SSatish Balay        assert ctx.log['destroy'] == 1
145*5808f684SSatish Balay        self.assertEqual(getrefcount(ctx), 2)
146*5808f684SSatish Balay
147*5808f684SSatish Balay    def _prepare(self):
148*5808f684SSatish Balay        A = PETSc.Mat().createAIJ([3,3], comm=PETSc.COMM_SELF)
149*5808f684SSatish Balay        A.setUp()
150*5808f684SSatish Balay        A.assemble()
151*5808f684SSatish Balay        A.shift(10)
152*5808f684SSatish Balay        x, y = A.createVecs()
153*5808f684SSatish Balay        x.setRandom()
154*5808f684SSatish Balay        self.pc.setOperators(A, A)
155*5808f684SSatish Balay        assert (A,A) == self.pc.getOperators()
156*5808f684SSatish Balay        return A, x, y
157*5808f684SSatish Balay
158*5808f684SSatish Balay    def _getCtx(self):
159*5808f684SSatish Balay        return self.pc.getPythonContext()
160*5808f684SSatish Balay
161*5808f684SSatish Balay    def _applyMeth(self, meth):
162*5808f684SSatish Balay        A, x, y = self._prepare()
163*5808f684SSatish Balay        getattr(self.pc, meth)(x,y)
164*5808f684SSatish Balay        if 'reset' not in self._getCtx().log:
165*5808f684SSatish Balay            assert self._getCtx().log['setUp'] == 1
166*5808f684SSatish Balay            assert self._getCtx().log[meth] == 1
167*5808f684SSatish Balay        else:
168*5808f684SSatish Balay            nreset = self._getCtx().log['reset']
169*5808f684SSatish Balay            nsetup = self._getCtx().log['setUp']
170*5808f684SSatish Balay            nmeth  = self._getCtx().log[meth]
171*5808f684SSatish Balay            assert (nreset == nsetup)
172*5808f684SSatish Balay            assert (nreset == nmeth)
173*5808f684SSatish Balay        if isinstance(self._getCtx().impl, MyPCNone):
174*5808f684SSatish Balay            self.assertTrue(y.equal(x))
175*5808f684SSatish Balay    def testApply(self):
176*5808f684SSatish Balay        self._applyMeth('apply')
177*5808f684SSatish Balay    def testApplySymmetricLeft(self):
178*5808f684SSatish Balay        self._applyMeth('applySymmetricLeft')
179*5808f684SSatish Balay    def testApplySymmetricRight(self):
180*5808f684SSatish Balay        self._applyMeth('applySymmetricRight')
181*5808f684SSatish Balay    def testApplyTranspose(self):
182*5808f684SSatish Balay        self._applyMeth('applyTranspose')
183*5808f684SSatish Balay    ## def testApplyRichardson(self):
184*5808f684SSatish Balay    ##     x, y = self._prepare()
185*5808f684SSatish Balay    ##     w = x.duplicate()
186*5808f684SSatish Balay    ##     tols = 0,0,0,0
187*5808f684SSatish Balay    ##     self.pc.applyRichardson(x,y,w,tols)
188*5808f684SSatish Balay    ##     assert self._getCtx().log['setUp'] == 1
189*5808f684SSatish Balay    ##     assert self._getCtx().log['applyRichardson'] == 1
190*5808f684SSatish Balay
191*5808f684SSatish Balay    ## def testView(self):
192*5808f684SSatish Balay    ##     vw = PETSc.ViewerString(100, self.pc.comm)
193*5808f684SSatish Balay    ##     self.pc.view(vw)
194*5808f684SSatish Balay    ##     s = vw.getString()
195*5808f684SSatish Balay    ##     assert 'python' in s
196*5808f684SSatish Balay    ##     module = __name__
197*5808f684SSatish Balay    ##     factory = 'self._getCtx()'
198*5808f684SSatish Balay    ##     assert '.'.join([module, factory]) in s
199*5808f684SSatish Balay
200*5808f684SSatish Balay    def testResetAndApply(self):
201*5808f684SSatish Balay        self.pc.reset()
202*5808f684SSatish Balay        self.testApply()
203*5808f684SSatish Balay        self.pc.reset()
204*5808f684SSatish Balay        self.testApply()
205*5808f684SSatish Balay        self.pc.reset()
206*5808f684SSatish Balay
207*5808f684SSatish Balay    def testKSPSolve(self):
208*5808f684SSatish Balay        A, x, y = self._prepare()
209*5808f684SSatish Balay        ksp = PETSc.KSP().create(self.pc.comm)
210*5808f684SSatish Balay        ksp.setType(PETSc.KSP.Type.PREONLY)
211*5808f684SSatish Balay        assert self.pc.getRefCount() == 1
212*5808f684SSatish Balay        ksp.setPC(self.pc)
213*5808f684SSatish Balay        assert self.pc.getRefCount() == 2
214*5808f684SSatish Balay        # normal ksp solve, twice
215*5808f684SSatish Balay        ksp.solve(x,y)
216*5808f684SSatish Balay        assert self._getCtx().log['setUp'    ] == 1
217*5808f684SSatish Balay        assert self._getCtx().log['apply'    ] == 1
218*5808f684SSatish Balay        assert self._getCtx().log['preSolve' ] == 1
219*5808f684SSatish Balay        assert self._getCtx().log['postSolve'] == 1
220*5808f684SSatish Balay        ksp.solve(x,y)
221*5808f684SSatish Balay        assert self._getCtx().log['setUp'    ] == 1
222*5808f684SSatish Balay        assert self._getCtx().log['apply'    ] == 2
223*5808f684SSatish Balay        assert self._getCtx().log['preSolve' ] == 2
224*5808f684SSatish Balay        assert self._getCtx().log['postSolve'] == 2
225*5808f684SSatish Balay        # transpose ksp solve, twice
226*5808f684SSatish Balay        ksp.solveTranspose(x,y)
227*5808f684SSatish Balay        assert self._getCtx().log['setUp'         ] == 1
228*5808f684SSatish Balay        assert self._getCtx().log['applyTranspose'] == 1
229*5808f684SSatish Balay        ksp.solveTranspose(x,y)
230*5808f684SSatish Balay        assert self._getCtx().log['setUp'         ] == 1
231*5808f684SSatish Balay        assert self._getCtx().log['applyTranspose'] == 2
232*5808f684SSatish Balay        del ksp # ksp.destroy()
233*5808f684SSatish Balay        assert self.pc.getRefCount() == 1
234*5808f684SSatish Balay
235*5808f684SSatish Balay    def testGetSetContext(self):
236*5808f684SSatish Balay        ctx = self.pc.getPythonContext()
237*5808f684SSatish Balay        self.pc.setPythonContext(ctx)
238*5808f684SSatish Balay        self.assertEqual(getrefcount(ctx), 3)
239*5808f684SSatish Balay        del ctx
240*5808f684SSatish Balay
241*5808f684SSatish Balay
242*5808f684SSatish Balayclass TestPCPYTHON2(TestPCPYTHON):
243*5808f684SSatish Balay    def setUp(self):
244*5808f684SSatish Balay        OptDB = PETSc.Options(self.PC_PREFIX)
245*5808f684SSatish Balay        OptDB['impl'] = 'MyPCJacobi'
246*5808f684SSatish Balay        super(TestPCPYTHON2, self).setUp()
247*5808f684SSatish Balay        clsname = type(self._getCtx().impl).__name__
248*5808f684SSatish Balay        assert clsname == OptDB['impl']
249*5808f684SSatish Balay        del OptDB['impl']
250*5808f684SSatish Balay
251*5808f684SSatish Balayclass TestPCPYTHON3(TestPCPYTHON):
252*5808f684SSatish Balay    def setUp(self):
253*5808f684SSatish Balay        pc = self.pc = PETSc.PC()
254*5808f684SSatish Balay        ctx = PC_PYTHON_CLASS()
255*5808f684SSatish Balay        pc.createPython(ctx, comm=PETSc.COMM_SELF)
256*5808f684SSatish Balay        self.pc.prefix = self.PC_PREFIX
257*5808f684SSatish Balay        self.pc.setFromOptions()
258*5808f684SSatish Balay        assert self._getCtx().log['create'] == 1
259*5808f684SSatish Balay        assert self._getCtx().log['setFromOptions'] == 1
260*5808f684SSatish Balay
261*5808f684SSatish Balayclass TestPCPYTHON4(TestPCPYTHON3):
262*5808f684SSatish Balay    def setUp(self):
263*5808f684SSatish Balay        OptDB = PETSc.Options(self.PC_PREFIX)
264*5808f684SSatish Balay        OptDB['impl'] = 'MyPCJacobi'
265*5808f684SSatish Balay        super(TestPCPYTHON4, self).setUp()
266*5808f684SSatish Balay        clsname = type(self._getCtx().impl).__name__
267*5808f684SSatish Balay        assert clsname == OptDB['impl']
268*5808f684SSatish Balay        del OptDB['impl']
269*5808f684SSatish Balay
270*5808f684SSatish Balay# --------------------------------------------------------------------
271*5808f684SSatish Balay
272*5808f684SSatish Balayif __name__ == '__main__':
273*5808f684SSatish Balay    unittest.main()
274