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