xref: /petsc/src/binding/petsc4py/test/test_pc_py.py (revision ebead697dbf761eb322f829370bbe90b3bd93fa3)
15808f684SSatish Balay# --------------------------------------------------------------------
25808f684SSatish Balay
35808f684SSatish Balayfrom petsc4py import PETSc
45808f684SSatish Balayimport unittest
55808f684SSatish Balayfrom sys import getrefcount
65808f684SSatish Balay
75808f684SSatish Balay# --------------------------------------------------------------------
85808f684SSatish Balay
95808f684SSatish Balayclass BaseMyPC(object):
105808f684SSatish Balay    def setup(self, pc):
115808f684SSatish Balay        pass
125808f684SSatish Balay    def reset(self, pc):
135808f684SSatish Balay        pass
145808f684SSatish Balay    def apply(self, pc, x, y):
155808f684SSatish Balay        raise NotImplementedError
165808f684SSatish Balay    def applyT(self, pc, x, y):
175808f684SSatish Balay        self.apply(pc, x, y)
185808f684SSatish Balay    def applyS(self, pc, x, y):
195808f684SSatish Balay        self.apply(pc, x, y)
205808f684SSatish Balay    def applySL(self, pc, x, y):
215808f684SSatish Balay        self.applyS(pc, x, y)
225808f684SSatish Balay    def applySR(self, pc, x, y):
235808f684SSatish Balay        self.applyS(pc, x, y)
245808f684SSatish Balay    def applyRich(self, pc, x, y, w, tols):
255808f684SSatish Balay        self.apply(pc, x, y)
26bda5c5f8SStefano Zampini    def applyM(self, pc, x, y):
27bda5c5f8SStefano Zampini        raise NotImplementedError
285808f684SSatish Balay
295808f684SSatish Balayclass MyPCNone(BaseMyPC):
305808f684SSatish Balay    def apply(self, pc, x, y):
315808f684SSatish Balay        x.copy(y)
32bda5c5f8SStefano Zampini    def applyM(self, pc, x, y):
33bda5c5f8SStefano Zampini        x.copy(y)
345808f684SSatish Balay
355808f684SSatish Balayclass MyPCJacobi(BaseMyPC):
365808f684SSatish Balay    def setup(self, pc):
375808f684SSatish Balay        A, P = pc.getOperators()
385808f684SSatish Balay        self.diag = P.getDiagonal()
395808f684SSatish Balay        self.diag.reciprocal()
405808f684SSatish Balay    def reset(self, pc):
415808f684SSatish Balay        self.diag.destroy()
425808f684SSatish Balay        del self.diag
435808f684SSatish Balay    def apply(self, pc, x, y):
445808f684SSatish Balay        y.pointwiseMult(self.diag, x)
455808f684SSatish Balay    def applyS(self, pc, x, y):
465808f684SSatish Balay        self.diag.copy(y)
475808f684SSatish Balay        y.sqrtabs()
485808f684SSatish Balay        y.pointwiseMult(y, x)
49bda5c5f8SStefano Zampini    def applyM(self, pc, x, y):
50bda5c5f8SStefano Zampini        x.copy(y)
51bda5c5f8SStefano Zampini        y.diagonalScale(L=self.diag)
525808f684SSatish Balay
535808f684SSatish Balayclass PC_PYTHON_CLASS(object):
545808f684SSatish Balay
555808f684SSatish Balay    def __init__(self):
565808f684SSatish Balay        self.impl = None
575808f684SSatish Balay        self.log = {}
585808f684SSatish Balay    def _log(self, method, *args):
595808f684SSatish Balay        self.log.setdefault(method, 0)
605808f684SSatish Balay        self.log[method] += 1
615808f684SSatish Balay    def create(self, pc):
625808f684SSatish Balay        self._log('create', pc)
635808f684SSatish Balay    def destroy(self, pc):
645808f684SSatish Balay        self._log('destroy')
655808f684SSatish Balay        self.impl = None
665808f684SSatish Balay    def reset(self, pc):
675808f684SSatish Balay        self._log('reset', pc)
685808f684SSatish Balay    def view(self, pc, vw):
695808f684SSatish Balay        self._log('view', pc, vw)
705808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
715808f684SSatish Balay        assert isinstance(vw, PETSc.Viewer)
725808f684SSatish Balay        pass
735808f684SSatish Balay    def setFromOptions(self, pc):
745808f684SSatish Balay        self._log('setFromOptions', pc)
755808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
765808f684SSatish Balay        OptDB = PETSc.Options(pc)
775808f684SSatish Balay        impl =  OptDB.getString('impl','MyPCNone')
785808f684SSatish Balay        klass = globals()[impl]
795808f684SSatish Balay        self.impl = klass()
805808f684SSatish Balay    def setUp(self, pc):
815808f684SSatish Balay        self._log('setUp', pc)
825808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
835808f684SSatish Balay        self.impl.setup(pc)
845808f684SSatish Balay    def preSolve(self, pc, ksp, b, x):
855808f684SSatish Balay        self._log('preSolve', pc, ksp, b, x)
865808f684SSatish Balay    def postSolve(self, pc, ksp, b, x):
875808f684SSatish Balay        self._log('postSolve', pc, ksp, b, x)
885808f684SSatish Balay    def apply(self, pc, x, y):
895808f684SSatish Balay        self._log('apply', pc, x, y)
905808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
915808f684SSatish Balay        assert isinstance(x,  PETSc.Vec)
925808f684SSatish Balay        assert isinstance(y,  PETSc.Vec)
935808f684SSatish Balay        self.impl.apply(pc, x, y)
945808f684SSatish Balay    def applySymmetricLeft(self, pc, x, y):
955808f684SSatish Balay        self._log('applySymmetricLeft', pc, x, y)
965808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
975808f684SSatish Balay        assert isinstance(x,  PETSc.Vec)
985808f684SSatish Balay        assert isinstance(y,  PETSc.Vec)
995808f684SSatish Balay        self.impl.applySL(pc, x, y)
1005808f684SSatish Balay    def applySymmetricRight(self, pc, x, y):
1015808f684SSatish Balay        self._log('applySymmetricRight', pc, x, y)
1025808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
1035808f684SSatish Balay        assert isinstance(x,  PETSc.Vec)
1045808f684SSatish Balay        assert isinstance(y,  PETSc.Vec)
1055808f684SSatish Balay        self.impl.applySR(pc, x, y)
1065808f684SSatish Balay    def applyTranspose(self, pc, x, y):
1075808f684SSatish Balay        self._log('applyTranspose', pc, x, y)
1085808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
1095808f684SSatish Balay        assert isinstance(x,  PETSc.Vec)
1105808f684SSatish Balay        assert isinstance(y,  PETSc.Vec)
1115808f684SSatish Balay        self.impl.applyT(pc, x, y)
112bda5c5f8SStefano Zampini    def matApply(self, pc, x, y):
113bda5c5f8SStefano Zampini        self._log('matApply', pc, x, y)
114bda5c5f8SStefano Zampini        assert isinstance(pc, PETSc.PC)
115bda5c5f8SStefano Zampini        assert isinstance(x,  PETSc.Mat)
116bda5c5f8SStefano Zampini        assert isinstance(y,  PETSc.Mat)
117bda5c5f8SStefano Zampini        self.impl.applyM(pc, x, y)
1185808f684SSatish Balay    def applyRichardson(self, pc, x, y, w, tols):
1195808f684SSatish Balay        self._log('applyRichardson', pc, x, y, w, tols)
1205808f684SSatish Balay        assert isinstance(pc, PETSc.PC)
1215808f684SSatish Balay        assert isinstance(x,  PETSc.Vec)
1225808f684SSatish Balay        assert isinstance(y,  PETSc.Vec)
1235808f684SSatish Balay        assert isinstance(w,  PETSc.Vec)
1245808f684SSatish Balay        assert isinstance(tols,  tuple)
1255808f684SSatish Balay        assert len(tols) == 4
1265808f684SSatish Balay        self.impl.applyRich(pc, x, y, w, tols)
1275808f684SSatish Balay
1285808f684SSatish Balay
1295808f684SSatish Balayclass TestPCPYTHON(unittest.TestCase):
1305808f684SSatish Balay
1315808f684SSatish Balay    PC_TYPE = PETSc.PC.Type.PYTHON
1325808f684SSatish Balay    PC_PREFIX = 'test-'
1335808f684SSatish Balay
1345808f684SSatish Balay    def setUp(self):
1355808f684SSatish Balay        pc = self.pc = PETSc.PC()
1365808f684SSatish Balay        pc.create(PETSc.COMM_SELF)
1375808f684SSatish Balay        pc.setType(self.PC_TYPE)
1385808f684SSatish Balay        module = __name__
1395808f684SSatish Balay        factory = 'PC_PYTHON_CLASS'
1405808f684SSatish Balay        self.pc.prefix = self.PC_PREFIX
1415808f684SSatish Balay        OptDB = PETSc.Options(self.pc)
1425808f684SSatish Balay        assert OptDB.prefix == self.pc.prefix
1435808f684SSatish Balay        OptDB['pc_python_type'] = '%s.%s' % (module, factory)
1445808f684SSatish Balay        self.pc.setFromOptions()
1455808f684SSatish Balay        del OptDB['pc_python_type']
1465808f684SSatish Balay        assert self._getCtx().log['create'] == 1
1475808f684SSatish Balay        assert self._getCtx().log['setFromOptions'] == 1
1485808f684SSatish Balay        ctx = self._getCtx()
1495808f684SSatish Balay        self.assertEqual(getrefcount(ctx), 3)
1505808f684SSatish Balay
151*ebead697SStefano Zampini    def testGetType(self):
152*ebead697SStefano Zampini        ctx = self.pc.getPythonContext()
153*ebead697SStefano Zampini        pytype = "{0}.{1}".format(ctx.__module__, type(ctx).__name__)
154*ebead697SStefano Zampini        self.assertTrue(self.pc.getPythonType() == pytype)
155*ebead697SStefano Zampini
1565808f684SSatish Balay    def tearDown(self):
1575808f684SSatish Balay        ctx = self._getCtx()
1585808f684SSatish Balay        self.pc.destroy() # XXX
1595808f684SSatish Balay        self.pc = None
1605808f684SSatish Balay        assert ctx.log['destroy'] == 1
1615808f684SSatish Balay        self.assertEqual(getrefcount(ctx), 2)
1625808f684SSatish Balay
1635808f684SSatish Balay    def _prepare(self):
1645808f684SSatish Balay        A = PETSc.Mat().createAIJ([3,3], comm=PETSc.COMM_SELF)
1655808f684SSatish Balay        A.setUp()
1665808f684SSatish Balay        A.assemble()
1675808f684SSatish Balay        A.shift(10)
1685808f684SSatish Balay        x, y = A.createVecs()
1695808f684SSatish Balay        x.setRandom()
1705808f684SSatish Balay        self.pc.setOperators(A, A)
171bda5c5f8SStefano Zampini        X = PETSc.Mat().createDense([3,5], comm=PETSc.COMM_SELF).setUp()
172bda5c5f8SStefano Zampini        X.assemble()
173bda5c5f8SStefano Zampini        Y = PETSc.Mat().createDense([3,5], comm=PETSc.COMM_SELF).setUp()
174bda5c5f8SStefano Zampini        Y.assemble()
1755808f684SSatish Balay        assert (A,A) == self.pc.getOperators()
176bda5c5f8SStefano Zampini        return A, x, y, X, Y
1775808f684SSatish Balay
1785808f684SSatish Balay    def _getCtx(self):
1795808f684SSatish Balay        return self.pc.getPythonContext()
1805808f684SSatish Balay
1815808f684SSatish Balay    def _applyMeth(self, meth):
182bda5c5f8SStefano Zampini        A, x, y, X, Y = self._prepare()
183bda5c5f8SStefano Zampini        if meth == 'matApply':
184bda5c5f8SStefano Zampini            getattr(self.pc, meth)(X,Y)
185bda5c5f8SStefano Zampini            x.copy(y)
186bda5c5f8SStefano Zampini        else:
1875808f684SSatish Balay            getattr(self.pc, meth)(x,y)
188bda5c5f8SStefano Zampini            X.copy(Y)
1895808f684SSatish Balay        if 'reset' not in self._getCtx().log:
1905808f684SSatish Balay            assert self._getCtx().log['setUp'] == 1
1915808f684SSatish Balay            assert self._getCtx().log[meth] == 1
1925808f684SSatish Balay        else:
1935808f684SSatish Balay            nreset = self._getCtx().log['reset']
1945808f684SSatish Balay            nsetup = self._getCtx().log['setUp']
1955808f684SSatish Balay            nmeth  = self._getCtx().log[meth]
1965808f684SSatish Balay            assert (nreset == nsetup)
1975808f684SSatish Balay            assert (nreset == nmeth)
1985808f684SSatish Balay        if isinstance(self._getCtx().impl, MyPCNone):
1995808f684SSatish Balay            self.assertTrue(y.equal(x))
200bda5c5f8SStefano Zampini            self.assertTrue(Y.equal(X))
2015808f684SSatish Balay    def testApply(self):
2025808f684SSatish Balay        self._applyMeth('apply')
2035808f684SSatish Balay    def testApplySymmetricLeft(self):
2045808f684SSatish Balay        self._applyMeth('applySymmetricLeft')
2055808f684SSatish Balay    def testApplySymmetricRight(self):
2065808f684SSatish Balay        self._applyMeth('applySymmetricRight')
2075808f684SSatish Balay    def testApplyTranspose(self):
2085808f684SSatish Balay        self._applyMeth('applyTranspose')
209bda5c5f8SStefano Zampini    def testApplyMat(self):
210bda5c5f8SStefano Zampini        self._applyMeth('matApply')
2115808f684SSatish Balay    ## def testApplyRichardson(self):
2125808f684SSatish Balay    ##     x, y = self._prepare()
2135808f684SSatish Balay    ##     w = x.duplicate()
2145808f684SSatish Balay    ##     tols = 0,0,0,0
2155808f684SSatish Balay    ##     self.pc.applyRichardson(x,y,w,tols)
2165808f684SSatish Balay    ##     assert self._getCtx().log['setUp'] == 1
2175808f684SSatish Balay    ##     assert self._getCtx().log['applyRichardson'] == 1
2185808f684SSatish Balay
2195808f684SSatish Balay    ## def testView(self):
2205808f684SSatish Balay    ##     vw = PETSc.ViewerString(100, self.pc.comm)
2215808f684SSatish Balay    ##     self.pc.view(vw)
2225808f684SSatish Balay    ##     s = vw.getString()
2235808f684SSatish Balay    ##     assert 'python' in s
2245808f684SSatish Balay    ##     module = __name__
2255808f684SSatish Balay    ##     factory = 'self._getCtx()'
2265808f684SSatish Balay    ##     assert '.'.join([module, factory]) in s
2275808f684SSatish Balay
2285808f684SSatish Balay    def testResetAndApply(self):
2295808f684SSatish Balay        self.pc.reset()
2305808f684SSatish Balay        self.testApply()
2315808f684SSatish Balay        self.pc.reset()
2325808f684SSatish Balay        self.testApply()
2335808f684SSatish Balay        self.pc.reset()
2345808f684SSatish Balay
2355808f684SSatish Balay    def testKSPSolve(self):
236bda5c5f8SStefano Zampini        A, x, y, _, _ = self._prepare()
2375808f684SSatish Balay        ksp = PETSc.KSP().create(self.pc.comm)
2385808f684SSatish Balay        ksp.setType(PETSc.KSP.Type.PREONLY)
2395808f684SSatish Balay        assert self.pc.getRefCount() == 1
2405808f684SSatish Balay        ksp.setPC(self.pc)
2415808f684SSatish Balay        assert self.pc.getRefCount() == 2
2425808f684SSatish Balay        # normal ksp solve, twice
2435808f684SSatish Balay        ksp.solve(x,y)
2445808f684SSatish Balay        assert self._getCtx().log['setUp'    ] == 1
2455808f684SSatish Balay        assert self._getCtx().log['apply'    ] == 1
2465808f684SSatish Balay        assert self._getCtx().log['preSolve' ] == 1
2475808f684SSatish Balay        assert self._getCtx().log['postSolve'] == 1
2485808f684SSatish Balay        ksp.solve(x,y)
2495808f684SSatish Balay        assert self._getCtx().log['setUp'    ] == 1
2505808f684SSatish Balay        assert self._getCtx().log['apply'    ] == 2
2515808f684SSatish Balay        assert self._getCtx().log['preSolve' ] == 2
2525808f684SSatish Balay        assert self._getCtx().log['postSolve'] == 2
2535808f684SSatish Balay        # transpose ksp solve, twice
2545808f684SSatish Balay        ksp.solveTranspose(x,y)
2555808f684SSatish Balay        assert self._getCtx().log['setUp'         ] == 1
2565808f684SSatish Balay        assert self._getCtx().log['applyTranspose'] == 1
2575808f684SSatish Balay        ksp.solveTranspose(x,y)
2585808f684SSatish Balay        assert self._getCtx().log['setUp'         ] == 1
2595808f684SSatish Balay        assert self._getCtx().log['applyTranspose'] == 2
2605808f684SSatish Balay        del ksp # ksp.destroy()
2615808f684SSatish Balay        assert self.pc.getRefCount() == 1
2625808f684SSatish Balay
2635808f684SSatish Balay    def testGetSetContext(self):
2645808f684SSatish Balay        ctx = self.pc.getPythonContext()
2655808f684SSatish Balay        self.pc.setPythonContext(ctx)
2665808f684SSatish Balay        self.assertEqual(getrefcount(ctx), 3)
2675808f684SSatish Balay        del ctx
2685808f684SSatish Balay
2695808f684SSatish Balay
2705808f684SSatish Balayclass TestPCPYTHON2(TestPCPYTHON):
2715808f684SSatish Balay    def setUp(self):
2725808f684SSatish Balay        OptDB = PETSc.Options(self.PC_PREFIX)
2735808f684SSatish Balay        OptDB['impl'] = 'MyPCJacobi'
2745808f684SSatish Balay        super(TestPCPYTHON2, self).setUp()
2755808f684SSatish Balay        clsname = type(self._getCtx().impl).__name__
2765808f684SSatish Balay        assert clsname == OptDB['impl']
2775808f684SSatish Balay        del OptDB['impl']
2785808f684SSatish Balay
2795808f684SSatish Balayclass TestPCPYTHON3(TestPCPYTHON):
2805808f684SSatish Balay    def setUp(self):
2815808f684SSatish Balay        pc = self.pc = PETSc.PC()
2825808f684SSatish Balay        ctx = PC_PYTHON_CLASS()
2835808f684SSatish Balay        pc.createPython(ctx, comm=PETSc.COMM_SELF)
2845808f684SSatish Balay        self.pc.prefix = self.PC_PREFIX
2855808f684SSatish Balay        self.pc.setFromOptions()
2865808f684SSatish Balay        assert self._getCtx().log['create'] == 1
2875808f684SSatish Balay        assert self._getCtx().log['setFromOptions'] == 1
2885808f684SSatish Balay
2895808f684SSatish Balayclass TestPCPYTHON4(TestPCPYTHON3):
2905808f684SSatish Balay    def setUp(self):
2915808f684SSatish Balay        OptDB = PETSc.Options(self.PC_PREFIX)
2925808f684SSatish Balay        OptDB['impl'] = 'MyPCJacobi'
2935808f684SSatish Balay        super(TestPCPYTHON4, self).setUp()
2945808f684SSatish Balay        clsname = type(self._getCtx().impl).__name__
2955808f684SSatish Balay        assert clsname == OptDB['impl']
2965808f684SSatish Balay        del OptDB['impl']
2975808f684SSatish Balay
2985808f684SSatish Balay# --------------------------------------------------------------------
2995808f684SSatish Balay
3005808f684SSatish Balayif __name__ == '__main__':
3015808f684SSatish Balay    unittest.main()
302