def annlinit(model, abstol=1.0e-3, reltol=1.0e-3, nsteps = 20000, itermaxstep = None): """ annlinit initializes the environment for simulations using CVODE INPUT: ------- model: a PySB model object abstol: absolute tolerance for CVODE integrator reltol: relative tolerance for CVODE integrator nsteps: number of time steps of integration (depends on the units of the parameters) itermaxstep: maximum number of iteration steps OUTPUT: ------- a list object containing: [f, rhs_exprs, y, odesize, data, xout, yout, nsteps, cvode_mem, yzero, reltol, abstol] f: the function called by cvodes calls that returns dy rhs_exprs: the python expression for the right hand side (list of strings) y: a CVode NVector object with the initial values for all species odesize: the number of odes data: a ctypes data structure (for Sundials) containing the parameter values (floats) xout: the numpy array where the time values will be put yout: the numpy array where the integrated timeseries will be put nsteps: the number of time steps cvode_mem: cvode memory object defining the step method yzero: a numpy array of the initial conditions paramarray: a numpy array containing the parameter values (floats). (same contents as data, but different datatype) reltol: integrator relative tolerance (float) abstol: integrator absolute tolerance (float) paramarray, a parameter array """ # Generate equations pysb.bng.generate_equations(model) odesize = len(model.odes) yzero = numpy.zeros(odesize) #initial values for yzero # assign the initial conditions for cplxptrn, ic_param in model.initial_conditions: speci = model.get_species_index(cplxptrn) yzero[speci] = ic_param.value # initialize y with the yzero values y = cvode.NVector(yzero) # make a dict of ydot functions. notice the functions are in this namespace. # replace the kxxxx constants with elements from the params array rhs_exprs = [] for i in range(0,odesize): # get the function string from sympy, replace the the "sN" with y[N] tempstring = re.sub(r's(\d+)', lambda m: 'y[%s]'%(int(m.group(1))), str(model.odes[i])) # replace the constants with 'p' array names; cycle through the whole list for j, parameter in enumerate(model.parameters): tempstring = re.sub('(?<![A-Za-z0-9_])%s(?![A-Za-z0-9_])' % parameter.name, 'p[%d]' % j, tempstring) # make a list of compiled rhs expressions which will be run by the integrator # use the ydots to build the function for analysis # (second arg is the "filename", useful for exception/debug output) rhs_exprs.append(compile(tempstring, '<ydot[%s]>' % i, 'eval')) # Create a generic "p" array to hold the parameters when calling the function numparams = len(model.parameters) class UserData(ctypes.Structure): _fields_ = [('p', cvode.realtype*numparams)] # parameters PUserData = ctypes.POINTER(UserData) data = UserData() # Create the paramarray to hold the parameters and pass them from C to Python # FIXME: could prob do this directly from data.p data.p[:] = [p.value for p in model.parameters] paramarray = numpy.array([p.value for p in model.parameters]) # allocate "p" as a pointer array that can be called by sundials "f" as needed def f(t, y, ydot, f_data): data = ctypes.cast(f_data, PUserData).contents rhs_locals = {'y': y, 'p': data.p} for i in range(0,len(model.odes)): ydot[i] = eval(rhs_exprs[i], rhs_locals) return 0 # initialize the cvode memory object, use BDF and Newton for stiff cvode_mem = cvode.CVodeCreate(cvode.CV_BDF, cvode.CV_NEWTON) # allocate the cvode memory as needed, pass the function and the initial ys cvode.CVodeMalloc(cvode_mem, f, 0.0, y, cvode.CV_SS, reltol, abstol) # point the parameters to the correct array cvode.CVodeSetFdata(cvode_mem, ctypes.pointer(data)) # link integrator with linear solver cvode.CVDense(cvode_mem, odesize) # maximum iteration steps if itermaxstep != None: cvode.CVodeSetMaxStep(cvode_mem, itermaxstep) #list of outputs xout = numpy.zeros(nsteps) yout = numpy.zeros([nsteps, odesize]) #initialize the arrays xout[0] = 0.0 # FIXME: this assumes that the integration starts at zero... CHANGE IF NEEDED #first step in yout for i in range(0, odesize): yout[0][i] = y[i] # f: the function called by cvodes calls that returns dy # rhs_exprs: the python expression for the right hand side (list of strings) # y: a CVode NVector object with the initial values for all species # odesize: the number of odes # data: a ctypes data structure (for Sundials) containing the parameter values (floats) # xout: the numpy array where the time values will be put # yout: the numpy array where the integrated timeseries will be put # nsteps: the number of time steps # cvode_mem: cvode memory object defining the step method # yzero: a numpy array of the initial conditions # paramarray: a numpy array containing the parameter values (floats). (same contents as data, but different datatype) # reltol: integrator relative tolerance (float) # abstol: integrator absolute tolerance (float) return [f, rhs_exprs, y, odesize, data, xout, yout, nsteps, cvode_mem, yzero, reltol, abstol], paramarray
def odeinit(model, reltol=1.0e-3, abstol=1.0e-3, nsteps=1000, itermaxstep=None): ''' must be run to set up the environment for annealing with pysundials ''' # Generate equations pysb.bng.generate_equations(model) # Get the size of the ODE array odesize = len(model.odes) # init the arrays we need yzero = numpy.zeros(odesize) #initial values for yzero # assign the initial conditions for cplxptrn, ic_param in model.initial_conditions: speci = model.get_species_index(cplxptrn) yzero[speci] = ic_param.value # initialize y with the yzero values y = cvode.NVector(yzero) # make a dict of ydot functions. notice the functions are in this namespace. # replace the kxxxx constants with elements from the params array rhs_exprs = [] for i in range(0, odesize): # first get the function string from sympy, replace the the "sN" with y[N] tempstring = re.sub(r's(\d+)', lambda m: 'y[%s]' % (int(m.group(1))), str(model.odes[i])) # now replace the constants with 'p' array names; cycle through the whole list #for j in range(0, numparams): # tempstring = re.sub('(?<![A-Za-z0-9_])%s(?![A-Za-z0-9_])'%(model.parameters[j].name),'p[%d]'%(j), tempstring) for j, parameter in enumerate(model.parameters): tempstring = re.sub( '(?<![A-Za-z0-9_])%s(?![A-Za-z0-9_])' % parameter.name, 'p[%d]' % j, tempstring) # make a list of compiled rhs expressions which will be run by the integrator # use the ydots to build the function for analysis # (second arg is the "filename", useful for exception/debug output) rhs_exprs.append(compile(tempstring, '<ydot[%s]>' % i, 'eval')) # Create the structure to hold the parameters when calling the function # This results in a generic "p" array numparams = len(model.parameters) class UserData(ctypes.Structure): _fields_ = [('p', cvode.realtype * numparams)] # parameters PUserData = ctypes.POINTER(UserData) data = UserData() data.p[:] = [p.value for p in model.parameters] paramarray = numpy.array([p.value for p in model.parameters]) # allocate the "p" array as a pointer array that can be called by sundials "f" as needed def f(t, y, ydot, f_data): data = ctypes.cast(f_data, PUserData).contents rhs_locals = {'y': y, 'p': data.p} for i in range(0, len(model.odes)): ydot[i] = eval(rhs_exprs[i], rhs_locals) return 0 # initialize the cvode memory object, use BDF and Newton for stiff systems cvode_mem = cvode.CVodeCreate(cvode.CV_BDF, cvode.CV_NEWTON) # allocate the cvode memory as needed, pass the function and the init ys cvode.CVodeMalloc(cvode_mem, f, 0.0, y, cvode.CV_SS, reltol, abstol) # point the parameters to the correct array # if the params are changed later this does not need to be reassigned (???) cvode.CVodeSetFdata(cvode_mem, ctypes.pointer(data)) # link integrator with linear solver cvode.CVDense(cvode_mem, odesize) #stepsize if itermaxstep != None: cvode.CVodeSetMaxStep(cvode_mem, itermaxstep) #list of outputs xout = numpy.zeros(nsteps) yout = numpy.zeros([nsteps, odesize]) #initialize the arrays #print "Initial parameter values:", y xout[0] = 0.0 #CHANGE IF NEEDED #first step in yout for i in range(0, odesize): yout[0][i] = y[i] return [ f, rhs_exprs, y, odesize, data, xout, yout, nsteps, cvode_mem, yzero, reltol, abstol ], paramarray