Пример #1
0
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
Пример #2
0
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