Exemple #1
0
    def _create_arc_integrator(self, trans_duration=3, res=100,
                               pulse_res=20):
        """ Create integrator and simulator objects for later use.
        trans_duration is number of periods to simulate perturbed
        trajectory and reference, res is the resolution (per period) of
        the output trajectories """

        # Use parameterized period so the integration length can be
        # controlled without re-initializing
        self.arcint = cs.CVodesIntegrator(self.modlT)
        self.arcint.setOption('abstol', self.intoptions['int_abstol'])
        self.arcint.setOption('reltol', self.intoptions['int_reltol'])
        self.arcint.setOption('tf', 1.)
        self.arcint.init()
        #
        # Simulate the perturbed trajectory for trans_duration.
        tf = 2*np.pi*trans_duration
        traj_res = int(res*trans_duration)
        self.arc_traj_ts = np.linspace(0, tf, num=traj_res,
                                       endpoint=True) 
        self.arcsim = cs.Simulator(self.arcint, self.arc_traj_ts/tf)
        self.arcsim.init()
        self.pulsesim = cs.Simulator(self.arcint,
                                     np.linspace(0, 1., num=pulse_res,
                                                 endpoint=True))
        self.pulsesim.init()
Exemple #2
0
    def solve_ode(self):
        """ Solve the ODE using casadi's CVODES wrapper to ensure that the
        collocated dynamics match the error-controlled dynamics of the ODE """

        self.ts.sort()  # Assert ts is increasing

        f_integrator = cs.SXFunction(
            'ode',
            cs.daeIn(t=self.dxdt.inputExpr(0),
                     x=self.dxdt.inputExpr(1),
                     p=self.dxdt.inputExpr(2)),
            cs.daeOut(ode=self.dxdt.outputExpr(0)))

        integrator = cs.Integrator('int', 'cvodes', f_integrator)
        simulator = cs.Simulator('sim', integrator, self.ts)
        simulator.setInput(self.sol[0], 'x0')
        simulator.setInput(self.var.p_op, 'p')
        simulator.evaluate()
        x_sim = self.sol_sim = np.array(simulator.getOutput()).T

        err = ((self.sol - x_sim).mean(0) / (self.sol.mean(0))).mean()

        if err > 1E-3:
            warn('Collocation does not match ODE Solution: \
                {:.2%} Error'.format(err))
    def limit_cycle(self):
        """
        integrate the solution for one period, remembering each of time
        points along the way
        """

        self.ts = np.linspace(0, self.T, self.intoptions['lc_res'])

        intlc = cs.Integrator('cvodes',self.model)
        intlc.setOption("abstol"       , self.intoptions['lc_abstol'])
        intlc.setOption("reltol"       , self.intoptions['lc_reltol'])
        intlc.setOption("max_num_steps", self.intoptions['lc_maxnumsteps'])
        intlc.setOption("tf"           , self.T)

        intsim = cs.Simulator(intlc, self.ts)
        intsim.init()

        # Input Arguments
        intsim.setInput(self.y0, cs.INTEGRATOR_X0)
        intsim.setInput(self.param, cs.INTEGRATOR_P)
        intsim.evaluate()
        self.sol = intsim.output().toArray().T

        # create interpolation object
        self.lc = self.interp_sol(self.ts, self.sol.T)
    def int_odes(self, tf, y0=None, numsteps=10000, return_endpt=False, ts=0):
        """
        This function integrates the ODEs until well past the transients. 
        This uses Casadi's simulator class, C++ wrapped in swig. Inputs:
            tf          -   the final time of integration.
            numsteps    -   the number of steps in the integration is the second argument
        """
        if y0 is None: y0 = self.y0

        self.integrator = cs.Integrator('cvodes', self.model)

        #Set up the tolerances etc.
        self.integrator.setOption("abstol", self.intoptions['int_abstol'])
        self.integrator.setOption("reltol", self.intoptions['int_reltol'])
        self.integrator.setOption("max_num_steps",
                                  self.intoptions['int_maxstepcount'])
        self.integrator.setOption("tf", tf)

        #Let's integrate
        self.integrator.init()
        self.ts = np.linspace(ts, tf, numsteps, endpoint=True)
        self.simulator = cs.Simulator(self.integrator, self.ts)
        self.simulator.init()
        self.simulator.setInput(y0, cs.INTEGRATOR_X0)
        self.simulator.setInput(self.param, cs.INTEGRATOR_P)
        self.simulator.evaluate()

        sol = self.simulator.output().toArray().T

        if return_endpt == True:
            return sol[-1]
        else:
            return sol
Exemple #5
0
    def _single_pulse_comparison_state(self, state, phase, amount,
                                       trans_duration):
        """ Compares a single perturbation of state to a reference
        trajectory """

        base = self.base_class

        # Use parameterized period so the integration length can be
        # controlled without re-initializing
        self.arcint = cs.CVodesIntegrator(base.modlT)
        self.arcint.setOption('abstol', self.int_opt['int_abstol'])
        self.arcint.setOption('reltol', self.int_opt['int_reltol'])
        self.arcint.setOption('tf', 1.)
        self.arcint.init()

        # Find y0 at start of pulse
        tstart = phase * base.y0[-1] / (2 * np.pi)
        y0 = base.lc(tstart)
        y0[state] += amount

        # Simulate the perturbed trajectory for trans_duration.
        tf = base.y0[-1] * trans_duration
        ts = np.linspace(0, tf, num=int(100 * trans_duration), endpoint=True)
        self.arcsim = cs.Simulator(self.arcint, ts / tf)
        self.arcsim.init()
        self.arcsim.setInput(y0, cs.INTEGRATOR_X0)
        self.arcsim.setInput(list(base.paramset) + [tf], cs.INTEGRATOR_P)

        self.arcsim.evaluate()
        trajectory = self.arcsim.output().toArray()
        yend = trajectory[-1]
        tend = ts[-1] % base.y0[-1] + tstart

        def resy(t):
            return np.linalg.norm(yend - base.lc(t % base.y0[-1]))

        # Minimize resy(t)
        tvals = np.linspace(0, base.y0[-1], num=25)
        tguess = tvals[np.array([resy(t) for t in tvals]).argmin()]
        tmin = sc.optimize.fmin(resy, tguess, disp=0)[0] % base.y0[-1]
        assert resy(tmin) / base.NEQ < 1E-3, "transient not converged"

        if tmin > base.y0[-1] / 2: tmin += -base.y0[-1]

        tdiff = tmin - tend

        # rescale tdiff from -T/2 to T/2
        tdiff = tdiff % base.y0[-1]
        if tdiff > base.y0[-1] / 2: tdiff += -base.y0[-1]

        reference = base.lc((ts + tend + tdiff) % base.y0[-1])

        # from scipy.integrate import cumtrapz
        # amp_change = cumtrapz((trajectory - reference).T, x=ts)[:,-1]

        return trajectory, reference, tdiff
Exemple #6
0
    def _create_arc_integrator(self, trans_duration=3):
        """ Create integrator and simulator objects for later use """

        # Use parameterized period so the integration length can be
        # controlled without re-initializing
        self.arcint = cs.CVodesIntegrator(self.modlT)
        self.arcint.setOption('abstol', self.intoptions['int_abstol'])
        self.arcint.setOption('reltol', self.intoptions['int_reltol'])
        self.arcint.setOption('tf', 1.)
        self.arcint.init()
        #
        # Simulate the perturbed trajectory for trans_duration.
        tf = self.y0[-1] * trans_duration
        self.arc_traj_ts = np.linspace(0,
                                       tf,
                                       num=int(100 * trans_duration),
                                       endpoint=True)
        self.arcsim = cs.Simulator(self.arcint, self.arc_traj_ts / tf)
        self.arcsim.init()
Exemple #7
0
    def fwd_simulation(self,
                       dE_start,
                       condition,
                       detail=True,
                       reltol=1e-6,
                       abstol=1e-8):

        Tem = condition.Temperature
        time = condition.TimeGrid

        opts = {}
        opts['abstol'] = abstol
        opts['reltol'] = reltol
        opts['disable_internal_warnings'] = True
        opts['max_num_steps'] = 1e5

        P_dae = np.hstack([dE_start, Tem])

        # Partial Pressure
        Pinlet = np.zeros(self.ngas)
        for idx, spe in enumerate(self.specieslist):
            if spe.phase == 'gaseous':
                Pinlet[idx] = condition.PartialPressure[str(spe)]
        x0 = Pinlet.tolist() + [0] * (self.nsurf - 1) + [1]
        # print(x0)

        Fint = cas.Integrator('Fint', 'cvodes', self._dae_, opts)
        Fsim = cas.Simulator('Fsim', Fint, time)
        Fsim.setInput(x0, 'x0')
        Fsim.setInput(P_dae, 'p')
        Fsim.evaluate()

        # Evalu
        out = Fsim.getOutput().full()

        tor_list = {}
        for i, spe in enumerate(self.specieslist):
            if spe.phase == 'gaseous':
                nt = int(condition.Ntime / 2)
                slope, intercept, r_value, p_value, std_err = stats.linregress(
                    condition.TimeGrid[nt:], out[i, nt:])
                tor_list[spe.name] = slope
        return out, tor_list
Exemple #8
0
    def _simulate(self, ts, y0=None, paramset=None):
        """ Simulate the class, outputing the solution at the times
        specified by ts. Optional inputs of y0 and paramsets to use ones
        other than those currently in the class """

        if y0 is None: y0 = self.y0[:-1]
        if paramset is None: paramset = self.paramset

        int = cs.CVodesIntegrator(self.model)
        int.setOption("abstol"       , self.intoptions['lc_abstol'])
        int.setOption("reltol"       , self.intoptions['lc_reltol'])
        int.setOption("max_num_steps", self.intoptions['lc_maxnumsteps'])
        int.setOption("tf"           , self.y0[-1])

        sim = cs.Simulator(int, ts)
        sim.init()
        
        # Input Arguments
        sim.setInput(y0, cs.INTEGRATOR_X0)
        sim.setInput(paramset, cs.INTEGRATOR_P)
        sim.evaluate()
        return sim.output().toArray()
Exemple #9
0
    def fwd_simulation(self,
                       dE_start,
                       condition,
                       detail=True,
                       reltol=1e-6,
                       abstol=1e-8):
        # reevaluate the reaction condition
        condition._calSim()
        condition._calGrid()
        time = condition.TimeGrid
        T0 = condition.T0
        beta = condition.Beta

        opts = {}
        opts['abstol'] = abstol
        opts['reltol'] = reltol
        opts['disable_internal_warnings'] = True
        opts['max_num_steps'] = 1e5

        x0 = self.init_condition(condition)
        P_dae = np.hstack([dE_start, T0, beta])
        #        print(x0)
        #        print(P_dae)
        #        print(time)
        #        opts['tf'] = 2
        #        Fint = cas.Integrator('Fint', 'cvodes', self._dae_, opts)
        #        F_sim = Fint(x0=x0, p=P_dae)

        Fint = cas.Integrator('Fint', 'cvodes', self._dae_, opts)
        Fsim = cas.Simulator('Fsim', Fint, time)
        Fsim.setInput(x0, 'x0')
        Fsim.setInput(P_dae, 'p')
        Fsim.evaluate()

        # Evaluate
        out = Fsim.getOutput().full()
        out[:self.ngas, :] *= self.pump_ratio
        return out
Exemple #10
0
    def eval_likeli(self, dE, conditionlist, evidence_info={}):
        reltol = evidence_info.get('reltol', 1e-12)
        abstol = evidence_info.get('abstol', 1e-12)

        err = evidence_info.get('peak_err', 10)

        opts = {}
        opts['abstol'] = abstol
        opts['reltol'] = reltol
        opts['disable_internal_warnings'] = True
        opts['max_num_steps'] = 1e5

        # Initialize simulator
        evidence = 0
        for condition in conditionlist:
            time = condition.TimeGrid
            T0 = condition.T0
            beta = condition.Beta
            x0 = self.init_condition(condition)

            P_dae = np.hstack([dE, T0, beta])

            Fint = cas.Integrator('Fint', 'cvodes', self._dae_, opts)
            Fsim = cas.Simulator('Fsim', Fint, time)
            Fsim.setInput(x0, 'x0')
            Fsim.setInput(P_dae, 'p')
            Fsim.evaluate()

            out = Fsim.getOutput().full()
            # Find the peak
            for spe, peak_exp in condition.PeakPosition.items():
                idx = get_index_species(spe, self.specieslist)
                des = out[idx, :]
                idx_peak = np.argmax(des)
                peak_sim = condition.TemGrid[idx_peak]
                dev = peak_sim - peak_exp
                evidence += (dev * dev) / err**2
        return -evidence
Exemple #11
0
    def solve_ode(self):
        """ Solve the ODE using casadi's CVODES wrapper to ensure that the
        collocated dynamics match the error-controlled dynamics of the ODE """

        f_integrator = cs.SXFunction(
            'ode',
            cs.daeIn(t=self.model.inputExpr(0),
                     x=self.model.inputExpr(1),
                     p=self.model.inputExpr(2)),
            cs.daeOut(ode=self.model.outputExpr(0)))

        integrator = cs.Integrator('int', 'cvodes', f_integrator)
        simulator = cs.Simulator('sim', integrator, self._tgrid)
        simulator.setInput(self._output['x_opt'][0], 'x0')
        simulator.setInput(self._output['p_opt'], 'p')
        simulator.evaluate()
        x_sim = self._output['x_sim'] = np.array(simulator.getOutput()).T

        err = ((self._output['x_opt'] - x_sim).mean(0) /
               (self._output['x_opt'].mean(0))).mean()

        if err > 1E-3:
            warn('Collocation does not match ODE Solution: \
                {:.2f}% Error'.format(100 * err))
Exemple #12
0
    def Integrate(self, t, sim=True, res=500, pars=None):
        """ Integrate the forced oscillator from t = 0 to t. sim=True,
        return vector of values. """

        # Get parameters over the limit cycle
        if pars is None:
            pars = np.array([self._get_paramset(tj)
                             for tj in self.tgrid_u]).flatten()

        apars = pars.reshape((self.nk, self.NP))
        y = self.y0

        integrator = cs.CVodesIntegrator(self.model)
        integrator.setOption('abstol', self.int_opt['int_abstol'])
        integrator.setOption('reltol', self.int_opt['int_reltol'])
        integrator.setOption('tf', self.h)
        integrator.init()

        t_i = 0

        if not sim:

            while t_i < t - self.h + 1E-5:
                element_index = int((t_i / self.h) % self.nk)
                integrator.setInput(y, cs.INTEGRATOR_X0)
                integrator.setInput(apars[element_index], cs.INTEGRATOR_P)
                integrator.evaluate()
                y = integrator.output()
                t_i += self.h

            if t - t_i > 1E-5:
                element_index = int((t_i / self.h) % self.nk)
                integrator.setOption('tf', t - t_i)
                integrator.init()
                integrator.setInput(y, cs.INTEGRATOR_X0)
                integrator.setInput(apars[element_index], cs.INTEGRATOR_P)
                integrator.evaluate()
                y = integrator.output()

            return t, y

        else:
            # Allow for specific ts requests in res
            try:
                ts = np.linspace(0, t, res)
            except TypeError:
                ts = res
            sol = np.zeros((0, self.NEQ))

            while t_i < t - self.h + 1E-5:
                element_index = int((t_i / self.h) % self.nk)
                ts_i = ts[np.all([ts < t_i + self.h, ts >= t_i], 0)] - t_i
                sim_i = cs.Simulator(integrator, np.hstack([0, ts_i, self.h]))
                sim_i.init()
                sim_i.setInput(y, cs.INTEGRATOR_X0)
                sim_i.setInput(apars[element_index], cs.INTEGRATOR_P)
                sim_i.evaluate()
                out = sim_i.output().toArray()
                sol = np.vstack([sol, out[1:-1]])
                y = out[-1]
                t_i += self.h

            if t - t_i > 1E-5:
                element_index = int((t_i / self.h) % self.nk)
                ts_i = ts[np.all([ts < t_i + self.h, ts >= t_i], 0)] - t_i
                sim_i = cs.Simulator(integrator, np.hstack([0, ts_i, t - t_i]))
                sim_i.init()
                sim_i.setInput(y, cs.INTEGRATOR_X0)
                sim_i.setInput(apars[element_index], cs.INTEGRATOR_P)
                sim_i.evaluate()
                out = sim_i.output().toArray()
                sol = np.vstack([sol, out[1:-1]])
                y = out[-1]

            # Close enough.
            elif len(sol) == len(ts) - 1:
                sol = np.vstack([sol, y])

            return ts, sol
Exemple #13
0
    def _single_pulse_comparison(self, param, phase, amount, pulse_duration,
                                 trans_duration):
        """ Compares a single perturbation to a reference trajectory """

        base = self.base_class
        try:
            par_ind = self.base_class.pdict[param]
        except KeyError:
            par_ind = int(param)

        # Use parameterized period so the integration length can be
        # controlled without re-initializing
        self.arcint = cs.CVodesIntegrator(base.modlT)
        self.arcint.setOption('abstol', self.int_opt['int_abstol'])
        self.arcint.setOption('reltol', self.int_opt['int_reltol'])
        self.arcint.setOption('tf', 1.)
        self.arcint.init()

        # Find y0 at start of pulse
        tstart = phase * base.y0[-1] / (2 * np.pi)
        tpulse = pulse_duration * base.y0[-1] / (2 * np.pi)
        y0 = base.lc(tstart)

        # Integrate trajectory through pulse
        # Find parameter set for pulse
        param_init = np.array(self.paramset)
        param_init[par_ind] *= (1 + amount)

        self.arcint.setInput(y0, cs.INTEGRATOR_X0)
        self.arcint.setInput(param_init.tolist() + [tpulse], cs.INTEGRATOR_P)
        self.arcint.evaluate()
        yf = np.array(self.arcint.output())

        # Simulate the perturbed trajectory for trans_duration.
        tf = base.y0[-1] * trans_duration
        ts = np.linspace(0, tf, num=int(100 * trans_duration), endpoint=True)
        self.arcsim = cs.Simulator(self.arcint, ts / tf)
        self.arcsim.init()
        self.arcsim.setInput(yf, cs.INTEGRATOR_X0)
        self.arcsim.setInput(list(base.paramset) + [tf], cs.INTEGRATOR_P)

        self.arcsim.evaluate()
        trajectory = self.arcsim.output().toArray()
        yend = trajectory[-1]
        tend = ts[-1] % base.y0[-1]

        def resy(t):
            return np.linalg.norm(yend - base.lc(t % base.y0[-1]))

        # Minimize resy(t)
        tvals = np.linspace(0, base.y0[-1], num=25)
        tguess = tvals[np.array([resy(t) for t in tvals]).argmin()]
        tmin = sc.optimize.fmin(resy, tguess, disp=0)[0] % base.y0[-1]
        assert resy(tmin) / base.NEQ < 1E-3, "transient not converged"

        tdiff = tmin - tend

        reference = base.lc((ts + tdiff) % base.y0[-1])

        from scipy.integrate import cumtrapz
        amp_change = cumtrapz((trajectory - reference).T, x=ts)[:, -1]

        return amp_change
Exemple #14
0
    def calcdSdp(self, res=50):
        """ Function to calculate the sensitivity state profile shapes
        to parameter perturbations, from wilkins. Might want to move
        this to a new class. """

        ts = np.linspace(0, self.y0[-1], res, endpoint=True)

        integrator = cs.CVodesIntegrator(self.model)

        integrator.setOption("abstol", self.intoptions['sensabstol'])
        integrator.setOption("reltol", self.intoptions['sensreltol'])
        integrator.setOption("max_num_steps",
                             self.intoptions['sensmaxnumsteps'])
        integrator.setOption("sensitivity_method",
                             self.intoptions['sensmethod']);
        integrator.setOption("t0", 0)
        integrator.setOption("tf", self.y0[-1])
        integrator.setOption("numeric_jacobian", True)
        integrator.setOption("number_of_fwd_dir", self.NP)
        integrator.setOption("fsens_err_con", 1)
        integrator.setOption("fsens_abstol",
                             self.intoptions['sensabstol'])
        integrator.setOption("fsens_reltol", self.intoptions['sensreltol'])
        integrator.init()
        integrator.setInput(self.y0[:-1],cs.INTEGRATOR_X0)
        integrator.setInput(self.paramset,cs.INTEGRATOR_P)

        p0_seed = np.eye(self.NP)
        for i in range(0,self.NP):
            integrator.setFwdSeed(p0_seed[i],cs.INTEGRATOR_P,i)
        
        for i in range(0,self.NP):
            integrator.setFwdSeed(self.S0[:,i],cs.INTEGRATOR_X0,i)

        sim = cs.Simulator(integrator, ts)
        sim.setOption("number_of_fwd_dir", self.NP)
        # sim.setOption("fsens_err_con", 1)
        # sim.setOption("fsens_abstol", self.intoptions['sensabstol'])
        # sim.setOption("fsens_reltol", self.intoptions['sensreltol'])
        sim.init()
        sim.setInput(self.y0[:-1],cs.INTEGRATOR_X0)
        sim.setInput(self.paramset,cs.INTEGRATOR_P)

        p0_seed = np.eye(self.NP)
        for i in range(0,self.NP):
            sim.setFwdSeed(p0_seed[i],cs.INTEGRATOR_P,i)
        
        for i in range(0,self.NP):
            sim.setFwdSeed(self.S0[:,i],cs.INTEGRATOR_X0,i)

        sim.evaluate(nfdir=self.NP)
        
        # Raw sensitivity matrix S, calculated with initial conditions
        # S_0 = Z[0]. This matrix is not periodic, and will grow
        # unbounded with time
        S = np.array([sim.fwdSens(cs.INTEGRATOR_X0, i).toArray() for i in
                      xrange(self.NP)])
        S = S.swapaxes(0,1).swapaxes(1,2) # S[t,y,p]
        y = sim.output().toArray()

        # Periodic Z matrix, defined as the state sensitivity with
        # constant period (Wilkins 2009, page 2710)
        Z = np.zeros(S.shape)
        for i in xrange(res):
            Z[i] = S[i] + (ts[i]/self.y0[-1])*np.outer(self.dydt(y[i]),
                                                       self.dTdp)

        self.Z = Z

        # Periodic W matrix, a projection of the Z matrix. Captures the
        # change in amplitude of the state trajectory without taking
        # into account changes in phase.
        W = np.zeros(S.shape)
        for i, (y_i, Z_i) in enumerate(zip(y,Z)):
            W[i] = (np.eye(self.NEQ) - 
                    np.outer(y_i, y_i)/np.linalg.norm(y_i)**2).dot(Z_i)

        self.W = W