155a74a43SLisandro Dalcin# Stiff scalar valued ODE problem with an exact solution 255a74a43SLisandro Dalcin 3*69777137SStefano Zampiniimport sys 4*69777137SStefano Zampiniimport petsc4py 5*69777137SStefano Zampini 655a74a43SLisandro Dalcinpetsc4py.init(sys.argv) 755a74a43SLisandro Dalcin 855a74a43SLisandro Dalcinfrom petsc4py import PETSc 955a74a43SLisandro Dalcinfrom math import sin, cos, exp 1055a74a43SLisandro Dalcin 11*69777137SStefano Zampini 12*69777137SStefano Zampiniclass CE: 1355a74a43SLisandro Dalcin n = 1 1455a74a43SLisandro Dalcin comm = PETSc.COMM_SELF 15*69777137SStefano Zampini 1655a74a43SLisandro Dalcin def __init__(self, lambda_=1.0): 1755a74a43SLisandro Dalcin self.lambda_ = lambda_ 18*69777137SStefano Zampini 1955a74a43SLisandro Dalcin def evalSolution(self, t, x): 20*69777137SStefano Zampini lam = self.lambda_ 21*69777137SStefano Zampini x[0] = lam / (lam * lam + 1) * (lam * cos(t) + sin(t)) - lam * lam / ( 22*69777137SStefano Zampini lam * lam + 1 23*69777137SStefano Zampini ) * exp(-lam * t) 2455a74a43SLisandro Dalcin x.assemble() 25*69777137SStefano Zampini 2655a74a43SLisandro Dalcin def evalFunction(self, ts, t, x, xdot, f): 27*69777137SStefano Zampini lam = self.lambda_ 28*69777137SStefano Zampini f[0] = xdot[0] + lam * (x[0] - cos(t)) 2955a74a43SLisandro Dalcin f.assemble() 30*69777137SStefano Zampini 3155a74a43SLisandro Dalcin def evalJacobian(self, ts, t, x, xdot, a, A, B): 3255a74a43SLisandro Dalcin J = B 33*69777137SStefano Zampini lam = self.lambda_ 34*69777137SStefano Zampini J[0, 0] = a + lam 3555a74a43SLisandro Dalcin J.assemble() 36*69777137SStefano Zampini if A != B: 37*69777137SStefano Zampini A.assemble() 38*69777137SStefano Zampini 3955a74a43SLisandro Dalcin 4055a74a43SLisandro DalcinOptDB = PETSc.Options() 4155a74a43SLisandro Dalcin 4255a74a43SLisandro Dalcinlambda_ = OptDB.getScalar('lambda', 10.0) 4355a74a43SLisandro Dalcinode = CE(lambda_) 4455a74a43SLisandro Dalcin 4555a74a43SLisandro DalcinJ = PETSc.Mat().createDense([ode.n, ode.n], comm=ode.comm) 4655a74a43SLisandro DalcinJ.setUp() 4755a74a43SLisandro Dalcinx = PETSc.Vec().createSeq(ode.n, comm=ode.comm) 4855a74a43SLisandro Dalcinf = x.duplicate() 4955a74a43SLisandro Dalcin 5055a74a43SLisandro Dalcints = PETSc.TS().create(comm=ode.comm) 5155a74a43SLisandro Dalcints.setProblemType(ts.ProblemType.NONLINEAR) 5255a74a43SLisandro Dalcints.setType(ts.Type.GLLE) 5355a74a43SLisandro Dalcin 5455a74a43SLisandro Dalcints.setIFunction(ode.evalFunction, f) 5555a74a43SLisandro Dalcints.setIJacobian(ode.evalJacobian, J) 5655a74a43SLisandro Dalcin 5755a74a43SLisandro Dalcints.setTime(0.0) 5855a74a43SLisandro Dalcints.setTimeStep(0.001) 5955a74a43SLisandro Dalcints.setMaxTime(10) 6055a74a43SLisandro Dalcints.setMaxSteps(10000) 6155a74a43SLisandro Dalcints.setExactFinalTime(PETSc.TS.ExactFinalTime.INTERPOLATE) 6255a74a43SLisandro Dalcin 63*69777137SStefano Zampini 64*69777137SStefano Zampiniclass Monitor: 6555a74a43SLisandro Dalcin def __init__(self, ode): 6655a74a43SLisandro Dalcin self.ode = ode 6755a74a43SLisandro Dalcin self.x = PETSc.Vec().createSeq(ode.n, comm=ode.comm) 68*69777137SStefano Zampini 6955a74a43SLisandro Dalcin def __call__(self, ts, k, t, x): 70*69777137SStefano Zampini self.ode.evalSolution(t, self.x) 7155a74a43SLisandro Dalcin self.x.axpy(-1, x) 7255a74a43SLisandro Dalcin e = self.x.norm() 7355a74a43SLisandro Dalcin h = ts.getTimeStep() 74*69777137SStefano Zampini PETSc.Sys.Print( 75*69777137SStefano Zampini 'step %3d t=%8.2e h=%8.2e error=%8.2e' % (k, t, h, e), comm=self.ode.comm 76*69777137SStefano Zampini ) 77*69777137SStefano Zampini 7855a74a43SLisandro Dalcin 7955a74a43SLisandro Dalcints.setMonitor(Monitor(ode)) 8055a74a43SLisandro Dalcin 8155a74a43SLisandro Dalcints.setFromOptions() 8255a74a43SLisandro Dalcinode.evalSolution(0.0, x) 8355a74a43SLisandro Dalcints.solve(x) 8455a74a43SLisandro Dalcin 8555a74a43SLisandro Dalcindel ode, J, x, f, ts 86