Example #1
0
                   del_H_cat, del_S_cat)

    #### Shipping
    return h**o, cat, nu_homo_index, nu_cat_index


if __name__ == '__main__':

    import constants
    react_system = 'OCM_two_reaction.txt'
    catalyst = 'La_Ce'

    homo_basis = 'mole_fraction'
    cat_basis = 'mole_fraction'

    const, thermo_object = constants.fixed_parameters(react_system)
    h**o, cat, \
    homo_index, cat_index = instantiate(react_system, const, catalyst)

    print(h**o.n_r)
    species = const['species']
    no_of_species = len(species)
    ID = np.arange(no_of_species)
    species_ID = dict(zip(species, ID))
    print(species_ID)

    inlet_species = 'CH4'
    inlet_ratio = 4

    F_A_in = inlet_ratio / (inlet_ratio + 1)
    F_B_in = 1 / (inlet_ratio + 1)
Example #2
0
def bif_dia_solver(fixed_dict, bif_par_dict, react_system, system, catalyst,
                   rate_basis, rate_units, inlet_species, break_val,
                   step_change, max_val, options):
    '''
    This function solves for the bifurcation diagram.
    
    fixed_dict= Dictionary of fixed variables and values.
    bif_par_dict= Dictionary of Bifurcation variable and value.
    react_system= Describes the reaction system chosen, e.g: 'OCM_three_reaction.txt'.

    system= Whether the system is catalytic only, homogeneous only, or homogeneous-heterogeneous coupled.
    inlet_species= The hydrocarbon species, as of now just hydrocarbon and O2 is taken as inlet.
    break_val= break value of the bifurcation parameter.
    
    step_change= step_change value of the bifurcation parameter, necessary in Pseudo-Arc Length Continuation.
    max_val= maximum value of the bifurcation parameter.
    options= Solver Options.
    '''

    #### Constant parameters involved with the system
    const, thermo_object = constants.fixed_parameters(react_system)
    species = const['species']
    no_of_species = len(species)
    ID = np.arange(no_of_species)
    species_ID = dict(zip(species, ID))
    print(species_ID)

    #### Manipulation of input variables
    all_dict = dict(fixed_dict, **bif_par_dict)

    bif_par_var = list(bif_par_dict.keys())[0]
    bif_par_val = bif_par_dict.get(bif_par_var)

    #### Initial guess
    inlet_ratio = all_dict['inlet_ratio']
    N2 = 0  # For the time being, we use pure O2
    F_A_in = inlet_ratio / (N2 + inlet_ratio + 1)
    F_B_in = 1 / (N2 + inlet_ratio + 1)

    F_in = 1e-08 * np.ones(no_of_species)

    A_index = species_ID[inlet_species]
    B_index = species_ID['O2']

    F_in[A_index] = F_A_in
    F_in[B_index] = F_B_in
    state_var_val = np.r_[F_in, F_in, all_dict['T_f_in'], all_dict['T_f_in'],
                          bif_par_val]

    #### Generating the reaction data
    h**o, cat, homo_index, cat_index = react.instantiate(
        react_system, const, catalyst)
    react_const = [h**o, cat, homo_index, cat_index]

    #### Function name
    func = bif_dia_func
    jac = bif_dia_jacobian

    if options['Testing']:
        #### Just testing the function(s)
        Ysol = func(state_var_val, bif_par_val, inlet_species, fixed_dict,
                    const, thermo_object, react_const, system, rate_basis,
                    rate_units, 0)
        return Ysol

    else:
        if options['continuation'] == 'arc_length':
            raise Exception(
                'This is not the correct solver to solve the problem')
        else:
            #### Solving for the bifurcation diagram
            iter_count = 0
            _run = True
            rand_count = 0

            while (_run):

                _run = False

                #### First Intial Guess
                while (True):

                    if (iter_count != 0):
                        rand_count += 1
                        print(rand_count)
                        if (rand_count == 1):
                            print(
                                'Working on generating the next initial guess')
                        ### Guessing the initial point through random number generation
                        T_s = np.random.randint(T_bd[-3, -1], 3000)
                        T_f = np.random.randint(T_bd[-2, -1], T_s)

                        state_var_val = np.r_[1e-01 *
                                              np.ones(2 * no_of_species), T_s,
                                              T_s]
                        bif_par_val = break_val

#                        while(True):
#                            #### Generating the new initial guess after the break point
#                            print('The last solution point is:\n{}'.format(T_bd[:,-1]))
#
#                            state_var_str = (input('Enter an initial guess close to this first point '
#                                                        '[comma-separeted]: ')).split(',')
#                            state_var_list = []
#                            for elem in state_var_str:
#                                try:
#                                    elem_float = float(elem)
#                                except ValueError:
#                                    print('Enter a valid float-type data input')
#                                else:
#                                    state_var_list.append(elem_float)
#
#                            if len(state_var_list) == (2*no_of_species + 2):
#                                state_var_val = np.array(state_var_list)
#                                #### Checking the validity of the input
#                                if (any(state_var_val < 0)) or (state_var_val[-1] < T_bd[-2, -1]):
#                                    print('Enter a valid input')
#                                else:
#                                    bif_par_val -= step_change
#                                    break

###  Solving with first initial guess
                    sol0 = root(func,
                                state_var_val,
                                args=(bif_par_val, inlet_species, fixed_dict,
                                      const, thermo_object, react_const,
                                      system, rate_basis, rate_units))
                    act_sol = sol0.x

                    #### Checking the validity of the solution
                    if (iter_count != 0):

                        delta = func(act_sol, bif_par_val, inlet_species,
                                     fixed_dict, const, thermo_object,
                                     react_const, system, rate_basis,
                                     rate_units)

                        if any(act_sol < 0) or any(act_sol.imag != 0) or any(
                                abs(delta) > 1e-03):
                            print(
                                'Didn\'t get a perfect solution, trying again!!!'
                            )

                        elif (abs(act_sol[-1] - bif_par_val) <= 1):
                            print('Oops!!! Got the first point, trying again.')


#                        elif (abs(act_sol[-1] - T_bd[-2,-1]) <= 5):
#                            print('Got the previous point, trying again.')

                        else:
                            print('The last solution point is:\n{}'.format(
                                T_bd[:, -1]))
                            sol_check = input(
                                'Do you think this is the solution: \n{}'.
                                format(act_sol))

                    else:
                        sol_check = 'y'

                    if (sol_check == 'y'):
                        iter_count += 1
                        sol_check = 'n'
                        Y0 = np.r_[act_sol, bif_par_val]
                        try:
                            T_bd = np.c_[T_bd, Y0[:]]
                        except NameError:
                            T_bd = Y0[:]
                        finally:
                            break
                print('We got the first point, moving on now!')

                #### Second initial guess
                bif_par_val += step_change

                ###  Solving with second initial guess
                sol0 = root(func,
                            state_var_val,
                            args=(bif_par_val, inlet_species, fixed_dict,
                                  const, thermo_object, react_const, system,
                                  rate_basis, rate_units))
                act_sol = sol0.x

                print('We got the second point too')
                iter_count += 1
                Y1 = np.r_[act_sol, bif_par_val]
                T_bd = np.c_[T_bd, Y1[:]]
                #                print(T_bd)

                #### Calculation of the suitable delta_s value
                if bif_par_var == 'tau':
                    plot_flag = 'log'
                    delta_s = np.log10(Y1[-1] / Y0[-1])
                else:
                    plot_flag = 'norm'
                    delta_s = np.linalg.norm(Y1 - Y0)

                #### Continuation method
                while (Y1[-1] <= max_val):
                    print(Y1[-1])
                    iter_count += 1
                    Y_guess = 2 * Y1 - Y0
                    delta_s = np.linalg.norm(Y1 - Y0)
                    sol2 = root(func,
                                Y_guess,
                                args=(Y1, inlet_species, fixed_dict, const,
                                      thermo_object, react_const, system,
                                      rate_basis, rate_units, delta_s))
                    Y2 = sol2.x
                    T_bd = np.c_[T_bd, Y2]
                    Y0[:] = Y1[:]
                    Y1[:] = Y2[:]

                    if (Y1[-1] < break_val):
                        print('Extinction point is lower than the '
                              'break point ({}).'.format(break_val))

                        while (True):
                            A = input(
                                'Do you want to start the calculation '
                                'with a different initial guess [y/n]?: ')

                            if (A.lower() == 'y') or (A.lower() == 'n'):
                                break
                            else:
                                print('Enter \'y\' for a yes and \'n\' for a '
                                      'no, no other input will be considered')

                        if (A.lower() == 'y'):
                            _run = True
                        break

        #### Plotting the figure
        fig = plt.figure()
        if plot_flag == 'log':
            plt.semilogx(T_bd[-1, :], T_bd[-2, :])
        else:
            plt.plot(T_bd[-1, :], T_bd[-2, :])
        plt.show

        #### Storing data
        data_vals = [value for (key, value) in sorted(fixed_dict.items())]
        n = len(data_vals)
        filename = 'bif_dia'

        for i in range(n):
            filename += '_{}'.format(data_vals[i])

        print(filename)

        if options['save']:
            #### Saving Data
            react_filename, ext = os.path.splitext(react_system)

            Target_folder = os.path.join(os.getcwd(), react_filename,
                                         catalyst.lower(), 'Data', system)

            if os.path.isdir(Target_folder) == False:
                New_Folder = react_filename + '/' + catalyst.lower() + '/' \
                           + '/Data/' + system
                os.makedirs(New_Folder)

            FullfileName = os.path.join(Target_folder, filename)
            np.savez(FullfileName, T_bd, Y_in, species_ID)

            #### Saving Diagrams (Why I don't know)
            Target_folder = os.path.join(os.getcwd(), react_filename,
                                         catalyst.lower(), 'Diagram', system)

            if os.path.isdir(Target_folder) == False:
                New_Folder = react_filename + '/' + catalyst.lower() + '/' \
                           + '/Diagram/' + system
                os.makedirs(New_Folder)

            dia_filename = filename + '.png'
            FullfileName = os.path.join(Target_folder, dia_filename)
            fig.savefig(FullfileName)

        #### Returning the final result
        return T_bd
Example #3
0
def bif_set_solver(fixed_dict, bif_par_dict, react_system, system, catalyst,
                   rate_basis, rate_units, inlet_species, break_dict,
                   step_change, max_val, options):
    '''
    This function solves for the bifurcation set (or ignition-extinction locus)
    The significance of different arguments are same as that of the bif_dia_solver.
    '''
    # Constant parameters involved with the system
    const = constants.fixed_parameters(react_system)
    species = const['species']
    no_of_species = len(species)

    # Manipulation of input variables
    all_dict = dict(fixed_dict, **bif_par_dict)

    bif_par_var = list(bif_par_dict.keys())[0]
    bif_par_val = bif_par_dict.get(bif_par_var)

    # Generating the reaction data
    h**o, cat, homo_index, cat_index = react.instantiate(
        react_system, const, catalyst)
    react_const = [h**o, cat, homo_index, cat_index]

    # First Dataset
    npzfile = _load_file(react_system, system, catalyst, all_dict)
    T_bd_arr, Y_in_arr, species_ID_arr = npzfile.files
    T_bd_0 = npzfile[T_bd_arr]

    index_0 = ig_ext_point_calculator(T_bd_0,
                                      system,
                                      'T_f_in',
                                      break_dict,
                                      fulloutput=True)

    # Second Dataset
    all_dict[bif_par_var] += step_change

    npzfile = _load_file(react_system, system, catalyst, all_dict)
    T_bd_arr, Y_in_arr, species_ID_arr = npzfile.files
    T_bd_1 = npzfile[T_bd_arr]

    index_1 = ig_ext_point_calculator(T_bd_1,
                                      system,
                                      'T_f_in',
                                      break_dict,
                                      fulloutput=True)

    # Function names
    func = bif_set_func
    #    jac = bif_set_jacobian

    # Solving for ignition-extinction locus

    # First Ignition
    y0 = np.zeros(2 * (no_of_species + 1))
    y0[1] = 1
    x0 = T_bd_0[:, index_0[0]]
    x_init = np.r_[y0, x0]

    J_0 = func(x_init,
               bif_par_val,
               inlet_species,
               fixed_dict,
               const,
               react_const,
               system,
               rate_basis,
               rate_units,
               get_jacobian=True)
    y_sol_0 = root(null_space, y0, args=J_0, method='lm')
    X_init_0 = np.r_[y_sol_0.x, x0]

    sol0 = root(func,
                X_init_0,
                args=(bif_par_val, inlet_species, fixed_dict, const,
                      react_const, system, rate_basis, rate_units))

    Y0 = np.r_[sol0.x, bif_par_val]
    T_bs = Y0[:]

    # Second solution
    bif_par_val += step_change

    x1 = T_bd_1[:, index_1[0]]
    x_init = np.r_[y0, x1]

    J_1 = func(x_init,
               bif_par_val,
               inlet_species,
               fixed_dict,
               const,
               react_const,
               system,
               rate_basis,
               rate_units,
               get_jacobian=True)
    y_sol_1 = root(null_space, y0, args=J_1, method='lm')
    X_init_1 = np.r_[y_sol_1.x, x1]

    sol1 = root(func,
                X_init_1,
                args=(bif_par_val, inlet_species, fixed_dict, const,
                      react_const, system, rate_basis, rate_units))

    Y1 = np.r_[sol1.x, bif_par_val]
    T_bs = np.c_[T_bs, Y1[:]]

    plot_flag = 'norm'
    delta_s = np.linalg.norm(Y1 - Y0)

    # Continuation method
    while (Y1[-1] <= max_val and Y1[-1] >= break_dict[bif_par_var]
           and Y1[-2] >= break_dict['T_f_in']):
        print(Y1[-1])
        Y_guess = 2 * Y1 - Y0

        sol2 = root(func,
                    Y_guess,
                    args=(Y1, inlet_species, fixed_dict, const, react_const,
                          system, rate_basis, rate_units, delta_s))
        Y2 = sol2.x

        T_bs = np.c_[T_bs, Y2]
        Y0[:] = Y1[:]
        Y1[:] = Y2[:]

    #### Plotting the figure
    fig = plt.figure()
    if plot_flag == 'log':
        plt.semilogx(T_bs[-1, :], T_bs[-2, :])
    else:
        plt.plot(T_bs[-1, :], T_bs[-2, :])
    plt.show

    #### Storing data
    data_vals = [value for (key, value) in sorted(fixed_dict.items())]
    n = len(data_vals)
    filename = 'bif_set'

    for i in range(n):
        filename += '_{}'.format(data_vals[i])

    print(filename)

    if options['save']:
        #### Saving Data
        react_filename, ext = os.path.splitext(react_system)

        Target_folder = os.path.join(os.getcwd(), react_filename,
                                     catalyst.lower(), 'Data', system)

        if os.path.isdir(Target_folder) == False:
            New_Folder = react_filename + '/' + catalyst.lower(
            ) + '/' + '/Data/' + system
            os.makedirs(New_Folder)

        FullfileName = os.path.join(Target_folder, filename)
        np.savez(FullfileName, T_bs, Y_in, species_ID)

        #### Saving Diagrams (Why I don't know)
        Target_folder = os.path.join(os.getcwd(), react_filename,
                                     catalyst.lower(), 'Diagram', system)

        if os.path.isdir(Target_folder) == False:
            New_Folder = react_filename + '/' + catalyst.lower(
            ) + '/' + '/Diagram/' + system
            os.makedirs(New_Folder)

        dia_filename = filename + '.png'
        FullfileName = os.path.join(Target_folder, dia_filename)
        fig.savefig(FullfileName)

    #### Returning the final result
    return T_bs
Example #4
0
def low_D_Sh_phi_solver(fixed_dict, T_f_in_span, tspan,
                        react_system, system, catalyst,
                        rate_basis, rate_units, inlet_species, n, nT, options):

    '''
    This function solves the low_D_Sh_phi function to generate the 
    conversion vs Temperature curve.

    fixed_dict : Dictionary of fixed variables and values.
    T_f_in_span : Span of inlet temperature
    react_system : Name of the reaction system
    system : Whether the system is 'cat'-alytic, 'coup'-led, or 
             'h**o'-geneous
    catalyst : Name of the catalyst used
    rate_basis : Basis of the rate expressions, whether pressure,
                 concentration, mole fraction
    rate_units : Units of the rate expressions
    inlet_species : Name of the fuel, e.g. 'CH4'
    n : No of discretized points in x
    options : Some options, like whether to save the result, or just 
              to test the model.
    '''

    #### Constant parameters involved with the system
    const, thermo_object = constants.fixed_parameters(react_system)
    species = const['species']
    no_of_species = len(species)
    ID = np.arange(no_of_species)
    species_ID = dict(zip(species, ID))
    print(species_ID)
    
    #### Generating the reaction objects
    h**o, cat, homo_index, cat_index = react.instantiate(react_system,
                                       const, catalyst)
    react_const = [h**o, cat, homo_index, cat_index]
    
    inlet_ratio = fixed_dict['inlet_ratio']
    y_A_in = inlet_ratio/(inlet_ratio + 1)
    y_B_in = 1/(inlet_ratio + 1)
    
    #### Function names
    func = low_D_Sh_phi
    
    T_f_in = np.linspace(T_f_in_span[0], T_f_in_span[1], nT)
    conv_A = np.zeros_like(T_f_in)
    conv_B = np.zeros_like(T_f_in)

    if options['model'] is 'both':
        conv_A_inf = np.zeros_like(T_f_in)
        conv_B_inf = np.zeros_like(T_f_in)

    for i in range(len(T_f_in)):
        
        #### Inlet values
        c_A_in = y_A_in * 101325 * fixed_dict['pressure']/(8.314 * T_f_in[i])
        c_B_in = y_B_in * 101325 * fixed_dict['pressure']/(8.314 * T_f_in[i])
    
        C_f_in = 1e-03 * np.ones(no_of_species)
        A_index = species_ID[inlet_species]
        B_index = species_ID['O2']
        C_f_in[A_index] = c_A_in
        C_f_in[B_index] = c_B_in
        
        C_f_0 = np.tile(C_f_in, n)
        C_w_0 = np.tile(C_f_in, n) 
        C_0 = np.r_[C_f_0, C_w_0]
        
        if options['model'] is not 'both':
            #### Calculating for only one model
            try:
                count = i + 1
                print('Solving for T_f_in = {0} with {1} model'
                      .format(T_f_in[i], options['model']))
                Y = odeint(func, C_0, tspan, args=(inlet_species, fixed_dict, 
                                                   C_f_in, T_f_in[i], 
                                                   const, thermo_object, 
                                                   react_const, system, 
                                                   rate_basis, rate_units,
                                                   options['model']))
            except RuntimeWarning as e:
                msg = ('The concentration of one of the reactants is going '
                       'close to zero, hence further calculations can result '
                       'in inaccurate results.')
                temp = msg + 'Calculated till {}'.format(T_f_in[i-1])
                print(temp)
                count = i
                break

        elif options['model'] is 'both':
            #### Comparing two models
            print('Solving for T_f_in = {0} with {1} model'
                  .format(T_f_in[i], 'Sh_phi'))
            Y = odeint(func, C_0, tspan, args=(inlet_species, fixed_dict, 
                                               C_f_in, T_f_in[i], 
                                               const, thermo_object, 
                                               react_const, system, 
                                               rate_basis, rate_units,
                                               'Sh_phi'))

            print('Solving for T_f_in = {0} with {1} model'
                  .format(T_f_in[i], 'Sh_inf'))
            Y_inf = odeint(func, C_0, tspan, args=(inlet_species, fixed_dict, 
                                               C_f_in, T_f_in[i], 
                                               const, thermo_object, 
                                               react_const, system, 
                                               rate_basis, rate_units,
                                               'Sh_inf'))
    
            #### Calculating the conversion for Sh_inf model
            C_f_ss_inf = Y_inf[-1, :no_of_species*n]

            C_f_ss_mat_inf = C_f_ss_inf.reshape((no_of_species, n), order='F')
            CH4_exit_inf = C_f_ss_mat_inf[A_index, -1]
            O2_exit_inf = C_f_ss_mat_inf[B_index, -1]
    
            conv_A_inf[i] = (1 - CH4_exit_inf/c_A_in)
            conv_B_inf[i] = (1 - O2_exit_inf/c_B_in)

        else:
            raise Exception ('No such model exists!!!')

        #### Conversion calculations
        C_f_ss = Y[-1, :no_of_species*n]

        C_f_ss_mat = C_f_ss.reshape((no_of_species, n), order='F')
        CH4_exit = C_f_ss_mat[A_index, -1]
        O2_exit = C_f_ss_mat[B_index, -1]
    
        conv_A[i] = (1 - CH4_exit/c_A_in)
        conv_B[i] = (1 - O2_exit/c_B_in)
        
    #### Some random plotting
    if options['model'] is not 'both': 
        fig, ax = plt.subplots()

        ax.plot(T_f_in[:count], conv_A[:count], color='b', label='CH4 conv')
        ax.plot(T_f_in[:count], conv_B[:count], color='r', label='O2 conv')
        ax.legend(loc='best')
        ax.set_xlim([0, 1])
        ax.set_ylim(T_f_in_span)
        ax.set_xlabel('Inlet Temperature, in K')
        ax.set_ylabel('Conversions')
    
    else:
        fig, ax = plt.subplots()

        ax.plot(T_f_in, conv_A, color='b', label=r'$\mathbf{Sh_\phi}$ model')
        ax.plot(T_f_in, conv_A_inf, color='r', label=r'$\mathbf{Sh_\infty}$ model')
        ax.legend(loc='best')
        ax.set_ylim([0, 1])
        ax.set_xlim(T_f_in_span)
        ax.set_xlabel('Inlet Temperature, in K')
        ax.set_ylabel(r'Conversion of $\mathbf{CH_4}$')
        
        fig, ax1 = plt.subplots()
        ax1.plot(T_f_in, conv_B, color='b', label= r'$\mathbf{Sh_\phi}$ model')
        ax1.plot(T_f_in, conv_B_inf, color='r', label= r'$\mathbf{Sh_\infty}$ model')
        ax1.legend(loc='best')
        ax1.set_ylim([0, 1])
        ax1.set_xlim(T_f_in_span)
        ax1.set_xlabel('Inlet Temperature, in K')
        ax1.set_ylabel(r'Conversion of $\mathbf{O_2}$')
    plt.show()
    return Y
def low_D_Sh_phi_solver(fixed_dict, T_f_in_span, tspan, react_system, system,
                        catalyst, rate_basis, rate_units, inlet_species, nT,
                        options):
    '''
    We will write this thing later
    '''

    #### Constant parameters involved with the system
    const, thermo_object = constants.fixed_parameters(react_system)
    species = const['species']
    no_of_species = len(species)
    ID = np.arange(no_of_species)
    species_ID = dict(zip(species, ID))
    print(species_ID)

    #### Generating the reaction objects
    h**o, cat, homo_index, cat_index = react.instantiate(
        react_system, const, catalyst)
    react_const = [h**o, cat, homo_index, cat_index]

    inlet_ratio = fixed_dict['inlet_ratio']
    y_A_in = inlet_ratio / (inlet_ratio + 1)
    y_B_in = 1 / (inlet_ratio + 1)

    #### Function names
    func = zero_D_sh_phi

    T_f_in = np.linspace(T_f_in_span[0], T_f_in_span[1], nT)
    conv_A = np.zeros_like(T_f_in)
    conv_B = np.zeros_like(T_f_in)

    if options['model'] is 'both':
        conv_A_inf = np.zeros_like(T_f_in)
        conv_B_inf = np.zeros_like(T_f_in)

    for i in range(len(T_f_in)):

        #### Inlet values
        c_A_in = y_A_in * 101325 * fixed_dict['pressure'] / (8.314 * T_f_in[i])
        c_B_in = y_B_in * 101325 * fixed_dict['pressure'] / (8.314 * T_f_in[i])

        C_f_in = 1e-03 * np.ones(no_of_species)
        A_index = species_ID[inlet_species]
        B_index = species_ID['O2']
        C_f_in[A_index] = c_A_in
        C_f_in[B_index] = c_B_in

        C_0 = np.r_[C_f_in, C_f_in]

        if options['model'] is not 'both':
            #### Calculating for only one model
            try:
                count = i + 1
                print('Solving for T_f_in = {0} with {1} model'.format(
                    T_f_in[i], options['model']))
                Y = odeint(func,
                           C_0,
                           tspan,
                           args=(inlet_species, fixed_dict, C_f_in, T_f_in[i],
                                 const, thermo_object, react_const, system,
                                 rate_basis, rate_units, options['model']))
            except RuntimeWarning as e:
                msg = ('The concentration of one of the reactants is going '
                       'close to zero, hence further calculations can result '
                       'in inaccurate results.')
                temp = msg + 'Calculated till {}'.format(T_f_in[i - 1])
                print(temp)
                count = i
                break

        elif options['model'] is 'both':
            #### Comparing two models
            print('Solving for T_f_in = {0} with {1} model'.format(
                T_f_in[i], 'Sh_phi'))
            Y = odeint(func,
                       C_0,
                       tspan,
                       args=(inlet_species, fixed_dict, C_f_in, T_f_in[i],
                             const, thermo_object, react_const, system,
                             rate_basis, rate_units, 'Sh_phi'))

            print('Solving for T_f_in = {0} with {1} model'.format(
                T_f_in[i], 'Sh_inf'))
            Y_inf = odeint(func,
                           C_0,
                           tspan,
                           args=(inlet_species, fixed_dict, C_f_in, T_f_in[i],
                                 const, thermo_object, react_const, system,
                                 rate_basis, rate_units, 'Sh_inf'))

            #### Calculating the conversion for Sh_inf model
            C_f_ss_inf = Y_inf[-1, :no_of_species]

            CH4_exit_inf = C_f_ss_inf[A_index, ]
            O2_exit_inf = C_f_ss_inf[B_index]

            conv_A_inf[i] = (1 - CH4_exit_inf / c_A_in)
            conv_B_inf[i] = (1 - O2_exit_inf / c_B_in)

        else:
            raise Exception('No such model exists!!!')

        #### Conversion calculations
        C_f_ss = Y[-1, :no_of_species]

        CH4_exit = C_f_ss[A_index]
        O2_exit = C_f_ss[B_index]

        conv_A[i] = (1 - CH4_exit / c_A_in)
        conv_B[i] = (1 - O2_exit / c_B_in)

    #### Some random plotting
    if options['model'] is not 'both':
        fig, ax = plt.subplots()

        ax.plot(T_f_in[:count], conv_A[:count], color='b', label='CH4 conv')
        ax.plot(T_f_in[:count], conv_B[:count], color='r', label='O2 conv')
        ax.legend(loc='best')
        ax.set_xlabel('Inlet Temperature, in K')
        ax.set_ylabel('Conversions')

    else:
        fig, ax = plt.subplots()

        ax.plot(T_f_in, conv_A, color='b', label='Sh(Phi)')
        ax.plot(T_f_in, conv_A_inf, color='r', label='Sh_inf')
        ax.legend(loc='best')
        ax.set_xlabel('Inlet Temperature, in K')
        ax.set_ylabel('Conversion of CH4')

        fig, ax1 = plt.subplots()
        ax1.plot(T_f_in, conv_B, color='b', label='Sh(Phi)')
        ax1.plot(T_f_in, conv_B_inf, color='r', label='Sh_inf')
        ax1.legend(loc='best')
        ax1.set_xlabel('Inlet Temperature, in K')
        ax1.set_ylabel('Conversion of O2')
    plt.show()
    return Y
def bif_dia_plot(fixed_dict, bif_par_var, react_system, system, catalyst,
                 inlet_species, b_options, a_options):
    '''
    This function will load the correct file in order to plot the 
    different bifurcation diagrams.'''

    #### Specifying linestyles and colors
    lines = [':', '-', '--', ':', '-.']
    no_of_lines = len(lines)

    units = {
        'inlet_ratio': '',
        'pressure': ' atm',
        'tau': 's',
        'R_omega': 'mm',
        'R_omega_wc': r'$\mathbf{\mu m}$',
        'particle_density': 'kg/m3'
    }

    symbol = {
        'inlet_ratio': r'$\mathbf{CH_4/O_2}$',
        'pressure': r'$\mathbf{P}$',
        'tau': r'$\mathbf{\tau}$',
        'R_omega': r'$\mathbf{R_\Omega}$',
        'R_omega_wc': r'$\mathbf{R_{\Omega, wc}}$',
        'particle_density': r'$\mathbf{\rho}$'
    }

    #### Identifying the variable with multiple inputs
    count = 0
    multiple = False
    multiple_variable = 'inlet_ratio'
    for key, val in fixed_dict.items():
        try:
            len(val)
        except TypeError:
            continue
        else:
            multiple = True
            multiple_variable = key
            break

    if multiple:
        values = fixed_dict[multiple_variable]
    else:
        values = []
        values.append(fixed_dict[multiple_variable])

    for val in values:
        count += 1
        fixed_dict[multiple_variable] = val
        if multiple_variable == 'R_omega':
            fixed_dict[
                'R_omega_wc'] = fixed_dict['R_omega'] / 0.25e-03 * 100e-06
        style_index = count % no_of_lines

        #### Retreiving the data from .npz file
        npzfile = _load_file(react_system, system, catalyst, fixed_dict)
        T_bd_arr, F_in_arr, species_ID_arr = npzfile.files
        T_bd = npzfile[T_bd_arr]
        F_in = npzfile[F_in_arr]
        species_ID = npzfile[species_ID_arr].item()
        n, m = T_bd.shape

        if multiple_variable == 'R_omega':
            label = (symbol[multiple_variable] + ' = ' + str(val * 1e03) +
                     units[multiple_variable])
        else:
            label = (symbol[multiple_variable] + ' = ' + str(val) +
                     units[multiple_variable])

        if b_options['basic_plot']:

            #### Retrieving the species_specific data from T_bd
            hc_index = species_ID[inlet_species]
            conv_hc = 1 - T_bd[hc_index, :] / F_in[hc_index]

            O2_index = species_ID['O2']
            conv_O2 = 1 - T_bd[O2_index, :] / F_in[O2_index]

            #### Plotting Area
            plot_dict = b_options['plots']

            if bif_par_var == 'tau':
                xplottype = 'log'
                x_axis = 'Residence Time (s)'
            else:
                xplottype = 'normal'
                x_axis = ('Inlet Fluid Temperature, ' +
                          r'$\mathbf{T_{f,in}}$' + ' (K)')

            #### Exit Fluid Temperature vs Inlet Fluid Temperature
            if plot_dict['fluid_temp']:

                if count == 1:
                    fig, ax1 = plt.subplots()
                    fig.subplots_adjust(left=0.145, bottom=0.11)
                    ax1.set_xlabel(x_axis)
                    ax1.set_ylabel(('Exit Fluid Temperature, ' +
                                    r'$\mathbf{T_f}$' + ' (K)'))
                    axis_limits = (b_options['xaxis_lim'] +
                                   b_options['yaxis_lim'])
                    ax1.axis(axis_limits)

                if xplottype == 'log':
                    ax1.semilogx(T_bd[-1, :],
                                 T_bd[-2, :],
                                 linestyle=lines[style_index],
                                 label=label)
                else:
                    ax1.plot(T_bd[-1, :],
                             T_bd[-2, :],
                             linestyle=lines[style_index],
                             label=label)
                ax1.legend(loc='lower right')
                plt.show()

            #### Solid Temperature vs Inlet Fluid Temperature
            if plot_dict['solid_temp']:

                if count == 1:
                    fig, ax2 = plt.subplots()
                    ax2.set_xlabel(x_axis, fontsize=14, fontweight='bold')
                    ax2.set_ylabel(('Catalyst Surface Temperature ' +
                                    r'$\mathbf{T_s}$' + ' (K)'))

                    axis_limits = (b_options['xaxis_lim'] +
                                   b_options['yaxis_lim'])
                    ax2.axis(axis_limits)

                if xplottype == 'log':
                    ax2.semilogx(T_bd[-1, :],
                                 T_bd[-3, :],
                                 linestyle=lines[style_index],
                                 label=label)
                else:
                    ax2.plot(T_bd[-1, :],
                             T_bd[-3, :],
                             linestyle=lines[style_index],
                             label=label)
                ax2.legend(loc='best')

            #### Conversion of Hydrocarbon and O2
            if plot_dict['conversion']:

                if count == 1:
                    fig31, ax31 = plt.subplots()
                    fig32, ax32 = plt.subplots()

                    axis_limits_CH4 = b_options['xaxis_lim'] + [0, 0.5]
                    ax31.set_xlabel(x_axis)
                    ax31.set_ylabel(('Conversion of ' + r'$\mathbf{CH_4}$'))
                    ax31.axis(axis_limits_CH4)

                    axis_limits = b_options['xaxis_lim'] + [0, 1]
                    ax32.set_xlabel(x_axis)
                    ax32.set_ylabel(('Conversion of ' + r'$\mathbf{O_2}$'))
                    ax32.axis(axis_limits)

                if xplottype == 'log':
                    ax31.semilogx(T_bd[-1, :],
                                  conv_hc,
                                  linestyle=lines[style_index],
                                  label=label)
                    ax32.semilogx(T_bd[-1, :],
                                  conv_O2,
                                  linestyle=lines[style_index],
                                  label=label)
                else:
                    ax31.plot(T_bd[-1, :],
                              conv_hc,
                              linestyle=lines[style_index],
                              label=label)
                    ax32.plot(T_bd[-1, :],
                              conv_O2,
                              linestyle=lines[style_index],
                              label=label)
                ax31.legend(loc='best')
                ax32.legend(loc='best')

            #### Combined Selectivities and Yields
            if (plot_dict['select_comb'] or plot_dict['yield_comb']):

                elem_comb = ['CO', 'CO2', 'C2H6', 'C2H4', 'C2H2']
                selectivity = [np.zeros(m)] * 5
                select_dict = dict(zip(elem_comb, selectivity))
                yield_dict = dict(zip(elem_comb, selectivity))

                for elem in elem_comb:
                    elem_index = species_ID.get(elem, None)
                    carbon_no = species_identifier(elem)
                    if (elem_index != None) and (carbon_no != 0):
                        yield_elem = (T_bd[elem_index, :] - F_in[elem_index]) \
                                   * carbon_no/F_in[hc_index]

                        selectivity_elem = (T_bd[elem_index, :]
                                         - F_in[elem_index]) \
                                         * carbon_no \
                                         / (F_in[hc_index] - T_bd[hc_index, :])

                        select_dict[elem] = selectivity_elem
                        yield_dict[elem] = yield_elem

                selectivity_COx = select_dict['CO'] + select_dict['CO2']
                selectivity_C2 = select_dict['C2H6'] + select_dict['C2H4'] \
                               + select_dict['C2H2']

                #selectivity_C2 = np.where(np.isnan(selectivity_C2), 0.0, selectivity_C2)
                #selectivity_C2 = np.where(np.isinf(selectivity_C2), 0.0, selectivity_C2)
                #selectivity_C2 = np.where(selectivity_C2 < 0.0, 0.0, selectivity_C2)
                #selectivity_C2 = np.where(selectivity_C2 > 1.0, 0.0, selectivity_C2)
                if fixed_dict['inlet_ratio'] == 4:
                    selectivity_C2[:
                                   1500] = 0.0  # Didn't find any better method,
                    selectivity_COx[:1500] = 1.0
                else:
                    selectivity_C2[:
                                   1000] = 0.0  # Didn't find any better method,
                    selectivity_COx[:1000] = 1.0
                if plot_dict['select_comb']:
                    if (count == 1):
                        fig61, ax6_sc1 = plt.subplots()
                        fig62, ax6_sc2 = plt.subplots()
                        axis_limits = b_options['xaxis_lim'] + [0, 1]

                        ax6_sc1.set_xlabel(x_axis)
                        ax6_sc1.set_ylabel(('Selectivity of (' +
                                            r'$\mathbf{CO + CO_{2}}$' + ')'))
                        ax6_sc1.axis(axis_limits)

                        ax6_sc2.set_xlabel(x_axis)
                        ax6_sc2.set_ylabel(
                            ('Selectivity of (' +
                             r'$\mathbf{C_{2}H_{6} + C_{2}H_{4}}$' + ')'))
                        ax6_sc2.axis(axis_limits)

                    if xplottype == 'log':
                        ax6_sc1.semilogx(T_bd[-1, :],
                                         selectivity_COx,
                                         linestyle=lines[style_index],
                                         label=label)
                        ax6_sc2.semilogx(T_bd[-1, :],
                                         selectivity_C2,
                                         linestyle=lines[style_index],
                                         label=label)
                    else:
                        ax6_sc1.plot(T_bd[-1, :],
                                     selectivity_COx,
                                     linestyle=lines[style_index],
                                     label=label)
                        ax6_sc2.plot(T_bd[-1, :],
                                     selectivity_C2,
                                     linestyle=lines[style_index],
                                     label=label)

                    ax6_sc1.legend(loc='best')
                    ax6_sc2.legend(loc='best')

                if plot_dict['yield_comb']:
                    yield_COx = yield_dict['CO'] + yield_dict['CO2']
                    yield_C2 = yield_dict['C2H6'] + yield_dict['C2H4']\
                             + yield_dict['C2H2']

                    if (count == 1):
                        fig71, ax7_yc1 = plt.subplots()
                        fig71.subplots_adjust(left=0.145, bottom=0.11)

                        fig72, ax7_yc2 = plt.subplots()
                        fig72.subplots_adjust(left=0.145, bottom=0.11)
                        axis_limits = b_options['xaxis_lim'] + [0, 0.3]

                        ax7_yc1.set_xlabel(x_axis)
                        ax7_yc1.set_ylabel(
                            ('Yields of (' + r'$\mathbf{CO + CO_{2}}$' + ')'))
                        ax7_yc1.axis(axis_limits)

                        ax7_yc2.set_xlabel(x_axis)
                        ax7_yc2.set_ylabel(
                            ('Yield of (' +
                             r'$\mathbf{C_{2}H_{6} + C_{2}H_{4}}$' + ')'))
                        ax7_yc2.axis(axis_limits)

                    if xplottype == 'log':
                        ax7_yc1.semilogx(T_bd[-1, :],
                                         yield_COx,
                                         linestyle=lines[style_index],
                                         label=label)
                        ax7_yc2.semilogx(T_bd[-1, :],
                                         yield_C2,
                                         linestyle=lines[style_index],
                                         label=label)
                    else:
                        ax7_yc1.plot(T_bd[-1, :],
                                     yield_COx,
                                     linestyle=lines[style_index],
                                     label=label)
                        ax7_yc2.plot(T_bd[-1, :],
                                     yield_C2,
                                     linestyle=lines[style_index],
                                     label=label)

                    ax7_yc1.legend(loc='best')
                    ax7_yc2.legend(loc='best')

            #### Yields of all 'products', (Identifying the compound and then
            #### identifying limiting reactant is
            #### important, we will do it later)
            if plot_dict['yield_all']:

                products = b_options['products']
                if products:
                    fig4, ax4_y = plt.subplots()
                    label = []
                    not_calc_elem = []

                    for elem in products:
                        elem_index = species_ID.get(elem, None)
                        carbon_no = species_identifier(elem)

                        if (elem_index != None) and (carbon_no != 0):
                            yield_elem = T_bd[elem_index, :] \
                                       * carbon_no/F_in[hc_index]

                            if xplottype == 'log':
                                ax4_y.semilogx(T_bd[-1, :], yield_elem)
                            else:
                                ax4_y.plot(T_bd[-1, :], yield_elem)
                            label.append(elem)
                        else:
                            not_calc_elem.append(elem)

                ax4_y.set_xlabel(x_axis)
                ax4_y.set_ylabel(('Yield of Products'))
                ax4_y.legend(tuple(label), loc='best')

                axis_limits = b_options['xaxis_lim'] + [0, 0.5]
                ax4_y.axis(axis_limits)
                title = ('Inlet ratio = ' + str(fixed_dict['inlet_ratio']) +
                         ', tau = ' + str(fixed_dict['tau']) + 's, Radius = ' +
                         str(fixed_dict['R_omega'] * 1e03) + 'mm.')
                ax4_y.set_title(title)

                if not_calc_elem:
                    print('The yields of {} are not calculated, '
                          'the program thinks they are '
                          'unimportant'.format(not_calc_elem))

            #### Selectivity of all products
            if plot_dict['select_all']:

                products = b_options['products']
                if products:
                    fig5, ax5_s = plt.subplots()
                    label = []
                    not_calc_elem = []

                    for elem in products:
                        elem_index = species_ID.get(elem, None)
                        carbon_no = species_identifier(elem)
                        if (elem_index != None) and (carbon_no != 0):
                            yield_elem = (T_bd[elem_index, :] - F_in[elem_index]) \
                                       * carbon_no/F_in[hc_index]
                            selectivity_elem = (T_bd[elem_index, :]
                                             - F_in[elem_index]) \
                                             * carbon_no \
                                             / (F_in[hc_index] - T_bd[hc_index, :])

                            if xplottype == 'log':
                                ax5_s.semilogx(T_bd[-1, :],
                                               selectivity_elem,
                                               linewidth=2.0)
                            else:
                                ax5_s.plot(T_bd[-1, :],
                                           selectivity_elem,
                                           linewidth=2.0)
                            label.append(elem)
                        else:
                            not_calc_elem.append(elem)

                ax5_s.set_xlabel(x_axis)
                ax5_s.set_ylabel(('Selectivity of Products'))
                ax5_s.legend(tuple(label), loc='best')
                axis_limits = b_options['xaxis_lim'] + [0, 1]
                ax5_s.axis(axis_limits)
                title = ('Inlet ratio = ' + str(fixed_dict['inlet_ratio']) +
                         ', tau = ' + str(fixed_dict['tau']) + 's, Radius = ' +
                         str(fixed_dict['R_omega'] * 1e03) + 'mm.')
                ax5_s.set_title(title)
                if not_calc_elem:
                    print('The yields of {} are not calculated, '
                          'the program thinks they are '
                          'unimportant'.format(not_calc_elem))

        if a_options['analysis_plot']:

            #### Retrieving the species_specific data from T_bd
            const, thermo_object = constants.fixed_parameters(react_system)
            h**o, cat, homo_index, cat_index = react.instantiate(
                react_system, const, catalyst)

            #### The local species ID is useful in Thiele Modulus calculations
            local_species = const['species']
            no_of_local_species = len(local_species)
            local_ID = np.arange(no_of_local_species)
            local_species_ID = dict(zip(local_species, local_ID))
            hc_local_index = local_species_ID[inlet_species]
            O2_local_index = local_species_ID['O2']

            #### This is the species_ID of the actual calculation coming from
            #### the calling function
            no_of_species = len(species_ID)
            species = list(species_ID.keys())
            hc_index = species_ID[inlet_species]
            O2_index = species_ID['O2']

            #### User-requested plots
            plot_dict = a_options['plots']

            if bif_par_var == 'tau':
                xplottype = 'log'
                x_axis = 'Residence Time (s)'
            else:
                xplottype = 'normal'
                x_axis = ('Inlet Fluid Temperature ' + r'$\mathbf{T_{f,in}}$' +
                          ' (K)')

            #### Calculation of reaction rates

            #### Unpacking the matrix T_bd
            F_j = T_bd[:no_of_species, :]
            C_s = T_bd[no_of_species:2 * no_of_species, :]
            T_s = T_bd[2 * no_of_species, :]
            T_f = T_bd[2 * no_of_species + 1, :]
            bif_par = T_bd[-1, :]
            no_of_iter = T_bd.shape[1]

            T_f_in = T_bd[-1, :]

            #### Unpacking the constants
            P = fixed_dict['pressure']
            R_omega = fixed_dict['R_omega']
            R_omega_wc = fixed_dict['R_omega_wc']
            R_omega_w = const['R_omega_w']
            nu = const['nu']

            nu_cat = nu.T[cat_index]
            nu_cat_inlet_species = nu_cat[:, hc_local_index]
            nu_cat_O2 = nu_cat[:, O2_local_index]

            eps_f = 4 * R_omega**2 / (2 * R_omega + R_omega_wc + R_omega_w)**2

            #### Defining mole fractions and concentrations
            C_total = 101325 * P / (8.314 * T_f)
            Y_j = F_j / np.sum(F_j, axis=0)
            C_f = Y_j * C_total
            C_in = 101325 * P / (8.314 * T_f_in)

            #### Calculation of reaction rates [Fig. 1]
            if plot_dict['reaction_rates'] or plot_dict['thiele_modulus']:
                homo_basis, cat_basis = a_options['rate_basis']
                homo_units, cat_units = a_options['rate_units']
                all_homo_rate = np.zeros([len(homo_index), no_of_iter],
                                         dtype=float)
                all_cat_rate = np.zeros([len(cat_index), no_of_iter],
                                        dtype=float)

                for i in range(no_of_iter):
                    if (system == 'cat'):
                        homo_rate = np.zeros(len(homo_index))
                        cat_rate = cat.act_rate(C_s[:, i], species, cat_basis,
                                                T_s[i], P)
                    elif (system == 'h**o'):
                        cat_rate = np.zeros(len(cat_index))
                        homo_rate = h**o.act_rate(C_f[:, i], species,
                                                  homo_basis, T_f[i], P)
                    else:
                        homo_rate = h**o.act_rate(C_f[:, i], species,
                                                  homo_basis, T_f[i], P)
                        cat_rate = cat.act_rate(C_s[:, i], species, cat_basis,
                                                T_s[i], P)

                    all_homo_rate[:, i] = homo_rate[:]
                    all_cat_rate[:, i] = cat_rate[:]

                #### This is not required for the time being
                # We got to check the units and perform subsequent calculations
                if homo_basis == 'mole_fraction':
                    if homo_units != 'second':
                        raise Exception('There is a discrepancy '
                                        'in the homogeneous reaction rate')
                if (cat_units == 'kg_sec'):
                    all_cat_rate *= fixed_dict['particle_density']
                elif (cat_units == 'gm_sec'):
                    all_cat_rate *= fixed_dict['particle_density'] * 1000

                # Here we make two separate variables for catalytic reactions
                #homo_rate_C0 = all_homo_rate/C_in
                cat_rate_C0 = all_cat_rate.copy()
                cat_rate_C0_surf = all_cat_rate.copy()
                all_cat_rate *= R_omega_wc * eps_f / R_omega

                #return all_cat_rate - cat_rate_C0
                #### Plotting the reaction rates
                if plot_dict['reaction_rates'] and not multiple:

                    #### Catalytic reaction rates
                    fig, ax1 = plt.subplots()
                    label_cat = ()
                    for i in range(len(cat_index)):
                        if xplottype == 'log':
                            ax1.loglog(bif_par,
                                       R_omega_wc * all_cat_rate[i, :])
                        else:
                            ax1.plot(bif_par, R_omega_wc * all_cat_rate[i, :])
                        label = 'Reaction No.= ' + str(cat_index[i] + 1)
                        label_cat += (label, )

                    ax1.set_xlabel(x_axis)
                    ax1.set_ylabel(('Catalytic reaction rates (' +
                                    r'$\mathbf{mol/m^2 s}$' + ')'))
                    ax1.axes.set_xlim(10, 1200)  # Hardcoded
                    ax1.legend(label_cat, loc='best')

                    #### Homogeneous reaction rates
                    fig, ax11 = plt.subplots()
                    label_homo = ()
                    for i in range(len(homo_index)):
                        if xplottype == 'log':
                            ax11.loglog(bif_par, all_homo_rate[i, :])
                        else:
                            ax11.plot(bif_par, all_homo_rate[i, :])
                        label = 'Reaction No.= ' + str(homo_index[i] + 1)
                        label_homo += (label, )

                    ax11.set_xlabel(x_axis)
                    ax11.set_ylabel(('Homogeneous reaction rates (' +
                                     r'$\mathbf{mol/m^3 s}$' + ')'))
                    ax11.axes.set_xlim(10, 1200)  # Hardcoded
                    ax11.legend(label_homo, loc='best')

                #### Plotting Thiele Modulus
                if plot_dict['thiele_modulus']:

                    #### Normal Thiele Modulus based on vol. cat. reac. rate
                    inlet_species_cat_rate = np.dot(-nu_cat_inlet_species,
                                                    cat_rate_C0)
                    D_f = 9.8e-10 * T_f**1.75
                    D_e = 0.01 * D_f
                    thiele_mod_inlet_species = (inlet_species_cat_rate /
                                                C_s[hc_index, :] *
                                                R_omega_wc**2 / D_e)

                    #### Surface Thiele Modulus based on surf. cat. reac. rate
                    cat_rate_C0_surf *= R_omega_wc
                    inlet_species_surf_cat_rate = np.dot(
                        -nu_cat_O2, cat_rate_C0_surf)
                    surf_thiele_modulus = (inlet_species_surf_cat_rate /
                                           C_s[O2_index, :] * R_omega / D_f)

                    #print(fixed_dict['tau'])
                    #damkohler_second_type = 1/ (inlet_species_surf_cat_rate
                    #                      / C_s[hc_index, :])
                    if multiple_variable == 'R_omega':
                        label1 = (symbol['R_omega_wc'] + ' = ' +
                                  str(int(100 * val / 0.25e-03)) +
                                  units['R_omega_wc'])
                        label2 = (symbol['R_omega'] + ' = ' + str(val * 1e03) +
                                  units['R_omega'])
                    else:
                        label1 = (symbol[multiple_variable] + ' = ' +
                                  str(val) + units[multiple_variable])
                        label2 = label1

                    if count == 1:
                        fig, ax111 = plt.subplots()
                        ax111.set_xlabel(x_axis)
                        ax111.set_ylabel(('Thiele Modulus (' +
                                          r'$\mathbf{\phi_{wc}^2}$' + ')'))
                        ax111.axes.set_xlim(10, 1200)  # Hardcoded

                        fig, ax112 = plt.subplots()
                        ax112.set_xlabel(x_axis)
                        ax112.set_ylabel(('External Damkohler No. (' +
                                          r'$\mathbf{Da_{ext}}$' + ')'))
                        ax112.axes.set_xlim(10, 1200)  # Hardcoded
                        ax112.axes.set_ylim(1e-06, 1e06)
                    ax111.plot(bif_par,
                               thiele_mod_inlet_species,
                               linestyle=lines[style_index],
                               label=label1)
                    ax112.semilogy(bif_par,
                                   surf_thiele_modulus,
                                   linestyle=lines[style_index],
                                   label=label2)

                    ax111.legend(loc='best')
                    ax112.legend(loc='best')
                    #ax113.legend(loc='best')
    return T_bd
def _analysis(fixed_dict, bif_par_var, react_system, system, catalyst,
              inlet_species, T_bd, F_in, species_ID, multiple, count,
              a_options):

    #### LineStyles
    lines = ['-', '--', '-.', ':']
    no_of_lines = len(lines)
    style_index = count % no_of_lines
    #linecycler = cycle(lines)

    #### Retrieving the species_specific data from T_bd
    const, thermo_object = constants.fixed_parameters(react_system)
    h**o, cat, homo_index, cat_index = react.instantiate(
        react_system, const, catalyst)

    #### The local species ID is useful in Thiele Modulus calculations
    local_species = const['species']
    no_of_local_species = len(local_species)
    local_ID = np.arange(no_of_local_species)
    local_species_ID = dict(zip(local_species, local_ID))
    hc_local_index = local_species_ID[inlet_species]
    O2_local_index = local_species_ID['O2']

    #### This is the species_ID of the actual calculation coming from
    #### the calling function
    no_of_species = len(species_ID)
    species = list(species_ID.keys())
    hc_index = species_ID[inlet_species]
    O2_index = species_ID['O2']

    #### User-requested plots
    plot_dict = a_options['plots']

    if bif_par_var == 'tau':
        xplottype = 'log'
        x_axis = 'Residence Time (s)'
    else:
        xplottype = 'normal'
        x_axis = ('Inlet Fluid Temperature ' + r'$\mathbf{T_{f,in}}$' + ' (K)')

    #### Calculation of reaction rates

    #### Unpacking the matrix T_bd
    F_j = T_bd[:no_of_species, :]
    C_s = T_bd[no_of_species:2 * no_of_species, :]
    T_s = T_bd[2 * no_of_species, :]
    T_f = T_bd[2 * no_of_species + 1, :]
    bif_par = T_bd[-1, :]
    no_of_iter = T_bd.shape[1]

    T_f_in = T_bd[-1, :]

    #### Unpacking the constants
    R_omega = fixed_dict['R_omega']
    R_omega_wc = fixed_dict['R_omega_wc']
    R_omega_w = const['R_omega_w']
    nu = const['nu']

    nu_cat = nu.T[cat_index]
    nu_cat_inlet_species = nu_cat[:, hc_local_index]
    nu_cat_O2 = nu_cat[:, O2_local_index]

    eps_f = 4 * R_omega**2 / (2 * R_omega + R_omega_wc + R_omega_w)**2

    #### Defining mole fractions and concentrations
    C_total = 101325 / (8.314 * T_f)
    Y_j = F_j / np.sum(F_j, axis=0)
    C_f = Y_j * C_total
    C_in = 101325 / (8.314 * T_f_in)

    #### Calculation of reaction rates [Fig. 1]
    if plot_dict['reaction_rates'] or plot_dict['thiele_modulus']:
        homo_basis, cat_basis = a_options['rate_basis']
        homo_units, cat_units = a_options['rate_units']
        all_homo_rate = np.zeros([len(homo_index), no_of_iter], dtype=float)
        all_cat_rate = np.zeros([len(cat_index), no_of_iter], dtype=float)

        for i in range(no_of_iter):
            if (system == 'cat'):
                homo_rate = np.zeros(len(homo_index))
                cat_rate = cat.act_rate(species, cat_basis, C_s[:, i], T_s[i])
            elif (system == 'h**o'):
                cat_rate = np.zeros(len(cat_index))
                homo_rate = h**o.act_rate(species, homo_basis, C_f[:, i],
                                          T_f[i])
            else:
                homo_rate = h**o.act_rate(species, homo_basis, C_f[:, i],
                                          T_f[i])
                cat_rate = cat.act_rate(species, cat_basis, C_s[:, i], T_s[i])

            all_homo_rate[:, i] = homo_rate[:]
            all_cat_rate[:, i] = cat_rate[:]

        #### This is not required for the time being
        # We got to check the units and perform subsequent calculations
        if homo_basis == 'mole_fraction':
            if homo_units != 'second':
                raise Exception('There is a discrepancy '
                                'in the homogeneous reaction rate')
        if (cat_units == 'kg_sec'):
            all_cat_rate *= fixed_dict['particle_density']
        elif (cat_units == 'gm_sec'):
            all_cat_rate *= fixed_dict['particle_density'] * 1000

        # Here we make two separate variables for catalytic reactions
        #homo_rate_C0 = all_homo_rate/C_in
        cat_rate_C0 = all_cat_rate.copy()
        all_cat_rate *= R_omega_wc * eps_f / R_omega

        #return all_cat_rate - cat_rate_C0
        #### Plotting the reaction rates
        if plot_dict['reaction_rates'] and not multiple:

            #### Catalytic reaction rates
            fig, ax1 = plt.subplots()
            label_cat = ()
            for i in range(len(cat_index)):
                if xplottype == 'log':
                    ax1.loglog(bif_par,
                               all_cat_rate[i, :],
                               linestyle=next(linecycler))
                else:
                    ax1.plot(bif_par,
                             all_cat_rate[i, :],
                             linestyle=next(linecycler))
                label = 'Reaction No.= ' + str(cat_index[i] + 1)
                label_cat += (label, )

            ax1.set_xlabel(x_axis)
            ax1.set_ylabel(
                ('Catalytic reaction rates (' + r'$\mathbf{mol/m^3 s}$' + ')'))
            ax1.axes.set_xlim(10, 1200)  # Hardcoded
            ax1.legend(label_cat, loc='best')

            #### Homogeneous reaction rates
            fig, ax11 = plt.subplots()
            label_homo = ()
            for i in range(len(homo_index)):
                if xplottype == 'log':
                    ax11.loglog(bif_par,
                                all_homo_rate[i, :],
                                linestyle=next(linecycler))
                else:
                    ax11.plot(bif_par,
                              all_homo_rate[i, :],
                              linestyle=next(linecycler))
                label = 'Reaction No.= ' + str(homo_index[i] + 1)
                label_homo += (label, )

            ax11.set_xlabel(x_axis)
            ax11.set_ylabel(('Homogeneous reaction rates (' +
                             r'$\mathbf{mol/m^3 s}$' + ')'))
            ax11.axes.set_xlim(10, 1200)  # Hardcoded
            ax11.legend(label_homo, loc='best')

        #### Plotting Thiele Modulus based on volumetric cat. reaction rates
        if plot_dict['thiele_modulus']:
            inlet_species_cat_rate = np.dot(-nu_cat_inlet_species, cat_rate_C0)
            thiele_mod_inlet_species = (inlet_species_cat_rate /
                                        C_s[hc_index, :] * R_omega_wc**2 /
                                        1e-06)

            inlet_species_surf_cat_rate = np.dot(-nu_cat_inlet_species,
                                                 all_cat_rate)
            surf_thiele_modulus = (inlet_species_surf_cat_rate /
                                   C_s[hc_index, :] * R_omega**2 / 1e-08)
            if count == 1:
                fig, ax111 = plt.subplots()
                ax111.set_xlabel(x_axis)
                ax111.set_ylabel(
                    ('Thiele Modulus (' + r'$\mathbf{\phi^2}$' + ')'))
                ax111.axes.set_xlim(10, 1200)  # Hardcoded

                fig, ax112 = plt.subplots()
                ax112.set_xlabel(x_axis)
                ax112.set_ylabel(('Surface Thiele Modulus (' +
                                  r'$\mathbf{\phi_{s}^2}$' + ')'))
                ax112.axes.set_xlim(10, 1200)  # Hardcoded

            ax111.plot(bif_par,
                       thiele_mod_inlet_species,
                       linestyle=lines[style_index])
            ax112.plot(bif_par,
                       surf_thiele_modulus,
                       linestyle=lines[style_index])

    #### Calculation of ratio at the surface [Fig. 2]
    if plot_dict['ratio_surface'] or plot_dict['surface_to_bulk']:
        conc_surf_hc = C_s[hc_index, :]
        conc_surf_O2 = C_s[O2_index, :]
        surface_ratio = conc_surf_hc / conc_surf_O2

        if plot_dict['ratio_surface']:
            fig, ax2 = plt.subplots()

            if xplottype == 'log':
                ax2.loglog(bif_par, surface_ratio)
            else:
                ax2.semilogy(bif_par, surface_ratio)
            ax2.set_xlabel(x_axis)
            ax2.set_ylabel(('HC to O2 ratio at surface'))
            #axis_limits = b_options['xaxis_lim'] + b_options['yaxis_lim']
            #ax1.axis(axis_limits)

    #### Calculation of ratio in bulk [Fig. 3]
    if plot_dict['ratio_bulk'] or plot_dict['surface_to_bulk']:
        molar_rate_hc = F_j[hc_index, :]
        molar_rate_O2 = F_j[O2_index, :]
        bulk_ratio = molar_rate_hc / molar_rate_O2

        if plot_dict['ratio_bulk']:
            fig, ax3 = plt.subplots()

            if xplottype == 'log':
                ax3.loglog(bif_par, bulk_ratio)
            else:
                ax3.semilogy(bif_par, bulk_ratio)
            ax3.set_xlabel(x_axis)
            ax3.set_ylabel('HC to O2 ratio at bulk')
            #axis_limits = b_options['xaxis_lim'] + b_options['yaxis_lim']
            #ax1.axis(axis_limits)

    #### Calculation of ratio of HC to O2 in surface to that in bulk [Fig. 4]
    if plot_dict['surface_to_bulk']:
        surface_to_bulk = surface_ratio / bulk_ratio

        fig, ax4 = plt.subplots()
        if xplottype == 'log':
            ax4.loglog(bif_par, surface_to_bulk, color='b', linewidth=2.0)
        else:
            ax4.semilogy(bif_par, surface_to_bulk, color='b', linewidth=2.0)
        ax4.set_xlabel(x_axis)
        ax4.set_ylabel('HC to O2 ratio at surface to that in bulk')
        #axis_limits = b_options['xaxis_lim'] + b_options['yaxis_lim']
        #ax1.axis(axis_limits)

    if plot_dict['C2H4_C2H6_ratio']:
        ethylene_index = species_ID['C2H4']
        ethane_index = species_ID['C2H6']

        ethylene_ethane_ratio = F_j[ethylene_index, :] / F_j[ethane_index, :]

        fig, ax5 = plt.subplots()
        if xplottype == 'log':
            ax5.loglog(bif_par, ethylene_ethane_ratio)
        else:
            ax5.semilogy(bif_par, ethylene_ethane_ratio)
        ax5.set_xlabel(x_axis)
        ax5.set_ylabel('Ethylene to Ethane ratio in bulk')
def low_D_non_iso_model_solver(fixed_dict, react_system, system, catalyst,
                               rate_basis, rate_units, inlet_species, n,
                               options):
    '''
    This function solves the low_D_Sh_phi function to generate the 
    conversion vs Temperature curve.

    fixed_dict : Dictionary of fixed variables and values.
    react_system : Name of the reaction system
    system : Whether the system is 'cat'-alytic, 'coup'-led, or 
             'h**o'-geneous
    catalyst : Name of the catalyst used
    rate_basis : Basis of the rate expressions, whether pressure,
                 concentration, mole fraction
    rate_units : Units of the rate expressions
    inlet_species : Name of the fuel, e.g. 'CH4'
    n : No of discretized points in x
    options : Some options, like whether to save the result, or just 
              to test the model.
    '''

    #### Constant parameters involved with the system
    const, thermo_object = constants.fixed_parameters(react_system)
    species = const['species']
    no_of_species = len(species)
    ID = np.arange(no_of_species)
    species_ID = dict(zip(species, ID))
    print(species_ID)

    #### Generating the reaction objects
    h**o, cat, homo_index, cat_index = react.instantiate(
        react_system, const, catalyst)
    react_const = [h**o, cat, homo_index, cat_index]

    inlet_ratio = fixed_dict['inlet_ratio']
    y_A_in = inlet_ratio / (inlet_ratio + 1)
    y_B_in = 1 / (inlet_ratio + 1)
    T_f_in = 300

    #### Function names
    func = low_D_non_iso_model
    tspan = np.linspace(0, 8000, 1000000)

    #### Inlet values
    c_A_in = y_A_in * 101325 * fixed_dict['pressure'] / (8.314 * T_f_in)
    c_B_in = y_B_in * 101325 * fixed_dict['pressure'] / (8.314 * T_f_in)

    C_f_in = 1e-03 * np.ones(no_of_species)
    A_index = species_ID[inlet_species]
    B_index = species_ID['O2']
    C_f_in[A_index] = c_A_in
    C_f_in[B_index] = c_B_in

    C_f_0 = np.tile(C_f_in, n)
    C_w_0 = np.tile(C_f_in, n)
    T_f_0 = np.tile(T_f_in, n)
    #    T_f_0 = np.linspace(300, 600, n)
    T_s_0 = np.tile(T_f_in, n)
    C_0 = np.r_[C_f_0, C_w_0, T_f_0, T_s_0]

    #### Testing
    if options['Testing']:

        Y = func(C_0, 4200, inlet_species, fixed_dict, const, thermo_object,
                 react_const, system, rate_basis, rate_units, options['model'])
        return Y
    else:
        #### Integration
        Y = odeint(func,
                   C_0,
                   tspan,
                   args=(inlet_species, fixed_dict, const, thermo_object,
                         react_const, system, rate_basis, rate_units,
                         options['model']))

        ### Conversion calculations
        T_f_in = np.array(list(map(temp_ramp_func, tspan)))
        C_in = 101325 * fixed_dict['pressure'] / (8.314 * T_f_in)

        CH4_in = y_A_in * C_in
        O2_in = y_B_in * C_in

        print(no_of_species * (n - 1))
        print(no_of_species * n)
        C_f_exit = Y[:, no_of_species * (n - 1):no_of_species * n]
        CH4_exit = C_f_exit[:, A_index]
        O2_exit = C_f_exit[:, B_index]

        conv_A = (1 - CH4_exit / CH4_in)
        conv_B = (1 - O2_exit / O2_in)

        print(n * (no_of_species * 2 + 1) - 1)
        T_f_exit = Y[:, n * (no_of_species * 2 + 1) - 1]

        #### Plotting
        fig, ax = plt.subplots()
        ax.plot(T_f_in, conv_B)
        ax.set_xlabel('Inlet Fluid Temperature (K)')
        ax.set_ylabel(r'Conversion of $\mathbf{O_2}$')
        ax.set_xlim([0, 1])

        fig, ax1 = plt.subplots()
        ax1.plot(T_f_in, T_f_exit)
        ax1.set_xlabel('Inlet fluid Temperature (K)')
        ax1.set_ylabel('Exit fluid Temperature (K)')
        plt.show()

        return Y
Example #9
0
def hys_locus_solver(fixed_dict, bif_par_dict, react_system, system, 
                     catalyst, rate_basis, rate_units, inlet_species,
                     break_dict, step_change, max_val, options):
    '''
    This function solves for the hysteresis locus.
    (Region of multiplicities)

    We will write other details later.

    Just to point out one important difference between hys_locus_solver
    and bif_dia_solver is that, here we take in the entire break_dict
    It is similar to bif_set_solver in that respect.
    '''
    #### Generating the constant parameters
    const, thermo_object = constants.fixed_parameters(react_system)
    species = const['species']
    no_of_species = len(species)
    ID = np.arange(no_of_species)
    species_ID = dict(zip(species, ID))
    print('This is the new species ID',species_ID)
     
    #### Manipulation of input variables 
    all_dict = dict(bif_par_dict, **fixed_dict)

    bif_par_var = list(bif_par_dict.keys())[0]  
    bif_par_val = bif_par_dict.get(bif_par_var)
    break_val = break_dict[bif_par_var]
    #y_A_in_max_val = max_dict['y_A_in']
    
    # Generating the reaction objects
    h**o, cat, homo_index, cat_index = react.instantiate(react_system, 
                                       const, catalyst)
    react_const = [h**o, cat, homo_index, cat_index]

    ##### First dataset
    if options['occurence']:
        filename = 'bif_set_{0}_{1}'.format(options['limit_point'],
                                                    options['occurence'])
    else:
        filename = 'bif_set_{0}'.fomat(options['limit_point'])
    npzfile = _load_file(react_system, system, catalyst, all_dict, 
                         filename=filename)
    T_bs_arr, species_ID_arr = npzfile.files
    T_bs = npzfile[T_bs_arr]
    species_ID_old = npzfile[species_ID_arr]

    index = ig_ext_point_calculator(T_bs, system, 'inlet_ratio', 
                                    break_dict, fulloutput= False,
                                    tol=1e-02)
    limit_index = 0
    #data_vals = [value for (key, value) in sorted(fixed_dict.items())]
    #n = len(data_vals)
    #
    #filename = 'hysteresis_locus_left_{}'.format(options['occurence'])
    #for i in range(n):
    #    filename += '_{}'.format(data_vals[i])
    #filename += '.npz'
    #print(filename)
    #
    #react_filename, ext = os.path.splitext(react_system)
    #
    #Target_folder = os.path.join(os.getcwd(), react_filename, 
    #                                 catalyst.lower(), 'Data', system)
    #FullfileName = os.path.join(Target_folder, filename)
    #
    #print(FullfileName)

    #npzfile = np.load(FullfileName)
    #T_hl_arr = npzfile.files
    #T_hl = npzfile[T_hl_arr[0]]
    #x = T_hl[4*(no_of_species+1):-1, -1]
    #bif_par_val = T_hl[-1, -1]

    #### Function name
    func = hys_locus_func
    jac = jacobian
    
    #### Initial guess of the left and right eigen vectors
    no_of_func = 2*(no_of_species + 1)
    y0 = np.zeros(no_of_func, dtype=float)
    v0 = np.zeros_like(y0)
    y0[1] = 1
    v0[1] = 1

    col_index = index[limit_index]
    if col_index == -1 or col_index == 0:
        raise Exception('Cusp point does not exist at this configuration')

    x_old = T_bs[:, col_index]

    #### Rearranging the species data (Because of different species IDs)
    fluid_f_old = x_old[:no_of_species]
    wc_f_old = x_old[no_of_species : 2*no_of_species]
    invariant = x_old[2*no_of_species : ]

    fluid_f_new = _rearrange_species(species_ID_old, species_ID, fluid_f_old)
    wc_f_new = _rearrange_species(species_ID_old, species_ID, wc_f_old)
    x = np.r_[fluid_f_new, wc_f_new, invariant]
    x_init = np.r_[y0, v0, x, bif_par_val]

    J, d2f = func(x_init, inlet_species, fixed_dict, const, thermo_object, 
                  react_const, system, rate_basis, rate_units, options, 
                  get_jacobian=True, get_second_deriv=True)
    Y_init = np.r_[y0, v0]

    Y0 = root(left_right_eigen_vector, Y_init, args=(J, d2f), method='lm')
    state_var_val = np.r_[Y0.x, x, bif_par_val]

    if options['Testing']:
        print('\nThe eigen vectors are calculated under the following status')
        print('Status: {0}, msg: {1}'.format(Y0.status, Y0.message))
        print('\nAll the varibles going into the function')
        print(state_var_val)
        F = func(state_var_val, inlet_species, fixed_dict, const, 
                 thermo_object, react_const, system, rate_basis, rate_units,
                 options)
        return F
    else:
        #### Solving for hysteresis locus
        no_of_var = len(state_var_val)
        pref = np.ones(no_of_var)
        no_of_func = 2*(no_of_species + 1)
        weights = np.ones(no_of_var)
        weights[:2*no_of_func] = 1e-04
        weights[-5:-2] = 1e-03
        weights[-2] = 1e-01
        jac_eps = options['jac_eps']

        T_hl = der.derpar(func, jac, state_var_val, pref, max_val, 
                          break_val, weights, jac_eps, initial=False, 
                          hh=step_change, maxout=5000, hhmax=10*step_change, 
                          ncorr=5, args=(inlet_species, fixed_dict, const, 
                          thermo_object, react_const, system, rate_basis, 
                          rate_units, options), kwargs=())

    ##### Plotting
    if bif_par_var == 'T_f_in' or bif_par_var == 'inlet_species':
        plot_flag = 'norm'
    else:
        plot_flag = 'log'

    fig = plt.figure()
    if plot_flag == 'log':
        plt.semilogx(T_hl[-1, :], 1/T_hl[-2, :])
    else:
        plt.plot(T_hl[-1, :], 1/T_hl[-2, :])
    plt.show()
    
    #### Storing data
    data_vals = [value for (key, value) in sorted(fixed_dict.items())]
    n = len(data_vals)
    if options['occurence']:
        filename = 'hysteresis_locus_left_{0}'.format(options['occurence'])
    else:
        filename = 'hysteresis_locus_left'

    for i in range(n):
        filename += '_{}'.format(data_vals[i])
    print(filename)
     
    if options['save']:
        #### Saving Data
        react_filename, ext = os.path.splitext(react_system)
        
        Target_folder = os.path.join(os.getcwd(), react_filename, 
                                     catalyst.lower(), 'Data', system)
    
        if os.path.isdir(Target_folder) == False:
            New_Folder = react_filename + '/' + catalyst.lower() + '/' \
                       + '/Data/' + system
            os.makedirs(New_Folder)
    
        FullfileName = os.path.join(Target_folder, filename)
        np.savez(FullfileName, T_hl[2*no_of_func:, :], species_ID)
        
        #### Saving Diagrams (Why I don't know)
        Target_folder = os.path.join(os.getcwd(), react_filename, 
                                     catalyst.lower(), 'Diagram', system)
    
        if os.path.isdir(Target_folder) == False:
            New_Folder = react_filename + '/' + catalyst.lower() + '/' \
                       + '/Diagram/' + system
            os.makedirs(New_Folder)
    
        dia_filename = filename + '.png'
        FullfileName = os.path.join(Target_folder, dia_filename)
        fig.savefig(FullfileName)
    
    #### Returning the final result
    return T_hl
Example #10
0
def bif_set_solver(fixed_dict, bif_par_dict, react_system, system, catalyst, 
                   rate_basis, rate_units, inlet_species, break_dict, 
                   step_change, max_val, options):

    '''
    This function solves for the bifurcation set 
    (ignition-extinction locus).

    we will write other details later

    Just to point out one important difference between bif_set_solver 
    and bif_dia_solver is that, here we take in the entire break_dict
    '''
    # Constant parameters involved with the system
    const, thermo_object = constants.fixed_parameters(react_system)
    species = const['species']
    no_of_species = len(species)
    ID = np.arange(no_of_species)
    species_ID = dict(zip(species, ID))
    print('This is the new species ID',species_ID)

    # Manipulation of input variables
    all_dict = dict(fixed_dict, **bif_par_dict)

    bif_par_var = list(bif_par_dict.keys())[0]
    bif_par_val = bif_par_dict.get(bif_par_var)
    break_val = break_dict[bif_par_var]
    temp_break_val = break_dict['T_f_in']

    # Generating the reaction objects
    h**o, cat, homo_index, cat_index = react.instantiate(react_system, 
                                       const, catalyst)
    react_const = [h**o, cat, homo_index, cat_index]

    # First Dataset
    npzfile = _load_file(react_system, system, catalyst, all_dict)
    T_bd_arr, Y_in_arr, species_ID_arr = npzfile.files
    T_bd = npzfile[T_bd_arr]
    species_ID_old = npzfile[species_ID_arr]

    T_bd_wo_noise = T_bd[:, 1000:]
    index = ig_ext_point_calculator(T_bd_wo_noise, system, 
                                      'T_f_in', break_dict, 
                                      fulloutput=True)

    #### Fixing the starting point (ignition/extinction, first/second)
    if options['limit_point'] == 'ignition':
        if options['occurence'] == 'first':
            limit_index = 0
        elif options['occurence'] == 'second':
            limit_index = 2
        else:
            raise Exception('Wrong value of occurence')
    elif options['limit_point'] == 'extinction':
        if options['occurence'] == 'first':
            limit_index = 1
        elif options['occurence'] == 'second':
            limit_index = 3
        else:
            raise Exception('Wrong value of occurence')
    else:
        raise Exception('Wrong value of limit_point')

    #### Function names
    func = bif_set_func
    jac = jacobian

    #### Initial guess
    no_of_func = 2*(no_of_species + 1)
    y0 = np.zeros(no_of_func)
    y0[1] = 1
    col_index = index[limit_index]
    if col_index == -1 or col_index == 0:
        raise Exception('Limit point does not exist at this configuration')

    x_old = T_bd_wo_noise[:, col_index]
    
    #### Rearranging the species data (Because of different species IDs)
    fluid_f_old = x_old[:no_of_species]
    wc_f_old = x_old[no_of_species : 2*no_of_species]
    invariant = x_old[2*no_of_species : ]

    fluid_f_new = _rearrange_species(species_ID_old, species_ID, fluid_f_old)
    wc_f_new = _rearrange_species(species_ID_old, species_ID, wc_f_old)
    x = np.r_[fluid_f_new, wc_f_new, invariant]
    x_init = np.r_[y0, x, bif_par_val]

    J = func(x_init, inlet_species, fixed_dict, const, thermo_object, 
            react_const, system, rate_basis, rate_units, options, 
            get_jacobian=True)
    y0_sol = root(null_space, y0, args= J, method= 'lm')
    state_var_val = np.r_[y0_sol.x, x, bif_par_val]

    if options['Testing']:
        print('\nThe eigen vectors are calculated under the following status')
        print('Status: {0}, msg: {1}'.format(y0_sol.status, y0_sol.message))
        print('\nAll the varibles going into the function')
        print(state_var_val)
        print('\nAnd the fixed variables are:')
        print(fixed_dict)
        Ysol = func(state_var_val, inlet_species, fixed_dict, const, 
                    thermo_object, react_const, system, rate_basis, 
                    rate_units, options)
        return Ysol
    else:
        #### Solving for ignition-extinction locus
        no_of_var = len(state_var_val)
        pref = np.ones(no_of_var)
        weights = np.ones(no_of_var)
#        weights[:2*(no_of_species + 1)] = 1e-03
#        weights[-4:-1] = 1e-03
#        weights[-1] = 1e-01
        jac_eps = options['jac_eps']

        T_bs = der.derpar(func, jac, state_var_val, pref, max_val, 
                          break_val, weights, jac_eps, initial=False, 
                          hh=step_change, maxout=100000, 
                          hhmax= 10*step_change, ncorr=5,
                          args=(inlet_species, fixed_dict, const, 
                          thermo_object, react_const, system, rate_basis,
                          rate_units, options), kwargs=(temp_break_val))

    #### Plotting the figure
    if bif_par_var == 'T_f_in' or bif_par_var == 'inlet_ratio':
        plot_flag = 'norm'
    else:
        plot_flag = 'log'

    fig = plt.figure()
    if plot_flag == 'log':
        plt.semilogx(T_bs[-1, :], T_bs[-2, :])
    else:
        plt.plot(T_bs[-1, :], T_bs[-2, :])
    plt.show()
    
    #### Storing data
    data_vals = [value for (key, value) in sorted(fixed_dict.items())]
    n = len(data_vals)
    filename = 'bif_set_{}_{}'.format(options['limit_point'], 
                                      options['occurence'])
    
    for i in range(n):
        filename += '_{}'.format(data_vals[i])
        
    print(filename)
    
    if options['save']:
        #### Saving Data
        react_filename, ext = os.path.splitext(react_system)
        
        Target_folder = os.path.join(os.getcwd(), react_filename, 
                                     catalyst.lower(), 'Data', system)
    
        if os.path.isdir(Target_folder) == False:
            New_Folder = react_filename + '/' + catalyst.lower() + '/' \
                       + '/Data/' + system
            os.makedirs(New_Folder)
    
        FullfileName = os.path.join(Target_folder, filename)
        np.savez(FullfileName, T_bs[no_of_func:, :], species_ID)
        
        #### Saving Diagrams (Why I don't know)
        Target_folder = os.path.join(os.getcwd(), react_filename, 
                                     catalyst.lower(), 'Diagram', system)
    
        if os.path.isdir(Target_folder) == False:
            New_Folder = react_filename + '/' + catalyst.lower() + '/' \
                       + '/Diagram/' + system
            os.makedirs(New_Folder)
    
        dia_filename = filename + '.png'
        FullfileName = os.path.join(Target_folder, dia_filename)
        fig.savefig(FullfileName)
    
    #### Returning the final result
    return T_bs
Example #11
0
def bif_dia_solver(fixed_dict, bif_par_dict, react_system, system, catalyst, 
                   rate_basis, rate_units, inlet_species, break_val, 
                   step_change, max_val, options):
    '''
    This function solves for the bifurcation diagram.
    
    fixed_dict= Dictionary of fixed variables and values.
    bif_par_dict= Dictionary of Bifurcation variable and value.
    react_system= Describes the reaction system chosen, 
                  e.g: 'OCM_three_reaction.txt'.

    system= Whether the system is catalytic only, homogeneous only, or 
            homogeneous-heterogeneous coupled.
    inlet_species= The hydrocarbon species, as of now just hydrocarbon and 
                   O2 is taken as inlet.
    break_val= break value of the bifurcation parameter.
    
    step_change= step_change value of the bifurcation parameter, necessary in 
                 Pseudo-Arc Length Continuation.
    max_val= maximum value of the bifurcation parameter.
    options= Solver Options.
    '''

    #### Constant parameters involved with the system
    const, thermo_object = constants.fixed_parameters(react_system)
    species = const['species']
    no_of_species = len(species)
    ID = np.arange(no_of_species)
    species_ID = dict(zip(species, ID))
    print(species_ID)

    #### Manipulation of input variables
    all_dict = dict(fixed_dict, **bif_par_dict)

    bif_par_var = list(bif_par_dict.keys())[0]
    bif_par_val = bif_par_dict.get(bif_par_var)

    #### Initial guess
    inlet_ratio = all_dict['inlet_ratio']
    N2 = 0  # For the time being, we use pure O2
    F_A_in = inlet_ratio/(N2 + inlet_ratio + 1)
    F_B_in = 1/(N2 + inlet_ratio + 1)
    
    F_in = 1e-08 * np.ones(no_of_species)
     
    A_index = species_ID[inlet_species]
    B_index = species_ID['O2']

    F_in[A_index] = F_A_in
    F_in[B_index] = F_B_in

    state_var_val = np.r_[F_in, F_in, all_dict['T_f_in'], 
                          all_dict['T_f_in'], bif_par_val]

    #### Generating the reaction objects
    h**o, cat, homo_index, cat_index = react.instantiate(react_system,
                                       const, catalyst)
    react_const = [h**o, cat, homo_index, cat_index]
    
    #### Function name
    func = bif_dia_func
    jac = jacobian
    plot_flag = 'norm'
    
    if options['Testing']:
        #### Just testing the function(s)
        print('\nAll the varibles going into the function')
        print(state_var_val)
        print('\nAnd the fixed valriables going into the function')
        print(fixed_dict)
        Ysol = func(state_var_val, inlet_species, fixed_dict, const, 
               thermo_object, react_const, system,  rate_basis, rate_units)
        return Ysol

    elif options['solver'] == 'python': 
        #### Solving the set of equations using Arc-Length method in Python
        no_of_var = len(state_var_val)
        pref = np.ones(no_of_var)
        weights = np.ones(no_of_var)
        weights[-2:] = 1e-03
        jac_eps = options['jac_eps']

        T_bd = der.derpar(func, jac, state_var_val, pref, max_val, break_val,
               weights, jac_eps, initial= False, hh = step_change, 
               maxout = 200000, hhmax = 10*step_change,
               args=(inlet_species, fixed_dict, const, 
               thermo_object, react_const, system, rate_basis, rate_units)) 

    else:
        #### Solving the set of equations using Arc-Length method in Fortran
        eps = 1e-08
        w = np.ones(no_of_var, dtype=float, order='F')
        initial = 0
        itin = 50
        
        hh = 0.05
        hmax = 0.1 * np.ones(no_of_var, dtype=float, order='F')
        ndir = np.ones(no_of_var, dtype=np.int64, order='F')
        
        e = 1e-06
        mxadms = 4
        ncorr = 4
        ncrad = 0
        maxout = 4

        nout, out  = arc_length.derpar(func, jac, state_var_val, 
                     break_val, max_val, eps, w, initial, itin, hh, 
                     hmax, pref, ndir, e, mxadms, ncorr, ncrad, maxout, 
                     func_extra_args=(inlet_species, fixed_dict, const, 
                     thermo_object, react_const, system, rate_basis,
                     rate_units),
                     jac_extra_args=(inlet_species, fixed_dict, const,
                     thermo_object, react_const, system, rate_basis, 
                     rate_units))
        
        out_act = out[:nout,:-1]
        T_bd = out_act.T
        
    #### Plotting the figure
    fig = plt.figure()
    if plot_flag == 'log':
        plt.semilogx(T_bd[-1, :], T_bd[-2, :])
    else:
        plt.plot(T_bd[-1, :], T_bd[-2, :])
    plt.show()
    
    #### Storing data
    data_vals = [value for (key, value) in sorted(fixed_dict.items())]
    n = len(data_vals)
    filename = 'bif_dia'
    
    for i in range(n):
        filename += '_{}'.format(data_vals[i])
        
    print(filename)
    
    if options['save']:
        #### Saving Data
        react_filename, ext = os.path.splitext(react_system)
        
        Target_folder = os.path.join(os.getcwd(), react_filename, 
                                     catalyst.lower(), 'Data', system)
    
        if os.path.isdir(Target_folder) == False:
            New_Folder = react_filename + '/' + catalyst.lower() + '/' \
                       + '/Data/' + system
            os.makedirs(New_Folder)
    
        FullfileName = os.path.join(Target_folder, filename)
        np.savez(FullfileName, T_bd, F_in, species_ID)
        
        #### Saving Diagrams (Why I don't know)
        Target_folder = os.path.join(os.getcwd(), react_filename, 
                                     catalyst.lower(), 'Diagram', system)

        if os.path.isdir(Target_folder) == False:
            New_Folder = react_filename + '/' + catalyst.lower() + '/' \
                       + '/Diagram/' + system
            os.makedirs(New_Folder)
    
        dia_filename = filename + '.png'
        FullfileName = os.path.join(Target_folder, dia_filename)
        fig.savefig(FullfileName)
    
    #### Returning the final result
    return T_bd
def bif_dia_solver(fixed_dict, bif_par_dict, react_system, system, catalyst,
                   rate_basis, rate_units, inlet_species, break_val,
                   step_change, max_val, options):
    '''
    We will write this thing later
    '''

    #### Constant parameters involved with the system
    const, thermo_object = constants.fixed_parameters(react_system)
    species = const['species']
    no_of_species = len(species)
    ID = np.arange(no_of_species)
    species_ID = dict(zip(species, ID))
    print(species_ID)

    #### Manipulation of input variables
    all_dict = dict(fixed_dict, **bif_par_dict)

    bif_par_var = list(bif_par_dict.keys())[0]
    bif_par_val = bif_par_dict.get(bif_par_var)

    #### Initial guess
    T_f_in = all_dict['T_f_in']
    inlet_ratio = all_dict['inlet_ratio']

    N2 = 0  # For the time being, we use pure O2
    F_A_in = inlet_ratio / (N2 + inlet_ratio + 1)
    F_B_in = 1 / (N2 + inlet_ratio + 1)

    F_in = 1e-08 * np.ones(no_of_species)

    A_index = species_ID[inlet_species]
    B_index = species_ID['O2']

    F_in[A_index] = F_A_in
    F_in[B_index] = F_B_in

    state_var_val = np.r_[F_in, F_in, T_f_in, T_f_in, bif_par_val]

    #### Generating the reaction objects
    h**o, cat, homo_index, cat_index = react.instantiate(
        react_system, const, catalyst)
    react_const = [h**o, cat, homo_index, cat_index]

    #### Function name
    func = bif_dia_func
    jac = jacobian
    plot_flag = 'norm'

    if options['Testing']:
        #### Just testing the function(s)
        print('\nAll the varibles going into the function')
        print(state_var_val)
        print('\nAnd the fixed valriables going into the function')
        print(fixed_dict)
        Ysol = func(state_var_val, inlet_species, fixed_dict, const,
                    thermo_object, react_const, system, rate_basis, rate_units,
                    options)
        return Ysol

    else:
        #### Solving the set of equations using Arc-Length method in Python
        no_of_var = len(state_var_val)
        pref = np.ones(no_of_var)
        weights = np.ones(no_of_var)
        weights[-2:] = 1e-03
        jac_eps = options['jac_eps']
        max_iter = options['max_iter']

        data_vals = [value for (key, value) in sorted(fixed_dict.items())]
        n = len(data_vals)
        react_filename, ext = os.path.splitext(react_system)

        if options['model'] is 'sh_phi' and options['write_eig_val']:
            #### Filename
            file = react_filename + '_' + catalyst.lower() + '_' + system
            for i in range(n):
                file += '_{}'.format(data_vals[i])
            file += '.txt'

            #### Directory
            folder = os.path.join(os.getcwd(), 'EigenValues')
            if not os.path.isdir(folder):
                os.mkdir('EigenValues')
            fullfilename = os.path.join(folder, file)

            print(fullfilename)
            #### Creating the file
            with open(fullfilename, "w") as fh:
                fh.write(react_system)
                fh.write('\n')
            options.update({'eig_val_filename': fullfilename})

        T_bd = der.derpar(func,
                          jac,
                          state_var_val,
                          pref,
                          max_val,
                          break_val,
                          weights,
                          jac_eps,
                          eps=1e-04,
                          initial=False,
                          maxIter=50,
                          hh=step_change,
                          maxout=max_iter,
                          hhmax=10 * step_change,
                          ncorr=6,
                          args=(inlet_species, fixed_dict, const,
                                thermo_object, react_const, system, rate_basis,
                                rate_units, options))

    #### Plotting the figure
    fig = plt.figure()
    if plot_flag == 'log':
        plt.semilogx(T_bd[-1, :], T_bd[-2, :])
    else:
        plt.plot(T_bd[-1, :], T_bd[-2, :])
    plt.show()

    #### Storing data
    filename = 'bif_dia_{}'.format(options['model'].lower())

    for i in range(n):
        filename += '_{}'.format(data_vals[i])

    print(filename)

    if options['save']:
        #### Saving Data
        Target_folder = os.path.join(os.getcwd(), 'Washcoat', react_filename,
                                     catalyst.lower(), 'Data', system)

        if os.path.isdir(Target_folder) == False:
            New_Folder = 'Washcoat/' + react_filename + '/' + catalyst.lower() + '/' \
                       + '/Data/' + system
            os.makedirs(New_Folder)

        FullfileName = os.path.join(Target_folder, filename)
        np.savez(FullfileName, T_bd, F_in, species_ID)

        #### Saving Diagrams (Why I don't know)
        Target_folder = os.path.join(os.getcwd(), 'Washcoat', react_filename,
                                     catalyst.lower(), 'Diagram', system)

        if os.path.isdir(Target_folder) == False:
            New_Folder = 'Washcoat/' + react_filename + '/' + catalyst.lower() + '/' \
                       + '/Diagram/' + system
            os.makedirs(New_Folder)

        dia_filename = filename + '.png'
        FullfileName = os.path.join(Target_folder, dia_filename)
        fig.savefig(FullfileName)

    #### Returning the final result
    return T_bd