xref: /petsc/src/binding/petsc4py/test/test_pc_py.py (revision b69d2765e9c8cde17308f61ee677dcd992b8a9cf)
15808f684SSatish Balay# --------------------------------------------------------------------
25808f684SSatish Balay
35808f684SSatish Balayfrom petsc4py import PETSc
45808f684SSatish Balayimport unittest
55808f684SSatish Balayfrom sys import getrefcount
65808f684SSatish Balay
75808f684SSatish Balay# --------------------------------------------------------------------
85808f684SSatish Balay
96f336411SStefano Zampini
106f336411SStefano Zampiniclass BaseMyPC:
115808f684SSatish Balay    def setup(self, pc):
125808f684SSatish Balay        pass
136f336411SStefano Zampini
145808f684SSatish Balay    def reset(self, pc):
155808f684SSatish Balay        pass
166f336411SStefano Zampini
175808f684SSatish Balay    def apply(self, pc, x, y):
185808f684SSatish Balay        raise NotImplementedError
196f336411SStefano Zampini
205808f684SSatish Balay    def applyT(self, pc, x, y):
215808f684SSatish Balay        self.apply(pc, x, y)
226f336411SStefano Zampini
235808f684SSatish Balay    def applyS(self, pc, x, y):
245808f684SSatish Balay        self.apply(pc, x, y)
256f336411SStefano Zampini
265808f684SSatish Balay    def applySL(self, pc, x, y):
275808f684SSatish Balay        self.applyS(pc, x, y)
286f336411SStefano Zampini
295808f684SSatish Balay    def applySR(self, pc, x, y):
305808f684SSatish Balay        self.applyS(pc, x, y)
316f336411SStefano Zampini
325808f684SSatish Balay    def applyRich(self, pc, x, y, w, tols):
335808f684SSatish Balay        self.apply(pc, x, y)
346f336411SStefano Zampini
35bda5c5f8SStefano Zampini    def applyM(self, pc, x, y):
36bda5c5f8SStefano Zampini        raise NotImplementedError
375808f684SSatish Balay
386f336411SStefano Zampini
395808f684SSatish Balayclass MyPCNone(BaseMyPC):
405808f684SSatish Balay    def apply(self, pc, x, y):
415808f684SSatish Balay        x.copy(y)
426f336411SStefano Zampini
43bda5c5f8SStefano Zampini    def applyM(self, pc, x, y):
44bda5c5f8SStefano Zampini        x.copy(y)
455808f684SSatish Balay
466f336411SStefano Zampini
475808f684SSatish Balayclass MyPCJacobi(BaseMyPC):
485808f684SSatish Balay    def setup(self, pc):
495808f684SSatish Balay        A, P = pc.getOperators()
505808f684SSatish Balay        self.diag = P.getDiagonal()
515808f684SSatish Balay        self.diag.reciprocal()
526f336411SStefano Zampini
535808f684SSatish Balay    def reset(self, pc):
545808f684SSatish Balay        self.diag.destroy()
555808f684SSatish Balay        del self.diag
566f336411SStefano Zampini
575808f684SSatish Balay    def apply(self, pc, x, y):
585808f684SSatish Balay        y.pointwiseMult(self.diag, x)
596f336411SStefano Zampini
605808f684SSatish Balay    def applyS(self, pc, x, y):
615808f684SSatish Balay        self.diag.copy(y)
625808f684SSatish Balay        y.sqrtabs()
635808f684SSatish Balay        y.pointwiseMult(y, x)
646f336411SStefano Zampini
65bda5c5f8SStefano Zampini    def applyM(self, pc, x, y):
66bda5c5f8SStefano Zampini        x.copy(y)
67bda5c5f8SStefano Zampini        y.diagonalScale(L=self.diag)
685808f684SSatish Balay
695808f684SSatish Balay
706f336411SStefano Zampiniclass PC_PYTHON_CLASS:
715808f684SSatish Balay    def __init__(self):
725808f684SSatish Balay        self.impl = None
735808f684SSatish Balay        self.log = {}
746f336411SStefano Zampini
755808f684SSatish Balay    def _log(self, method, *args):
765808f684SSatish Balay        self.log.setdefault(method, 0)
775808f684SSatish Balay        self.log[method] += 1
786f336411SStefano Zampini
795808f684SSatish Balay    def create(self, pc):
805808f684SSatish Balay        self._log('create', pc)
816f336411SStefano Zampini
825808f684SSatish Balay    def destroy(self, pc):
835808f684SSatish Balay        self._log('destroy')
845808f684SSatish Balay        self.impl = None
856f336411SStefano Zampini
865808f684SSatish Balay    def reset(self, pc):
875808f684SSatish Balay        self._log('reset', pc)
886f336411SStefano Zampini
895808f684SSatish Balay    def view(self, pc, vw):
905808f684SSatish Balay        self._log('view', pc, vw)
916f336411SStefano Zampini
925808f684SSatish Balay    def setFromOptions(self, pc):
935808f684SSatish Balay        self._log('setFromOptions', pc)
945808f684SSatish Balay        OptDB = PETSc.Options(pc)
955808f684SSatish Balay        impl = OptDB.getString('impl', 'MyPCNone')
965808f684SSatish Balay        klass = globals()[impl]
975808f684SSatish Balay        self.impl = klass()
986f336411SStefano Zampini
995808f684SSatish Balay    def setUp(self, pc):
1005808f684SSatish Balay        self._log('setUp', pc)
1015808f684SSatish Balay        self.impl.setup(pc)
1026f336411SStefano Zampini
1035808f684SSatish Balay    def preSolve(self, pc, ksp, b, x):
1045808f684SSatish Balay        self._log('preSolve', pc, ksp, b, x)
1056f336411SStefano Zampini
1065808f684SSatish Balay    def postSolve(self, pc, ksp, b, x):
1075808f684SSatish Balay        self._log('postSolve', pc, ksp, b, x)
1086f336411SStefano Zampini
1095808f684SSatish Balay    def apply(self, pc, x, y):
1105808f684SSatish Balay        self._log('apply', pc, x, y)
1115808f684SSatish Balay        self.impl.apply(pc, x, y)
1126f336411SStefano Zampini
1135808f684SSatish Balay    def applySymmetricLeft(self, pc, x, y):
1145808f684SSatish Balay        self._log('applySymmetricLeft', pc, x, y)
1155808f684SSatish Balay        self.impl.applySL(pc, x, y)
1166f336411SStefano Zampini
1175808f684SSatish Balay    def applySymmetricRight(self, pc, x, y):
1185808f684SSatish Balay        self._log('applySymmetricRight', pc, x, y)
1195808f684SSatish Balay        self.impl.applySR(pc, x, y)
1206f336411SStefano Zampini
1215808f684SSatish Balay    def applyTranspose(self, pc, x, y):
1225808f684SSatish Balay        self._log('applyTranspose', pc, x, y)
1235808f684SSatish Balay        self.impl.applyT(pc, x, y)
1246f336411SStefano Zampini
125bda5c5f8SStefano Zampini    def matApply(self, pc, x, y):
126bda5c5f8SStefano Zampini        self._log('matApply', pc, x, y)
127bda5c5f8SStefano Zampini        self.impl.applyM(pc, x, y)
1286f336411SStefano Zampini
1295808f684SSatish Balay    def applyRichardson(self, pc, x, y, w, tols):
1305808f684SSatish Balay        self._log('applyRichardson', pc, x, y, w, tols)
1315808f684SSatish Balay        self.impl.applyRich(pc, x, y, w, tols)
1325808f684SSatish Balay
1335808f684SSatish Balay
1345808f684SSatish Balayclass TestPCPYTHON(unittest.TestCase):
1355808f684SSatish Balay    PC_TYPE = PETSc.PC.Type.PYTHON
1365808f684SSatish Balay    PC_PREFIX = 'test-'
1375808f684SSatish Balay
1385808f684SSatish Balay    def setUp(self):
1395808f684SSatish Balay        pc = self.pc = PETSc.PC()
1405808f684SSatish Balay        pc.create(PETSc.COMM_SELF)
1415808f684SSatish Balay        pc.setType(self.PC_TYPE)
1425808f684SSatish Balay        module = __name__
1435808f684SSatish Balay        factory = 'PC_PYTHON_CLASS'
1445808f684SSatish Balay        self.pc.prefix = self.PC_PREFIX
1455808f684SSatish Balay        OptDB = PETSc.Options(self.pc)
1466f336411SStefano Zampini        self.assertTrue(OptDB.prefix == self.pc.prefix)
1476f336411SStefano Zampini        OptDB['pc_python_type'] = f'{module}.{factory}'
1485808f684SSatish Balay        self.pc.setFromOptions()
1495808f684SSatish Balay        del OptDB['pc_python_type']
1506f336411SStefano Zampini        self.assertTrue(self._getCtx().log['create'] == 1)
1516f336411SStefano Zampini        self.assertTrue(self._getCtx().log['setFromOptions'] == 1)
152*39933f97SStefano Zampini        self.assertEqual(getrefcount(self._getCtx()), 2)
1535808f684SSatish Balay
154ebead697SStefano Zampini    def testGetType(self):
155ebead697SStefano Zampini        ctx = self.pc.getPythonContext()
1566f336411SStefano Zampini        pytype = f'{ctx.__module__}.{type(ctx).__name__}'
157ebead697SStefano Zampini        self.assertTrue(self.pc.getPythonType() == pytype)
158ebead697SStefano Zampini
1595808f684SSatish Balay    def tearDown(self):
1605808f684SSatish Balay        ctx = self._getCtx()
1615808f684SSatish Balay        self.pc.destroy()  # XXX
1625808f684SSatish Balay        self.pc = None
16362e5d2d2SJDBetteridge        PETSc.garbage_cleanup()
1646f336411SStefano Zampini        self.assertTrue(ctx.log['destroy'] == 1)
1655808f684SSatish Balay
1665808f684SSatish Balay    def _prepare(self):
1675808f684SSatish Balay        A = PETSc.Mat().createAIJ([3, 3], comm=PETSc.COMM_SELF)
1685808f684SSatish Balay        A.setUp()
1695808f684SSatish Balay        A.assemble()
1705808f684SSatish Balay        A.shift(10)
1715808f684SSatish Balay        x, y = A.createVecs()
1725808f684SSatish Balay        x.setRandom()
1735808f684SSatish Balay        self.pc.setOperators(A, A)
174bda5c5f8SStefano Zampini        X = PETSc.Mat().createDense([3, 5], comm=PETSc.COMM_SELF).setUp()
175bda5c5f8SStefano Zampini        X.assemble()
176bda5c5f8SStefano Zampini        Y = PETSc.Mat().createDense([3, 5], comm=PETSc.COMM_SELF).setUp()
177bda5c5f8SStefano Zampini        Y.assemble()
1786f336411SStefano Zampini        self.assertTrue((A, A) == self.pc.getOperators())
179bda5c5f8SStefano Zampini        return A, x, y, X, Y
1805808f684SSatish Balay
1815808f684SSatish Balay    def _getCtx(self):
1825808f684SSatish Balay        return self.pc.getPythonContext()
1835808f684SSatish Balay
1845808f684SSatish Balay    def _applyMeth(self, meth):
185bda5c5f8SStefano Zampini        A, x, y, X, Y = self._prepare()
186bda5c5f8SStefano Zampini        if meth == 'matApply':
187bda5c5f8SStefano Zampini            getattr(self.pc, meth)(X, Y)
188bda5c5f8SStefano Zampini            x.copy(y)
189bda5c5f8SStefano Zampini        else:
1905808f684SSatish Balay            getattr(self.pc, meth)(x, y)
191bda5c5f8SStefano Zampini            X.copy(Y)
1925808f684SSatish Balay        if 'reset' not in self._getCtx().log:
1936f336411SStefano Zampini            self.assertTrue(self._getCtx().log['setUp'] == 1)
1946f336411SStefano Zampini            self.assertTrue(self._getCtx().log[meth] == 1)
1955808f684SSatish Balay        else:
1965808f684SSatish Balay            nreset = self._getCtx().log['reset']
1975808f684SSatish Balay            nsetup = self._getCtx().log['setUp']
1985808f684SSatish Balay            nmeth = self._getCtx().log[meth]
1996f336411SStefano Zampini            self.assertTrue(nreset == nsetup)
2006f336411SStefano Zampini            self.assertTrue(nreset == nmeth)
2015808f684SSatish Balay        if isinstance(self._getCtx().impl, MyPCNone):
2025808f684SSatish Balay            self.assertTrue(y.equal(x))
203bda5c5f8SStefano Zampini            self.assertTrue(Y.equal(X))
2046f336411SStefano Zampini
2055808f684SSatish Balay    def testApply(self):
2065808f684SSatish Balay        self._applyMeth('apply')
2076f336411SStefano Zampini
2085808f684SSatish Balay    def testApplySymmetricLeft(self):
2095808f684SSatish Balay        self._applyMeth('applySymmetricLeft')
2106f336411SStefano Zampini
2115808f684SSatish Balay    def testApplySymmetricRight(self):
2125808f684SSatish Balay        self._applyMeth('applySymmetricRight')
2136f336411SStefano Zampini
2145808f684SSatish Balay    def testApplyTranspose(self):
2155808f684SSatish Balay        self._applyMeth('applyTranspose')
2166f336411SStefano Zampini
217bda5c5f8SStefano Zampini    def testApplyMat(self):
218bda5c5f8SStefano Zampini        self._applyMeth('matApply')
2196f336411SStefano Zampini
2205808f684SSatish Balay    ## def testApplyRichardson(self):
2215808f684SSatish Balay    ##     x, y = self._prepare()
2225808f684SSatish Balay    ##     w = x.duplicate()
2235808f684SSatish Balay    ##     tols = 0,0,0,0
2245808f684SSatish Balay    ##     self.pc.applyRichardson(x,y,w,tols)
2255808f684SSatish Balay    ##     assert self._getCtx().log['setUp'] == 1
2265808f684SSatish Balay    ##     assert self._getCtx().log['applyRichardson'] == 1
2275808f684SSatish Balay
2285808f684SSatish Balay    ## def testView(self):
2295808f684SSatish Balay    ##     vw = PETSc.ViewerString(100, self.pc.comm)
2305808f684SSatish Balay    ##     self.pc.view(vw)
2315808f684SSatish Balay    ##     s = vw.getString()
2325808f684SSatish Balay    ##     assert 'python' in s
2335808f684SSatish Balay    ##     module = __name__
2345808f684SSatish Balay    ##     factory = 'self._getCtx()'
2355808f684SSatish Balay    ##     assert '.'.join([module, factory]) in s
2365808f684SSatish Balay
2375808f684SSatish Balay    def testResetAndApply(self):
2385808f684SSatish Balay        self.pc.reset()
2395808f684SSatish Balay        self.testApply()
2405808f684SSatish Balay        self.pc.reset()
2415808f684SSatish Balay        self.testApply()
2425808f684SSatish Balay        self.pc.reset()
2435808f684SSatish Balay
2445808f684SSatish Balay    def testKSPSolve(self):
245bda5c5f8SStefano Zampini        A, x, y, _, _ = self._prepare()
2465808f684SSatish Balay        ksp = PETSc.KSP().create(self.pc.comm)
2475808f684SSatish Balay        ksp.setType(PETSc.KSP.Type.PREONLY)
2486f336411SStefano Zampini        self.assertTrue(self.pc.getRefCount() == 1)
2495808f684SSatish Balay        ksp.setPC(self.pc)
2506f336411SStefano Zampini        self.assertTrue(self.pc.getRefCount() == 2)
2515808f684SSatish Balay        # normal ksp solve, twice
2525808f684SSatish Balay        ksp.solve(x, y)
2536f336411SStefano Zampini        self.assertTrue(self._getCtx().log['setUp'] == 1)
2546f336411SStefano Zampini        self.assertTrue(self._getCtx().log['apply'] == 1)
2556f336411SStefano Zampini        self.assertTrue(self._getCtx().log['preSolve'] == 1)
2566f336411SStefano Zampini        self.assertTrue(self._getCtx().log['postSolve'] == 1)
2575808f684SSatish Balay        ksp.solve(x, y)
2586f336411SStefano Zampini        self.assertTrue(self._getCtx().log['setUp'] == 1)
2596f336411SStefano Zampini        self.assertTrue(self._getCtx().log['apply'] == 2)
2606f336411SStefano Zampini        self.assertTrue(self._getCtx().log['preSolve'] == 2)
2616f336411SStefano Zampini        self.assertTrue(self._getCtx().log['postSolve'] == 2)
2625808f684SSatish Balay        # transpose ksp solve, twice
2635808f684SSatish Balay        ksp.solveTranspose(x, y)
2646f336411SStefano Zampini        self.assertTrue(self._getCtx().log['setUp'] == 1)
2656f336411SStefano Zampini        self.assertTrue(self._getCtx().log['applyTranspose'] == 1)
2665808f684SSatish Balay        ksp.solveTranspose(x, y)
2676f336411SStefano Zampini        self.assertTrue(self._getCtx().log['setUp'] == 1)
2686f336411SStefano Zampini        self.assertTrue(self._getCtx().log['applyTranspose'] == 2)
2695808f684SSatish Balay        del ksp  # ksp.destroy()
27062e5d2d2SJDBetteridge        PETSc.garbage_cleanup()
27162e5d2d2SJDBetteridge        self.assertEqual(self.pc.getRefCount(), 1)
2725808f684SSatish Balay
2735808f684SSatish Balay    def testGetSetContext(self):
274*39933f97SStefano Zampini        self.pc.setPythonContext(self._getCtx())
275*39933f97SStefano Zampini        self.assertEqual(getrefcount(self.pc.getPythonContext()), 2)
2765808f684SSatish Balay
2775808f684SSatish Balay
2785808f684SSatish Balayclass TestPCPYTHON2(TestPCPYTHON):
2795808f684SSatish Balay    def setUp(self):
2805808f684SSatish Balay        OptDB = PETSc.Options(self.PC_PREFIX)
2815808f684SSatish Balay        OptDB['impl'] = 'MyPCJacobi'
2826f336411SStefano Zampini        super().setUp()
2835808f684SSatish Balay        clsname = type(self._getCtx().impl).__name__
2846f336411SStefano Zampini        self.assertTrue(clsname == OptDB['impl'])
2855808f684SSatish Balay        del OptDB['impl']
2865808f684SSatish Balay
2876f336411SStefano Zampini
2885808f684SSatish Balayclass TestPCPYTHON3(TestPCPYTHON):
2895808f684SSatish Balay    def setUp(self):
2905808f684SSatish Balay        pc = self.pc = PETSc.PC()
2915808f684SSatish Balay        ctx = PC_PYTHON_CLASS()
2925808f684SSatish Balay        pc.createPython(ctx, comm=PETSc.COMM_SELF)
2935808f684SSatish Balay        self.pc.prefix = self.PC_PREFIX
2945808f684SSatish Balay        self.pc.setFromOptions()
2956f336411SStefano Zampini        self.assertTrue(self._getCtx().log['create'] == 1)
2966f336411SStefano Zampini        self.assertTrue(self._getCtx().log['setFromOptions'] == 1)
2976f336411SStefano Zampini
2985808f684SSatish Balay
2995808f684SSatish Balayclass TestPCPYTHON4(TestPCPYTHON3):
3005808f684SSatish Balay    def setUp(self):
3015808f684SSatish Balay        OptDB = PETSc.Options(self.PC_PREFIX)
3025808f684SSatish Balay        OptDB['impl'] = 'MyPCJacobi'
3036f336411SStefano Zampini        super().setUp()
3045808f684SSatish Balay        clsname = type(self._getCtx().impl).__name__
3056f336411SStefano Zampini        self.assertTrue(clsname == OptDB['impl'])
3065808f684SSatish Balay        del OptDB['impl']
3075808f684SSatish Balay
3086f336411SStefano Zampini
3095808f684SSatish Balay# --------------------------------------------------------------------
3105808f684SSatish Balay
3115808f684SSatish Balayif __name__ == '__main__':
3125808f684SSatish Balay    unittest.main()
313