1import unittest 2from petsc4py import PETSc 3from sys import getrefcount 4import gc 5 6# -------------------------------------------------------------------- 7 8class MyODE: 9 """ 10 du/dt + u**2 = 0; 11 u0 = 1 12 """ 13 14 def __init__(self): 15 self.function_calls = 0 16 self.jacobian_calls = 0 17 18 def function(self,ts,t,u,du,F): 19 #print 'MyODE.function()' 20 self.function_calls += 1 21 f = du + u * u 22 f.copy(F) 23 24 def jacobian(self,ts,t,u,du,a,J,P): 25 #print 'MyODE.jacobian()' 26 self.jacobian_calls += 1 27 P.zeroEntries() 28 diag = a + 2 * u 29 P.setDiagonal(diag) 30 P.assemble() 31 if J != P: J.assemble() 32 return False # same_nz 33 34class MyTS: 35 def __init__(self): 36 self.log = {} 37 def _log(self, method, *args): 38 self.log.setdefault(method, 0) 39 self.log[method] += 1 40 41 def create(self, ts, *args): 42 self._log('create', *args) 43 self.vec_update = PETSc.Vec() 44 45 def destroy(self, ts, *args): 46 self._log('destroy', *args) 47 self.vec_update.destroy() 48 49 def setFromOptions(self, ts, *args): 50 self._log('setFromOptions', *args) 51 52 def setUp(self, ts, *args): 53 self._log('setUp', ts, *args) 54 self.vec_update = ts.getSolution().duplicate() 55 56 def reset(self, ts, *args): 57 self._log('reset', ts, *args) 58 59 def solveStep(self, ts, t, u, *args): 60 self._log('solveStep', ts, t, u, *args) 61 ts.snes.solve(None, u) 62 63 def adaptStep(self, ts, t, u, *args): 64 self._log('adaptStep', ts, t, u, *args) 65 return (ts.getTimeStep(), True) 66 67 68class TestTSPython(unittest.TestCase): 69 70 def setUp(self): 71 self.ts = PETSc.TS() 72 self.ts.createPython(MyTS(), comm=PETSc.COMM_SELF) 73 eft = PETSc.TS.ExactFinalTime.STEPOVER 74 self.ts.setExactFinalTime(eft) 75 ctx = self.ts.getPythonContext() 76 self.assertEqual(getrefcount(ctx), 3) 77 self.assertEqual(ctx.log['create'], 1) 78 self.nsolve = 0 79 80 def tearDown(self): 81 ctx = self.ts.getPythonContext() 82 self.assertEqual(getrefcount(ctx), 3) 83 self.assertTrue('destroy' not in ctx.log) 84 self.ts.destroy() # XXX 85 self.ts = None 86 self.assertEqual(ctx.log['destroy'], 1) 87 self.assertEqual(getrefcount(ctx), 2) 88 89 def testSolve(self): 90 ts = self.ts 91 ts.setProblemType(ts.ProblemType.NONLINEAR) 92 ode = MyODE() 93 J = PETSc.Mat().create(ts.comm) 94 J.setSizes(3); 95 J.setFromOptions() 96 J.setUp() 97 u, f = J.createVecs() 98 99 ts.setAppCtx(ode) 100 ts.setIFunction(ode.function, f) 101 ts.setIJacobian(ode.jacobian, J, J) 102 ts.snes.ksp.pc.setType('none') 103 104 T0, dT, nT = 0.0, 0.1, 10 105 T = T0 + nT*dT 106 ts.setTime(T0) 107 ts.setTimeStep(dT) 108 ts.setMaxTime(T) 109 ts.setMaxSteps(nT) 110 ts.setFromOptions() 111 u[0], u[1], u[2] = 1, 2, 3 112 ts.solve(u) 113 self.nsolve +=1 114 115 self.assertTrue(ode.function_calls > 0) 116 self.assertTrue(ode.jacobian_calls > 0) 117 118 ctx = self.ts.getPythonContext() 119 ncalls = self.nsolve * ts.step_number 120 self.assertTrue(ctx.log['solveStep'] == ncalls) 121 self.assertTrue(ctx.log['adaptStep'] == ncalls) 122 del ctx 123 124 dct = self.ts.getDict() 125 self.assertTrue('__appctx__' in dct) 126 self.assertTrue('__ifunction__' in dct) 127 self.assertTrue('__ijacobian__' in dct) 128 129 def testFDColor(self): 130 # 131 ts = self.ts 132 ts.setProblemType(ts.ProblemType.NONLINEAR) 133 ode = MyODE() 134 J = PETSc.Mat().create(ts.comm) 135 J.setSizes(5); J.setType('aij'); 136 J.setPreallocationNNZ(1) 137 J.setFromOptions() 138 u, f = J.createVecs() 139 140 ts.setAppCtx(ode) 141 ts.setIFunction(ode.function, f) 142 ts.setIJacobian(ode.jacobian, J, J) 143 144 T0, dT, nT = 0.00, 0.1, 10 145 T = T0 + nT*dT 146 ts.setTime(T0) 147 ts.setTimeStep(dT) 148 ts.setMaxTime(T) 149 ts.setMaxSteps(nT) 150 ts.setFromOptions() 151 u[:] = 1, 2, 3, 4, 5 152 153 ts.setSolution(u) 154 ode.jacobian(ts,0.0,u,u,1.0,J,J) 155 ts.snes.setUseFD(True) 156 ts.solve(u) 157 self.nsolve +=1 158 159 def testResetAndSolve(self): 160 self.ts.reset() 161 self.ts.setStepNumber(0) 162 self.testSolve() 163 self.ts.reset() 164 self.ts.setStepNumber(0) 165 self.testFDColor() 166 self.ts.reset() 167 self.ts.setStepNumber(0) 168 self.testSolve() 169 self.ts.reset() 170 171 def testSetAdaptLimits(self): 172 self.ts.setStepLimits(1.0, 2.0) 173 hmin, hmax = self.ts.getStepLimits() 174 self.assertEqual(1.0, hmin) 175 self.assertEqual(2.0, hmax) 176 177# -------------------------------------------------------------------- 178 179if __name__ == '__main__': 180 unittest.main() 181 182# -------------------------------------------------------------------- 183