def single_block_search(self):
        print()
        print(
            f'Search number {self.current_block + 1}/{self.number_of_blocks}. Solving for {self.tspan}.\n'
        )
        print()

        start = tm.time()  # CPU Clock begins

        # Stochastic integration using diffeqpy
        self.sol = de.solve(self.prob,
                            de.SOSRI(),
                            callback=self.transition_cb,
                            saveat=self.dt,
                            maxiters=self.max_iters)

        # Update results if we find a transition
        if self.sol.retcode == 'Terminated':
            print(
                f'Found transition in search number {self.current_block + 1}. Saving Results.\n'
            )

            # CPU Time Since Last Success
            end = tm.time()
            cpu_time = end - start

            # Time results updated
            self.experiment_time_results['cpu_times(s)'].append(cpu_time)
            self.experiment_time_results['residence_times'].append(
                self.current_residence_time)
            self.experiment_time_results['number_of_transitions'] += 1

            # Saving Path and Residence time
            print(self.current_residence_time)
            self.looker.look(self.sol)
            self.looker._parameters[
                'residence_time'] = self.current_residence_time
            print(self.looker.observations.attrs)
            self.save_results()

            # Check if we have found enough samples and can stop
            if self.experiment_time_results[
                    'number_of_transitions'] == self.transition_limit:
                print(
                    f'Found {self.transition_limit} transitions - will quit.')
                sys.exit()

            # Reset Experiment
            self.last_successful_block = self.current_block
            self.prob = de.remake(self.prob, u0=self.ic, tspan=self.tspan)

        # If we don't find a transition, remake the problem
        else:
            print(f'Exited due to {self.sol.retcode}\n')
            self.prob = de.remake(self.prob,
                                  u0=self.sol.u[-1],
                                  tspan=self.tspan)

        self.current_block += 1
        return
                   maxiters=max_iters)

    # If we find a transtions, save the result

    if sol.retcode == 'Terminated':  #i.e. callback ended the integration, so we save results
        end = tm.time()
        cpu_time = end - start
        integration_time = sol.t[-1]
        update_results()
        save_results()
        last_success_block = i

        # Check if we have found enough samples and can stop
        if experiment_results['number_of_transitions'] == 100:
            print(f'Found 100 transitions - will quit.')
            quit()

    elif sol.retcode == 'MaxIters':
        print(
            f'Integration ended due to {sol.retcode}. Will reset and try increasing max_iters.\n'
        )
        max_iters = max_iters * 2

    else:
        print(f'Exited due to {sol.retcode}\n')

    # Reset Experiment
    ic = get_random_point(cold_file)
    start = tm.time()
    prob = de.remake(prob, u0=ic, tspan=tspan)
예제 #3
0
            pd = save_directory + 'cold_ic/'
        else:
            pd = save_directory + 'hot_ic/'
        sd = pd + f'{run_number}/'
        if not os.path.exists(sd):
            os.makedirs(sd)

        # Setting up diffeqpy solver
        t = 0.
        tspan = (0., block_length)
        prob = de.SDEProblem(numba_f, numba_g, u0, tspan, p)
        looker = SolutionObserver(prob.p)

        for i in range(number_of_blocks):
            print(prob.tspan)

            # Integrate
            sol = de.solve(prob,
                           de.SRIW1(),
                           reltol=1e-3,
                           abstol=1e-3,
                           saveat=0.1)
            looker.look(sol)

            # Save Observations
            looker.dump(sd)

            # Update Step
            t += block_length
            prob = de.remake(prob, u0=sol.u[-1], tspan=(t, t + block_length))
def run_experiment(S=10, epsilon=5, delta=1, cold=True):
    """
    S, float - reduced solar constant.
    epsilon, float - noise strength.
    cold, boolean - whether we start on cold attractor or not.
    """

    ####################################
    ### Fixed Experiment Settings
    ####################################

    # Time Set Up
    end_time = 1000.  # Length of integration where we look for a transitions
    dt = 1.0  # How often output is saved, since we're not saving integrations it can be coarse
    number_of_searches = int(1.e4)  # How many integration runs we do
    tspan = (0., end_time)
    max_iters = 1.e20

    # Fixed L96 EBM Parameters
    K = 50
    a0 = 0.5
    a1 = 0.4
    sigma = 1 / 180**4
    F = 8.
    Tref = 270.
    delT = 60.
    alpha = 2.
    beta = 1.

    p = np.array(
        [K, S, a0, a1, sigma, F, Tref, delT, alpha, beta, epsilon, delta])

    # Initialising Dictionary to Store Experiment Results
    global experiment_results
    global cpu_time
    global integration_time
    experiment_results = {
        'epsilon': epsilon,
        'delta': delta,
        'S': S,
        'cpu_times(s)': [],
        'integration_times': [],
        'number_of_transitions': 0,
        'parameters': p
    }

    # Setting IC & Callbacks, File locations will need updating for cluster run
    if cold:
        ic = get_random_cold_point(S=S)
        cb_condition = get_entered_hot_condition(S, K)
        cb = de.DiscreteCallback(cb_condition, de.terminate_b)
    else:
        ic = get_random_hot_point(S=S)
        cb_condition = get_entered_cold_condition(S, K)
        cb = de.DiscreteCallback(cb_condition, de.terminate_b)

    # Setting up diffeqpy solver
    prob = de.SDEProblem(numba_f, numba_multiplicative_g, ic, tspan, p)

    ####################################
    ### Looped Search for Transitions
    ####################################

    experiment_header(epsilon, delta, S, cold)
    start = tm.time()  # CPU Clock begins
    last_successful_block = -1

    for i in range(number_of_searches):
        print()
        print(
            f'Search number {i + 1}/{number_of_searches}. Solving for {prob.tspan}.\n'
        )

        # Integrate only saving T variable
        sol = de.solve(prob,
                       de.SOSRI(),
                       saveat=dt,
                       callback=cb,
                       maxiters=max_iters)

        # If we find a transition, save the result & reset experiment
        if sol.retcode == 'Terminated':
            print(
                f'Found transition in search number {i + 1}. Saving Results.\n'
            )

            # CPU Time Since Last Success
            end = tm.time()
            cpu_time = end - start

            # Integration Time Since Last Success
            completed_blocks_since_last_success = i - (last_successful_block +
                                                       1)
            block_length = end_time
            integration_time_in_this_block = sol.t[-1]
            integration_time = completed_blocks_since_last_success * block_length + integration_time_in_this_block
            update_results()
            save_results(pd=experiment_results_pd,
                         S=S,
                         epsilon=epsilon,
                         cold=cold,
                         delta=delta)

            # Check if we have found enough samples and can stop
            if experiment_results['number_of_transitions'] == 100:
                print(f'Found 100 transitions - will quit.')
                quit()

            # Reset Experiment
            start = tm.time()
            last_successful_block = i
            if cold:
                ic = get_random_cold_point(S=S)
            else:
                ic = get_random_hot_point(S=S)
            prob = de.remake(prob, u0=ic, tspan=tspan)

        # If we don't find a transition, remake the problem
        else:
            print(f'Exited due to {sol.retcode}\n')
            prob = de.remake(prob, u0=sol.u[-1], tspan=(0, end_time))
    return
예제 #5
0
def run_l96_ebm_multiplicative(p,
                               u0,
                               block_length,
                               number_of_blocks,
                               sd=None,
                               dt=0.1):
    """
    Use diffeqpy solver to stochastically integrate the L96 EBM Equations w multiplicative noise.

    Arguments
    ------------
    p, list:
        Parameters for the model run.

    ic, np array:
        The intial condition for the model run.

    block_length, int:
        How often model output is saved.

    number_of_blocks, int:
        How many times we save model output.
        Note no. of obs = (blocklength * number of blocks)/dt

    sd, string:
        Where model output is saved.

    dt, float:
        Time between model observations.
        Note integrator uses adaptive timestepper that may be smaller.
    """

    # Setting up diffeqpy solver
    t = 0.
    tspan = (0., block_length)
    prob = de.SDEProblem(numba_f, numba_g, u0, tspan, p)

    # Creating Observer Object to do saving
    looker = SolutionObserver(prob.p)

    # Loop with intermitment saves
    for i in range(number_of_blocks):
        print(f'Solving for {prob.tspan}\n')

        # Integrate
        sol = de.solve(prob, de.SRIW1(), reltol=1e-3, abstol=1e-3, saveat=dt)
        looker.look(sol)

        # Save Observations
        if sd is not None:
            looker.dump(sd)

        # Update Step
        t += block_length
        prob = de.remake(prob, u0=sol.u[-1], tspan=(t, t + block_length))

    # Output results if no save directory
    if sd is None:
        return looker.observations
    else:
        return