GUI

This file is designated for executing the AlphaPEM software package through a graphical user interface (GUI). Most of the functionalities are available, but some are not implemented.

about()

This function displays information about the program and its author in a dialog box when the "About" button is clicked.

Source code in GUI.py
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
def about():
    """This function displays information about the program and its author in a dialog box when the "About" button is
    clicked.
    """
    msg = """AlphaPEM is an open-source software package for simulating proton exchange membrane fuel cell (PEMFC) 
     systems using physics-based models for embedded applications. It is based on a physics-based, finite-volume,
     one-dimensional (1D), dynamic, two-phase, and non-isothermal model. It can quickly simulate the internal states and 
     voltage dynamics of PEMFC systems, and produce polarization and EIS curves. It can also automatically calibrate 
     the undetermined parameters of the model to simulate a given real fuel cell system.

     AlphaPEM is firstly developed by Raphaël Gass during his PhD thesis in control engineering at the LIS Laboratory in 
     Aix-Marseille University, and in co-supervision with FEMTO-ST Institute, within the FCLab, in Franche-Comté 
     University, from 2021 to 2024. This work has been supervised by Prof. Zhongliang Li (FEMTO-ST), Prof. Rachid Outbib 
     (LIS), Prof. Samir Jemei (FEMTO-ST) and Prof. Daniel Hissel (FEMTO-ST). It has been supported by French National 
     Research Agency via project DEAL (Grant no. ANR-20-CE05-0016-01, https://deal.lis-lab.fr/), the Region 
     Provence-Alpes-Côte d’Azur, the EIPHI Graduate School (contract ANR-17-EURE-0002) and the Region Bourgogne 
     Franche-Comté.

     The development of AlphaPEM was subsequently continued by Raphaël Gass during his postdoctoral research from 2025 
     to 2027 at ENERGY-Lab, University of Reunion island, in partnership with the ZSW Institute in Ulm, Germany. 
     This work was supervised by Prof. Michel Benne (ENERGY-Lab), Associate Prof. Cédric Damour (ENERGY-Lab), Associate
     Prof. Dominique Grondin (ENERGY-Lab), and Dr. Florian Wilhelm (ZSW). It has been supported by European FEDER funds 
     via project OPUS-H2 (https://www.energylab.re/projets/projets-en-cours/opus-h2/) and the Region Reunion.

     It is related to the following articles:
         - Gass et al 2024 J. Electrochem. Soc. https://doi.org/10.1149/1945-7111/ad305a,
         - Gass et al 2025 I.J. of Hydrogen Energy https://doi.org/10.1016/j.ijhydene.2024.11.374.
         - Gass et al 2025 SoftwareX https://doi.org/10.1016/j.softx.2024.102002.

     More information can be found in:
         - AlphaPEM GitHub webpage: https://github.com/gassraphael/AlphaPEM
         - AlphaPEM documentation webpage: https://gassraphael.github.io/AlphaPEM/
         - Author webpage: https://gassraphael.github.io/

     If you want to contact me, please send an email to: raphael.gass@univ-reunion.fr."""

    # Create a new top-level window
    about_window = tk.Toplevel()
    about_window.title('About this program')

    # Set the size of the window
    about_window.geometry('730x460')  # Width x Height

    # Create a label with the message
    label = ttk.Label(about_window, text=msg, wraplength=700)  # wraplength to wrap text within the given width
    label.pack(padx=15, pady=15)  # Add padding around the label

    # Create an OK button to close the window
    ok_button = ttk.Button(about_window, text='OK', command=about_window.destroy)
    ok_button.pack(pady=10)

control_current_button(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons, current_button)

This function is responsible for validating the user inputs by calling the value_control() function. If the input is valid, it then calls the show_current_button function to perform the requested action based on the button_type.

Parameters:
  • choice_operating_conditions (dict) –

    A dictionary containing the operating condition information.

  • choice_accessible_parameters (dict) –

    A dictionary containing the accessible parameter information.

  • choice_undetermined_parameters (dict) –

    A dictionary containing the undetermined parameter information.

  • choice_current_density_parameters (dict) –

    A dictionary containing the current density parameter information.

  • choice_computing_parameters (dict) –

    A dictionary containing the computing parameter information.

  • choice_buttons (dict) –

    A dictionary containing the button information.

  • current_button (dict) –

    A dictionary representing the clicked button.

Source code in GUI.py
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
def control_current_button(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters,
                           choice_current_density_parameters, choice_computing_parameters, choice_buttons,
                           current_button):
    """This function is responsible for validating the user inputs by calling the value_control() function. If the input
    is valid, it then calls the show_current_button function to perform the requested action based on the button_type.

    Parameters
    ----------
    choice_operating_conditions : dict
        A dictionary containing the operating condition information.
    choice_accessible_parameters : dict
        A dictionary containing the accessible parameter information.
    choice_undetermined_parameters : dict
        A dictionary containing the undetermined parameter information.
    choice_current_density_parameters : dict
        A dictionary containing the current density parameter information.
    choice_computing_parameters : dict
        A dictionary containing the computing parameter information.
    choice_buttons : dict
        A dictionary containing the button information.
    current_button : dict
        A dictionary representing the clicked button.
    """
    # Control the values
    value_control(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters,
                  choice_current_density_parameters, choice_computing_parameters, choice_buttons, current_button)

    # Activate the action
    show_current_button(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters,
                        choice_current_density_parameters, choice_computing_parameters, choice_buttons, current_button)

create_application()

This function creates the main application window and setting its title. It calls the main_frame() function to create the main graphical elements of the window.

Source code in GUI.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
def create_application():
    """This function creates the main application window and setting its title.
    It calls the main_frame() function to create the main graphical elements of the window.
    """
    # Create the main application window
    root = ThemedTk(theme="arc")
    root.configure(background='#f5f6f7')
    root.title("AlphaPEM")

    # Create a canvas and add a scrollbar to it
    canvas = tk.Canvas(root)
    scrollbar = ttk.Scrollbar(root, command=canvas.yview)
    canvas.configure(yscrollcommand=scrollbar.set)
    frame = ttk.Frame(canvas) # Create a frame inside the canvas to add your widgets

    # Add all the widgets to the frame
    main_frame(frame, canvas)
    canvas.create_window((0,0), window=frame, anchor='nw') # Add the frame to the canvas

    # Adjust the main window and canvas size
    frame.update_idletasks()
    root.geometry(f"{frame.winfo_width()}x{frame.winfo_height()}")
    canvas.configure(scrollregion=canvas.bbox('all'))
    canvas.pack(fill='both', expand=True, side='left') # Organize the widgets
    scrollbar.pack(fill='y', side='right')

    root.mainloop()

main_frame(root, canvas)

This function creates the main graphical elements, such as labels, entry widgets, radio buttons, and buttons. It arranges them in the application window (root). It also initializes the choice dictionary variables for various parameters and settings.

Parameters:

root : ThemedTk The main application window where the graphical elements will be placed. canvas : tk.Canvas The canvas where the main graphical elements will be placed.

Source code in GUI.py
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
def main_frame(root, canvas):
    """This function creates the main graphical elements, such as labels, entry widgets, radio buttons, and buttons.
    It arranges them in the application window (root). It also initializes the choice dictionary variables for various
    parameters and settings.

    Parameters:
    -----------
    root : ThemedTk
        The main application window where the graphical elements will be placed.
    canvas : tk.Canvas
        The canvas where the main graphical elements will be placed.
    """
    # Create a custom styles
    style = ttk.Style()
    style.configure('Custom.TFrame', background='#f5f6f7')
    style.configure('Blue.TButton', foreground='blue', font=('cmr10', 10, 'bold'))  # Set the font color to blue
    style.configure('Green.TButton', foreground='green', font=('cmr10', 10, 'bold'))  # Set the font color to green
    style.configure('Red.TButton', foreground='red', font=('cmr10', 10, 'bold'))  # Set the font color to red
    style.configure('Black.TButton', foreground='black', font=('cmr10', 10, 'bold'))  # Set the font color to black
    style.configure('Big.TButton', font=('cmr10', 12, 'bold'))

    # Create control variables to track the visibility state of some frame
    show_info_undetermined_parameters = tk.BooleanVar(value=False)
    show_info_current_density_parameters = tk.BooleanVar(value=False)
    show_info_computing_parameters = tk.BooleanVar(value=False)

    # Create the frames to hold the different set of information
    #   Fuel cell type and operating conditions
    operating_conditions_frame = ttk.Frame(root, style='Custom.TFrame')
    operating_conditions_frame.grid(row=1, column=0, padx=5, pady=5)
    #   Accessible physical parameters
    accessible_parameters_frame = ttk.Frame(root, style='Custom.TFrame')
    accessible_parameters_frame.grid(row=3, column=0, padx=5, pady=5)
    #   Undetermined physical parameters
    undetermined_parameters_frame = ttk.Frame(root, style='Custom.TFrame')
    undetermined_parameters_frame.grid(row=5, column=0, padx=5, pady=5)
    undetermined_parameters_frame.grid_remove()  # Hide the frame by default
    #   Current density parameters
    current_density_parameters_frame = ttk.Frame(root, style='Custom.TFrame')
    current_density_parameters_frame.grid(row=7, column=0, padx=5, pady=5)
    current_density_parameters_frame.grid_remove()  # Hide the frame by default
    #   Computing parameters
    computing_parameters_frame = ttk.Frame(root, style='Custom.TFrame')
    computing_parameters_frame.grid(row=9, column=0, padx=5, pady=5)
    computing_parameters_frame.grid_remove()  # Hide the frame by default
    #   Model possibilities and current density choice
    model_possibilities_frame = ttk.Frame(root, style='Custom.TFrame')
    model_possibilities_frame.grid(row=11, column=0, padx=5, pady=5)

    # Import the current density parameters from the settings file for default value
    (step_current_parameters, pola_current_parameters, pola_current_for_cali_parameters, i_EIS, ratio_EIS, f_EIS, t_EIS,
     current_density) = calculate_current_density_parameters()
    f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS


    # Create the choice dictionaries
    choice_operating_conditions = \
        {'Temperature - Tfc (°C)': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 2, 'label_column': 1},
         'Anode pressure - Pa (bar)': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 2, 'label_column': 3},
         'Cathode pressure - Pc (bar)': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 2, 'label_column': 5},
         'Anode stoichiometry - Sa': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 3, 'label_column': 1},
         'Cathode stoichiometry - Sc': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 3, 'label_column': 3},
         'Anode humidity - Φa': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 4, 'label_column': 1},
         'Cathode humidity - Φc': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 4, 'label_column': 3},
         'Anode inlet H2 ratio - y_H2_in\n(flow-through anode only)': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 4, 'label_column': 5}}

    choice_accessible_parameters = \
        {'Active area - Aact (cm²)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 1},
         'Number of cells - nb_cell': {'value': tk.IntVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 3},
         'Anode gas channel\nthickness - Hagc (µm)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 1},
         'Cathode gas channel\nthickness - Hcgc (µm)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 3},
         'Anode gas channel\nwidth - Wagc (µm)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 5},
         'Cathode gas channel\nwidth - Wcgc (µm)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 3, 'label_column': 5},
         'Gas channel\nlength - Lgc (mm)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 3, 'label_column': 1},
         'Number of channels inside the\ngas channel - nb_channel_in_gc' : {'value': tk.IntVar(accessible_parameters_frame), 'label_row': 3, 'label_column': 3},
         'Distributor length - Ldist (mm)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 4, 'label_column': 1},
         'Exhaust anode manifold throttle\narea - A_T_a (cm²)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 4, 'label_column': 3},
         'Exhaust cathode manifold throttle\narea - A_T_c (cm²)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 4, 'label_column': 5},
         'Supply anode manifold\nvolume - Vasm (cm³)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 5, 'label_column': 1},
         'Supply cathode manifold\nvolume - Vcsm (cm³)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 5, 'label_column': 3},
         'Exhaust anode manifold\nvolume - Vaem (cm³)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 6, 'label_column': 1},
         'Exhaust cathode manifold\nvolume - Vcem (cm³)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 6, 'label_column': 3}}


    choice_undetermined_parameters = \
        {'GDL thickness - Hgdl (µm)\n(without the transition layer)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 0, 'label_column': 1},
         'MPL thickness - Hmpl (µm)\n(without the transition layer)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 0, 'label_column': 3},
         'ACL thickness - Hacl (µm)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 0, 'label_column': 5},
         'CCL thickness - Hccl (µm)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 1},
         'Membrane thickness - Hmem (µm)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 3},
         'GDL porosity - ε_gdl': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 1, 'label_column': 5},
         'CL porosity - ε_cl': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 2, 'label_column': 1},
         'MPL porosity - ε_mpl': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 2, 'label_column': 3},
         'Ionomer volume fraction - ε_mc': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 2, 'label_column': 5},
         'Compression ratio - ε_c': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 3, 'label_column': 1},
         'Capillary exponent - e': {'value': tk.IntVar(undetermined_parameters_frame), 'label_row': 3, 'label_column': 3},
         'Electron conduction\nresistance - Re (Ω.mm²)': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 4, 'label_column': 1},
         'Dry reference exchange current\ndensity - i0_d_c_ref (A/m²)': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 4, 'label_column': 3},
         'Humid reference exchange current\ndensity - i0_h_c_ref (A/m²)': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 4, 'label_column': 5},
         'Crossover correction coefficient\n- κ_co (mol/(m.s.Pa))': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 5, 'label_column': 1},
         'Overpotential correction\nexponent - κ_c': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 5, 'label_column': 3},
         'Limit liquid saturation\ncoefficient - a_slim': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 5, 'label_column': 5},
         'Limit liquid saturation\ncoefficient - b_slim': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 6, 'label_column': 1},
         'Limit liquid saturation\ncoefficient - a_switch': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 6, 'label_column': 3},
         'Volumetric space-charge layer\ncapacitance - C_scl (F/cm³)': {'value': tk.DoubleVar(undetermined_parameters_frame), 'label_row': 6, 'label_column': 5}}

    choice_current_density_parameters = \
        {'Stabilisation time\n- Δt_ini_step (min)': {'value': tk.DoubleVar(current_density_parameters_frame, step_current_parameters['delta_t_ini_step']/60),
                                                   'label_row': 0, 'label_column': 3},
         'Loading time\n- Δt_load_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, step_current_parameters['delta_t_load_step']),
                                              'label_row': 0, 'label_column': 5},
         'Breaking time\n- Δt_break_step (min)': {'value': tk.DoubleVar(current_density_parameters_frame, step_current_parameters['delta_t_break_step']/60),
                                                'label_row': 1, 'label_column': 3},
         'Current density step\n- i_step (A/cm²)': {'value': tk.DoubleVar(current_density_parameters_frame, step_current_parameters['i_step']/1e4),
                                                'label_row': 1, 'label_column': 5},

         'Stabilisation time\n- Δt_ini_pola (min)': {'value': tk.DoubleVar(current_density_parameters_frame, pola_current_parameters['delta_t_ini_pola']/60),
                                                   'label_row': 2, 'label_column': 3},
         'Loading time\n- Δt_load_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, pola_current_parameters['delta_t_load_pola']),
                                              'label_row': 2, 'label_column': 5},
         'Breaking time\n- Δt_break_pola (min)': {'value': tk.DoubleVar(current_density_parameters_frame, pola_current_parameters['delta_t_break_pola']/60),
                                                'label_row': 3, 'label_column': 3},
         'Current density step\n- Δi_pola (A/cm²)': {'value': tk.DoubleVar(current_density_parameters_frame, pola_current_parameters['delta_i_pola']/1e4),
                                                     'label_row': 3, 'label_column': 5},
         'Maximum current density\n- i_max_pola (A/cm²)': {'value': tk.DoubleVar(current_density_parameters_frame, 1.5),
                                                           'label_row': 4, 'label_column': 3},

         'Static current\n- i_EIS (A/cm²)': {'value': tk.DoubleVar(current_density_parameters_frame, i_EIS),
                                             'label_row': 5, 'label_column': 3},
         'Current ratio\n- ratio_EIS (%)': {'value': tk.DoubleVar(current_density_parameters_frame, ratio_EIS),
                                            'label_row': 5, 'label_column': 5},
         'Number of points\ncalculated - nb_points_EIS': {'value': tk.IntVar(current_density_parameters_frame, nb_points_EIS),
                                                          'label_row': 6, 'label_column': 3},
         'Power of the\ninitial frequency\n- f_power_min_EIS': {'value': tk.IntVar(current_density_parameters_frame, f_power_min_EIS),
                                                                'label_row': 6, 'label_column': 5},
         'Power of the\nfinal frequency\n- f_power_max_EIS': {'value': tk.IntVar(current_density_parameters_frame, f_power_max_EIS),
                                                              'label_row': 7, 'label_column': 3},
         'Number of frequencies\ntested - nb_f_EIS': {'value': tk.IntVar(current_density_parameters_frame, nb_f_EIS),
                                                      'label_row': 7, 'label_column': 5}}

    choice_computing_parameters = \
        {'Time for dynamic\ndisplay - Δt_dyn_step (s)': {'value': tk.DoubleVar(computing_parameters_frame, 300),
                                                         'label_row': 0, 'label_column': 1},
         'Purge time - t_purge (s)': {'value': tk.DoubleVar(computing_parameters_frame, 0.6),
                                      'label_row': 0, 'label_column': 3},
         'Time between two purges\n- Δt_purge (s)': {'value': tk.DoubleVar(computing_parameters_frame, 15),
                                                     'label_row': 0, 'label_column': 5},
         'Number of GC nodes - nb_gc': {'value': tk.IntVar(computing_parameters_frame, 5),
                                            'label_row': 1, 'label_column': 1},
         'Number of GDL nodes - nb_gdl': {'value': tk.IntVar(computing_parameters_frame, 5),
                                         'label_row': 1, 'label_column': 3},
         'Number of MPL nodes - nb_mpl': {'value': tk.IntVar(computing_parameters_frame, 5),
                                         'label_row': 1, 'label_column': 5},
         'Solver relative tolerance - rtol': {'value': tk.DoubleVar(computing_parameters_frame, 1e-5),
                                         'label_row': 2, 'label_column': 1},
         'Solver absolute tolerance - atol': {'value': tk.DoubleVar(computing_parameters_frame, 1e-8),
                                         'label_row': 2, 'label_column': 3}
         }

    choice_buttons = \
        {'type_fuel_cell': {'value': tk.StringVar(operating_conditions_frame, 'Enter your specifications'),
                            'label_row': 0},
         'type_auxiliary': {'value': tk.IntVar(model_possibilities_frame, 2), 'label_row': 1},
         'voltage_zone': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 2},
         'type_control': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 3},
         'type_purge': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 4},
         'type_display': {'value': tk.IntVar(model_possibilities_frame, 1), 'label_row': 5},
         'type_plot': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 6}}

    # Displays operating conditions and physical parameters on the screen (without their values)
    #   Display the dropdown menu buttons
    ttk.Button(root, text='Undetermined physical parameters', style='Big.TButton',
               command=lambda: toggle_info(undetermined_parameters_frame, show_info_undetermined_parameters, canvas)). \
        grid(row=4, column=0, padx=5, pady=5)
    ttk.Button(root, text='Current density parameters', style='Big.TButton',
               command=lambda: toggle_info(current_density_parameters_frame, show_info_current_density_parameters,
                                           canvas)). \
        grid(row=6, column=0, padx=5, pady=5)
    ttk.Button(root, text='Computing parameters', style='Big.TButton',
               command=lambda: toggle_info(computing_parameters_frame, show_info_computing_parameters, canvas)). \
        grid(row=8, column=0, padx=5, pady=5)
    #   Display the labels
    display_parameter_labels(operating_conditions_frame, accessible_parameters_frame, undetermined_parameters_frame,
                             current_density_parameters_frame, computing_parameters_frame, choice_operating_conditions,
                             choice_accessible_parameters, choice_undetermined_parameters,
                             choice_current_density_parameters, choice_computing_parameters)

    # Displays the value of the operating conditions and physical parameters on the screen.
    display_parameters_value(operating_conditions_frame, accessible_parameters_frame, undetermined_parameters_frame,
                             current_density_parameters_frame, computing_parameters_frame, choice_operating_conditions,
                             choice_accessible_parameters, choice_undetermined_parameters,
                             choice_current_density_parameters, choice_computing_parameters)

    # Display the radiobuttons on the screen
    display_radiobuttons(model_possibilities_frame, choice_buttons)

    # Display the 'type of fuel cell' widget on the screen.
    ttk.Label(operating_conditions_frame, text='Fuel cell:', font=('cmr10', 12, 'bold')). \
        grid(row=0, column=0, columnspan=2)
    ttk.OptionMenu(operating_conditions_frame, choice_buttons['type_fuel_cell']['value'],
                   'Enter your specifications', 'Enter your specifications', 'EH-31 1.5 bar (2021)',
                   'EH-31 2.0 bar (2021)', 'EH-31 2.25 bar (2021)', 'EH-31 2.5 bar (2021)',
                   command=lambda value: changeValue(operating_conditions_frame, accessible_parameters_frame,
                                                     undetermined_parameters_frame, current_density_parameters_frame,
                                                     computing_parameters_frame, choice_operating_conditions,
                                                     choice_accessible_parameters, choice_undetermined_parameters,
                                                     choice_current_density_parameters, choice_computing_parameters,
                                                     choice_buttons)). \
        grid(row=0, column=2, columnspan=2)

    # Display the action buttons to select the type of current density to be applied.
    ttk.Label(model_possibilities_frame, text='Current density:', font=('cmr10', 12, 'bold')). \
        grid(row=6, column=0, columnspan=2, sticky="w")
    current_button = {'Step curve': 0, 'Pola curve': 1, 'EIS curve': 2}
    #       Button to generate the step curve
    ttk.Button(model_possibilities_frame, text='Step curve', style='Blue.TButton',
               command=lambda: control_current_button(choice_operating_conditions, choice_accessible_parameters,
                                                      choice_undetermined_parameters, choice_current_density_parameters,
                                                      choice_computing_parameters, choice_buttons,
                                                      current_button['Step curve'])) \
        .grid(row=7, column=2, padx=10, pady=20)
    #       Button to generate the Pola curve
    ttk.Button(model_possibilities_frame, text='Pola curve', style='Green.TButton',
               command=lambda: control_current_button(choice_operating_conditions, choice_accessible_parameters,
                                                      choice_undetermined_parameters, choice_current_density_parameters,
                                                      choice_computing_parameters, choice_buttons,
                                                      current_button['Pola curve'])) \
        .grid(row=7, column=3, padx=10, pady=20)
    #       Button to generate the EIS curve
    ttk.Button(model_possibilities_frame, text='EIS curve', style='Red.TButton',
               command=lambda: control_current_button(choice_operating_conditions, choice_accessible_parameters,
                                                      choice_undetermined_parameters, choice_current_density_parameters,
                                                      choice_computing_parameters, choice_buttons,
                                                      current_button['EIS curve'])) \
        .grid(row=7, column=4, padx=10, pady=20)
    #       About button
    ttk.Button(model_possibilities_frame, text='About', style='Black.TButton', command=about) \
        .grid(row=7, column=5, ipadx=12)

    # Ensure the frame sizes are updated
    root.update_idletasks()
    set_equal_width(operating_conditions_frame, accessible_parameters_frame, undetermined_parameters_frame,
                    current_density_parameters_frame, computing_parameters_frame, model_possibilities_frame)

show_current_button(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons, current_button)

This function determines the action to be performed based on the button_type.

Parameters:
  • choice_operating_conditions (dict) –

    A dictionary containing the operating condition information.

  • choice_accessible_parameters (dict) –

    A dictionary containing the accessible parameter information.

  • choice_undetermined_parameters (dict) –

    A dictionary containing the undetermined parameter information.

  • choice_current_density_parameters (dict) –

    A dictionary containing the current density parameter information.

  • choice_computing_parameters (dict) –

    A dictionary containing the computing parameter information.

  • choice_buttons (dict) –

    A dictionary containing the button information.

  • current_button (dict) –

    A dictionary representing the clicked button.

Source code in GUI.py
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
def show_current_button(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters,
                        choice_current_density_parameters, choice_computing_parameters, choice_buttons, current_button):
    """This function determines the action to be performed based on the button_type.

    Parameters
    ----------
    choice_operating_conditions : dict
        A dictionary containing the operating condition information.
    choice_accessible_parameters : dict
        A dictionary containing the accessible parameter information.
    choice_undetermined_parameters : dict
        A dictionary containing the undetermined parameter information.
    choice_current_density_parameters : dict
        A dictionary containing the current density parameter information.
    choice_computing_parameters : dict
        A dictionary containing the computing parameter information.
    choice_buttons : dict
        A dictionary containing the button information.
    current_button : dict
        A dictionary representing the clicked button.
    """

    # Retrieves parameter values for predefined stacks and keeps them in their standard unit, or converts user-selected
    # quantities into standard units.
    (T_des, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, y_H2_in, Aact, nb_cell, Hgdl, Hmpl, Hacl, Hccl, Hmem, Hagc,
     Hcgc, Wagc, Wcgc, Lgc, Lm, L_endplate, L_man_gc, A_T_a, A_T_c, Vasm, Vcsm, Vaem, Vcem, V_endplate_a, V_endplate_c,
     V_man_agc, V_man_cgc, epsilon_gdl, epsilon_cl, epsilon_mpl, epsilon_mc, epsilon_c, e, Re, i0_d_c_ref, i0_h_c_ref,
     kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, step_current_parameters, pola_current_parameters,
     pola_current_for_cali_parameters, i_EIS, ratio_EIS, f_EIS, t_EIS, t_purge, delta_t_purge, nb_gdl, nb_mpl, nb_tl, rtol,
     atol, type_fuel_cell, voltage_zone, type_auxiliary, type_control, type_purge, type_display, type_plot) = \
        recover_for_use_operating_inputs_and_physical_parameters(choice_operating_conditions,
                                                                 choice_accessible_parameters,
                                                                 choice_undetermined_parameters,
                                                                 choice_current_density_parameters,
                                                                 choice_computing_parameters,
                                                                 choice_buttons)

    # Initialize the operating inputs and parameters dictionaries.
    current_parameters = {'step_current_parameters': step_current_parameters,
                          'pola_current_parameters': pola_current_parameters,
                          'pola_current_for_cali_parameters': pola_current_for_cali_parameters,
                          'i_EIS': i_EIS, 'ratio_EIS': ratio_EIS, 't_EIS': t_EIS, 'f_EIS': f_EIS}
    accessible_physical_parameters = {'Aact': Aact, 'nb_cell': nb_cell, 'Hagc': Hagc, 'Hcgc': Hcgc, 'Wagc': Wagc,
                                      'Wcgc': Wcgc, 'Lgc': Lgc, 'nb_channel_in_gc': nb_channel_in_gc, 'Ldist': Ldist,
                                      'Lm': Lm, 'A_T_a': A_T_a, 'A_T_c': A_T_c, 'Vasm': Vasm, 'Vcsm': Vcsm,
                                      'Vaem': Vaem, 'Vcem': Vcem}
    undetermined_physical_parameters = {'Hgdl': Hgdl, 'Hmpl': Hmpl, 'Hmem': Hmem, 'Hacl': Hacl, 'Hccl': Hccl,
                                        'epsilon_gdl': epsilon_gdl, 'epsilon_cl': epsilon_cl,
                                        'epsilon_mpl': epsilon_mpl, 'epsilon_mc': epsilon_mc, 'epsilon_c': epsilon_c,
                                        'e': e, 'Re': Re, 'i0_d_c_ref': i0_d_c_ref, 'i0_h_c_ref': i0_h_c_ref,
                                        'kappa_co': kappa_co, 'kappa_c': kappa_c, 'a_slim': a_slim, 'b_slim': b_slim,
                                        'a_switch': a_switch, 'C_scl': C_scl}

    if current_button == 0:
        type_current = "step"
        current_density = step_current
        operating_inputs = {'current_density': current_density, 'T_des': T_des, 'Pa_des': Pa_des, 'Pc_des': Pc_des,
                            'Sa': Sa, 'Sc': Sc, 'Phi_a_des': Phi_a_des, 'Phi_c_des': Phi_c_des, 'y_H2_in': y_H2_in}
        computing_parameters = {'nb_gc': nb_gc, 'nb_gdl': nb_gdl, 'nb_mpl': nb_mpl, 'nb_tl': nb_tl, 't_purge': t_purge,
                                'rtol': rtol, 'atol': atol, 'type_fuel_cell': type_fuel_cell,
                                'type_current': type_current, 'voltage_zone': voltage_zone,
                                'type_auxiliary': type_auxiliary, 'type_control': type_control,
                                'type_purge': type_purge, 'type_display': type_display, 'type_plot': type_plot}
        launch_AlphaPEM_for_step_current(operating_inputs, current_parameters, accessible_physical_parameters,
                                         undetermined_physical_parameters, computing_parameters)

    if current_button == 1:
        type_current = "polarization"
        current_density = polarization_current
        operating_inputs = {'current_density': current_density, 'T_des': T_des, 'Pa_des': Pa_des, 'Pc_des': Pc_des,
                            'Sa': Sa, 'Sc': Sc, 'Phi_a_des': Phi_a_des, 'Phi_c_des': Phi_c_des, 'y_H2_in': y_H2_in}
        computing_parameters = {'nb_gc': nb_gc, 'nb_gdl': nb_gdl, 'nb_mpl': nb_mpl, 'nb_tl': nb_tl, 't_purge': t_purge,
                                'rtol': rtol, 'atol': atol, 'type_fuel_cell': type_fuel_cell,
                                'type_current': type_current, 'voltage_zone': voltage_zone,
                                'type_auxiliary': type_auxiliary, 'type_control': type_control,
                                'type_purge': type_purge, 'type_display': type_display, 'type_plot': type_plot}
        launch_AlphaPEM_for_polarization_current(operating_inputs, current_parameters, accessible_physical_parameters,
                                                 undetermined_physical_parameters, computing_parameters)

    if current_button == 2:
        type_current = "EIS"
        current_density = EIS_current
        operating_inputs = {'current_density': current_density, 'T_des': T_des, 'Pa_des': Pa_des, 'Pc_des': Pc_des,
                            'Sa': Sa, 'Sc': Sc, 'Phi_a_des': Phi_a_des, 'Phi_c_des': Phi_c_des, 'y_H2_in': y_H2_in}
        computing_parameters = {'nb_gc': nb_gc, 'nb_gdl': nb_gdl, 'nb_mpl': nb_mpl, 'nb_tl': nb_tl, 't_purge': t_purge,
                                'rtol': rtol, 'atol': atol, 'type_fuel_cell': type_fuel_cell,
                                'type_current': type_current, 'voltage_zone': voltage_zone,
                                'type_auxiliary': type_auxiliary, 'type_control': type_control,
                                'type_purge': type_purge, 'type_display': type_display, 'type_plot': type_plot}
        launch_AlphaPEM_for_EIS_current(operating_inputs, current_parameters, accessible_physical_parameters,
                                        undetermined_physical_parameters, computing_parameters)

toggle_info(frame, show_info, canvas)

Toggles the visibility of the given frame and updates the scroll region of the given canvas.

Parameters:
  • frame (Frame) –

    The frame to show or hide.

  • show_info (BooleanVar) –

    A boolean variable to track the current visibility state.

  • canvas (Canvas) –

    The canvas to update the scroll region.

Source code in GUI.py
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
def toggle_info(frame, show_info, canvas):
    """
    Toggles the visibility of the given frame and updates the scroll region of the given canvas.

    Parameters
    ----------
    frame : ttk.Frame
        The frame to show or hide.
    show_info : tk.BooleanVar
        A boolean variable to track the current visibility state.
    canvas : tk.Canvas
        The canvas to update the scroll region.
    """
    if show_info.get():
        frame.grid_remove()  # Hide the info frame
        show_info.set(False)  # Update the visibility state
    else:
        frame.grid()  # Show the info frame
        show_info.set(True)  # Update the visibility state

    canvas.update_idletasks() # Update the scroll region of the given canvas.
    canvas.configure(scrollregion=canvas.bbox('all'))