Closed kmaitreys closed 2 months ago
Hi kmaitreys,
I do not fully understand the interaction with argument_to_rhs
based on the code snippets you provide. However, I would advise to create your own implementation of an Explicit_Problem
class and use class attributes for additional parameters in your right-hand side or jacobian.
Here an example:
from assimulo.problem import Explicit_Problem
from assimulo.solvers import CVode
import numpy as np
import matplotlib.pyplot as pl
pl.close("all")
class MyProb(Explicit_Problem):
param = 0
y0 = np.array([1.])
def set_my_param(self, param):
self.param = param
def rhs(self, t, y):
return self.param * y
prob = MyProb()
sim = CVode(prob)
pl.figure()
for i, t_end in enumerate([1, 2, 3]):
prob.set_my_param(i) # update problem/rhs
sim.atol = np.array([10**-(4+i)]) # update CVode options
res = sim.simulate(t_end)
pl.plot(*res, label = str(i))
pl.legend()
pl.show()
Resulting plot:
From the output you should also be able to see that the absolute tolerance was indeed changed for each (sub)simulation.
As for the sparse Jacobian question:
(n +1)
and 2 of length #nnz
. This format needs to be consistent over the whole simulation. A Jacobian may have non-structural zeros at times (i.e., values that just happen to be zero for a specific set of inputs). Taking the dense Jacobian and converting it to a sparse matrix will eliminate such non-structural zeros and create a non-consistent output format and cause the issues you experience. I hope this is helpful, let me know if there are any follow-up questions.
@PeterMeisrimelModelon Thank you for such a detailed reply. I tried your methods, but still couldn't get it working. I will admit it's probably due to me not understanding exactly what I am doing.
However, I would like to have another go at it in the next few days. So, if possible, please keep this issue open so I can visit later and we can discuss further if necessary.
Closing due to being resolved/inactivity. Please re-open/reply if otherwise.
I am having difficulty in understanding how do I implement the
CVode
solver in the way I want:What I want?
I have a number of time points for which I want to simulate (basically
ncp_list
of thesimulate()
method). Between these time points, I want to modify the state of the solver in some way. Those ways are as follows:atol
for each equationrhs_function
, so whensimulate()
calls it next time, it's updated value is used.Why do I want this?
I am trying to solve a very stiff system (chemical kinetics) with
CVode
in hopes of greater robustness and speed. I have two implementations available as a benchmark. One is an old Fortran one which usesDLSODES
and one is that I have written which usesscipy.integrate.ode
with theLSODA
method. Note thatLSODA
is different thatDLSODES
as in the former automatically switches between a stiff and non-stiff solver but the latter always uses a stiff solver (BDF, I think). I have heard thatCVode
is arguably better thanDLSODES
so I wanted to try it.What I have done so far?
I wrote the following code (only the relevant parts):
Here are the RHS and Jacobian functions (wrappers):
This works only for first time step (which is a very small value) and then it fails with the following error:
One more thing you can perhaps note that I am supplying the
size
of my 2-D Jacobian matrix tonnz
which is obviously not the number of non-zero values. When I did the following however:I got the following error:
An equivalent working
scipy
implementation