def test_evolve_bsimp(): dimension = 2 step = odeiv.step_bsimp(dimension, func, jac, mu) control = odeiv.control_y_new(step, 1e-6, 1e-6) evolve = odeiv.evolve(step, control, dimension) step1 = odeiv.step_rkf45(dimension, func, jac, mu) control1 = odeiv.control_y_new(step1, 1e-6, 1e-6) evolve1 = odeiv.evolve(step1, control1, dimension) h = 1 t = 0.0 t1 = 100.0 y = numx.array((1.0, 0.0)) while t < t1: t, h, y = evolve.apply(t, t1, h, y) sys.stdout = file h = 1 t = 0.0 t1 = 100.0 y = (1.0, 0.0) while t < t1: t, h, y = evolve1.apply(t, t1, h, y)
def test_evolve_bsimp(): dimension = 2 step = odeiv.step_bsimp(dimension, func,jac, mu) control = odeiv.control_y_new(step, 1e-6, 1e-6) evolve = odeiv.evolve(step, control, dimension) step1 = odeiv.step_rkf45(dimension, func,jac,mu) control1 = odeiv.control_y_new(step1, 1e-6, 1e-6) evolve1 = odeiv.evolve(step1, control1, dimension) h = 1 t = 0.0 t1 = 100.0 y = numx.array((1.0, 0.0)) while t<t1: t, h, y = evolve.apply(t, t1, h, y) sys.stdout = file h = 1 t = 0.0 t1 = 100.0 y = (1.0, 0.0) while t<t1: t, h, y = evolve1.apply(t, t1, h, y)
def test_evolve(): dimension = 2 step = odeiv.step_bsimp(dimension, func, jac, mu) control = odeiv.control_y_new(step, 1e-6, 1e-6) evolve = odeiv.evolve(step, control, dimension) h = 1 t = 0.0 t1 = 1.0 y = numx.array([1.0, 0.0]) print step.name(), step.order() while t<t1: t, h, y = evolve.apply(t, t1, h, y) dimension = 2 steps = ( odeiv.step_rk2, odeiv.step_rk4, odeiv.step_rkf45, odeiv.step_rkck, odeiv.step_rk8pd, odeiv.step_rk2imp, odeiv.step_rk4imp, odeiv.step_gear1, odeiv.step_gear2) for s in steps: step = s(dimension, func, None, mu) print step.name(), step.order() control = odeiv.control_y_new(step, 1e-6, 1e-6) print control.name() evolve = odeiv.evolve(step, control, dimension) h = 1 t = 0.0 t1 = 1.0 y = (1.0, 0.0) while t<t1/2.0: t, h, y = evolve.apply(t, t1, h, y) y, yerr, dydt = step.apply(t, h, y, None) h, msg = control.hadjust(y, yerr, dydt, h) assert(msg == odeiv.HADJ_DEC or msg == odeiv.HADJ_INC or msg == odeiv.HADJ_NIL ) step.reset() evolve.reset() while t<t1: t, h, y = evolve.apply(t, t1, h, y) y = y
def lorenz(a = 10.0, b = 8.0 / 3.0, c = 28.0): def func(t, y, t2): f = np.zeros(3) f[0] = a * (y[1] - y[0]) f[1] = c * y[0] - y[1] - y[0] * y[2] f[2] = y[0] * y[1] - b * y[2] return f dimension = 3 step = odeiv.step_rk4(dimension, func) control = odeiv.control_y_new(step, 1e-6, 1e-6) evolve = odeiv.evolve(step, control, dimension) h = 1 t = 0.0 t1 = 100.0 y = (1.0, 1.0, 1.0) t, h, y = evolve.apply(t, t1, h, y) states = np.array([y[0], y[1], y[2]]) while t<t1: t, h, y = evolve.apply(t, t1, h, y) states = np.vstack((states, np.array([y[0], y[1], y[2]]))) return states
def run_sim(mu, nr_timepoints, func, npS): import pygsl._numobj import pygsl from pygsl import odeiv, Float import numpy dimension = 5 step = odeiv.step_rkf45(dimension, func, None, mu) control = odeiv.control_y_new(step, 1e-6, 1e-6) evolve = odeiv.evolve(step, control, dimension) h = 1 t1 = float(nr_timepoints) # initial values - all 0. y = pygsl._numobj.array((0.5, 0.5, 0.0, 0.01, 0.0)) op = numpy.zeros((nr_timepoints, dimension)) iters = 0 for t in numpy.linspace(0, t1, nr_timepoints): t, h, y = evolve.apply(t, t1, h, y) op[iters] = y y += numpy.concatenate((numpy.random.randn(2) * mu["noise_level"], [0.0, 0.0, 0.0])) iters += 1 op = numpy.array(op) # naka rushton on activities: npS(op[:, 0], mu) npS(op[:, 1], mu) # return both output and parameter dictionary return [mu, op]
def run(): mu = 10.0 dimension = 2 # The different possible steppers for the function # Comment your favourite one out to test it. #stepper = odeiv.step_rk2 #stepper = odeiv.step_rk4 stepper = odeiv.step_rkf45 #stepper = odeiv.step_rkck #stepper = odeiv.step_rk8pd #stepper = odeiv.step_rk2imp #stepper = odeiv.step_rk4imp #stepper = odeiv.step_gear1 #stepper = odeiv.step_gear2 #stepper = odeiv.step_bsimp step = stepper(dimension, func, jac, mu) # All above steppers exept the odeiv.step_bsimp (Buerlisch - Stoer Improved # method can calculate without an jacobian ... step = stepper(dimension, func, args=mu) control = odeiv.control_y_new(step, 1e-6, 1e-6) evolve = odeiv.evolve(step, control, dimension) print "# Using stepper %s with order %d" %(step.name(), step.order()) print "# Using Control ", control.name() print "# %9s %9s %9s %9s " % ("t", "h", "y[0]", "y[1]") hstart = 1 tstart = 0.0 t1 = (50.0) #t1 = (500000.0,) ystart = (1.0, 0.0) t = tstart y = ystart stamp = time.time() nsteps = 1000 #nsteps = 10000000 h = hstart for i in xrange(nsteps): if t >= t1: break t, h, y = evolve.apply(t, t1, h, y) #print " %5d % 10.6f % 10.6f % 10.6f " %(i, t, y[0], y[1]) else: raise ValueError, "Maximum number of steps exceeded!" print "Needed %f seconds" %( time.time() - stamp,) print " % 10.6f % 10.6f % 10.6f % 10.6f " %(t, h, y[0], y[1]) stamp = time.time() t, h, y = evolve.apply_vector(tstart, t1, hstart, ystart, nsteps=1000, hmax=.1) print "Needed %f seconds" %(time.time() - stamp,) print " % 10.6f % 10.6f % 10.6f % 10.6f " %(t, h, y[0, 0], y[0, 1])
def test_evolve(): dimension = 2 step = odeiv.step_bsimp(dimension, func, jac, mu) control = odeiv.control_y_new(step, 1e-6, 1e-6) evolve = odeiv.evolve(step, control, dimension) h = 1 t = 0.0 t1 = 1.0 y = numx.array([1.0, 0.0]) print step.name(), step.order() while t < t1: t, h, y = evolve.apply(t, t1, h, y) dimension = 2 steps = (odeiv.step_rk2, odeiv.step_rk4, odeiv.step_rkf45, odeiv.step_rkck, odeiv.step_rk8pd, odeiv.step_rk2imp, odeiv.step_rk4imp, odeiv.step_gear1, odeiv.step_gear2) for s in steps: step = s(dimension, func, None, mu) print step.name(), step.order() control = odeiv.control_y_new(step, 1e-6, 1e-6) print control.name() evolve = odeiv.evolve(step, control, dimension) h = 1 t = 0.0 t1 = 1.0 y = (1.0, 0.0) while t < t1 / 2.0: t, h, y = evolve.apply(t, t1, h, y) y, yerr, dydt = step.apply(t, h, y, None) h, msg = control.hadjust(y, yerr, dydt, h) assert (msg == odeiv.HADJ_DEC or msg == odeiv.HADJ_INC or msg == odeiv.HADJ_NIL) step.reset() evolve.reset() while t < t1: t, h, y = evolve.apply(t, t1, h, y) y = y
def test_memory_usage(): dimension = 2 for i in range(1000): step1 = odeiv.step_bsimp(dimension, func, jac, mu) control1 = odeiv.control_y_new(step1, 1e-6, 1e-6) evolve1 = odeiv.evolve(step1, control1, dimension) h = 1 t = 0.0 t1 = 100.0 y = (1.0, 0.0) y, yerr, dydt = step1.apply(t, h, y) while t < t1: control1.hadjust(y, yerr, dydt, h)
def test_memory_usage(): dimension = 2 for i in range(1000): step1 = odeiv.step_bsimp(dimension, func,jac, mu) control1 = odeiv.control_y_new(step1, 1e-6, 1e-6) evolve1 = odeiv.evolve(step1, control1, dimension) h = 1 t = 0.0 t1 = 100.0 y = (1.0, 0.0) y, yerr, dydt = step1.apply(t, h, y) while t<t1: control1.hadjust(y, yerr, dydt, h)
def run_sim(mu, nr_timepoints, func, npS): import pygsl._numobj import pygsl from pygsl import odeiv, Float import numpy def S( input, NRa, NRs ): if input >= 0. : return pow(input,NRa)/(pow(input,NRa) + pow(NRs,NRa)) else: return 0.00001 dimension = 5 step = odeiv.step_rkf45(dimension, func, None, mu) control = odeiv.control_y_new(step, 1e-6, 1e-6) evolve = odeiv.evolve(step, control, dimension) h = 1 t1 = float(nr_timepoints) # initial values - all 0. y = pygsl._numobj.array((0.5, 0.5, 0.0, 0.01, 1.0)) op = numpy.zeros((nr_timepoints, dimension)) iters = 0 for t in numpy.linspace(0, t1, nr_timepoints): t, h, y = evolve.apply(t, t1, h, y) op[iters] = y # add noise to instantaneous activity: # y += numpy.concatenate((numpy.random.randn(2) * mu['noise_level'], [0.0, 0.0, 0.0])) # add noise to novel interaction # y += numpy.concatenate(([0.0, 0.0, 0.0, 0.0], numpy.random.randn(1) * mu['noise_level'])) # add noise to activities and to novel interaction y += numpy.array([numpy.random.randn(1) * mu['noise_level'] / (mu['var_inh_noise_infl'] * S(y[4], mu['NRa_var_inh'], mu['NRs_var_inh'])), numpy.random.randn(1) * mu['noise_level'] / (mu['var_inh_noise_infl'] * S(y[4], mu['NRa_var_inh'], mu['NRs_var_inh'])), 0.0, 0.0, numpy.random.randn(1) * mu['var_inh_noise_level']]) # y[4] * numpy.random.randn(1) * mu['var_inh_noise_level']] # add noise only to novel interaction, but graded by the inverse of its value. # y += numpy.concatenate(([0.0, 0.0, 0.0, 0.0], numpy.random.randn(1) * mu['noise_level'])) # add noise to both populations and transient signal # y += numpy.array([numpy.random.randn(1) * mu['noise_level'], numpy.random.randn(1) * mu['noise_level'], 0.0, 0.0, numpy.random.randn(1) * mu['var_inh_noise_level']]) iters += 1 op = numpy.array(op) # naka rushton on activities: npS(op[:,0], mu) npS(op[:,1], mu) # return both output and parameter dictionary return [mu, op]
def int_de(y, N, Nend, kount, kmax, ypp, xpp, NEQS, derivs): h = 1e-6 i = None status = 0 count = 0 s = odeiv.step_rk4(NEQS, derivs) c = odeiv.control_y_new(s, 1e-8, 1e-8) e = odeiv.evolve(s, c, NEQS) ydoub = y.copy() if N > Nend: h = -h while N != Nend: try: N, h, ydoub = e.apply(N, Nend, h, ydoub) except: status = 1 break for i in range(NEQS): y[i] = ydoub[i] ypp[:, count] = y.copy() xpp[count] = N count += 1 if count == kmax: break ypp_temp = ypp[:, 0:count].copy() xpp_temp = xpp[0:count].copy() ypp.resize((NEQS, count), refcheck=False) xpp.resize(count, refcheck=False) ypp[:, :] = ypp_temp.copy() xpp[:] = xpp_temp.copy() kount = count return status, kount
def evaluate_integrator(self, h, integrator, accuracy, spike_rate, sim_time, raise_errors=True): """ This function computes the average step size and the minimal step size that a given integration method from GSL uses to evolve a certain system of ODEs during a certain simulation time, integration method from GSL and spike train for a given maximal stepsize. :param h: The maximal stepsize for one evolution step in miliseconds :param integrator: A method from the GSL library for evolving ODES, e.g. rk4 :param y: The 'state variables' in f(y)=y' :return: Average and minimal step size. """ s_min = h # the minimal step size cannot be larger than the maximal stepsize h simulation_slices = int(round(sim_time / h)) numpy.random.seed(42) spikes = self._generate_spikes(sim_time, h, spike_rate) y = self._compute_initial_state_vector() self._prepare_jacobian_matrix() gsl_stepper = integrator(len(y), self.step, self.jacobian) control = odeiv.control_y_new(gsl_stepper, accuracy, accuracy) evolve = odeiv.evolve(gsl_stepper, control, len(y)) t = 0.0 step_counter = 0 sum_last_steps = 0 s_min_old = 0 runtime = 0.0 s_min_lower_bound = 5e-09 for time_slice in range(simulation_slices): t_new = t + h counter_while_loop = 0 t_old = 0 while t < t_new: counter_while_loop += 1 t_old = t time_start = time.time() try: # h_ is NOT the reached step size but the suggested next step size! t, h_, y = evolve.apply(t, t_new, h, y) except Exception as e: print( " ===> Failure of %s at t=%.2f with h=%.2f (y=%s)" % (gsl_stepper.name(), t, h, y)) if raise_errors: raise runtime += time.time() - time_start step_counter += 1 s_min_old = s_min s_min = min(s_min, t - t_old) if s_min < s_min_lower_bound: estr = "Integration step below %.e (s=%.f). Please check your ODE." % ( s_min_lower_bound, s_min) if raise_errors: raise Exception(estr) else: print(estr) if counter_while_loop > 1: step_counter -= 1 sum_last_steps += t_new - t_old # it is possible that the last step in a simulation_slot is very small, as it is simply # the length of the remaining slot. Therefore we don't take the last step into account s_min = s_min_old threshold_crossed = False for threshold in self.thresholds: _globals = self.math_module_funcs.copy() local_parameters = self.parameters.copy() local_parameters.update( {"y__%i" % i: y for i, y in enumerate(y)}) if eval(threshold, _globals, local_parameters): threshold_crossed = True break # break inner loop if threshold_crossed: # break outer loop break for idx, initial_value in enumerate(self.initial_values): matcher = re.compile(r".*(\d)+$") oder_order_number = int( matcher.match(initial_value).groups(0)[0]) # TODO: Why is there no convolution here? Is it correct # and meaningful to just sum up the number of spikes? _globals = self.math_module_funcs.copy() y[oder_order_number] += eval( self.initial_values[initial_value], _globals, self.parameters) * spikes[idx][time_slice] step_average = (t - sum_last_steps) / step_counter return s_min_old, step_average, runtime
def evaluate_integrator(h, simulation_slices, integrator, step_function, jacobian, spikes, y, initial_values, thresholds): """ This function computes the average step size and the minimal step size that a given integration method from GSL uses to evolve a certain system of ODEs during a certain simulation time, integration method from GSL and spike train for a given maximal stepsize. :param h: The maximal stepsize for one evolution step in miliseconds :param integrator: A method from the GSL library for evolving ODES, e.g. rk4 :param step_function: The function f that defines the system of ODEs as f(y)= y' that is evolved by the GSL method :param jacobian: the jacobian matrix of the function `step_function` :param spikes: A representative spike train for the given simulation time `sim_time` :param y: The 'state variables' in f(y)=y' :return: Average and minimal step size. """ s_min = h # the minimal step size cannot be larger than the maximal stepsize h gls_stepper = integrator(len(y), step_function, jacobian) # must be jacobian control = odeiv.control_y_new(gls_stepper, 1e-3, 1e-3) evolve = odeiv.evolve(gls_stepper, control, len(y)) t = 0.0 step_counter = 0 sum_last_steps = 0 s_min_old = 0 for time_slice in range(simulation_slices): t_new = t + h # print "Start while loop at slot " + str(time_slice) counter_while_loop = 0 t_old = 0 while t < t_new: counter_while_loop += 1 t_old = t t, h_, y = evolve.apply(t, t_new, h, y) # h_ is NOT the reached step size but the suggested next step size! step_counter += 1 s_min_old = s_min s_min = min(s_min, t - t_old) # print str(time_slice) + ": t=%.15f, current stepsize=%.15f y=" % (t, t - t_old), y if s_min < 0.000000005: raise Exception("Check your ODE system. The integrator step becomes to small in order to support " "reasonable simulation", s_min) if counter_while_loop > 1: step_counter -= 1 sum_last_steps += t_new - t_old # it is possible that the last step in a simulation_slot is very small, as it is simply # the length of the remaining slot. Therefore we don't take the last step into account s_min = s_min_old # print "End while loop" threshold_crossed = False for threshold in thresholds: parameters_with_locals = parameters.copy() parameters_with_locals["y"] = y if eval(threshold, parameters_with_locals): threshold_crossed = True break # break inner loop if threshold_crossed: # break outer loop break for idx, initial_value in enumerate(initial_values): matcher = re.compile(r".*(\d)+$") oder_order_number = int(matcher.match(initial_value).groups(0)[0]) parameters_with_locals = globals().copy() for key in parameters: parameters_with_locals[key] = parameters[key] y[oder_order_number] += eval(initial_values[initial_value], parameters_with_locals) * spikes[idx][time_slice] step_average = (t - sum_last_steps) / step_counter return s_min_old, step_average
def spectrum(y_final, y, u_s, u_t, N, derivs1, scalarsys, tensorsys): i = None h = 0.01 h2 = 1.e-6 # init step size for mode integration abserr1 = 1.e-8 # absolute error tolerance - DO NOT ADJUST THESE VALUES! relerr1 = 1.e-8 # relative error tolerance abserr2 = 1e-10 # absolute error tolerance relerr2 = 1e-10 # relative error tolerance spec_params = params() # Read in k files k = None ks = np.empty(knos) kis = np.empty(kinos) try: ks = np.loadtxt(k_file) except IOError as e: print(f"Could not open file {k_file}, errno = {e}.") sys.exit() try: kis = np.loadtxt(ki_file) except IOError as e: print(f"Could not open file {ki_file}, errno = {e}.") sys.exit() realu_init = np.empty(2) imu_init = np.empty(2) realu_s = np.empty(kmax) realu_t = np.empty(kmax) imu_s = np.empty(kmax) imu_t = np.empty(kmax) P_s = np.empty(kinos) P_t = np.empty(kinos) j = None l = None m = None o = None status = None countback = 0 count = 0 ydoub = np.empty(NEQS) Ninit = None # N_obs from flow integration Nfinal = None # Smallest N value from flow integration spec_norm = None ru_init = None dru_init = None iu_init = None diu_init = None nu = None Yeff = None Phi = None # Buffers for interpolations Nefoldsback = np.empty(kmax) flowback = np.empty((5, kmax)) Nordered = np.empty(kmax) uordered_s = np.empty(kmax) uordered_t = np.empty(kmax) """ Initialize/allocate gsl stepper routines and variable step-size routines. Define ode system. """ s = odeiv.step_rk4(NEQS, derivs1) c = odeiv.control_y_new(s, abserr1, relerr1) e = odeiv.evolve(s, c, NEQS) """ Set the initial value of the scale factor. This is chosen so that k = aH (with k corresponding to the quadrupole) at the value N_obs from the path file. The scale factor as a function of N is a(N) = a_init*exp(-# of efolds). Units are hM_PL """ Ninit = N spec_params.a_init = (1.73e-61 / y[1]) * np.exp(Ninit) spec_params.k = k """ To improve stability/efficiency, we first generate an interpolating function for H, epsilon, sigma and xi^2. We then pass these values as parameters to the mode equation, rather than solving the mode equation along with the full set of flow equations each time. """ """ Integrate backwards from end of inflation to the earliest time needed in order to initialize the largest scale fluctuations in the BD limlt. """ ydoub[:] = y_final[:NEQS].copy() N = y_final[NEQS] Nfinal = N while (kis[0] * 5.41e-58) / (spec_params.a_init * np.exp(-N) * ydoub[1]) < Y: flowback[:, countback] = ydoub[:5].copy() Nefoldsback[countback] = N try: N, h2, ydoub = e.apply(N, 1000, h2, ydoub) except: status = 0 return status else: status = 0 countback += 1 Nefoldsback[countback] = N flowback[:, countback] = ydoub[:5].copy() H = np.empty(countback + 1) eps = np.empty(countback + 1) sig = np.empty(countback + 1) xi = np.empty(countback + 1) Nefolds = np.empty(kmax) # Nefolds = np.empty(countback+1) phi = np.empty(countback + 1) H[:] = flowback[1, :countback + 1].copy() eps[:] = flowback[2, :countback + 1].copy() sig[:] = flowback[3, :countback + 1].copy() xi[:] = flowback[4, :countback + 1].copy() phi[:] = flowback[0, :countback + 1].copy() Nefolds[:countback + 1] = Nefoldsback[:countback + 1].copy() # Generate interpolating functions for H, eps, sig, xi and phi (for path gen. only) spline1 = spline.cspline(countback + 1) spline1.init(Nefolds[:countback + 1], H) spline2 = spline.cspline(countback + 1) spline2.init(Nefolds[:countback + 1], eps) spline3 = spline.cspline(countback + 1) spline3.init(Nefolds[:countback + 1], sig) spline4 = spline.cspline(countback + 1) spline4.init(Nefolds[:countback + 1], xi) spline0 = spline.cspline(countback + 1) spline0.init(Nefolds[:countback + 1], phi) h2 = -h2 """ Find scalar spectra first. """ for m in range(kinos): print(m) k = kis[m] * 5.41e-58 # converts to Planck from hMpc^-1 kis[m] = k N = Ninit ydoub[1] = spline1.eval(N) ydoub[2] = spline2.eval(N) count = 0 """ First, check to see if the given k value is in the Bunch-Davies limit at the start of inflation. This limit is set by the #define Y=k/aH. If the given k value yields a larger Y than the BD limit, then we must integrate forward (to smaller N) until we reach the proper value for Y. If it is smaller, we must integrate backwards (to larger N). These integrators are given a fixed stepsize to ensure that we don't inadvertently step too far beyond Y. """ if k / 1.73e-61 > Y: # 1.73e-61 is the present Hubble radius (~3.2e-4 hMpc^-1) in Planck units while k / (spec_params.a_init * np.exp(-N) * ydoub[1] * (1 - ydoub[2])) > Y: N += -0.01 ydoub[1] = spline1.eval(N) ydoub[2] = spline2.eval(N) else: while k / (spec_params.a_init * np.exp(-N) * ydoub[1] * (1 - ydoub[2])) < Y: N += 0.01 ydoub[1] = spline1.eval(N) ydoub[2] = spline2.eval(N) spec_params.k = k nu = (3 - spline2.eval(N)) / (2 * (1 - spline2.eval(N))) # print(nu) Yeff = k / (spec_params.a_init * (np.exp(-N) * (spline1.eval(N) * (1. - spline2.eval(N))))) # print(Yeff) if spline2.eval(N) < 1.: ru_init = realu_init[0] = 0.5 * np.sqrt( np.pi / k) * np.sqrt(Yeff) * _ufuncs.sf_bessel_Jnu(nu, Yeff) dru_init = realu_init[1] = 0.5 * np.sqrt(np.pi / k) * ( k / (spec_params.a_init * np.exp(-N) * spline1.eval(N)) ) * (_ufuncs.sf_bessel_Jnu(nu, Yeff) / (2. * np.sqrt(Yeff)) + (np.sqrt(Yeff) * (-_ufuncs.sf_bessel_Jnu(nu + 1., Yeff) + (nu * (1. - spline2.eval(N)) * _ufuncs.sf_bessel_Jnu(nu, Yeff)) / (Yeff * (1. - spline2.eval(N)))))) iu_init = imu_init[0] = 0.5 * np.sqrt( np.pi / k) * np.sqrt(Yeff) * _ufuncs.sf_bessel_Ynu(nu, Yeff) diu_init = imu_init[1] = 0.5 * np.sqrt(np.pi / k) * ( k / (spec_params.a_init * np.exp(-N) * spline1.eval(N)) ) * (_ufuncs.sf_bessel_Ynu(nu, Yeff) / (2. * np.sqrt(Yeff)) + (np.sqrt(Yeff) * (-_ufuncs.sf_bessel_Ynu(nu + 1., Yeff) + (nu * (1. - spline2.eval(N)) * _ufuncs.sf_bessel_Ynu(nu, Yeff)) / (Yeff * (1. - spline2.eval(N)))))) else: ru_init = realu_init[0] = -0.5 * np.sqrt( np.pi / k) * np.sqrt(Yeff) * _ufuncs.sf_bessel_Ynu(nu, Yeff) dru_init = realu_init[1] = -0.5 * np.sqrt(np.pi / k) * ( k / (spec_params.a_init * np.exp(-N) * spline1.eval(N)) ) * (_ufuncs.sf_bessel_Ynu(nu, Yeff) / (2. * np.sqrt(Yeff)) + (np.sqrt(Yeff) * (-_ufuncs.sf_bessel_Ynu(nu + 1., Yeff) + (nu * (1. - spline2.eval(N)) * _ufuncs.sf_bessel_Ynu(nu, Yeff)) / (Yeff * (1. - spline2.eval(N)))))) iu_init = imu_init[0] = 0.5 * np.sqrt( np.pi / k) * np.sqrt(Yeff) * _ufuncs.sf_bessel_Jnu(nu, Yeff) diu_init = imu_init[1] = 0.5 * np.sqrt(np.pi / k) * ( k / (spec_params.a_init * np.exp(-N) * spline1.eval(N)) ) * (_ufuncs.sf_bessel_Jnu(nu, Yeff) / (2. * np.sqrt(Yeff)) + (np.sqrt(Yeff) * (-_ufuncs.sf_bessel_Jnu(nu + 1., Yeff) + (nu * (1. - spline2.eval(N)) * _ufuncs.sf_bessel_Jnu(nu, Yeff)) / (Yeff * (1. - spline2.eval(N)))))) """ Solve for real part of u first. """ s2 = odeiv.step_rkf45(2, scalarsys, args=spec_params) c2 = odeiv.control_y_new(s2, abserr2, relerr2) while N > Nfinal: realu_s[count] = realu_init[0] * realu_init[0] Nefolds[count] = N spec_params.H = spline1.eval(N) spec_params.eps = spline2.eval(N) spec_params.sig = spline3.eval(N) spec_params.xi = spline4.eval(N) Phi = spline0.eval(N) e2 = odeiv.evolve(s2, c2, 2) # mode eqs try: N, h2, realu_init = e2.apply(N, 0, h2, realu_init) except: status = 0 return status else: status = 0 count += 1 if count == kmax: status = 0 return status realu_s[count] = realu_init[0] * realu_init[0] Nefolds[count] = N for j in range(count + 1): Nordered[j] = Nefolds[count - j] uordered_s[j] = realu_s[count - j] """ Generate interpolating function for realu(N) """ spline5 = spline.cspline(count + 1) spline5.init(Nordered[:count + 1], uordered_s[:count + 1]) """ Imaginary part """ count = 0 N = Nefolds[0] s2 = odeiv.step_rkf45(2, scalarsys, args=spec_params) c2 = odeiv.control_y_new(s2, abserr2, relerr2) e2 = odeiv.evolve(s2, c2, 2) # mode eqs while N > Nfinal: imu_s[count] = imu_init[0] * imu_init[0] Nefolds[count] = N spec_params.H = spline1.eval(N) spec_params.eps = spline2.eval(N) spec_params.sig = spline3.eval(N) spec_params.xi = spline4.eval(N) try: N, h2, imu_init = e2.apply(N, 0, h2, imu_init) except: status = 0 return status else: status = 0 count += 1 if count == kmax: status = 0 return status imu_s[count] = imu_init[0] * imu_init[0] Nefolds[count] = N count -= 1 P_s[m] = (k**3. / (2. * (np.pi**2.))) * ( spline5.eval(Nefolds[count]) + imu_s[count]) / ( (spec_params.a_init * np.exp(-Nefolds[count]) * spec_params.a_init * np.exp(-Nefolds[count]) * spline2.eval(Nefolds[count])) / (4 * np.pi)) """ Tensor spectra """ count = 0 N = Nefolds[0] realu_init[0] = ru_init realu_init[1] = dru_init s2 = odeiv.step_rkf45(2, tensorsys, args=spec_params) c2 = odeiv.control_y_new(s2, abserr2, relerr2) while N > Nfinal: realu_t[count] = realu_init[0] * realu_init[0] Nefolds[count] = N spec_params.H = spline1.eval(N) spec_params.eps = spline2.eval(N) e2 = odeiv.evolve(s2, c2, 2) # mode eqs try: N, h2, realu_init = e2.apply(N, 0, h2, realu_init) except: status = 0 return status else: status = 0 count += 1 if count == kmax: status = 0 return status realu_t[count] = realu_init[0] * realu_init[0] Nefolds[count] = N for j in range(count + 1): Nordered[j] = Nefolds[count - j] uordered_t[j] = realu_t[count - j] spline7 = spline.cspline(count + 1) spline7.init(Nordered[:count + 1], uordered_t[:count + 1]) """ Imaginary part """ count = 0 N = Nefolds[0] imu_init[0] = iu_init imu_init[1] = diu_init s2 = odeiv.step_rkf45(2, tensorsys, args=spec_params) c2 = odeiv.control_y_new(s2, abserr2, relerr2) while N > Nfinal: imu_t[count] = imu_init[0] * imu_init[0] Nefolds[count] = N spec_params.H = spline1.eval(N) spec_params.eps = spline2.eval(N) e2 = odeiv.evolve(s2, c2, 2) # mode eqs try: N, h2, imu_init = e2.apply(N, 0, h2, imu_init) except: status = 0 return status else: status = 0 count += 1 if count == kmax: status = 0 return status imu_t[count] = imu_init[0] * imu_init[0] Nefolds[count] = N count -= 1 P_t[m] = 64. * np.pi * (k**3. / (2. * np.pi**2.)) * ( spline7.eval(Nefolds[count]) + imu_t[count]) / ( (spec_params.a_init * np.exp(-Nefolds[count]) * spec_params.a_init * np.exp(-Nefolds[count]))) if kis[m] == knorm * 5.41e-58: # normalize here spec_norm = Amp / (P_s[m] + P_t[m]) """ This is a little different from the C code, because the y[1] change is outside the if statement """ y[1] = np.sqrt(spec_norm) # normalize H for later recon """ Now that we have finished calculating the spectra, interpolate each spectrum and evaluate at k-values of interest """ spline8 = spline.cspline(kinos) spline8.init(kis, P_t) spline6 = spline.cspline(kinos) spline6.init(kis, P_s) for i in range(knos): u_s[0, i] = ks[i] u_s[1, i] = spec_norm * spline6.eval(ks[i] * 5.41e-58) u_t[0, i] = ks[i] u_t[1, i] = spec_norm * spline8.eval(ks[i] * 5.41e-58) return status
Msets.append(Mset) step = odeiv.step_rkf45(dimension, nf.dxdt_no_NLT_p, args=(dimension, system, Msets)) elif opts.function == "dqdt_no_NLT": step = odeiv.step_rkf45(dimension, nf.dqdt_no_NLT, args=(dimension, system)) elif opts.function == "dxdt_no_NLT": step = odeiv.step_rkf45(dimension, nf.dxdt_no_NLT, args=(dimension, system)) elif opts.function == "dxdt_no_NLT_withPHI": step = odeiv.step_rkf45(dimension+1, nf.dxdt_no_NLT_withPHI, args=(dimension, system)) else: sys.exit("unkown derivative function: "+ opts.function) control = odeiv.control_y_new(step, opts.abs_err, opts.rel_err) if use_phase: evolve = odeiv.evolve(step, control, dimension+1) else: evolve = odeiv.evolve(step, control, dimension) #################################################################################################### # # # run integration # # #################################################################################################### # integrate the system and report when necessary if opts.time_integration: ### time integrations: individual steps and total time import time
# # test_pygsl.py # import numpy as np from numpy.testing import assert_allclose from pygsl import odeiv import linearosc # Create the GSL ODE solver ndim = 2 step = odeiv.step_rk8pd(ndim, linearosc.vectorfield, linearosc.jacobian) control = odeiv.control_y_new(step, eps_abs=1e-12, eps_rel=1e-9) evolve = odeiv.evolve(step, control, ndim) stoptime = np.pi # Initial step size is stoptime/500 h = stoptime / 500.0 t = 0 y = [1.0, 0.0] # Call evolve.apply(...) until the solution reaches stoptime while t < stoptime: t, h, y = evolve.apply(t, stoptime, h, y) assert_allclose(y, [-1, 0], rtol=1e-8, atol=1e-9)
def integrate_ode(self, initial_values=None, h_min_lower_bound=5E-9, raise_errors=True, debug=False): r""" This function computes the average step size and the minimal step size that a given integration method from GSL uses to evolve a certain system of ODEs during a certain simulation time, integration method from GSL and spike train. :param initial_values: A dictionary mapping variable names (as strings) to initial value expressions. :param h_min_lower_bound: The minimum acceptable step size. :param raise_errors: Stop and raise exception when error occurs, or try to continue. :param debug: Return extra values useful for debugging. :return: Average and minimal step size, and elapsed wall clock time. """ if initial_values is None: initial_values = {} assert all([ type(k) == sympy.Symbol for k in initial_values.keys() ]), 'Initial value dictionary keys should be of type sympy.Symbol' # # grab stimulus spike times # all_spike_times, all_spike_times_sym = self.get_sorted_spike_times() # # initialise analytic integrator # if not self.analytic_solver_dict is None: analytic_integrator_spike_times = { sym: st for sym, st in self.get_spike_times().items() if str(sym) in self.analytic_solver_dict["state_variables"] } self.analytic_integrator = AnalyticIntegrator( self.analytic_solver_dict, analytic_integrator_spike_times) analytic_integrator_initial_values = { sym: iv for sym, iv in initial_values.items() if sym in self.analytic_integrator.get_all_variable_symbols() } self.analytic_integrator.set_initial_values( analytic_integrator_initial_values) # # convert initial value expressions to floats # for sym in self._system_of_shapes.x_: if not sym in initial_values.keys(): initial_values[sym] = float( self._system_of_shapes.get_initial_value( str(sym)).evalf(subs=self._parameters)) upper_bound_crossed = False y = np.array( [initial_values[sym] for sym in self._system_of_shapes.x_]) if debug: y_log = [y] t_log = [0.] h_log = [] gsl_stepper = self.numeric_integrator(len(y), self.step, self.numerical_jacobian) control = odeiv.control_y_new(gsl_stepper, self.integration_accuracy_abs, self.integration_accuracy_rel) evolve = odeiv.evolve(gsl_stepper, control, len(y)) # # make NumPy warnings errors. Without this, we can't catch overflow errors that can occur in the step() function, which might indicate a problem with the ODE, the grid resolution or the stiffness testing framework itself. # old_numpy_fp_overflow_error_level = np.geterr()['over'] np.seterr(over='raise') try: h_min = np.inf # # grab starting wall clock time # time_start = time.time() # # main loop # h_sum = 0. n_timesteps_taken = 0 t = 0. idx_next_spike = 0 while t < self.sim_time: if self.alias_spikes: # # simulate by one timestep # t_target = t + self.max_step_size else: # # simulate until the time of the next upcoming spike # if idx_next_spike >= len(all_spike_times): t_target = self.sim_time syms_next_spike = [] else: t_target = all_spike_times[idx_next_spike] if t_target >= self.sim_time: t_target = self.sim_time syms_next_spike = [] else: syms_next_spike = all_spike_times_sym[ idx_next_spike] idx_next_spike += 1 # "queue" the next upcoming spike for the next iteration of the while loop while t < t_target: t_target_requested = min(t + self.max_step_size, t_target) h_requested = t_target_requested - t try: if not self.analytic_integrator is None: self.analytic_integrator.disable_cache_update() t, h_suggested, y = evolve.apply( t, t_target_requested, h_requested, y ) # evolve.apply parameters: start time, end time, initial step size, start vector except FloatingPointError as e: msg = "Failure of numerical integrator (method: %s) at t=%.2f with requested timestep = %.2f (y = %s)" % ( gsl_stepper.name(), t, h_requested, y) raise FloatingPointError(msg) if not self.analytic_integrator is None: self.analytic_integrator.enable_cache_update() self.analytic_integrator.get_value(t) if debug: t_log.append(t) h_log.append(h_suggested) y_log.append(y) if h_suggested < h_requested: # ignore small requested step sizes; look only at actually obtained step sizes h_min = min(h_min, h_suggested) if h_min < h_min_lower_bound: estr = "Integration step below %.e (s=%.f). Please check your ODE." % ( h_min_lower_bound, h_min) if raise_errors: raise Exception(estr) else: print(estr) h_sum += h_suggested n_timesteps_taken += 1 # # enforce bounds/thresholds # for shape in self._shapes: if not shape.upper_bound is None: idx = [ str(sym) for sym in list(self._system_of_shapes.x_) ].index(str(shape.symbol)) upper_bound_numeric = float( shape.upper_bound.evalf(subs=self._locals)) if y[idx] > upper_bound_numeric: upper_bound_crossed = True y[idx] = initial_values[shape.symbol] # # evaluate to numeric values those ODEs that are solved analytically # self._locals.update({ str(sym): y[i] for i, sym in enumerate(self._system_of_shapes.x_) }) if not self.analytic_integrator is None: self._locals.update(self.analytic_integrator.get_value(t)) # # apply the spikes, i.e. add the "initial values" to the system dynamical state vector # if self.alias_spikes: # # apply all the spikes from <t - dt, t] # if idx_next_spike < len(all_spike_times): t_next_spike = all_spike_times[idx_next_spike] else: t_next_spike = np.inf while t_next_spike <= t: syms_next_spike = all_spike_times_sym[idx_next_spike] for sym in syms_next_spike: if sym in [ str(sym_) for sym_ in self._system_of_shapes.x_ ]: idx = [ str(sym_) for sym_ in list(self._system_of_shapes.x_) ].index(sym) y[idx] += float( self._system_of_shapes.get_initial_value( sym).evalf(subs=self._locals)) idx_next_spike += 1 if idx_next_spike < len(all_spike_times): t_next_spike = all_spike_times[idx_next_spike] else: t_next_spike = np.inf else: for sym in syms_next_spike: if sym in [ str(sym_) for sym_ in self._system_of_shapes.x_ ]: idx = [ str(sym_) for sym_ in list(self._system_of_shapes.x_) ].index(sym) y[idx] += float( self._system_of_shapes.get_initial_value( sym).evalf(subs=self._locals)) h_avg = h_sum / n_timesteps_taken runtime = time.time() - time_start finally: np.seterr(over=old_numpy_fp_overflow_error_level) if debug: t_log = np.array(t_log) h_log = np.array(h_log) y_log = np.array(y_log) if INTEGRATOR_DEBUG_PLOT: self.integrator_debug_plot(t_log, h_log, y_log, dir=INTEGRATOR_DEBUG_PLOT_DIR) logging.info("For integrator = " + str(self.numeric_integrator) + ": h_min = " + str(h_min) + ", h_avg = " + str(h_avg) + ", runtime = " + str(runtime)) sym_list = self._system_of_shapes.x_ if debug: return h_min, h_avg, runtime, upper_bound_crossed, t_log, h_log, y_log, sym_list else: return h_min, h_avg, runtime
def run(): mu = 10.0 dimension = 2 # The different possible steppers for the function # Comment your favourite one out to test it. #stepper = odeiv.step_rk2 #stepper = odeiv.step_rk4 stepper = odeiv.step_rkf45 #stepper = odeiv.step_rkck #stepper = odeiv.step_rk8pd #stepper = odeiv.step_rk2imp #stepper = odeiv.step_rk4imp #stepper = odeiv.step_gear1 #stepper = odeiv.step_gear2 #stepper = odeiv.step_bsimp step = stepper(dimension, func, jac, mu) # All above steppers exept the odeiv.step_bsimp (Buerlisch - Stoer Improved # method can calculate without an jacobian ... step = stepper(dimension, func, args=mu) control = odeiv.control_y_new(step, 1e-6, 1e-6) evolve = odeiv.evolve(step, control, dimension) print "# Using stepper %s with order %d" % (step.name(), step.order()) print "# Using Control ", control.name() print "# %9s %9s %9s %9s " % ("t", "h", "y[0]", "y[1]") hstart = 1 tstart = 0.0 t1 = (50.0) #t1 = (500000.0,) ystart = (1.0, 0.0) t = tstart y = ystart stamp = time.time() nsteps = 1000 #nsteps = 10000000 h = hstart for i in xrange(nsteps): if t >= t1: break t, h, y = evolve.apply(t, t1, h, y) #print " %5d % 10.6f % 10.6f % 10.6f " %(i, t, y[0], y[1]) else: raise ValueError, "Maximum number of steps exceeded!" print "Needed %f seconds" % (time.time() - stamp, ) print " % 10.6f % 10.6f % 10.6f % 10.6f " % (t, h, y[0], y[1]) stamp = time.time() t, h, y = evolve.apply_vector(tstart, t1, hstart, ystart, nsteps=1000, hmax=.1) print "Needed %f seconds" % (time.time() - stamp, ) print " % 10.6f % 10.6f % 10.6f % 10.6f " % (t, h, y[0, 0], y[0, 1])