xref: /petsc/src/binding/petsc4py/demo/legacy/ode/ce.py (revision d53c7dcfa6b151504f6ca0aeb7a446ad68fe4d68)
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