diff --git a/functions/model/cell_voltage/index.html b/functions/model/cell_voltage/index.html
index f8a6514..9ec79be 100644
--- a/functions/model/cell_voltage/index.html
+++ b/functions/model/cell_voltage/index.html
@@ -299,11 +299,9 @@
Rmem = Hmem / (0.1879 * np.exp(1268 * (1 / 303.15 - 1 / Tfc)))
# The proton resistance at the cathode catalyst layer : Rccl
if lambda_ccl >= 1:
- Rccl = 1 / 3 * 1 / (epsilon_mc / tau) * \
- Hcl / ((0.5139 * lambda_ccl - 0.326) * np.exp(1268 * (1 / 303.15 - 1 / Tfc)))
+ Rccl = Hcl / ((epsilon_mc ** tau) * (0.5139 * lambda_ccl - 0.326) * np.exp(1268 * (1 / 303.15 - 1 / Tfc)))
else:
- Rccl = 1 / 3 * 1 / (epsilon_mc / tau) * \
- Hcl / (0.1879 * np.exp(1268 * (1 / 303.15 - 1 / Tfc)))
+ Rccl = Hcl / ((epsilon_mc ** tau) * 0.1879 * np.exp(1268 * (1 / 303.15 - 1 / Tfc)))
# The total proton resistance
Rp = Rmem + Rccl # its value is around [4-7]e-6 ohm.m².
diff --git a/index.html b/index.html
index 227432a..2410ccb 100644
--- a/index.html
+++ b/index.html
@@ -167,6 +167,10 @@ Major updates
- V1.0 - 2024.09.05 - This version of AlphaPEM corresponds to the one developed during Raphaël Gass's PhD from 2021 to 2024.
+Work in progress
+
+- The polarization curves from the EH-31 fuel cells, provided by default, are no longer calibrated due to recent modifications made to the equations. A calibration of the indeterminate parameters will be performed in the future to correct this issue.
+
The detailed model description and simulation results can be found in the following articles and thesis.
@@ -254,5 +258,5 @@
diff --git a/search/search_index.json b/search/search_index.json
index 3a95a09..610f607 100644
--- a/search/search_index.json
+++ b/search/search_index.json
@@ -1 +1 @@
-{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"AlphaPEM AlphaPEM is an open-source software package for simulating proton exchange membrane fuel cell (PEMFC) systems for embedded applications. It is based on a physics-based, one-dimensional (1D), dynamic, two-phase, and 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. A detailed presentation of this program was published in the peer-reviewed journal SoftwareX. Improvements to AlphaPEM , such as the addition of heat transfer modelling and spatial extension to 1D+1D, will be available in the future. Table of Contents Installation Major updates Related publications Installation To install AlphaPEM , follow these steps in a shell: Clone the repository: git clone https://github.com/gassraphael/AlphaPEM.git Navigate to the project directory: cd AlphaPEM Update the Python package manager, pip, to the latest available version: pip install --upgrade pip Install the required dependencies (eventually in a specific environment): pip install numpy scipy matplotlib colorama geneticalgorithm2 python3 -m pip install git+https://github.com/RedFantom/ttkthemes Major updates V1.0 - 2024.09.05 - This version of AlphaPEM corresponds to the one developed during Rapha\u00ebl Gass's PhD from 2021 to 2024. Related publications The detailed model description and simulation results can be found in the following articles and thesis. Submitted journal papers: AlphaPEM: An Open-Source Dynamic 1D Physics-Based Pem Fuel Cell Model for Embedded Applications In the journal SoftwareX, in arXiv , in HAL or in SSRN (preprint). The objective of this work is to highlight the AlphaPEM software, which has been published as open-source on GitHub. The first version of this PEM fuel cell simulator is based on the dynamic 1D model developed during 2021-2024. An Advanced 1D Physics-Based Model for PEM Hydrogen Fuel Cells With Enhanced Overvoltage Prediction In the International Journal of Hydrogen Energy, in arXiv or in HAL (preprint). The aim of this study was to introduce the dynamic 1D model developed during 2021-2024, emphasizing the adjustment of the equations for this specific model and their numerical resolution. Furthermore, a novel coefficient is proposed to establish a physical relationship between the voltage drop at high currents, the quantity of liquid water in the cell, and operating conditions. Published journal papers: A Critical Review of Proton Exchange Membrane Fuel Cells Matter Transports and Voltage Polarisation for Modelling In the Journal of the Electrochemical Society or in HAL (postprint). The aim of this work was to compile, within a single article, all the equations required for the physical modeling of a fuel cell. Each equation is complemented with explanations, critical analysis, and suggestions for potential enhancements. Thesis: to complete.","title":"Home"},{"location":"#alphapem","text":"AlphaPEM is an open-source software package for simulating proton exchange membrane fuel cell (PEMFC) systems for embedded applications. It is based on a physics-based, one-dimensional (1D), dynamic, two-phase, and 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. A detailed presentation of this program was published in the peer-reviewed journal SoftwareX. Improvements to AlphaPEM , such as the addition of heat transfer modelling and spatial extension to 1D+1D, will be available in the future.","title":"AlphaPEM"},{"location":"#table-of-contents","text":"Installation Major updates Related publications","title":"Table of Contents"},{"location":"#installation","text":"To install AlphaPEM , follow these steps in a shell: Clone the repository: git clone https://github.com/gassraphael/AlphaPEM.git Navigate to the project directory: cd AlphaPEM Update the Python package manager, pip, to the latest available version: pip install --upgrade pip Install the required dependencies (eventually in a specific environment): pip install numpy scipy matplotlib colorama geneticalgorithm2 python3 -m pip install git+https://github.com/RedFantom/ttkthemes","title":"Installation"},{"location":"#major-updates","text":"V1.0 - 2024.09.05 - This version of AlphaPEM corresponds to the one developed during Rapha\u00ebl Gass's PhD from 2021 to 2024.","title":"Major updates"},{"location":"#related-publications","text":"The detailed model description and simulation results can be found in the following articles and thesis. Submitted journal papers: AlphaPEM: An Open-Source Dynamic 1D Physics-Based Pem Fuel Cell Model for Embedded Applications In the journal SoftwareX, in arXiv , in HAL or in SSRN (preprint). The objective of this work is to highlight the AlphaPEM software, which has been published as open-source on GitHub. The first version of this PEM fuel cell simulator is based on the dynamic 1D model developed during 2021-2024. An Advanced 1D Physics-Based Model for PEM Hydrogen Fuel Cells With Enhanced Overvoltage Prediction In the International Journal of Hydrogen Energy, in arXiv or in HAL (preprint). The aim of this study was to introduce the dynamic 1D model developed during 2021-2024, emphasizing the adjustment of the equations for this specific model and their numerical resolution. Furthermore, a novel coefficient is proposed to establish a physical relationship between the voltage drop at high currents, the quantity of liquid water in the cell, and operating conditions. Published journal papers: A Critical Review of Proton Exchange Membrane Fuel Cells Matter Transports and Voltage Polarisation for Modelling In the Journal of the Electrochemical Society or in HAL (postprint). The aim of this work was to compile, within a single article, all the equations required for the physical modeling of a fuel cell. Each equation is complemented with explanations, critical analysis, and suggestions for potential enhancements. Thesis: to complete.","title":"Related publications"},{"location":"about/","text":"Contributions Authors AlphaPEM is firstly developed by Rapha\u00ebl Gass during his PhD thesis from 2021 to 2024, supervised by Prof. Zhongliang Li, Prof. Rachid Outbib, Prof. Samir Jemei and Prof. Daniel Hissel. Financial support This work has been supported: - from 2021 to 2024 by French National Research Agency via project DEAL (Grant no. ANR-20-CE05-0016-01), the Region Provence-Alpes-C\u00f4te d\u2019Azur, the EIPHI Graduate School (contract ANR-17-EURE-0002) and the Region Bourgogne Franche-Comt\u00e9. Licenses AlphaPEM is licensed under the GNU GPL 3.0. See the LICENSE file for more details. It also includes components licensed under the MIT license : calibration/parameter_calibration.py from geneticalgorithm2 . New contributors Contributions from the community are welcome! If you would like to contribute to AlphaPEM , please follow these steps: Fork the repository. Create a new branch ( git checkout -b feature/YourFeature ). Commit your changes ( git commit -am 'Add some feature' ). Push to the branch ( git push origin feature/YourFeature ). Create a new Pull Request. Contact For any questions or support, please contact me at gassraphael@proton.me .","title":"About"},{"location":"about/#contributions","text":"","title":"Contributions"},{"location":"about/#authors","text":"AlphaPEM is firstly developed by Rapha\u00ebl Gass during his PhD thesis from 2021 to 2024, supervised by Prof. Zhongliang Li, Prof. Rachid Outbib, Prof. Samir Jemei and Prof. Daniel Hissel.","title":"Authors"},{"location":"about/#financial-support","text":"This work has been supported: - from 2021 to 2024 by French National Research Agency via project DEAL (Grant no. ANR-20-CE05-0016-01), the Region Provence-Alpes-C\u00f4te d\u2019Azur, the EIPHI Graduate School (contract ANR-17-EURE-0002) and the Region Bourgogne Franche-Comt\u00e9.","title":"Financial support"},{"location":"about/#licenses","text":"AlphaPEM is licensed under the GNU GPL 3.0. See the LICENSE file for more details. It also includes components licensed under the MIT license : calibration/parameter_calibration.py from geneticalgorithm2 .","title":"Licenses"},{"location":"about/#new-contributors","text":"Contributions from the community are welcome! If you would like to contribute to AlphaPEM , please follow these steps: Fork the repository. Create a new branch ( git checkout -b feature/YourFeature ). Commit your changes ( git commit -am 'Add some feature' ). Push to the branch ( git push origin feature/YourFeature ). Create a new Pull Request.","title":"New contributors"},{"location":"about/#contact","text":"For any questions or support, please contact me at gassraphael@proton.me .","title":"Contact"},{"location":"functions/GUI/","text":"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 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. \\nIt is based on a physics-based, \" \\ \"one-dimensional (1D), dynamic, two-phase, and 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.\" \\ \"\\n\\nAlphaPEM is firstly developed by Rapha\u00ebl Gass during his PhD thesis from 2021 to 2024, supervised by \" \\ \"Prof. Zhongliang Li, Prof. Rachid Outbib, Prof. Samir Jemei and Prof. Daniel Hissel. \\nIt has been \" \\ \"supported by French National Research Agency via project DEAL (Grant no. ANR-20-CE05-0016-01), the Region \" \\ \"Provence-Alpes-C\u00f4te d\u2019Azur, the EIPHI Graduate School (contract ANR-17-EURE-0002) and the Region \" \\ \"Bourgogne Franche-Comt\u00e9.\" \\ \"\\n\\nIt is related to the following articles:\" \\ \"\\n - Gass et al 2024 J. Electrochem. Soc. https://doi.org/10.1149/1945-7111/ad305a,\" \\ \"\\n - Gass et al 2024 SSRN http://dx.doi.org/10.2139/ssrn.4812343.\" \\ \"\\n\\nMore information can be found in:\" \\ \"\\n - GitHub webpage: https://github.com/gassraphael/AlphaPEM\" \\ \"\\n - Documentation webpage: to do\" \\ \"\\n\\nIf you want to contact me, please send an email to: gassraphael@proton.me.\" # 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 ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in GUI.py 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 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 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) # Create the choice dictionaries choice_operating_conditions = \\ {'Temperature - Tfc (\u00b0C)': {'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 - \u03a6a': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 4, 'label_column': 1}, 'Cathode humidity - \u03a6c': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 4, 'label_column': 3}} choice_accessible_parameters = \\ {'GDL thickness - Hgdl (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 1}, 'CL thickness - Hcl (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 3}, 'Membrane thickness - Hmem (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 5}, 'GC thickness - Hgc (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 1}, 'GC width - Wgc (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 3}, 'GC cumulated length - Lgc (m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 5}, 'Active area - Aact (cm\u00b2)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 3, 'label_column': 1}} choice_undetermined_parameters = \\ {'GDL porosity - \u03b5_gdl': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.6), 'label_row': 0, 'label_column': 1}, 'Ionomer volume fraction\\n- \u03b5_mc': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.25), 'label_row': 0, 'label_column': 3}, 'Tortuosity - \u03c4': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.5), 'label_row': 0, 'label_column': 5}, 'Compression ratio - \u03b5_c': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.2), 'label_row': 1, 'label_column': 1}, 'Capillary exponent - e': {'value': tk.IntVar(undetermined_parameters_frame, 4), 'label_row': 1, 'label_column': 3}, 'Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.0), 'label_row': 1, 'label_column': 5}, 'Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)': {'value': tk.DoubleVar(undetermined_parameters_frame, 3.0), 'label_row': 2, 'label_column': 1}, 'Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.0), 'label_row': 2, 'label_column': 3}, 'Overpotential correction\\nexponent - \u03ba_c': {'value': tk.DoubleVar(undetermined_parameters_frame, 2.0), 'label_row': 2, 'label_column': 5}, 'Limit liquid saturation\\ncoefficient - a_slim': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.05), 'label_row': 3, 'label_column': 1}, 'Limit liquid saturation\\ncoefficient - b_slim': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.1), 'label_row': 3, 'label_column': 3}, 'Limit liquid saturation\\ncoefficient - a_switch': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.7), 'label_row': 3, 'label_column': 5}, 'Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)': {'value': tk.DoubleVar(undetermined_parameters_frame, 20), 'label_row': 4, 'label_column': 1}} choice_current_density_parameters = \\ {'Initial time - t0_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 0), 'label_row': 0, 'label_column': 1}, 'Final time - tf_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 1000), 'label_row': 0, 'label_column': 3}, 'Loading time\\n- \u0394t_load_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 50), 'label_row': 0, 'label_column': 5}, 'Initial current density\\n- i_ini_step (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 1, 'label_column': 1}, 'Final current density\\n- i_final_step (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 1.5), 'label_row': 1, 'label_column': 3}, 'Loading time\\n- \u0394t_load_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 30), 'label_row': 2, 'label_column': 1}, 'Breaking time\\n- \u0394t_break_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 30), 'label_row': 2, 'label_column': 3}, 'Initial breaking time\\n- \u0394t_ini_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 60), 'label_row': 2, 'label_column': 5}, 'Maximum current density\\n- i_max_pola (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 3, 'label_column': 1}, 'Current density step\\n- \u0394i_pola (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.1), 'label_row': 3, 'label_column': 3}, 'Static current\\n- i_EIS (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 4, 'label_column': 1}, 'Current ratio\\n- ratio_EIS (%)': {'value': tk.DoubleVar(current_density_parameters_frame, 5), 'label_row': 4, 'label_column': 3}, 'Number of points\\ncalculated - nb_points_EIS': {'value': tk.IntVar(current_density_parameters_frame, 50), 'label_row': 4, 'label_column': 5}, 'Power of the\\ninitial frequency\\n- f_power_min_EIS': {'value': tk.IntVar(current_density_parameters_frame, -3), 'label_row': 5, 'label_column': 1}, 'Power of the\\nfinal frequency\\n- f_power_max_EIS': {'value': tk.IntVar(current_density_parameters_frame, 5), 'label_row': 5, 'label_column': 3}, 'Number of frequencies\\ntested - nb_f_EIS': {'value': tk.IntVar(current_density_parameters_frame, 60), 'label_row': 5, 'label_column': 5}} choice_computing_parameters = \\ {'Time for dynamic\\ndisplay - \u0394t_dyn_step (s)': {'value': tk.DoubleVar(computing_parameters_frame, 10), '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- \u0394t_purge (s)': {'value': tk.DoubleVar(computing_parameters_frame, 15), 'label_row': 0, 'label_column': 5}, 'Maximum time step\\n- max_step (s)': {'value': tk.DoubleVar(computing_parameters_frame, 0.1), 'label_row': 1, 'label_column': 1}, 'Number of GDL nodes - n_gdl': {'value': tk.IntVar(computing_parameters_frame, 10), 'label_row': 1, '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}, 'type_control': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 2}, 'type_purge': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 3}, 'type_display': {'value': tk.IntVar(model_possibilities_frame, 1), 'label_row': 4}, 'type_plot': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 5}} # 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)', 'Linhao Fan (2010)', 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=6, 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=6, 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=6, column=4, padx=10, pady=20) # About button ttk.Button(model_possibilities_frame, text='About', style='Black.TButton', command=about) \\ .grid(row=6, 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 ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in GUI.py 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. Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, Aact, Hgdl, Hcl, Hmem, Hgc, Wgc, Lgc, epsilon_gdl, \\ epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, t_step, \\ i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, t_purge, delta_t_purge, max_step, n_gdl, \\ type_fuel_cell, 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) if current_button == 0: type_current = \"step\" current_density = step_current launch_AlphaPEM_for_step_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) if current_button == 1: type_current = \"polarization\" current_density = polarization_current launch_AlphaPEM_for_polarization_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) if current_button == 2: type_current = \"EIS\" current_density = EIS_current launch_AlphaPEM_for_EIS_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) 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 ) \u2013 The frame to show or hide. show_info ( BooleanVar ) \u2013 A boolean variable to track the current visibility state. canvas ( Canvas ) \u2013 The canvas to update the scroll region. Source code in GUI.py 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'))","title":"GUI"},{"location":"functions/GUI/#gui","text":"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.","title":"GUI"},{"location":"functions/GUI/#GUI.about","text":"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 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. \\nIt is based on a physics-based, \" \\ \"one-dimensional (1D), dynamic, two-phase, and 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.\" \\ \"\\n\\nAlphaPEM is firstly developed by Rapha\u00ebl Gass during his PhD thesis from 2021 to 2024, supervised by \" \\ \"Prof. Zhongliang Li, Prof. Rachid Outbib, Prof. Samir Jemei and Prof. Daniel Hissel. \\nIt has been \" \\ \"supported by French National Research Agency via project DEAL (Grant no. ANR-20-CE05-0016-01), the Region \" \\ \"Provence-Alpes-C\u00f4te d\u2019Azur, the EIPHI Graduate School (contract ANR-17-EURE-0002) and the Region \" \\ \"Bourgogne Franche-Comt\u00e9.\" \\ \"\\n\\nIt is related to the following articles:\" \\ \"\\n - Gass et al 2024 J. Electrochem. Soc. https://doi.org/10.1149/1945-7111/ad305a,\" \\ \"\\n - Gass et al 2024 SSRN http://dx.doi.org/10.2139/ssrn.4812343.\" \\ \"\\n\\nMore information can be found in:\" \\ \"\\n - GitHub webpage: https://github.com/gassraphael/AlphaPEM\" \\ \"\\n - Documentation webpage: to do\" \\ \"\\n\\nIf you want to contact me, please send an email to: gassraphael@proton.me.\" # 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)","title":"about"},{"location":"functions/GUI/#GUI.control_current_button","text":"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 ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in GUI.py 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)","title":"control_current_button"},{"location":"functions/GUI/#GUI.create_application","text":"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 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()","title":"create_application"},{"location":"functions/GUI/#GUI.main_frame","text":"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 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) # Create the choice dictionaries choice_operating_conditions = \\ {'Temperature - Tfc (\u00b0C)': {'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 - \u03a6a': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 4, 'label_column': 1}, 'Cathode humidity - \u03a6c': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 4, 'label_column': 3}} choice_accessible_parameters = \\ {'GDL thickness - Hgdl (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 1}, 'CL thickness - Hcl (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 3}, 'Membrane thickness - Hmem (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 5}, 'GC thickness - Hgc (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 1}, 'GC width - Wgc (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 3}, 'GC cumulated length - Lgc (m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 5}, 'Active area - Aact (cm\u00b2)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 3, 'label_column': 1}} choice_undetermined_parameters = \\ {'GDL porosity - \u03b5_gdl': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.6), 'label_row': 0, 'label_column': 1}, 'Ionomer volume fraction\\n- \u03b5_mc': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.25), 'label_row': 0, 'label_column': 3}, 'Tortuosity - \u03c4': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.5), 'label_row': 0, 'label_column': 5}, 'Compression ratio - \u03b5_c': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.2), 'label_row': 1, 'label_column': 1}, 'Capillary exponent - e': {'value': tk.IntVar(undetermined_parameters_frame, 4), 'label_row': 1, 'label_column': 3}, 'Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.0), 'label_row': 1, 'label_column': 5}, 'Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)': {'value': tk.DoubleVar(undetermined_parameters_frame, 3.0), 'label_row': 2, 'label_column': 1}, 'Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.0), 'label_row': 2, 'label_column': 3}, 'Overpotential correction\\nexponent - \u03ba_c': {'value': tk.DoubleVar(undetermined_parameters_frame, 2.0), 'label_row': 2, 'label_column': 5}, 'Limit liquid saturation\\ncoefficient - a_slim': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.05), 'label_row': 3, 'label_column': 1}, 'Limit liquid saturation\\ncoefficient - b_slim': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.1), 'label_row': 3, 'label_column': 3}, 'Limit liquid saturation\\ncoefficient - a_switch': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.7), 'label_row': 3, 'label_column': 5}, 'Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)': {'value': tk.DoubleVar(undetermined_parameters_frame, 20), 'label_row': 4, 'label_column': 1}} choice_current_density_parameters = \\ {'Initial time - t0_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 0), 'label_row': 0, 'label_column': 1}, 'Final time - tf_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 1000), 'label_row': 0, 'label_column': 3}, 'Loading time\\n- \u0394t_load_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 50), 'label_row': 0, 'label_column': 5}, 'Initial current density\\n- i_ini_step (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 1, 'label_column': 1}, 'Final current density\\n- i_final_step (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 1.5), 'label_row': 1, 'label_column': 3}, 'Loading time\\n- \u0394t_load_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 30), 'label_row': 2, 'label_column': 1}, 'Breaking time\\n- \u0394t_break_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 30), 'label_row': 2, 'label_column': 3}, 'Initial breaking time\\n- \u0394t_ini_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 60), 'label_row': 2, 'label_column': 5}, 'Maximum current density\\n- i_max_pola (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 3, 'label_column': 1}, 'Current density step\\n- \u0394i_pola (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.1), 'label_row': 3, 'label_column': 3}, 'Static current\\n- i_EIS (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 4, 'label_column': 1}, 'Current ratio\\n- ratio_EIS (%)': {'value': tk.DoubleVar(current_density_parameters_frame, 5), 'label_row': 4, 'label_column': 3}, 'Number of points\\ncalculated - nb_points_EIS': {'value': tk.IntVar(current_density_parameters_frame, 50), 'label_row': 4, 'label_column': 5}, 'Power of the\\ninitial frequency\\n- f_power_min_EIS': {'value': tk.IntVar(current_density_parameters_frame, -3), 'label_row': 5, 'label_column': 1}, 'Power of the\\nfinal frequency\\n- f_power_max_EIS': {'value': tk.IntVar(current_density_parameters_frame, 5), 'label_row': 5, 'label_column': 3}, 'Number of frequencies\\ntested - nb_f_EIS': {'value': tk.IntVar(current_density_parameters_frame, 60), 'label_row': 5, 'label_column': 5}} choice_computing_parameters = \\ {'Time for dynamic\\ndisplay - \u0394t_dyn_step (s)': {'value': tk.DoubleVar(computing_parameters_frame, 10), '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- \u0394t_purge (s)': {'value': tk.DoubleVar(computing_parameters_frame, 15), 'label_row': 0, 'label_column': 5}, 'Maximum time step\\n- max_step (s)': {'value': tk.DoubleVar(computing_parameters_frame, 0.1), 'label_row': 1, 'label_column': 1}, 'Number of GDL nodes - n_gdl': {'value': tk.IntVar(computing_parameters_frame, 10), 'label_row': 1, '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}, 'type_control': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 2}, 'type_purge': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 3}, 'type_display': {'value': tk.IntVar(model_possibilities_frame, 1), 'label_row': 4}, 'type_plot': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 5}} # 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)', 'Linhao Fan (2010)', 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=6, 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=6, 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=6, column=4, padx=10, pady=20) # About button ttk.Button(model_possibilities_frame, text='About', style='Black.TButton', command=about) \\ .grid(row=6, 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)","title":"main_frame"},{"location":"functions/GUI/#GUI.show_current_button","text":"This function determines the action to be performed based on the button_type. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in GUI.py 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. Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, Aact, Hgdl, Hcl, Hmem, Hgc, Wgc, Lgc, epsilon_gdl, \\ epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, t_step, \\ i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, t_purge, delta_t_purge, max_step, n_gdl, \\ type_fuel_cell, 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) if current_button == 0: type_current = \"step\" current_density = step_current launch_AlphaPEM_for_step_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) if current_button == 1: type_current = \"polarization\" current_density = polarization_current launch_AlphaPEM_for_polarization_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) if current_button == 2: type_current = \"EIS\" current_density = EIS_current launch_AlphaPEM_for_EIS_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot)","title":"show_current_button"},{"location":"functions/GUI/#GUI.toggle_info","text":"Toggles the visibility of the given frame and updates the scroll region of the given canvas. Parameters: frame ( Frame ) \u2013 The frame to show or hide. show_info ( BooleanVar ) \u2013 A boolean variable to track the current visibility state. canvas ( Canvas ) \u2013 The canvas to update the scroll region. Source code in GUI.py 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'))","title":"toggle_info"},{"location":"functions/main/","text":"main This file is designated for executing the AlphaPEM software package. Most of it should remain unaltered for regular program usage. In the section \"AlphaPEM settings\", users can select various preconfigured configurations for execution: the fuel cell, current density, auxiliary system, control strategy, purge, display and plot used. Adjustments to these configurations can be made within setting.py or current_densities.py and their associated files.","title":"Main"},{"location":"functions/main/#main","text":"This file is designated for executing the AlphaPEM software package. Most of it should remain unaltered for regular program usage. In the section \"AlphaPEM settings\", users can select various preconfigured configurations for execution: the fuel cell, current density, auxiliary system, control strategy, purge, display and plot used. Adjustments to these configurations can be made within setting.py or current_densities.py and their associated files.","title":"main"},{"location":"functions/calibration/experimental_values/","text":"Experimental values This file is designated for executing the AlphaPEM software package. plot_experimental_polarisation_curve(type_fuel_cell, i_fc_t, U_exp_t, ax) This function plots the experimental polarisation curve on the same graph as the model results. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. i_fc_t ( ndarray ) \u2013 Current density values. U_exp_t ( ndarray ) \u2013 Experimental values of the voltage. ax ( Axes ) \u2013 Axes object on which the experimental data is plotted. Source code in calibration/experimental_values.py def plot_experimental_polarisation_curve(type_fuel_cell, i_fc_t, U_exp_t, ax): \"\"\" This function plots the experimental polarisation curve on the same graph as the model results. Parameters ---------- type_fuel_cell : str Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. i_fc_t : numpy.ndarray Current density values. U_exp_t : numpy.ndarray Experimental values of the voltage. ax : matplotlib.axes.Axes Axes object on which the experimental data is plotted. \"\"\" if type_fuel_cell == \"EH-31_1.5\": # at 1.5 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"s\", color=\"black\", label=\"Exp. - P = 1.5 bar\") elif type_fuel_cell == \"EH-31_2.0\": # at 2.0 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"o\", color=\"black\", label=\"Exp. - P = 2.0 bar\") elif type_fuel_cell == \"EH-31_2.25\": # at 2.25 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"^\", color=\"black\", label=\"Exp. - P = 2.25 bar\") elif type_fuel_cell == \"EH-31_2.5\": # at 2.5 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=(5, 1), color=\"black\", label=\"Exp. - P = 2.5 bar\") elif type_fuel_cell == \"BX_1.0\": # at 1.0 atm ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"^\", color=\"black\", label=\"Exp. - P = 1.0 atm\") elif type_fuel_cell == \"BX_1.35\": # at 1.35 atm ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"s\", color=\"black\", label=\"Exp. - P = 1.35 atm\") elif type_fuel_cell == \"LF\": ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"s\", color=\"black\", label=\"Experimental data\") ax.legend(loc='best', markerscale=0.5) pola_exp_values(type_fuel_cell) This function returns the experimental values of polarisation curves made on different fuel cells at different operating conditions. The experimental values are used to compare the model results with the experimental data. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. Returns: i_exp_t ( ndarray ) \u2013 Experimental values of the current density. U_exp_t ( ndarray ) \u2013 Experimental values of the voltage. Source code in calibration/experimental_values.py def pola_exp_values(type_fuel_cell): \"\"\" This function returns the experimental values of polarisation curves made on different fuel cells at different operating conditions. The experimental values are used to compare the model results with the experimental data. Parameters ---------- type_fuel_cell : str Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. Returns ------- i_exp_t : numpy.ndarray Experimental values of the current density. U_exp_t : numpy.ndarray Experimental values of the voltage. \"\"\" if type_fuel_cell == \"EH-31_1.5\": # at 1.5 bar # Current density i_exp_t = np.zeros(37) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.050, 0.068, 0.089, 0.110, 0.147 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.185, 0.233, 0.293, 0.352, 0.395 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.455, 0.510, 0.556, 0.620, 0.672 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.738, 0.799, 0.850, 0.892, 0.942 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 1.039, 1.139, 1.212, 1.269, 1.360 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.432, 1.525, 1.604, 1.683, 1.765 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.878, 1.966, 2.050, 2.109, 2.151 i_exp_t[35], i_exp_t[36] = 2.188, 2.246 # Voltage U_exp_t = np.zeros(37) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.882, 0.865, 0.850, 0.834 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.823, 0.811, 0.794, 0.781, 0.772 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.761, 0.752, 0.745, 0.735, 0.728 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.719, 0.712, 0.706, 0.700, 0.694 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.681, 0.668, 0.660, 0.653, 0.641 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.634, 0.622, 0.610, 0.599, 0.586 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.570, 0.556, 0.540, 0.530, 0.521 U_exp_t[35], U_exp_t[36] = 0.513, 0.500 elif type_fuel_cell == \"EH-31_2.0\": # at 2.0 bar # Current density i_exp_t = np.zeros(49) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.050, 0.057, 0.079, 0.106, 0.135 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.171, 0.206, 0.242, 0.302, 0.346 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.395, 0.434, 0.476, 0.531, 0.570 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.623, 0.681, 0.731, 0.779, 0.822 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.868, 0.930, 0.976, 1.031, 1.090 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.134, 1.205, 1.242, 1.312, 1.358 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.403, 1.453, 1.501, 1.569, 1.634, i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.725, 1.786, 1.857, 1.924, 1.979 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.050, 2.125, 2.168, 2.214, 2.258 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48] = 2.308, 2.348, 2.413, 2.459 # Voltage U_exp_t = np.zeros(49) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.889, 0.874, 0.860, 0.853 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.845, 0.837, 0.830, 0.817, 0.808 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.800, 0.792, 0.786, 0.779, 0.772 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.765, 0.759, 0.753, 0.747, 0.742, U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.737, 0.730, 0.726, 0.720, 0.714, U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.710, 0.702, 0.698, 0.690, 0.684 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.679, 0.673, 0.668, 0.659, 0.651 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.640, 0.631, 0.620, 0.608, 0.598 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.586, 0.573, 0.565, 0.557, 0.548 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48] = 0.537, 0.528, 0.513, 0.502 elif type_fuel_cell == \"EH-31_2.25\": # at 2.25 bar # Current density i_exp_t = np.zeros(54) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.056, 0.095, 0.120, 0.138, 0.160 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.183, 0.218, 0.248, 0.279, 0.315 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.364, 0.409, 0.477, 0.536, 0.594 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.641, 0.697, 0.748, 0.809, 0.866 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.944, 1.011, 1.074, 1.142, 1.193 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.252, 1.322, 1.381, 1.442, 1.496 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.545, 1.599, 1.675, 1.746, 1.827 i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.868, 1.918, 2.004, 2.053, 2.114 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.156, 2.209, 2.257, 2.310, 2.356 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48], i_exp_t[49] = 2.403, 2.468, 2.513, 2.552, 2.600 i_exp_t[50], i_exp_t[51], i_exp_t[52], i_exp_t[53] = 2.636, 2.679, 2.728, 2.794 # Voltage U_exp_t = np.zeros(54) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.894, 0.882, 0.873, 0.867, 0.861 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.854, 0.847, 0.840, 0.834, 0.827 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.819, 0.812, 0.801, 0.793, 0.786 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.781, 0.775, 0.771, 0.764, 0.759 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.751, 0.746, 0.740, 0.734, 0.728 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.723, 0.715, 0.709, 0.703, 0.698 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.692, 0.686, 0.678, 0.670, 0.660 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.654, 0.647, 0.635, 0.628, 0.618 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.613, 0.604, 0.596, 0.587, 0.580 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48], U_exp_t[49] = 0.570, 0.559, 0.551, 0.545, 0.536 U_exp_t[50], U_exp_t[51], U_exp_t[52], U_exp_t[53] = 0.528, 0.520, 0.511, 0.497 elif type_fuel_cell == \"EH-31_2.5\": # at 2.5 bar # Current density i_exp_t = np.zeros(56) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.057, 0.070, 0.082, 0.101, 0.127 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.145, 0.168, 0.200, 0.234, 0.267 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.296, 0.331, 0.355, 0.388, 0.423 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.467, 0.527, 0.577, 0.632, 0.685 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.740, 0.789, 0.845, 0.898, 0.953 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.030, 1.124, 1.192, 1.254, 1.314 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.364, 1.434, 1.514, 1.587, 1.643 i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.707, 1.769, 1.826, 1.892, 1.972 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.040, 2.124, 2.192, 2.265, 2.358 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48], i_exp_t[49] = 2.429, 2.508, 2.572, 2.624, 2.691 i_exp_t[50], i_exp_t[51], i_exp_t[52], i_exp_t[53], i_exp_t[54] = 2.750, 2.822, 2.879, 2.918, 2.956 i_exp_t[55] = 2.988 # Voltage U_exp_t = np.zeros(56) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.892, 0.884, 0.875, 0.866 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.861, 0.856, 0.850, 0.845, 0.840 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.835, 0.829, 0.824, 0.820, 0.814 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.807, 0.800, 0.793, 0.787, 0.783 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.778, 0.775, 0.771, 0.767, 0.763 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.758, 0.750, 0.744, 0.738, 0.732 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.726, 0.719, 0.712, 0.703, 0.697 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.691, 0.685, 0.679, 0.672, 0.663 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.657, 0.648, 0.640, 0.632, 0.621 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48], U_exp_t[49] = 0.610, 0.600, 0.591, 0.584, 0.575 U_exp_t[50], U_exp_t[51], U_exp_t[52], U_exp_t[53], U_exp_t[54] = 0.566, 0.555, 0.546, 0.537, 0.531 U_exp_t[55] = 0.524 elif type_fuel_cell == \"BX_1.0\": # at 1.0 atm # Current density i_exp_t = np.zeros(9) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.00, 0.07, 0.17, 0.31, 0.48 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8] = 0.63, 0.74, 0.88, 0.99 # Voltage U_exp_t = np.zeros(9) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.97, 0.80, 0.75, 0.70, 0.65 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8] = 0.60, 0.55, 0.50, 0.44 elif type_fuel_cell == \"BX_1.35\": # at 1.35 atm # Current density i_exp_t = np.zeros(7) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3] = 0.00, 0.07, 0.23, 0.52 i_exp_t[4], i_exp_t[5], i_exp_t[6] = 0.86, 1.13, 1.35 # Voltage U_exp_t = np.zeros(7) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3] = 0.94, 0.80, 0.75, 0.70 U_exp_t[4], U_exp_t[5], U_exp_t[6] = 0.65, 0.60, 0.55 elif type_fuel_cell == \"LF\": # Current density i_exp_t = np.zeros(13) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.00, 0.04, 0.08, 0.16, 0.25 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.32, 0.39, 0.48, 0.64, 0.80 i_exp_t[10], i_exp_t[11], i_exp_t[12] = 1.00, 1.20, 1.40 # Voltage U_exp_t = np.zeros(13) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.98, 0.87, 0.84, 0.80, 0.77 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.74, 0.72, 0.69, 0.65, 0.60 U_exp_t[10], U_exp_t[11], U_exp_t[12] = 0.54, 0.46, 0.32 return i_exp_t, U_exp_t","title":"Experimental values"},{"location":"functions/calibration/experimental_values/#experimental-values","text":"This file is designated for executing the AlphaPEM software package.","title":"Experimental values"},{"location":"functions/calibration/experimental_values/#calibration.experimental_values.plot_experimental_polarisation_curve","text":"This function plots the experimental polarisation curve on the same graph as the model results. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. i_fc_t ( ndarray ) \u2013 Current density values. U_exp_t ( ndarray ) \u2013 Experimental values of the voltage. ax ( Axes ) \u2013 Axes object on which the experimental data is plotted. Source code in calibration/experimental_values.py def plot_experimental_polarisation_curve(type_fuel_cell, i_fc_t, U_exp_t, ax): \"\"\" This function plots the experimental polarisation curve on the same graph as the model results. Parameters ---------- type_fuel_cell : str Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. i_fc_t : numpy.ndarray Current density values. U_exp_t : numpy.ndarray Experimental values of the voltage. ax : matplotlib.axes.Axes Axes object on which the experimental data is plotted. \"\"\" if type_fuel_cell == \"EH-31_1.5\": # at 1.5 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"s\", color=\"black\", label=\"Exp. - P = 1.5 bar\") elif type_fuel_cell == \"EH-31_2.0\": # at 2.0 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"o\", color=\"black\", label=\"Exp. - P = 2.0 bar\") elif type_fuel_cell == \"EH-31_2.25\": # at 2.25 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"^\", color=\"black\", label=\"Exp. - P = 2.25 bar\") elif type_fuel_cell == \"EH-31_2.5\": # at 2.5 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=(5, 1), color=\"black\", label=\"Exp. - P = 2.5 bar\") elif type_fuel_cell == \"BX_1.0\": # at 1.0 atm ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"^\", color=\"black\", label=\"Exp. - P = 1.0 atm\") elif type_fuel_cell == \"BX_1.35\": # at 1.35 atm ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"s\", color=\"black\", label=\"Exp. - P = 1.35 atm\") elif type_fuel_cell == \"LF\": ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"s\", color=\"black\", label=\"Experimental data\") ax.legend(loc='best', markerscale=0.5)","title":"plot_experimental_polarisation_curve"},{"location":"functions/calibration/experimental_values/#calibration.experimental_values.pola_exp_values","text":"This function returns the experimental values of polarisation curves made on different fuel cells at different operating conditions. The experimental values are used to compare the model results with the experimental data. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. Returns: i_exp_t ( ndarray ) \u2013 Experimental values of the current density. U_exp_t ( ndarray ) \u2013 Experimental values of the voltage. Source code in calibration/experimental_values.py def pola_exp_values(type_fuel_cell): \"\"\" This function returns the experimental values of polarisation curves made on different fuel cells at different operating conditions. The experimental values are used to compare the model results with the experimental data. Parameters ---------- type_fuel_cell : str Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. Returns ------- i_exp_t : numpy.ndarray Experimental values of the current density. U_exp_t : numpy.ndarray Experimental values of the voltage. \"\"\" if type_fuel_cell == \"EH-31_1.5\": # at 1.5 bar # Current density i_exp_t = np.zeros(37) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.050, 0.068, 0.089, 0.110, 0.147 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.185, 0.233, 0.293, 0.352, 0.395 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.455, 0.510, 0.556, 0.620, 0.672 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.738, 0.799, 0.850, 0.892, 0.942 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 1.039, 1.139, 1.212, 1.269, 1.360 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.432, 1.525, 1.604, 1.683, 1.765 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.878, 1.966, 2.050, 2.109, 2.151 i_exp_t[35], i_exp_t[36] = 2.188, 2.246 # Voltage U_exp_t = np.zeros(37) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.882, 0.865, 0.850, 0.834 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.823, 0.811, 0.794, 0.781, 0.772 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.761, 0.752, 0.745, 0.735, 0.728 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.719, 0.712, 0.706, 0.700, 0.694 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.681, 0.668, 0.660, 0.653, 0.641 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.634, 0.622, 0.610, 0.599, 0.586 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.570, 0.556, 0.540, 0.530, 0.521 U_exp_t[35], U_exp_t[36] = 0.513, 0.500 elif type_fuel_cell == \"EH-31_2.0\": # at 2.0 bar # Current density i_exp_t = np.zeros(49) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.050, 0.057, 0.079, 0.106, 0.135 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.171, 0.206, 0.242, 0.302, 0.346 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.395, 0.434, 0.476, 0.531, 0.570 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.623, 0.681, 0.731, 0.779, 0.822 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.868, 0.930, 0.976, 1.031, 1.090 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.134, 1.205, 1.242, 1.312, 1.358 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.403, 1.453, 1.501, 1.569, 1.634, i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.725, 1.786, 1.857, 1.924, 1.979 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.050, 2.125, 2.168, 2.214, 2.258 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48] = 2.308, 2.348, 2.413, 2.459 # Voltage U_exp_t = np.zeros(49) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.889, 0.874, 0.860, 0.853 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.845, 0.837, 0.830, 0.817, 0.808 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.800, 0.792, 0.786, 0.779, 0.772 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.765, 0.759, 0.753, 0.747, 0.742, U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.737, 0.730, 0.726, 0.720, 0.714, U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.710, 0.702, 0.698, 0.690, 0.684 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.679, 0.673, 0.668, 0.659, 0.651 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.640, 0.631, 0.620, 0.608, 0.598 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.586, 0.573, 0.565, 0.557, 0.548 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48] = 0.537, 0.528, 0.513, 0.502 elif type_fuel_cell == \"EH-31_2.25\": # at 2.25 bar # Current density i_exp_t = np.zeros(54) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.056, 0.095, 0.120, 0.138, 0.160 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.183, 0.218, 0.248, 0.279, 0.315 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.364, 0.409, 0.477, 0.536, 0.594 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.641, 0.697, 0.748, 0.809, 0.866 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.944, 1.011, 1.074, 1.142, 1.193 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.252, 1.322, 1.381, 1.442, 1.496 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.545, 1.599, 1.675, 1.746, 1.827 i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.868, 1.918, 2.004, 2.053, 2.114 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.156, 2.209, 2.257, 2.310, 2.356 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48], i_exp_t[49] = 2.403, 2.468, 2.513, 2.552, 2.600 i_exp_t[50], i_exp_t[51], i_exp_t[52], i_exp_t[53] = 2.636, 2.679, 2.728, 2.794 # Voltage U_exp_t = np.zeros(54) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.894, 0.882, 0.873, 0.867, 0.861 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.854, 0.847, 0.840, 0.834, 0.827 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.819, 0.812, 0.801, 0.793, 0.786 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.781, 0.775, 0.771, 0.764, 0.759 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.751, 0.746, 0.740, 0.734, 0.728 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.723, 0.715, 0.709, 0.703, 0.698 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.692, 0.686, 0.678, 0.670, 0.660 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.654, 0.647, 0.635, 0.628, 0.618 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.613, 0.604, 0.596, 0.587, 0.580 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48], U_exp_t[49] = 0.570, 0.559, 0.551, 0.545, 0.536 U_exp_t[50], U_exp_t[51], U_exp_t[52], U_exp_t[53] = 0.528, 0.520, 0.511, 0.497 elif type_fuel_cell == \"EH-31_2.5\": # at 2.5 bar # Current density i_exp_t = np.zeros(56) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.057, 0.070, 0.082, 0.101, 0.127 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.145, 0.168, 0.200, 0.234, 0.267 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.296, 0.331, 0.355, 0.388, 0.423 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.467, 0.527, 0.577, 0.632, 0.685 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.740, 0.789, 0.845, 0.898, 0.953 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.030, 1.124, 1.192, 1.254, 1.314 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.364, 1.434, 1.514, 1.587, 1.643 i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.707, 1.769, 1.826, 1.892, 1.972 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.040, 2.124, 2.192, 2.265, 2.358 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48], i_exp_t[49] = 2.429, 2.508, 2.572, 2.624, 2.691 i_exp_t[50], i_exp_t[51], i_exp_t[52], i_exp_t[53], i_exp_t[54] = 2.750, 2.822, 2.879, 2.918, 2.956 i_exp_t[55] = 2.988 # Voltage U_exp_t = np.zeros(56) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.892, 0.884, 0.875, 0.866 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.861, 0.856, 0.850, 0.845, 0.840 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.835, 0.829, 0.824, 0.820, 0.814 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.807, 0.800, 0.793, 0.787, 0.783 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.778, 0.775, 0.771, 0.767, 0.763 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.758, 0.750, 0.744, 0.738, 0.732 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.726, 0.719, 0.712, 0.703, 0.697 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.691, 0.685, 0.679, 0.672, 0.663 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.657, 0.648, 0.640, 0.632, 0.621 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48], U_exp_t[49] = 0.610, 0.600, 0.591, 0.584, 0.575 U_exp_t[50], U_exp_t[51], U_exp_t[52], U_exp_t[53], U_exp_t[54] = 0.566, 0.555, 0.546, 0.537, 0.531 U_exp_t[55] = 0.524 elif type_fuel_cell == \"BX_1.0\": # at 1.0 atm # Current density i_exp_t = np.zeros(9) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.00, 0.07, 0.17, 0.31, 0.48 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8] = 0.63, 0.74, 0.88, 0.99 # Voltage U_exp_t = np.zeros(9) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.97, 0.80, 0.75, 0.70, 0.65 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8] = 0.60, 0.55, 0.50, 0.44 elif type_fuel_cell == \"BX_1.35\": # at 1.35 atm # Current density i_exp_t = np.zeros(7) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3] = 0.00, 0.07, 0.23, 0.52 i_exp_t[4], i_exp_t[5], i_exp_t[6] = 0.86, 1.13, 1.35 # Voltage U_exp_t = np.zeros(7) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3] = 0.94, 0.80, 0.75, 0.70 U_exp_t[4], U_exp_t[5], U_exp_t[6] = 0.65, 0.60, 0.55 elif type_fuel_cell == \"LF\": # Current density i_exp_t = np.zeros(13) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.00, 0.04, 0.08, 0.16, 0.25 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.32, 0.39, 0.48, 0.64, 0.80 i_exp_t[10], i_exp_t[11], i_exp_t[12] = 1.00, 1.20, 1.40 # Voltage U_exp_t = np.zeros(13) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.98, 0.87, 0.84, 0.80, 0.77 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.74, 0.72, 0.69, 0.65, 0.60 U_exp_t[10], U_exp_t[11], U_exp_t[12] = 0.54, 0.46, 0.32 return i_exp_t, U_exp_t","title":"pola_exp_values"},{"location":"functions/calibration/parameter_calibration/","text":"Parameter Calibration This file is designated for executing the undetermined parameters' calibration. Most of it should remain unaltered for regular program usage. Users can select here the fuel cell to calibrate, along with the undetermined parameters to modify, and the parameters for the Genetic Algorithm. The experimental fuel cell data are stored in the files calibration_modules.py and experimental_values.py. The parameters employed for the Genetic Algorithm here have proven to be effective, though not necessarily optimal.","title":"Parameter calibration"},{"location":"functions/calibration/parameter_calibration/#parameter-calibration","text":"This file is designated for executing the undetermined parameters' calibration. Most of it should remain unaltered for regular program usage. Users can select here the fuel cell to calibrate, along with the undetermined parameters to modify, and the parameters for the Genetic Algorithm. The experimental fuel cell data are stored in the files calibration_modules.py and experimental_values.py. The parameters employed for the Genetic Algorithm here have proven to be effective, though not necessarily optimal.","title":"Parameter Calibration"},{"location":"functions/configuration/current_densities/","text":"Current densities This file contains the functions that generate the current densities for the simulation. EIS_current(t, parameters) Represents a current density used for creating an EIS curve and Bode diagrams. The current density is first equilibrated at i_EIS A.m-2 from 0 to t0_EIS seconds using a step increase. Then, a sinusoidal perturbation is added to the current density. This perturbation has an amplitude of (ratio_EIS * i_EIS) A.m-2 and a frequency of f[n_inf] Hz. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The polarization current density at time t. Source code in configuration/current_densities.py def EIS_current(t, parameters): \"\"\" Represents a current density used for creating an EIS curve and Bode diagrams. The current density is first equilibrated at i_EIS A.m-2 from 0 to t0_EIS seconds using a step increase. Then, a sinusoidal perturbation is added to the current density. This perturbation has an amplitude of (ratio_EIS * i_EIS) A.m-2 and a frequency of f[n_inf] Hz. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The polarization current density at time t. \"\"\" # Initialisation i_EIS, ratio_EIS = parameters['i_EIS'], parameters['ratio_EIS'] # (A/m\u00b2, ). i_EIS is the current for which a # ratio_EIS perturbation is added. t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = parameters['t_EIS'] # It is the initial # EIS time after stack equilibrium, a list of time parameters which gives the beginning of each frequency # change, the final time, a list of time parameters which gives the estimated time for reaching equilibrium # at each frequency, and a list of time parameters which gives the estimated time for measuring the voltage # response at each frequency. f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = parameters['f_EIS'] # It is the power of the initial # frequency: f_min_EIS = 10**f_power_min_EIS, the power of the final frequency, the number of frequencies # tested and the number of points calculated per specific period. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is a list of all the frequency tested, # ranged logarithmically. # Current density for the EIS curve if t < t0_EIS: delta_t_ini = t0_EIS / 4 # s. It is the required time for elevating i_fc from 0 to i_EIS without starving the # cell. i_fc = i_EIS * (1.0 + np.tanh(4 * (t - 2 * (delta_t_ini / 2)) / delta_t_ini)) / 2 else: n_inf = np.where(t_new_start_EIS <= t)[0][-1] # It is the number of frequency changes which has been made so far. i_disruption = (ratio_EIS * i_EIS) * np.cos(2 * np.pi * f[n_inf] * t) i_fc = i_EIS + i_disruption return i_fc polarization_current(t, parameters) Represents a current density used for creating a polarization curve. Starting from 0, the current density increases by the value of delta_i_pola every delta_t, following C\u221e step current increments, until it reaches i_max_pola. Each increment lasts for delta_t_load_pola seconds. After each increment, there is a pause of delta_t_break_pola seconds to allow the stack to reach equilibrium. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The polarization current density at time t. Source code in configuration/current_densities.py def polarization_current(t, parameters): \"\"\"Represents a current density used for creating a polarization curve. Starting from 0, the current density increases by the value of delta_i_pola every delta_t, following C\u221e step current increments, until it reaches i_max_pola. Each increment lasts for delta_t_load_pola seconds. After each increment, there is a pause of delta_t_break_pola seconds to allow the stack to reach equilibrium. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The polarization current density at time t. \"\"\" # Initialisation delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = parameters['delta_pola'] # (s, s, A.m-2, s). It is the loading time, the breaking time, the current density # step, and the initial breaking time. i_max_pola = parameters['i_max_pola'] # A.m-2. It is the maximum current density for the polarization curve. delta_t = delta_t_load_pola + delta_t_break_pola # s. It is the time of one load. tf = delta_t_ini_pola + int(i_max_pola / delta_i_pola + 1) * delta_t # s. It is the duration of this polarization current. n = int(tf / delta_t) # . It is the number of loads made for this polarization current. # Current density for the polarization curve i_fc = 0 # A.m-2. Initialisation of the current density. if t < delta_t_ini_pola: # It is the initial break for having homogeneity inside the cell i_fc = 0 # before starting the measurements. else: for i in range(n): t_switch = delta_t * i # The current density value changes around this time. i_fc += delta_i_pola * (1.0 + np.tanh(4 * (t - delta_t_ini_pola - delta_t - t_switch - (delta_t_load_pola / 2)) / delta_t_load_pola)) / 2 return i_fc step_current(t, parameters) Represents a step change in current density. The current starts at 0 and smoothly stabilizes at i_ini_step A.m-2 in delta_t_load seconds. Around t_switch seconds, the current increases smoothly and stabilizes at i_final_step A.m-2 in delta_t_load seconds. This is a C\u221e function, which is advantageous for enhancing the overall stability of the results. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The step current density at time t. Source code in configuration/current_densities.py def step_current(t, parameters): \"\"\"Represents a step change in current density. The current starts at 0 and smoothly stabilizes at i_ini_step A.m-2 in delta_t_load seconds. Around t_switch seconds, the current increases smoothly and stabilizes at i_final_step A.m-2 in delta_t_load seconds. This is a C\u221e function, which is advantageous for enhancing the overall stability of the results. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The step current density at time t. \"\"\" # Initialisation t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = parameters['t_step'] # (s, s, s, s). It is the initial, final, # loading and dynamic time for display. i_ini_step, i_final_step = parameters['i_step'] # (A.m-2, A.m-2). It is the initial and final current density values. t_switch = tf_step // 2 # The current density value changes around this time. # Step current density i_fc = i_ini_step * (1.0 + np.tanh(4 * (t - 2 * (delta_t_load_step / 2)) / delta_t_load_step)) / 2 + \\ + (i_final_step - i_ini_step) * (1.0 + np.tanh(4 * (t - t_switch - (delta_t_load_step / 2)) / delta_t_load_step)) / 2 return i_fc","title":"Current densities"},{"location":"functions/configuration/current_densities/#current-densities","text":"This file contains the functions that generate the current densities for the simulation.","title":"Current densities"},{"location":"functions/configuration/current_densities/#configuration.current_densities.EIS_current","text":"Represents a current density used for creating an EIS curve and Bode diagrams. The current density is first equilibrated at i_EIS A.m-2 from 0 to t0_EIS seconds using a step increase. Then, a sinusoidal perturbation is added to the current density. This perturbation has an amplitude of (ratio_EIS * i_EIS) A.m-2 and a frequency of f[n_inf] Hz. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The polarization current density at time t. Source code in configuration/current_densities.py def EIS_current(t, parameters): \"\"\" Represents a current density used for creating an EIS curve and Bode diagrams. The current density is first equilibrated at i_EIS A.m-2 from 0 to t0_EIS seconds using a step increase. Then, a sinusoidal perturbation is added to the current density. This perturbation has an amplitude of (ratio_EIS * i_EIS) A.m-2 and a frequency of f[n_inf] Hz. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The polarization current density at time t. \"\"\" # Initialisation i_EIS, ratio_EIS = parameters['i_EIS'], parameters['ratio_EIS'] # (A/m\u00b2, ). i_EIS is the current for which a # ratio_EIS perturbation is added. t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = parameters['t_EIS'] # It is the initial # EIS time after stack equilibrium, a list of time parameters which gives the beginning of each frequency # change, the final time, a list of time parameters which gives the estimated time for reaching equilibrium # at each frequency, and a list of time parameters which gives the estimated time for measuring the voltage # response at each frequency. f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = parameters['f_EIS'] # It is the power of the initial # frequency: f_min_EIS = 10**f_power_min_EIS, the power of the final frequency, the number of frequencies # tested and the number of points calculated per specific period. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is a list of all the frequency tested, # ranged logarithmically. # Current density for the EIS curve if t < t0_EIS: delta_t_ini = t0_EIS / 4 # s. It is the required time for elevating i_fc from 0 to i_EIS without starving the # cell. i_fc = i_EIS * (1.0 + np.tanh(4 * (t - 2 * (delta_t_ini / 2)) / delta_t_ini)) / 2 else: n_inf = np.where(t_new_start_EIS <= t)[0][-1] # It is the number of frequency changes which has been made so far. i_disruption = (ratio_EIS * i_EIS) * np.cos(2 * np.pi * f[n_inf] * t) i_fc = i_EIS + i_disruption return i_fc","title":"EIS_current"},{"location":"functions/configuration/current_densities/#configuration.current_densities.polarization_current","text":"Represents a current density used for creating a polarization curve. Starting from 0, the current density increases by the value of delta_i_pola every delta_t, following C\u221e step current increments, until it reaches i_max_pola. Each increment lasts for delta_t_load_pola seconds. After each increment, there is a pause of delta_t_break_pola seconds to allow the stack to reach equilibrium. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The polarization current density at time t. Source code in configuration/current_densities.py def polarization_current(t, parameters): \"\"\"Represents a current density used for creating a polarization curve. Starting from 0, the current density increases by the value of delta_i_pola every delta_t, following C\u221e step current increments, until it reaches i_max_pola. Each increment lasts for delta_t_load_pola seconds. After each increment, there is a pause of delta_t_break_pola seconds to allow the stack to reach equilibrium. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The polarization current density at time t. \"\"\" # Initialisation delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = parameters['delta_pola'] # (s, s, A.m-2, s). It is the loading time, the breaking time, the current density # step, and the initial breaking time. i_max_pola = parameters['i_max_pola'] # A.m-2. It is the maximum current density for the polarization curve. delta_t = delta_t_load_pola + delta_t_break_pola # s. It is the time of one load. tf = delta_t_ini_pola + int(i_max_pola / delta_i_pola + 1) * delta_t # s. It is the duration of this polarization current. n = int(tf / delta_t) # . It is the number of loads made for this polarization current. # Current density for the polarization curve i_fc = 0 # A.m-2. Initialisation of the current density. if t < delta_t_ini_pola: # It is the initial break for having homogeneity inside the cell i_fc = 0 # before starting the measurements. else: for i in range(n): t_switch = delta_t * i # The current density value changes around this time. i_fc += delta_i_pola * (1.0 + np.tanh(4 * (t - delta_t_ini_pola - delta_t - t_switch - (delta_t_load_pola / 2)) / delta_t_load_pola)) / 2 return i_fc","title":"polarization_current"},{"location":"functions/configuration/current_densities/#configuration.current_densities.step_current","text":"Represents a step change in current density. The current starts at 0 and smoothly stabilizes at i_ini_step A.m-2 in delta_t_load seconds. Around t_switch seconds, the current increases smoothly and stabilizes at i_final_step A.m-2 in delta_t_load seconds. This is a C\u221e function, which is advantageous for enhancing the overall stability of the results. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The step current density at time t. Source code in configuration/current_densities.py def step_current(t, parameters): \"\"\"Represents a step change in current density. The current starts at 0 and smoothly stabilizes at i_ini_step A.m-2 in delta_t_load seconds. Around t_switch seconds, the current increases smoothly and stabilizes at i_final_step A.m-2 in delta_t_load seconds. This is a C\u221e function, which is advantageous for enhancing the overall stability of the results. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The step current density at time t. \"\"\" # Initialisation t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = parameters['t_step'] # (s, s, s, s). It is the initial, final, # loading and dynamic time for display. i_ini_step, i_final_step = parameters['i_step'] # (A.m-2, A.m-2). It is the initial and final current density values. t_switch = tf_step // 2 # The current density value changes around this time. # Step current density i_fc = i_ini_step * (1.0 + np.tanh(4 * (t - 2 * (delta_t_load_step / 2)) / delta_t_load_step)) / 2 + \\ + (i_final_step - i_ini_step) * (1.0 + np.tanh(4 * (t - t_switch - (delta_t_load_step / 2)) / delta_t_load_step)) / 2 return i_fc","title":"step_current"},{"location":"functions/configuration/settings/","text":"Settings This file is used to set the parameters of the fuel cell system. computing_parameters(type_current, Hgdl, Hcl) This function is used to set the computing parameters of the fuel cell system. Parameters: type_current ( str ) \u2013 Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in meters. Hcl ( float ) \u2013 Thickness of the anode or cathode catalyst layer in meters. Returns: max_step ( float ) \u2013 Maximum time step for the resolution of the system of differential equations. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. t_purge ( tuple ) \u2013 Time parameters for purging the system. It is a tuple containing the purge time 'purge_time' in seconds, and the time between two purges 'delta_purge' in seconds. Source code in configuration/settings.py def computing_parameters(type_current, Hgdl, Hcl): \"\"\"This function is used to set the computing parameters of the fuel cell system. Parameters ---------- type_current : str Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Hgdl : float Thickness of the gas diffusion layer in meters. Hcl : float Thickness of the anode or cathode catalyst layer in meters. Returns ------- max_step : float Maximum time step for the resolution of the system of differential equations. n_gdl : int Number of model nodes placed inside each GDL. t_purge : tuple Time parameters for purging the system. It is a tuple containing the purge time 'purge_time' in seconds, and the time between two purges 'delta_purge' in seconds. \"\"\" if type_current == \"polarization\": max_step = 0.1 # Once the undetermined parameters are at their optimal values, this max_step can be used. elif type_current == \"step\": max_step = 0.1 # it is good enough for having graphs without instabilities. else: max_step = 0.1 n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. # A good value is int(Hgdl/Hcl/2), which is usually around 10. t_purge = 0.6, 15 # (s, s). It is the time parameters for purging the system. return max_step, n_gdl, t_purge current_density_parameters(type_current) This function is used to set the parameters of the current density which is imposed to the fuel cell system. Parameters: type_current ( str ) \u2013 Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Returns: t_step ( tuple ) \u2013 Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step' in seconds, final time 'tf_step' in seconds, loading time 'delta_t_load_step' in seconds, and time for dynamic display 'delta_t_dyn_step' in seconds. i_step ( tuple ) \u2013 Current parameters for the step_current density function. It is a tuple containing the initial and final current density values 'i_ini_step' and 'i_final_step', both in A.m-2. delta_pola ( tuple ) \u2013 Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load_pola' in seconds, the breaking time 'delta_t_break_pola' in seconds, the current density step 'delta_i_pola' in A.m-2, and the initial breaking time 'delta_t_ini_pola' in seconds. i_EIS ( float ) \u2013 Parameters for the EIS curve. It is the current for which a perturbation is added. ratio_EIS ( float ) \u2013 Parameters for the EIS curve. It is the ratio of the current for which a perturbation is added. f_EIS ( tuple ) \u2013 Frequency parameters for the EIS_current density function. It is a tuple containing the power of the initial frequency 'f_power_min_EIS' (f_min_EIS = 10**f_power_min_EIS), the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS', and the number of points calculated per specific period 'nb_points_EIS'. t_EIS ( tuple ) \u2013 Time parameters for the EIS_current density function. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS' in seconds, a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS' in seconds, the final time 'tf_EIS' in seconds, a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS' in seconds, and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS' in seconds. current_density ( function ) \u2013 Current density function. Source code in configuration/settings.py def current_density_parameters(type_current): \"\"\"This function is used to set the parameters of the current density which is imposed to the fuel cell system. Parameters ---------- type_current : str Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Returns ------- t_step : tuple Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step' in seconds, final time 'tf_step' in seconds, loading time 'delta_t_load_step' in seconds, and time for dynamic display 'delta_t_dyn_step' in seconds. i_step : tuple Current parameters for the step_current density function. It is a tuple containing the initial and final current density values 'i_ini_step' and 'i_final_step', both in A.m-2. delta_pola : tuple Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load_pola' in seconds, the breaking time 'delta_t_break_pola' in seconds, the current density step 'delta_i_pola' in A.m-2, and the initial breaking time 'delta_t_ini_pola' in seconds. i_EIS : float Parameters for the EIS curve. It is the current for which a perturbation is added. ratio_EIS : float Parameters for the EIS curve. It is the ratio of the current for which a perturbation is added. f_EIS : tuple Frequency parameters for the EIS_current density function. It is a tuple containing the power of the initial frequency 'f_power_min_EIS' (f_min_EIS = 10**f_power_min_EIS), the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS', and the number of points calculated per specific period 'nb_points_EIS'. t_EIS : tuple Time parameters for the EIS_current density function. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS' in seconds, a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS' in seconds, the final time 'tf_EIS' in seconds, a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS' in seconds, and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS' in seconds. current_density : function Current density function. \"\"\" t_step = 0, 1000, 50, 10 # (s, s, s, s). Time parameters for the step_current density function. i_step = 0.5e4, 1.5e4 # (A.m-2, A.m-2). Current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 1 * 60 # (s, s, A.m-2, s). Parameters for the polarization curve. i_EIS, ratio_EIS = 1.0e4, 5/100 # (A/m\u00b2, ). Parameters for the EIS curve. f_EIS = -3, 5, 90, 50 # Frequency parameters for the EIS_current density function. t_EIS = EIS_parameters(f_EIS) # Time parameters for the EIS_current density function. if type_current == \"step\": current_density = step_current # It is the current density function. elif type_current == \"polarization\": current_density = polarization_current # It is the current density function. elif type_current == \"EIS\": current_density = EIS_current # It is the current density function. else: raise ValueError('You have to specify a type_current which is on the list.') return t_step, i_step, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, current_density operating_inputs(type_fuel_cell) This function is used to set the operating inputs of the fuel cell system. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve. Source code in configuration/settings.py def operating_inputs(type_fuel_cell): \"\"\"This function is used to set the operating inputs of the fuel cell system. Parameters ---------- type_fuel_cell : str Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_max_pola : float Maximum current density for the polarization curve. \"\"\" if type_fuel_cell == \"manual_setup\": # Setup which are not stored in \"stored_operating_inputs\". Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. else: # Stored setup in \"stored_operating_inputs\". Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola = stored_operating_inputs(type_fuel_cell) return Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola physical_parameters(type_fuel_cell) This function is used to set the physical parameters of the fuel cell system. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns: Hcl ( float ) \u2013 Thickness of the anode or cathode catalyst layer in meters. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the catalyst layer. tau ( float ) \u2013 Pore structure coefficient. Hmem ( float ) \u2013 Thickness of the membrane in meters. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in meters. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. Hgc ( float ) \u2013 Thickness of the gas channel in meters. Wgc ( float ) \u2013 Width of the gas channel in meters. Lgc ( float ) \u2013 Length of the gas channel in meters. Aact ( float ) \u2013 Active area of the catalyst layer in meters squared. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl ( float ) \u2013 Volumetric double layer capacitance in F.m-3. Source code in configuration/settings.py def physical_parameters(type_fuel_cell): \"\"\"This function is used to set the physical parameters of the fuel cell system. Parameters ---------- type_fuel_cell : str Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns ------- Hcl : float Thickness of the anode or cathode catalyst layer in meters. epsilon_mc : float Volume fraction of ionomer in the catalyst layer. tau : float Pore structure coefficient. Hmem : float Thickness of the membrane in meters. Hgdl : float Thickness of the gas diffusion layer in meters. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_c : float Compression ratio of the GDL. Hgc : float Thickness of the gas channel in meters. Wgc : float Width of the gas channel in meters. Lgc : float Length of the gas channel in meters. Aact : float Active area of the catalyst layer in meters squared. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl : float Volumetric double layer capacitance in F.m-3. \"\"\" if type_fuel_cell == \"manual_setup\": # Setup which are not stored in \"stored_physical_parameters\". # Fuel cell physical parameters: \ud835\udf14 (which are not controllable by the system) # Catalyst layer Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.3949198274842546 # It is the volume fraction of ionomer in the CL. tau = 1.015639135686993 # It is the pore structure coefficient, without units. # Membrane Hmem = 2e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.7011156494971454 # It is the anode/cathode GDL porosity. epsilon_c = 0.27052745219052654 # It is the compression ratio of the GDL. # Gas channel Hgc = 5e-4 # m. It is the thickness of the gas channel. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Interaction parameters between water and PEMFC structure e = 5.0 # It is the capillary exponent # Voltage polarization Re = 5.694464714060734e-07 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 2.787917581303015 # A.m-2. It is the reference exchange current density at the cathode. kappa_co = 29.793535549174077 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.6136446641573106 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0.0555312850726664, 0.10514269908118055, 0.6365424991141914 # It is the limit # liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. else: # Stored setup in \"stored_physical_parameters\". (Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl) = stored_physical_parameters(type_fuel_cell) return (Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl)","title":"Settings"},{"location":"functions/configuration/settings/#settings","text":"This file is used to set the parameters of the fuel cell system.","title":"Settings"},{"location":"functions/configuration/settings/#configuration.settings.computing_parameters","text":"This function is used to set the computing parameters of the fuel cell system. Parameters: type_current ( str ) \u2013 Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in meters. Hcl ( float ) \u2013 Thickness of the anode or cathode catalyst layer in meters. Returns: max_step ( float ) \u2013 Maximum time step for the resolution of the system of differential equations. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. t_purge ( tuple ) \u2013 Time parameters for purging the system. It is a tuple containing the purge time 'purge_time' in seconds, and the time between two purges 'delta_purge' in seconds. Source code in configuration/settings.py def computing_parameters(type_current, Hgdl, Hcl): \"\"\"This function is used to set the computing parameters of the fuel cell system. Parameters ---------- type_current : str Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Hgdl : float Thickness of the gas diffusion layer in meters. Hcl : float Thickness of the anode or cathode catalyst layer in meters. Returns ------- max_step : float Maximum time step for the resolution of the system of differential equations. n_gdl : int Number of model nodes placed inside each GDL. t_purge : tuple Time parameters for purging the system. It is a tuple containing the purge time 'purge_time' in seconds, and the time between two purges 'delta_purge' in seconds. \"\"\" if type_current == \"polarization\": max_step = 0.1 # Once the undetermined parameters are at their optimal values, this max_step can be used. elif type_current == \"step\": max_step = 0.1 # it is good enough for having graphs without instabilities. else: max_step = 0.1 n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. # A good value is int(Hgdl/Hcl/2), which is usually around 10. t_purge = 0.6, 15 # (s, s). It is the time parameters for purging the system. return max_step, n_gdl, t_purge","title":"computing_parameters"},{"location":"functions/configuration/settings/#configuration.settings.current_density_parameters","text":"This function is used to set the parameters of the current density which is imposed to the fuel cell system. Parameters: type_current ( str ) \u2013 Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Returns: t_step ( tuple ) \u2013 Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step' in seconds, final time 'tf_step' in seconds, loading time 'delta_t_load_step' in seconds, and time for dynamic display 'delta_t_dyn_step' in seconds. i_step ( tuple ) \u2013 Current parameters for the step_current density function. It is a tuple containing the initial and final current density values 'i_ini_step' and 'i_final_step', both in A.m-2. delta_pola ( tuple ) \u2013 Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load_pola' in seconds, the breaking time 'delta_t_break_pola' in seconds, the current density step 'delta_i_pola' in A.m-2, and the initial breaking time 'delta_t_ini_pola' in seconds. i_EIS ( float ) \u2013 Parameters for the EIS curve. It is the current for which a perturbation is added. ratio_EIS ( float ) \u2013 Parameters for the EIS curve. It is the ratio of the current for which a perturbation is added. f_EIS ( tuple ) \u2013 Frequency parameters for the EIS_current density function. It is a tuple containing the power of the initial frequency 'f_power_min_EIS' (f_min_EIS = 10**f_power_min_EIS), the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS', and the number of points calculated per specific period 'nb_points_EIS'. t_EIS ( tuple ) \u2013 Time parameters for the EIS_current density function. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS' in seconds, a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS' in seconds, the final time 'tf_EIS' in seconds, a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS' in seconds, and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS' in seconds. current_density ( function ) \u2013 Current density function. Source code in configuration/settings.py def current_density_parameters(type_current): \"\"\"This function is used to set the parameters of the current density which is imposed to the fuel cell system. Parameters ---------- type_current : str Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Returns ------- t_step : tuple Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step' in seconds, final time 'tf_step' in seconds, loading time 'delta_t_load_step' in seconds, and time for dynamic display 'delta_t_dyn_step' in seconds. i_step : tuple Current parameters for the step_current density function. It is a tuple containing the initial and final current density values 'i_ini_step' and 'i_final_step', both in A.m-2. delta_pola : tuple Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load_pola' in seconds, the breaking time 'delta_t_break_pola' in seconds, the current density step 'delta_i_pola' in A.m-2, and the initial breaking time 'delta_t_ini_pola' in seconds. i_EIS : float Parameters for the EIS curve. It is the current for which a perturbation is added. ratio_EIS : float Parameters for the EIS curve. It is the ratio of the current for which a perturbation is added. f_EIS : tuple Frequency parameters for the EIS_current density function. It is a tuple containing the power of the initial frequency 'f_power_min_EIS' (f_min_EIS = 10**f_power_min_EIS), the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS', and the number of points calculated per specific period 'nb_points_EIS'. t_EIS : tuple Time parameters for the EIS_current density function. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS' in seconds, a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS' in seconds, the final time 'tf_EIS' in seconds, a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS' in seconds, and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS' in seconds. current_density : function Current density function. \"\"\" t_step = 0, 1000, 50, 10 # (s, s, s, s). Time parameters for the step_current density function. i_step = 0.5e4, 1.5e4 # (A.m-2, A.m-2). Current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 1 * 60 # (s, s, A.m-2, s). Parameters for the polarization curve. i_EIS, ratio_EIS = 1.0e4, 5/100 # (A/m\u00b2, ). Parameters for the EIS curve. f_EIS = -3, 5, 90, 50 # Frequency parameters for the EIS_current density function. t_EIS = EIS_parameters(f_EIS) # Time parameters for the EIS_current density function. if type_current == \"step\": current_density = step_current # It is the current density function. elif type_current == \"polarization\": current_density = polarization_current # It is the current density function. elif type_current == \"EIS\": current_density = EIS_current # It is the current density function. else: raise ValueError('You have to specify a type_current which is on the list.') return t_step, i_step, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, current_density","title":"current_density_parameters"},{"location":"functions/configuration/settings/#configuration.settings.operating_inputs","text":"This function is used to set the operating inputs of the fuel cell system. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve. Source code in configuration/settings.py def operating_inputs(type_fuel_cell): \"\"\"This function is used to set the operating inputs of the fuel cell system. Parameters ---------- type_fuel_cell : str Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_max_pola : float Maximum current density for the polarization curve. \"\"\" if type_fuel_cell == \"manual_setup\": # Setup which are not stored in \"stored_operating_inputs\". Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. else: # Stored setup in \"stored_operating_inputs\". Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola = stored_operating_inputs(type_fuel_cell) return Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola","title":"operating_inputs"},{"location":"functions/configuration/settings/#configuration.settings.physical_parameters","text":"This function is used to set the physical parameters of the fuel cell system. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns: Hcl ( float ) \u2013 Thickness of the anode or cathode catalyst layer in meters. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the catalyst layer. tau ( float ) \u2013 Pore structure coefficient. Hmem ( float ) \u2013 Thickness of the membrane in meters. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in meters. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. Hgc ( float ) \u2013 Thickness of the gas channel in meters. Wgc ( float ) \u2013 Width of the gas channel in meters. Lgc ( float ) \u2013 Length of the gas channel in meters. Aact ( float ) \u2013 Active area of the catalyst layer in meters squared. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl ( float ) \u2013 Volumetric double layer capacitance in F.m-3. Source code in configuration/settings.py def physical_parameters(type_fuel_cell): \"\"\"This function is used to set the physical parameters of the fuel cell system. Parameters ---------- type_fuel_cell : str Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns ------- Hcl : float Thickness of the anode or cathode catalyst layer in meters. epsilon_mc : float Volume fraction of ionomer in the catalyst layer. tau : float Pore structure coefficient. Hmem : float Thickness of the membrane in meters. Hgdl : float Thickness of the gas diffusion layer in meters. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_c : float Compression ratio of the GDL. Hgc : float Thickness of the gas channel in meters. Wgc : float Width of the gas channel in meters. Lgc : float Length of the gas channel in meters. Aact : float Active area of the catalyst layer in meters squared. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl : float Volumetric double layer capacitance in F.m-3. \"\"\" if type_fuel_cell == \"manual_setup\": # Setup which are not stored in \"stored_physical_parameters\". # Fuel cell physical parameters: \ud835\udf14 (which are not controllable by the system) # Catalyst layer Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.3949198274842546 # It is the volume fraction of ionomer in the CL. tau = 1.015639135686993 # It is the pore structure coefficient, without units. # Membrane Hmem = 2e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.7011156494971454 # It is the anode/cathode GDL porosity. epsilon_c = 0.27052745219052654 # It is the compression ratio of the GDL. # Gas channel Hgc = 5e-4 # m. It is the thickness of the gas channel. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Interaction parameters between water and PEMFC structure e = 5.0 # It is the capillary exponent # Voltage polarization Re = 5.694464714060734e-07 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 2.787917581303015 # A.m-2. It is the reference exchange current density at the cathode. kappa_co = 29.793535549174077 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.6136446641573106 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0.0555312850726664, 0.10514269908118055, 0.6365424991141914 # It is the limit # liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. else: # Stored setup in \"stored_physical_parameters\". (Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl) = stored_physical_parameters(type_fuel_cell) return (Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl)","title":"physical_parameters"},{"location":"functions/model/AlphaPEM/","text":"AlphaPEM Objectives: Create an open-source software package to simulate the PEM fuel cell for control system applications. Authors: Rapha\u00ebl GASS, Zhongliang LI, Rachid OUTBIB, Samir JEMEI and Daniel HISSEL. This file describes the AlphaPEM class, which is a PEM fuel cell system simulator. The model is one-dimensional, dynamic, biphasic, and isothermal. It has been published in the following articles: - Gass et al 2024 J. Electrochem. Soc. https://doi.org/10.1149/1945-7111/ad305a - Gass et al 2024 SSRN http://dx.doi.org/10.2139/ssrn.4812343 AlphaPEM Source code in model/AlphaPEM.py class AlphaPEM: def __init__(self, current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values=None, time_interval=None): \"\"\"Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). initial_variable_values : list, optional Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval : list, optional Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. \"\"\" # Initialize the operating inputs and parameters dictionaries. self.operating_inputs = {'current_density': current_density, 'Tfc': Tfc, 'Pa_des': Pa_des, 'Pc_des': Pc_des, 'Sa': Sa, 'Sc': Sc, 'Phi_a_des': Phi_a_des, 'Phi_c_des': Phi_c_des} self.current_parameters = {'t_step': t_step, 'i_step': i_step, 'delta_pola': delta_pola, 'i_max_pola': i_max_pola, 'i_EIS': i_EIS, 'ratio_EIS': ratio_EIS, 't_EIS': t_EIS, 'f_EIS': f_EIS} self.accessible_physical_parameters = {'Aact': Aact, 'Hgdl': Hgdl, 'Hmem': Hmem, 'Hcl': Hcl, 'Hgc': Hgc, 'Wgc': Wgc, 'Lgc': Lgc} self.undetermined_physical_parameters = {'epsilon_gdl': epsilon_gdl, 'tau': tau, 'epsilon_mc': epsilon_mc, 'epsilon_c': epsilon_c, 'e': e, 'kappa_co': kappa_co, 'Re': Re, 'i0_c_ref': i0_c_ref, 'kappa_c': kappa_c, 'a_slim': a_slim, 'b_slim': b_slim, 'a_switch': a_switch, 'C_scl': C_scl} self.computing_parameters = {'max_step': max_step, 'n_gdl': n_gdl, 't_purge': t_purge, 'type_fuel_cell': type_fuel_cell, 'type_current': type_current, 'type_auxiliary': type_auxiliary, 'type_control': type_control, 'type_purge': type_purge, 'type_display': type_display, 'type_plot': type_plot} self.parameters = {**self.current_parameters, **self.accessible_physical_parameters, **self.undetermined_physical_parameters, **self.computing_parameters} if self.operating_inputs['Pa_des'] < Pext or self.operating_inputs['Pc_des'] < Pext: raise ValueError('The desired pressure is too low. It cannot be lower than the pressure outside the stack.') # Initialize the variables' dictionary. self.solver_variable_names = ['C_v_agc', 'C_v_agdl', 'C_v_acl', 'C_v_ccl', 'C_v_cgdl', 'C_v_cgc', 's_agdl', 's_acl', 's_ccl', 's_cgdl', 'lambda_acl', 'lambda_mem', 'lambda_ccl', 'C_H2_agc', 'C_H2_agdl', 'C_H2_acl', 'C_O2_ccl', 'C_O2_cgdl', 'C_O2_cgc', 'C_N2', 'eta_c', 'Pasm', 'Paem', 'Pcsm', 'Pcem', 'Phi_asm', 'Phi_aem', 'Phi_csm', 'Phi_cem', 'Wcp', 'Wa_inj', 'Wc_inj', 'Abp_a', 'Abp_c'] self.solver_variable_names_extension() # Several points are considered in each GDL and must be inserted into # the solver_variable_names. self.all_variable_names = self.solver_variable_names + ['t', 'Ucell', 'S_sorp_acl', 'S_sorp_ccl'] + \\ ['J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc', 'Phi_a_des', 'Phi_c_des'] self.variables = {key: [] for key in self.all_variable_names} # Initialize the control_variables dictionary. self.control_variables = {'t_control_Phi': self.parameters['t_step'][0], 'Phi_a_des': self.operating_inputs['Phi_a_des'], 'Phi_c_des': self.operating_inputs['Phi_c_des']} # Create the dynamic evolution. # Create time intervals if time_interval is not None: # Initial time interval may be given to the Simulator. self.time_interval = time_interval else: # If not, it is automatically generated. self.time_interval = self._create_time_interval() # Create the initial variable values if initial_variable_values is not None: # Initial variable values may be given to the Simulator. self.initial_variable_values = initial_variable_values else: # If not, they are generated considering an equilibrium at the operating inputs without current. self.initial_variable_values = self._create_initial_variable_values() # Resolution of the system of differential equations. event_negative.terminal = True # Integration is stopped if one of the crucial variables becomes negative. self.sol = solve_ivp(dydt, self.time_interval, self.initial_variable_values, method='BDF', max_step=self.parameters['max_step'], events=event_negative, args=(self.operating_inputs, self.parameters, self.solver_variable_names, self.control_variables)) # Recover the variable values calculated by the solver into the dictionary. self._recovery() # Calculate the cell voltage after computing the internal states of the cell. self.variables[\"Ucell\"].extend(calculate_cell_voltage(self.variables, self.operating_inputs, self.parameters)) def solver_variable_names_extension(self): \"\"\"Several points are considered in each GDL and must be inserted into the solver_variable_names. \"\"\" new_points_location = ['C_v_agdl', 'C_v_cgdl', 's_agdl', 's_cgdl', 'C_H2_agdl', 'C_O2_cgdl'] for variable in new_points_location: index = self.solver_variable_names.index(variable) # Delete the previous points self.solver_variable_names.pop(index) # Increase the number of points self.solver_variable_names[index:index] = [f'{variable}_{i}' for i in range(1, self.parameters['n_gdl'] + 1)] def _create_time_interval(self): \"\"\"Calculate the time intervals for numerical resolution, according to the current chosen, if it is not provided. Returns ------- list Time interval for numerical resolution. It is used when initial_variable_values == None. \"\"\" # Extraction of the parameters t_step, delta_pola, i_max_pola = self.parameters['t_step'], self.parameters['delta_pola'], self.parameters['i_max_pola'] type_current = self.parameters['type_current'] # Recovery of the good time interval if type_current == \"step\": t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = t_step t0_interval = t0_step tf_interval = tf_step elif type_current == \"polarization\": delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola t0_interval = 0 tf_interval = delta_t_ini_pola + int(i_max_pola / delta_i_pola + 1) * (delta_t_load_pola + delta_t_break_pola) else: # EIS time_interval is calculated in the main.py file. raise ValueError(\"Please enter a recognized type_current option for calculating the time interval.\") # To be reviewed self.control_variables['t_control_Phi'] = t0_interval return [t0_interval, tf_interval] def _create_initial_variable_values(self): \"\"\"Create the initial values of the solver variables if it is not provided. It is generated considering an equilibrium at the operating inputs without current. Returns ------- list Initial values of the solver variables. It is used when initial_variable_values == None. \"\"\" # Extraction of the operating inputs and parameters current_density, Tfc = self.operating_inputs['current_density'], self.operating_inputs['Tfc'] Pa_des, Pc_des = self.operating_inputs['Pa_des'], self.operating_inputs['Pc_des'] Phi_a_des, Phi_c_des = self.operating_inputs['Phi_a_des'], self.operating_inputs['Phi_c_des'] Hmem, kappa_co, i0_c_ref, = self.parameters['Hmem'], self.parameters['kappa_co'], self.parameters['i0_c_ref'] kappa_c = self.parameters['kappa_c'] a_slim, b_slim, a_switch = self.parameters['a_slim'], self.parameters['b_slim'], self.parameters['a_switch'] n_gdl = self.parameters['n_gdl'] # Mean value of the operating inputs Phi_des_moy = (Phi_a_des + Phi_c_des) / 2 P_des_moy = (Pa_des + Pc_des) / 2 # Initial fuel cell states # Intermediate values Psat_ini = 101325 * 10 ** (-2.1794 + 0.02953 * (Tfc - 273.15) - 9.1837e-5 * (Tfc - 273.15) ** 2 + 1.4454e-7 * (Tfc - 273.15) ** 3) slim = a_slim * (Pc_des / 1e5) + b_slim s_switch = a_switch * slim # Initial fuel cell states C_v_ini = Phi_des_moy * Psat_ini / (R * Tfc) # mol.m-3. It is the initial vapor concentration. C_H2_ini = (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial H2 concentration # in the fuel cell. C_O2_ini = yO2_ext * (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial O2 # concentration in the fuel cell. C_N2_ini = (1 - yO2_ext) * (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial N2 # concentration in the fuel cell. s_ini = 0 # It is the initial liquid water saturation in the fuel cell. lambda_mem_ini = lambda_eq(C_v_ini, s_ini, Tfc, Kshape) # It is the initial water # content in the fuel cell. i_fc_ini = current_density(self.time_interval[0], self.parameters) i_n_ini = 2 * F * R * Tfc / Hmem * C_H2_ini * k_H2(lambda_mem_ini, Tfc, kappa_co) + \\ 4 * F * R * Tfc / Hmem * C_O2_ini * k_O2(lambda_mem_ini, Tfc, kappa_co) f_drop_ini = 0.5 * (1.0 - np.tanh((4 * s_ini - 2 * slim - 2 * s_switch) / (slim - s_switch))) eta_c_ini = 1 / f_drop_ini * R * Tfc / (alpha_c * F) * \\ np.log((i_fc_ini + i_n_ini) / i0_c_ref * (C_O2ref / C_O2_ini) ** kappa_c) # It is the initial # cathode overpotential in the fuel cell. # Initial auxiliary system state Pasm_ini, Paem_ini = Pa_des, P_des_moy # Pa. It is the supply/exhaust manifold pressure at the anode side. Pcsm_ini, Pcem_ini = Pc_des, P_des_moy # Pa. It is the supply/exhaust manifold pressure at the cathode side. Phi_asm_ini, Phi_aem_ini = Phi_a_des, Phi_des_moy # It is the supply/exhaust manifold relative humidity # at the anode side. Phi_csm_ini, Phi_cem_ini = Phi_c_des, Phi_des_moy # It is the supply/exhaust manifold relative humidity # at the cathode side. Wcp_ini = 0 # kg.s-1. It is the flow rate of the air compressor. Wa_inj_ini = 0 # kg.s-1. It is the flow rate of the air compressor at the anode side. Wc_inj_ini = 0 # kg.s-1. It is the flow rate of the air compressor at the cathode side. Abp_a_ini = 0 # It is the throttle area of the back pressure valve at the anode. Abp_c_ini = 0 # It is the throttle area of the back pressure valve at the cathode. # Main variable initialization C_v_agc, C_v_agdl, C_v_acl, C_v_ccl, C_v_cgdl, C_v_cgc = [C_v_ini] * 6 s_agdl, s_acl, s_ccl, s_cgdl = [s_ini] * 4 s_boundary = 0 # Dirichlet boundary condition lambda_acl, lambda_mem, lambda_ccl = [lambda_mem_ini] * 3 C_H2_agc, C_H2_agdl, C_H2_acl = C_H2_ini, C_H2_ini, C_H2_ini C_O2_ccl, C_O2_cgdl, C_O2_cgc = C_O2_ini, C_O2_ini, C_O2_ini C_N2, eta_c = C_N2_ini, eta_c_ini Pasm, Paem, Pcsm, Pcem = Pasm_ini, Paem_ini, Pcsm_ini, Pcem_ini Phi_asm, Phi_aem, Phi_csm, Phi_cem = Phi_asm_ini, Phi_aem_ini, Phi_csm_ini, Phi_cem_ini Wcp, Wa_inj, Wc_inj, Abp_a, Abp_c = Wcp_ini, Wa_inj_ini, Wc_inj_ini, Abp_a_ini, Abp_c_ini # Gathering of the variables initial value into one list initial_variable_values = [C_v_agc] + [C_v_agdl] * n_gdl + [C_v_acl, C_v_ccl] + [C_v_cgdl] * n_gdl + \\ [C_v_cgc] + \\ [s_boundary] + [s_agdl] * (n_gdl - 1) + [s_acl, s_ccl] + [s_cgdl] * (n_gdl - 1) + \\ [s_boundary] + [lambda_acl, lambda_mem, lambda_ccl] + \\ [C_H2_agc] + [C_H2_agdl] * n_gdl + [C_H2_acl, C_O2_ccl] + [C_O2_cgdl] * n_gdl + \\ [C_O2_cgc, C_N2] + [eta_c] + \\ [Pasm, Paem, Pcsm, Pcem, Phi_asm, Phi_aem, Phi_csm, Phi_cem] + \\ [Wcp, Wa_inj, Wc_inj, Abp_a, Abp_c] return initial_variable_values def _recovery(self): \"\"\"Recover the values which have been calculated by the solver and add them into the variables' dictionary. However, the numerical resolution method does not, by design, recover all the internal states of the stack, even though they are calculated during this process. They therefore have to be recovered manually. \"\"\" # Recovery of the time span self.variables['t'].extend(list(self.sol.t)) # Recovery of the main variables dynamic evolution for index, key in enumerate(self.solver_variable_names): self.variables[key].extend(list(self.sol.y[index])) # Recovery of more variables # The control variables should be reinitialized. To be reviewed. if self.parameters['type_current'] == \"step\": self.control_variables['t_control_Phi'] = self.parameters['t_step'][0] else: self.control_variables['t_control_Phi'] = 0 self.control_variables['Phi_a_des'] = self.operating_inputs['Phi_a_des'] self.control_variables['Phi_c_des'] = self.operating_inputs['Phi_c_des'] for j in range(len(self.sol.t)): # For each time... # ... recovery of i_fc. i_fc = self.operating_inputs[\"current_density\"](self.variables['t'][j], self.parameters) # ... recovery of S_sorp_acl, S_sorp_ccl, Jmem_acl, Jmem_ccl, Pagc, Pcgc. last_solver_variables = {key: self.variables[key][j] for key in self.solver_variable_names} flows_recovery = calculate_flows(self.variables['t'][j], last_solver_variables, self.control_variables, i_fc, self.operating_inputs, self.parameters) for key in ['S_sorp_acl', 'S_sorp_ccl', 'J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc']: self.variables[key].append(flows_recovery[key]) # ... recovery of Phi_a_des and Phi_c_des. if self.parameters[\"type_control\"] == \"Phi_des\": sv = {'lambda_mem': self.variables['lambda_mem'][j], 's_ccl': self.variables['s_ccl'][j]} control_operating_conditions(self.variables['t'][j], sv, self.operating_inputs, self.parameters, self.control_variables) for key in ['Phi_a_des', 'Phi_c_des']: self.variables[key].append(self.control_variables[key]) def Display(self, ax1=None, ax2=None, ax3=None): \"\"\"Display the plots of the program. Parameters ---------- ax1 : matplotlib.axes.Axes, optional Axes for the first set of plots. The default is None. ax2 : matplotlib.axes.Axes, optional Axes for the second set of plots. The default is None. \"\"\" # Extraction of the operating inputs and parameters Tfc = self.operating_inputs['Tfc'] n_gdl, type_fuel_cell = self.parameters['n_gdl'], self.parameters['type_fuel_cell'] type_current, type_display = self.parameters['type_current'], self.parameters['type_display'] # Parameters' preparation n = len(self.variables['t']) subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 \\ else type_fuel_cell # Display if type_current == \"step\": if type_display == \"multiple\": figs, axes = zip(*[plt.subplots(figsize=(8, 8)) for _ in range(12)]) plot_ifc(self.variables, self.operating_inputs, self.parameters, n, axes[0]) plot_J(self.variables, self.parameters, axes[1]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, axes[2]) plot_lambda(self.variables, self.operating_inputs, self.parameters, axes[3]) plot_s(self.variables, self.operating_inputs, self.parameters, axes[4]) plot_C_O2(self.variables, n_gdl, axes[5]) plot_C_H2(self.variables, n_gdl, axes[6]) plot_C_N2(self.variables, axes[7]) plot_Ucell(self.variables, axes[8]) plot_P(self.variables, axes[9]) plot_Phi_a(self.variables, self.operating_inputs, axes[10]) plot_Phi_c(self.variables, self.operating_inputs, axes[11]) # Considering the number of plots, the saving instructions are made here and not in the main.py file. saving_instructions(\"results\", subfolder_name, \"step_current_ifc_1.pdf\", figs[0]) saving_instructions(\"results\", subfolder_name, \"step_current_J_1.pdf\", figs[1]) saving_instructions(\"results\", subfolder_name, \"step_current_Cv_1.pdf\", figs[2]) saving_instructions(\"results\", subfolder_name, \"step_current_lambda_1.pdf\", figs[3]) saving_instructions(\"results\", subfolder_name, \"step_current_s_1.pdf\", figs[4]) saving_instructions(\"results\", subfolder_name, \"step_current_C_O2_1.pdf\", figs[5]) saving_instructions(\"results\", subfolder_name, \"step_current_C_H2_1.pdf\", figs[6]) saving_instructions(\"results\", subfolder_name, \"step_current_C_N2_1.pdf\", figs[7]) saving_instructions(\"results\", subfolder_name, \"step_current_Ucell_1.pdf\", figs[8]) saving_instructions(\"results\", subfolder_name, \"step_current_P_1.pdf\", figs[9]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_a_1.pdf\", figs[10]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_c_1.pdf\", figs[11]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_ifc(self.variables, self.operating_inputs, self.parameters, n, ax1[0, 0]) plot_Ucell(self.variables, ax1[0, 1]) plot_J(self.variables, self.parameters, ax1[0, 2]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, ax1[1, 0]) plot_s(self.variables, self.operating_inputs, self.parameters, ax1[1, 1]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax1[1, 2]) plot_C_H2(self.variables, n_gdl, ax1[2, 0]) plot_C_O2(self.variables, n_gdl, ax1[2, 1]) plot_P(self.variables, ax1[2, 2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"polarization\": if type_display == \"multiple\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1[0]) plot_power_density_curve(self.variables, self.operating_inputs, self.parameters, n, ax1[1]) plot_cell_efficiency(self.variables, self.operating_inputs, self.parameters, n, ax1[2]) plot_Phi_des(self.variables, self.operating_inputs, self.parameters, ax2[0]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax2[1]) plot_s(self.variables, self.operating_inputs, self.parameters, ax2[2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"EIS\": if type_display == \"multiple\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax2) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax3) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1[0]) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax1[1]) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax1[2]) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode Display(ax1=None, ax2=None, ax3=None) Display the plots of the program. Parameters: ax1 ( Axes , default: None ) \u2013 Axes for the first set of plots. The default is None. ax2 ( Axes , default: None ) \u2013 Axes for the second set of plots. The default is None. Source code in model/AlphaPEM.py def Display(self, ax1=None, ax2=None, ax3=None): \"\"\"Display the plots of the program. Parameters ---------- ax1 : matplotlib.axes.Axes, optional Axes for the first set of plots. The default is None. ax2 : matplotlib.axes.Axes, optional Axes for the second set of plots. The default is None. \"\"\" # Extraction of the operating inputs and parameters Tfc = self.operating_inputs['Tfc'] n_gdl, type_fuel_cell = self.parameters['n_gdl'], self.parameters['type_fuel_cell'] type_current, type_display = self.parameters['type_current'], self.parameters['type_display'] # Parameters' preparation n = len(self.variables['t']) subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 \\ else type_fuel_cell # Display if type_current == \"step\": if type_display == \"multiple\": figs, axes = zip(*[plt.subplots(figsize=(8, 8)) for _ in range(12)]) plot_ifc(self.variables, self.operating_inputs, self.parameters, n, axes[0]) plot_J(self.variables, self.parameters, axes[1]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, axes[2]) plot_lambda(self.variables, self.operating_inputs, self.parameters, axes[3]) plot_s(self.variables, self.operating_inputs, self.parameters, axes[4]) plot_C_O2(self.variables, n_gdl, axes[5]) plot_C_H2(self.variables, n_gdl, axes[6]) plot_C_N2(self.variables, axes[7]) plot_Ucell(self.variables, axes[8]) plot_P(self.variables, axes[9]) plot_Phi_a(self.variables, self.operating_inputs, axes[10]) plot_Phi_c(self.variables, self.operating_inputs, axes[11]) # Considering the number of plots, the saving instructions are made here and not in the main.py file. saving_instructions(\"results\", subfolder_name, \"step_current_ifc_1.pdf\", figs[0]) saving_instructions(\"results\", subfolder_name, \"step_current_J_1.pdf\", figs[1]) saving_instructions(\"results\", subfolder_name, \"step_current_Cv_1.pdf\", figs[2]) saving_instructions(\"results\", subfolder_name, \"step_current_lambda_1.pdf\", figs[3]) saving_instructions(\"results\", subfolder_name, \"step_current_s_1.pdf\", figs[4]) saving_instructions(\"results\", subfolder_name, \"step_current_C_O2_1.pdf\", figs[5]) saving_instructions(\"results\", subfolder_name, \"step_current_C_H2_1.pdf\", figs[6]) saving_instructions(\"results\", subfolder_name, \"step_current_C_N2_1.pdf\", figs[7]) saving_instructions(\"results\", subfolder_name, \"step_current_Ucell_1.pdf\", figs[8]) saving_instructions(\"results\", subfolder_name, \"step_current_P_1.pdf\", figs[9]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_a_1.pdf\", figs[10]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_c_1.pdf\", figs[11]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_ifc(self.variables, self.operating_inputs, self.parameters, n, ax1[0, 0]) plot_Ucell(self.variables, ax1[0, 1]) plot_J(self.variables, self.parameters, ax1[0, 2]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, ax1[1, 0]) plot_s(self.variables, self.operating_inputs, self.parameters, ax1[1, 1]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax1[1, 2]) plot_C_H2(self.variables, n_gdl, ax1[2, 0]) plot_C_O2(self.variables, n_gdl, ax1[2, 1]) plot_P(self.variables, ax1[2, 2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"polarization\": if type_display == \"multiple\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1[0]) plot_power_density_curve(self.variables, self.operating_inputs, self.parameters, n, ax1[1]) plot_cell_efficiency(self.variables, self.operating_inputs, self.parameters, n, ax1[2]) plot_Phi_des(self.variables, self.operating_inputs, self.parameters, ax2[0]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax2[1]) plot_s(self.variables, self.operating_inputs, self.parameters, ax2[2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"EIS\": if type_display == \"multiple\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax2) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax3) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1[0]) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax1[1]) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax1[2]) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode __init__(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values=None, time_interval=None) Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). initial_variable_values ( list , default: None ) \u2013 Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval ( list , default: None ) \u2013 Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. Source code in model/AlphaPEM.py def __init__(self, current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values=None, time_interval=None): \"\"\"Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). initial_variable_values : list, optional Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval : list, optional Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. \"\"\" # Initialize the operating inputs and parameters dictionaries. self.operating_inputs = {'current_density': current_density, 'Tfc': Tfc, 'Pa_des': Pa_des, 'Pc_des': Pc_des, 'Sa': Sa, 'Sc': Sc, 'Phi_a_des': Phi_a_des, 'Phi_c_des': Phi_c_des} self.current_parameters = {'t_step': t_step, 'i_step': i_step, 'delta_pola': delta_pola, 'i_max_pola': i_max_pola, 'i_EIS': i_EIS, 'ratio_EIS': ratio_EIS, 't_EIS': t_EIS, 'f_EIS': f_EIS} self.accessible_physical_parameters = {'Aact': Aact, 'Hgdl': Hgdl, 'Hmem': Hmem, 'Hcl': Hcl, 'Hgc': Hgc, 'Wgc': Wgc, 'Lgc': Lgc} self.undetermined_physical_parameters = {'epsilon_gdl': epsilon_gdl, 'tau': tau, 'epsilon_mc': epsilon_mc, 'epsilon_c': epsilon_c, 'e': e, 'kappa_co': kappa_co, 'Re': Re, 'i0_c_ref': i0_c_ref, 'kappa_c': kappa_c, 'a_slim': a_slim, 'b_slim': b_slim, 'a_switch': a_switch, 'C_scl': C_scl} self.computing_parameters = {'max_step': max_step, 'n_gdl': n_gdl, 't_purge': t_purge, 'type_fuel_cell': type_fuel_cell, 'type_current': type_current, 'type_auxiliary': type_auxiliary, 'type_control': type_control, 'type_purge': type_purge, 'type_display': type_display, 'type_plot': type_plot} self.parameters = {**self.current_parameters, **self.accessible_physical_parameters, **self.undetermined_physical_parameters, **self.computing_parameters} if self.operating_inputs['Pa_des'] < Pext or self.operating_inputs['Pc_des'] < Pext: raise ValueError('The desired pressure is too low. It cannot be lower than the pressure outside the stack.') # Initialize the variables' dictionary. self.solver_variable_names = ['C_v_agc', 'C_v_agdl', 'C_v_acl', 'C_v_ccl', 'C_v_cgdl', 'C_v_cgc', 's_agdl', 's_acl', 's_ccl', 's_cgdl', 'lambda_acl', 'lambda_mem', 'lambda_ccl', 'C_H2_agc', 'C_H2_agdl', 'C_H2_acl', 'C_O2_ccl', 'C_O2_cgdl', 'C_O2_cgc', 'C_N2', 'eta_c', 'Pasm', 'Paem', 'Pcsm', 'Pcem', 'Phi_asm', 'Phi_aem', 'Phi_csm', 'Phi_cem', 'Wcp', 'Wa_inj', 'Wc_inj', 'Abp_a', 'Abp_c'] self.solver_variable_names_extension() # Several points are considered in each GDL and must be inserted into # the solver_variable_names. self.all_variable_names = self.solver_variable_names + ['t', 'Ucell', 'S_sorp_acl', 'S_sorp_ccl'] + \\ ['J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc', 'Phi_a_des', 'Phi_c_des'] self.variables = {key: [] for key in self.all_variable_names} # Initialize the control_variables dictionary. self.control_variables = {'t_control_Phi': self.parameters['t_step'][0], 'Phi_a_des': self.operating_inputs['Phi_a_des'], 'Phi_c_des': self.operating_inputs['Phi_c_des']} # Create the dynamic evolution. # Create time intervals if time_interval is not None: # Initial time interval may be given to the Simulator. self.time_interval = time_interval else: # If not, it is automatically generated. self.time_interval = self._create_time_interval() # Create the initial variable values if initial_variable_values is not None: # Initial variable values may be given to the Simulator. self.initial_variable_values = initial_variable_values else: # If not, they are generated considering an equilibrium at the operating inputs without current. self.initial_variable_values = self._create_initial_variable_values() # Resolution of the system of differential equations. event_negative.terminal = True # Integration is stopped if one of the crucial variables becomes negative. self.sol = solve_ivp(dydt, self.time_interval, self.initial_variable_values, method='BDF', max_step=self.parameters['max_step'], events=event_negative, args=(self.operating_inputs, self.parameters, self.solver_variable_names, self.control_variables)) # Recover the variable values calculated by the solver into the dictionary. self._recovery() # Calculate the cell voltage after computing the internal states of the cell. self.variables[\"Ucell\"].extend(calculate_cell_voltage(self.variables, self.operating_inputs, self.parameters)) solver_variable_names_extension() Several points are considered in each GDL and must be inserted into the solver_variable_names. Source code in model/AlphaPEM.py def solver_variable_names_extension(self): \"\"\"Several points are considered in each GDL and must be inserted into the solver_variable_names. \"\"\" new_points_location = ['C_v_agdl', 'C_v_cgdl', 's_agdl', 's_cgdl', 'C_H2_agdl', 'C_O2_cgdl'] for variable in new_points_location: index = self.solver_variable_names.index(variable) # Delete the previous points self.solver_variable_names.pop(index) # Increase the number of points self.solver_variable_names[index:index] = [f'{variable}_{i}' for i in range(1, self.parameters['n_gdl'] + 1)]","title":"AlphaPEM"},{"location":"functions/model/AlphaPEM/#alphapem","text":"Objectives: Create an open-source software package to simulate the PEM fuel cell for control system applications. Authors: Rapha\u00ebl GASS, Zhongliang LI, Rachid OUTBIB, Samir JEMEI and Daniel HISSEL. This file describes the AlphaPEM class, which is a PEM fuel cell system simulator. The model is one-dimensional, dynamic, biphasic, and isothermal. It has been published in the following articles: - Gass et al 2024 J. Electrochem. Soc. https://doi.org/10.1149/1945-7111/ad305a - Gass et al 2024 SSRN http://dx.doi.org/10.2139/ssrn.4812343","title":"AlphaPEM"},{"location":"functions/model/AlphaPEM/#model.AlphaPEM.AlphaPEM","text":"Source code in model/AlphaPEM.py class AlphaPEM: def __init__(self, current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values=None, time_interval=None): \"\"\"Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). initial_variable_values : list, optional Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval : list, optional Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. \"\"\" # Initialize the operating inputs and parameters dictionaries. self.operating_inputs = {'current_density': current_density, 'Tfc': Tfc, 'Pa_des': Pa_des, 'Pc_des': Pc_des, 'Sa': Sa, 'Sc': Sc, 'Phi_a_des': Phi_a_des, 'Phi_c_des': Phi_c_des} self.current_parameters = {'t_step': t_step, 'i_step': i_step, 'delta_pola': delta_pola, 'i_max_pola': i_max_pola, 'i_EIS': i_EIS, 'ratio_EIS': ratio_EIS, 't_EIS': t_EIS, 'f_EIS': f_EIS} self.accessible_physical_parameters = {'Aact': Aact, 'Hgdl': Hgdl, 'Hmem': Hmem, 'Hcl': Hcl, 'Hgc': Hgc, 'Wgc': Wgc, 'Lgc': Lgc} self.undetermined_physical_parameters = {'epsilon_gdl': epsilon_gdl, 'tau': tau, 'epsilon_mc': epsilon_mc, 'epsilon_c': epsilon_c, 'e': e, 'kappa_co': kappa_co, 'Re': Re, 'i0_c_ref': i0_c_ref, 'kappa_c': kappa_c, 'a_slim': a_slim, 'b_slim': b_slim, 'a_switch': a_switch, 'C_scl': C_scl} self.computing_parameters = {'max_step': max_step, 'n_gdl': n_gdl, 't_purge': t_purge, 'type_fuel_cell': type_fuel_cell, 'type_current': type_current, 'type_auxiliary': type_auxiliary, 'type_control': type_control, 'type_purge': type_purge, 'type_display': type_display, 'type_plot': type_plot} self.parameters = {**self.current_parameters, **self.accessible_physical_parameters, **self.undetermined_physical_parameters, **self.computing_parameters} if self.operating_inputs['Pa_des'] < Pext or self.operating_inputs['Pc_des'] < Pext: raise ValueError('The desired pressure is too low. It cannot be lower than the pressure outside the stack.') # Initialize the variables' dictionary. self.solver_variable_names = ['C_v_agc', 'C_v_agdl', 'C_v_acl', 'C_v_ccl', 'C_v_cgdl', 'C_v_cgc', 's_agdl', 's_acl', 's_ccl', 's_cgdl', 'lambda_acl', 'lambda_mem', 'lambda_ccl', 'C_H2_agc', 'C_H2_agdl', 'C_H2_acl', 'C_O2_ccl', 'C_O2_cgdl', 'C_O2_cgc', 'C_N2', 'eta_c', 'Pasm', 'Paem', 'Pcsm', 'Pcem', 'Phi_asm', 'Phi_aem', 'Phi_csm', 'Phi_cem', 'Wcp', 'Wa_inj', 'Wc_inj', 'Abp_a', 'Abp_c'] self.solver_variable_names_extension() # Several points are considered in each GDL and must be inserted into # the solver_variable_names. self.all_variable_names = self.solver_variable_names + ['t', 'Ucell', 'S_sorp_acl', 'S_sorp_ccl'] + \\ ['J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc', 'Phi_a_des', 'Phi_c_des'] self.variables = {key: [] for key in self.all_variable_names} # Initialize the control_variables dictionary. self.control_variables = {'t_control_Phi': self.parameters['t_step'][0], 'Phi_a_des': self.operating_inputs['Phi_a_des'], 'Phi_c_des': self.operating_inputs['Phi_c_des']} # Create the dynamic evolution. # Create time intervals if time_interval is not None: # Initial time interval may be given to the Simulator. self.time_interval = time_interval else: # If not, it is automatically generated. self.time_interval = self._create_time_interval() # Create the initial variable values if initial_variable_values is not None: # Initial variable values may be given to the Simulator. self.initial_variable_values = initial_variable_values else: # If not, they are generated considering an equilibrium at the operating inputs without current. self.initial_variable_values = self._create_initial_variable_values() # Resolution of the system of differential equations. event_negative.terminal = True # Integration is stopped if one of the crucial variables becomes negative. self.sol = solve_ivp(dydt, self.time_interval, self.initial_variable_values, method='BDF', max_step=self.parameters['max_step'], events=event_negative, args=(self.operating_inputs, self.parameters, self.solver_variable_names, self.control_variables)) # Recover the variable values calculated by the solver into the dictionary. self._recovery() # Calculate the cell voltage after computing the internal states of the cell. self.variables[\"Ucell\"].extend(calculate_cell_voltage(self.variables, self.operating_inputs, self.parameters)) def solver_variable_names_extension(self): \"\"\"Several points are considered in each GDL and must be inserted into the solver_variable_names. \"\"\" new_points_location = ['C_v_agdl', 'C_v_cgdl', 's_agdl', 's_cgdl', 'C_H2_agdl', 'C_O2_cgdl'] for variable in new_points_location: index = self.solver_variable_names.index(variable) # Delete the previous points self.solver_variable_names.pop(index) # Increase the number of points self.solver_variable_names[index:index] = [f'{variable}_{i}' for i in range(1, self.parameters['n_gdl'] + 1)] def _create_time_interval(self): \"\"\"Calculate the time intervals for numerical resolution, according to the current chosen, if it is not provided. Returns ------- list Time interval for numerical resolution. It is used when initial_variable_values == None. \"\"\" # Extraction of the parameters t_step, delta_pola, i_max_pola = self.parameters['t_step'], self.parameters['delta_pola'], self.parameters['i_max_pola'] type_current = self.parameters['type_current'] # Recovery of the good time interval if type_current == \"step\": t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = t_step t0_interval = t0_step tf_interval = tf_step elif type_current == \"polarization\": delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola t0_interval = 0 tf_interval = delta_t_ini_pola + int(i_max_pola / delta_i_pola + 1) * (delta_t_load_pola + delta_t_break_pola) else: # EIS time_interval is calculated in the main.py file. raise ValueError(\"Please enter a recognized type_current option for calculating the time interval.\") # To be reviewed self.control_variables['t_control_Phi'] = t0_interval return [t0_interval, tf_interval] def _create_initial_variable_values(self): \"\"\"Create the initial values of the solver variables if it is not provided. It is generated considering an equilibrium at the operating inputs without current. Returns ------- list Initial values of the solver variables. It is used when initial_variable_values == None. \"\"\" # Extraction of the operating inputs and parameters current_density, Tfc = self.operating_inputs['current_density'], self.operating_inputs['Tfc'] Pa_des, Pc_des = self.operating_inputs['Pa_des'], self.operating_inputs['Pc_des'] Phi_a_des, Phi_c_des = self.operating_inputs['Phi_a_des'], self.operating_inputs['Phi_c_des'] Hmem, kappa_co, i0_c_ref, = self.parameters['Hmem'], self.parameters['kappa_co'], self.parameters['i0_c_ref'] kappa_c = self.parameters['kappa_c'] a_slim, b_slim, a_switch = self.parameters['a_slim'], self.parameters['b_slim'], self.parameters['a_switch'] n_gdl = self.parameters['n_gdl'] # Mean value of the operating inputs Phi_des_moy = (Phi_a_des + Phi_c_des) / 2 P_des_moy = (Pa_des + Pc_des) / 2 # Initial fuel cell states # Intermediate values Psat_ini = 101325 * 10 ** (-2.1794 + 0.02953 * (Tfc - 273.15) - 9.1837e-5 * (Tfc - 273.15) ** 2 + 1.4454e-7 * (Tfc - 273.15) ** 3) slim = a_slim * (Pc_des / 1e5) + b_slim s_switch = a_switch * slim # Initial fuel cell states C_v_ini = Phi_des_moy * Psat_ini / (R * Tfc) # mol.m-3. It is the initial vapor concentration. C_H2_ini = (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial H2 concentration # in the fuel cell. C_O2_ini = yO2_ext * (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial O2 # concentration in the fuel cell. C_N2_ini = (1 - yO2_ext) * (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial N2 # concentration in the fuel cell. s_ini = 0 # It is the initial liquid water saturation in the fuel cell. lambda_mem_ini = lambda_eq(C_v_ini, s_ini, Tfc, Kshape) # It is the initial water # content in the fuel cell. i_fc_ini = current_density(self.time_interval[0], self.parameters) i_n_ini = 2 * F * R * Tfc / Hmem * C_H2_ini * k_H2(lambda_mem_ini, Tfc, kappa_co) + \\ 4 * F * R * Tfc / Hmem * C_O2_ini * k_O2(lambda_mem_ini, Tfc, kappa_co) f_drop_ini = 0.5 * (1.0 - np.tanh((4 * s_ini - 2 * slim - 2 * s_switch) / (slim - s_switch))) eta_c_ini = 1 / f_drop_ini * R * Tfc / (alpha_c * F) * \\ np.log((i_fc_ini + i_n_ini) / i0_c_ref * (C_O2ref / C_O2_ini) ** kappa_c) # It is the initial # cathode overpotential in the fuel cell. # Initial auxiliary system state Pasm_ini, Paem_ini = Pa_des, P_des_moy # Pa. It is the supply/exhaust manifold pressure at the anode side. Pcsm_ini, Pcem_ini = Pc_des, P_des_moy # Pa. It is the supply/exhaust manifold pressure at the cathode side. Phi_asm_ini, Phi_aem_ini = Phi_a_des, Phi_des_moy # It is the supply/exhaust manifold relative humidity # at the anode side. Phi_csm_ini, Phi_cem_ini = Phi_c_des, Phi_des_moy # It is the supply/exhaust manifold relative humidity # at the cathode side. Wcp_ini = 0 # kg.s-1. It is the flow rate of the air compressor. Wa_inj_ini = 0 # kg.s-1. It is the flow rate of the air compressor at the anode side. Wc_inj_ini = 0 # kg.s-1. It is the flow rate of the air compressor at the cathode side. Abp_a_ini = 0 # It is the throttle area of the back pressure valve at the anode. Abp_c_ini = 0 # It is the throttle area of the back pressure valve at the cathode. # Main variable initialization C_v_agc, C_v_agdl, C_v_acl, C_v_ccl, C_v_cgdl, C_v_cgc = [C_v_ini] * 6 s_agdl, s_acl, s_ccl, s_cgdl = [s_ini] * 4 s_boundary = 0 # Dirichlet boundary condition lambda_acl, lambda_mem, lambda_ccl = [lambda_mem_ini] * 3 C_H2_agc, C_H2_agdl, C_H2_acl = C_H2_ini, C_H2_ini, C_H2_ini C_O2_ccl, C_O2_cgdl, C_O2_cgc = C_O2_ini, C_O2_ini, C_O2_ini C_N2, eta_c = C_N2_ini, eta_c_ini Pasm, Paem, Pcsm, Pcem = Pasm_ini, Paem_ini, Pcsm_ini, Pcem_ini Phi_asm, Phi_aem, Phi_csm, Phi_cem = Phi_asm_ini, Phi_aem_ini, Phi_csm_ini, Phi_cem_ini Wcp, Wa_inj, Wc_inj, Abp_a, Abp_c = Wcp_ini, Wa_inj_ini, Wc_inj_ini, Abp_a_ini, Abp_c_ini # Gathering of the variables initial value into one list initial_variable_values = [C_v_agc] + [C_v_agdl] * n_gdl + [C_v_acl, C_v_ccl] + [C_v_cgdl] * n_gdl + \\ [C_v_cgc] + \\ [s_boundary] + [s_agdl] * (n_gdl - 1) + [s_acl, s_ccl] + [s_cgdl] * (n_gdl - 1) + \\ [s_boundary] + [lambda_acl, lambda_mem, lambda_ccl] + \\ [C_H2_agc] + [C_H2_agdl] * n_gdl + [C_H2_acl, C_O2_ccl] + [C_O2_cgdl] * n_gdl + \\ [C_O2_cgc, C_N2] + [eta_c] + \\ [Pasm, Paem, Pcsm, Pcem, Phi_asm, Phi_aem, Phi_csm, Phi_cem] + \\ [Wcp, Wa_inj, Wc_inj, Abp_a, Abp_c] return initial_variable_values def _recovery(self): \"\"\"Recover the values which have been calculated by the solver and add them into the variables' dictionary. However, the numerical resolution method does not, by design, recover all the internal states of the stack, even though they are calculated during this process. They therefore have to be recovered manually. \"\"\" # Recovery of the time span self.variables['t'].extend(list(self.sol.t)) # Recovery of the main variables dynamic evolution for index, key in enumerate(self.solver_variable_names): self.variables[key].extend(list(self.sol.y[index])) # Recovery of more variables # The control variables should be reinitialized. To be reviewed. if self.parameters['type_current'] == \"step\": self.control_variables['t_control_Phi'] = self.parameters['t_step'][0] else: self.control_variables['t_control_Phi'] = 0 self.control_variables['Phi_a_des'] = self.operating_inputs['Phi_a_des'] self.control_variables['Phi_c_des'] = self.operating_inputs['Phi_c_des'] for j in range(len(self.sol.t)): # For each time... # ... recovery of i_fc. i_fc = self.operating_inputs[\"current_density\"](self.variables['t'][j], self.parameters) # ... recovery of S_sorp_acl, S_sorp_ccl, Jmem_acl, Jmem_ccl, Pagc, Pcgc. last_solver_variables = {key: self.variables[key][j] for key in self.solver_variable_names} flows_recovery = calculate_flows(self.variables['t'][j], last_solver_variables, self.control_variables, i_fc, self.operating_inputs, self.parameters) for key in ['S_sorp_acl', 'S_sorp_ccl', 'J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc']: self.variables[key].append(flows_recovery[key]) # ... recovery of Phi_a_des and Phi_c_des. if self.parameters[\"type_control\"] == \"Phi_des\": sv = {'lambda_mem': self.variables['lambda_mem'][j], 's_ccl': self.variables['s_ccl'][j]} control_operating_conditions(self.variables['t'][j], sv, self.operating_inputs, self.parameters, self.control_variables) for key in ['Phi_a_des', 'Phi_c_des']: self.variables[key].append(self.control_variables[key]) def Display(self, ax1=None, ax2=None, ax3=None): \"\"\"Display the plots of the program. Parameters ---------- ax1 : matplotlib.axes.Axes, optional Axes for the first set of plots. The default is None. ax2 : matplotlib.axes.Axes, optional Axes for the second set of plots. The default is None. \"\"\" # Extraction of the operating inputs and parameters Tfc = self.operating_inputs['Tfc'] n_gdl, type_fuel_cell = self.parameters['n_gdl'], self.parameters['type_fuel_cell'] type_current, type_display = self.parameters['type_current'], self.parameters['type_display'] # Parameters' preparation n = len(self.variables['t']) subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 \\ else type_fuel_cell # Display if type_current == \"step\": if type_display == \"multiple\": figs, axes = zip(*[plt.subplots(figsize=(8, 8)) for _ in range(12)]) plot_ifc(self.variables, self.operating_inputs, self.parameters, n, axes[0]) plot_J(self.variables, self.parameters, axes[1]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, axes[2]) plot_lambda(self.variables, self.operating_inputs, self.parameters, axes[3]) plot_s(self.variables, self.operating_inputs, self.parameters, axes[4]) plot_C_O2(self.variables, n_gdl, axes[5]) plot_C_H2(self.variables, n_gdl, axes[6]) plot_C_N2(self.variables, axes[7]) plot_Ucell(self.variables, axes[8]) plot_P(self.variables, axes[9]) plot_Phi_a(self.variables, self.operating_inputs, axes[10]) plot_Phi_c(self.variables, self.operating_inputs, axes[11]) # Considering the number of plots, the saving instructions are made here and not in the main.py file. saving_instructions(\"results\", subfolder_name, \"step_current_ifc_1.pdf\", figs[0]) saving_instructions(\"results\", subfolder_name, \"step_current_J_1.pdf\", figs[1]) saving_instructions(\"results\", subfolder_name, \"step_current_Cv_1.pdf\", figs[2]) saving_instructions(\"results\", subfolder_name, \"step_current_lambda_1.pdf\", figs[3]) saving_instructions(\"results\", subfolder_name, \"step_current_s_1.pdf\", figs[4]) saving_instructions(\"results\", subfolder_name, \"step_current_C_O2_1.pdf\", figs[5]) saving_instructions(\"results\", subfolder_name, \"step_current_C_H2_1.pdf\", figs[6]) saving_instructions(\"results\", subfolder_name, \"step_current_C_N2_1.pdf\", figs[7]) saving_instructions(\"results\", subfolder_name, \"step_current_Ucell_1.pdf\", figs[8]) saving_instructions(\"results\", subfolder_name, \"step_current_P_1.pdf\", figs[9]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_a_1.pdf\", figs[10]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_c_1.pdf\", figs[11]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_ifc(self.variables, self.operating_inputs, self.parameters, n, ax1[0, 0]) plot_Ucell(self.variables, ax1[0, 1]) plot_J(self.variables, self.parameters, ax1[0, 2]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, ax1[1, 0]) plot_s(self.variables, self.operating_inputs, self.parameters, ax1[1, 1]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax1[1, 2]) plot_C_H2(self.variables, n_gdl, ax1[2, 0]) plot_C_O2(self.variables, n_gdl, ax1[2, 1]) plot_P(self.variables, ax1[2, 2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"polarization\": if type_display == \"multiple\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1[0]) plot_power_density_curve(self.variables, self.operating_inputs, self.parameters, n, ax1[1]) plot_cell_efficiency(self.variables, self.operating_inputs, self.parameters, n, ax1[2]) plot_Phi_des(self.variables, self.operating_inputs, self.parameters, ax2[0]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax2[1]) plot_s(self.variables, self.operating_inputs, self.parameters, ax2[2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"EIS\": if type_display == \"multiple\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax2) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax3) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1[0]) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax1[1]) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax1[2]) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode","title":"AlphaPEM"},{"location":"functions/model/AlphaPEM/#model.AlphaPEM.AlphaPEM.Display","text":"Display the plots of the program. Parameters: ax1 ( Axes , default: None ) \u2013 Axes for the first set of plots. The default is None. ax2 ( Axes , default: None ) \u2013 Axes for the second set of plots. The default is None. Source code in model/AlphaPEM.py def Display(self, ax1=None, ax2=None, ax3=None): \"\"\"Display the plots of the program. Parameters ---------- ax1 : matplotlib.axes.Axes, optional Axes for the first set of plots. The default is None. ax2 : matplotlib.axes.Axes, optional Axes for the second set of plots. The default is None. \"\"\" # Extraction of the operating inputs and parameters Tfc = self.operating_inputs['Tfc'] n_gdl, type_fuel_cell = self.parameters['n_gdl'], self.parameters['type_fuel_cell'] type_current, type_display = self.parameters['type_current'], self.parameters['type_display'] # Parameters' preparation n = len(self.variables['t']) subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 \\ else type_fuel_cell # Display if type_current == \"step\": if type_display == \"multiple\": figs, axes = zip(*[plt.subplots(figsize=(8, 8)) for _ in range(12)]) plot_ifc(self.variables, self.operating_inputs, self.parameters, n, axes[0]) plot_J(self.variables, self.parameters, axes[1]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, axes[2]) plot_lambda(self.variables, self.operating_inputs, self.parameters, axes[3]) plot_s(self.variables, self.operating_inputs, self.parameters, axes[4]) plot_C_O2(self.variables, n_gdl, axes[5]) plot_C_H2(self.variables, n_gdl, axes[6]) plot_C_N2(self.variables, axes[7]) plot_Ucell(self.variables, axes[8]) plot_P(self.variables, axes[9]) plot_Phi_a(self.variables, self.operating_inputs, axes[10]) plot_Phi_c(self.variables, self.operating_inputs, axes[11]) # Considering the number of plots, the saving instructions are made here and not in the main.py file. saving_instructions(\"results\", subfolder_name, \"step_current_ifc_1.pdf\", figs[0]) saving_instructions(\"results\", subfolder_name, \"step_current_J_1.pdf\", figs[1]) saving_instructions(\"results\", subfolder_name, \"step_current_Cv_1.pdf\", figs[2]) saving_instructions(\"results\", subfolder_name, \"step_current_lambda_1.pdf\", figs[3]) saving_instructions(\"results\", subfolder_name, \"step_current_s_1.pdf\", figs[4]) saving_instructions(\"results\", subfolder_name, \"step_current_C_O2_1.pdf\", figs[5]) saving_instructions(\"results\", subfolder_name, \"step_current_C_H2_1.pdf\", figs[6]) saving_instructions(\"results\", subfolder_name, \"step_current_C_N2_1.pdf\", figs[7]) saving_instructions(\"results\", subfolder_name, \"step_current_Ucell_1.pdf\", figs[8]) saving_instructions(\"results\", subfolder_name, \"step_current_P_1.pdf\", figs[9]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_a_1.pdf\", figs[10]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_c_1.pdf\", figs[11]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_ifc(self.variables, self.operating_inputs, self.parameters, n, ax1[0, 0]) plot_Ucell(self.variables, ax1[0, 1]) plot_J(self.variables, self.parameters, ax1[0, 2]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, ax1[1, 0]) plot_s(self.variables, self.operating_inputs, self.parameters, ax1[1, 1]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax1[1, 2]) plot_C_H2(self.variables, n_gdl, ax1[2, 0]) plot_C_O2(self.variables, n_gdl, ax1[2, 1]) plot_P(self.variables, ax1[2, 2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"polarization\": if type_display == \"multiple\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1[0]) plot_power_density_curve(self.variables, self.operating_inputs, self.parameters, n, ax1[1]) plot_cell_efficiency(self.variables, self.operating_inputs, self.parameters, n, ax1[2]) plot_Phi_des(self.variables, self.operating_inputs, self.parameters, ax2[0]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax2[1]) plot_s(self.variables, self.operating_inputs, self.parameters, ax2[2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"EIS\": if type_display == \"multiple\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax2) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax3) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1[0]) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax1[1]) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax1[2]) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode","title":"Display"},{"location":"functions/model/AlphaPEM/#model.AlphaPEM.AlphaPEM.__init__","text":"Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). initial_variable_values ( list , default: None ) \u2013 Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval ( list , default: None ) \u2013 Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. Source code in model/AlphaPEM.py def __init__(self, current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values=None, time_interval=None): \"\"\"Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). initial_variable_values : list, optional Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval : list, optional Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. \"\"\" # Initialize the operating inputs and parameters dictionaries. self.operating_inputs = {'current_density': current_density, 'Tfc': Tfc, 'Pa_des': Pa_des, 'Pc_des': Pc_des, 'Sa': Sa, 'Sc': Sc, 'Phi_a_des': Phi_a_des, 'Phi_c_des': Phi_c_des} self.current_parameters = {'t_step': t_step, 'i_step': i_step, 'delta_pola': delta_pola, 'i_max_pola': i_max_pola, 'i_EIS': i_EIS, 'ratio_EIS': ratio_EIS, 't_EIS': t_EIS, 'f_EIS': f_EIS} self.accessible_physical_parameters = {'Aact': Aact, 'Hgdl': Hgdl, 'Hmem': Hmem, 'Hcl': Hcl, 'Hgc': Hgc, 'Wgc': Wgc, 'Lgc': Lgc} self.undetermined_physical_parameters = {'epsilon_gdl': epsilon_gdl, 'tau': tau, 'epsilon_mc': epsilon_mc, 'epsilon_c': epsilon_c, 'e': e, 'kappa_co': kappa_co, 'Re': Re, 'i0_c_ref': i0_c_ref, 'kappa_c': kappa_c, 'a_slim': a_slim, 'b_slim': b_slim, 'a_switch': a_switch, 'C_scl': C_scl} self.computing_parameters = {'max_step': max_step, 'n_gdl': n_gdl, 't_purge': t_purge, 'type_fuel_cell': type_fuel_cell, 'type_current': type_current, 'type_auxiliary': type_auxiliary, 'type_control': type_control, 'type_purge': type_purge, 'type_display': type_display, 'type_plot': type_plot} self.parameters = {**self.current_parameters, **self.accessible_physical_parameters, **self.undetermined_physical_parameters, **self.computing_parameters} if self.operating_inputs['Pa_des'] < Pext or self.operating_inputs['Pc_des'] < Pext: raise ValueError('The desired pressure is too low. It cannot be lower than the pressure outside the stack.') # Initialize the variables' dictionary. self.solver_variable_names = ['C_v_agc', 'C_v_agdl', 'C_v_acl', 'C_v_ccl', 'C_v_cgdl', 'C_v_cgc', 's_agdl', 's_acl', 's_ccl', 's_cgdl', 'lambda_acl', 'lambda_mem', 'lambda_ccl', 'C_H2_agc', 'C_H2_agdl', 'C_H2_acl', 'C_O2_ccl', 'C_O2_cgdl', 'C_O2_cgc', 'C_N2', 'eta_c', 'Pasm', 'Paem', 'Pcsm', 'Pcem', 'Phi_asm', 'Phi_aem', 'Phi_csm', 'Phi_cem', 'Wcp', 'Wa_inj', 'Wc_inj', 'Abp_a', 'Abp_c'] self.solver_variable_names_extension() # Several points are considered in each GDL and must be inserted into # the solver_variable_names. self.all_variable_names = self.solver_variable_names + ['t', 'Ucell', 'S_sorp_acl', 'S_sorp_ccl'] + \\ ['J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc', 'Phi_a_des', 'Phi_c_des'] self.variables = {key: [] for key in self.all_variable_names} # Initialize the control_variables dictionary. self.control_variables = {'t_control_Phi': self.parameters['t_step'][0], 'Phi_a_des': self.operating_inputs['Phi_a_des'], 'Phi_c_des': self.operating_inputs['Phi_c_des']} # Create the dynamic evolution. # Create time intervals if time_interval is not None: # Initial time interval may be given to the Simulator. self.time_interval = time_interval else: # If not, it is automatically generated. self.time_interval = self._create_time_interval() # Create the initial variable values if initial_variable_values is not None: # Initial variable values may be given to the Simulator. self.initial_variable_values = initial_variable_values else: # If not, they are generated considering an equilibrium at the operating inputs without current. self.initial_variable_values = self._create_initial_variable_values() # Resolution of the system of differential equations. event_negative.terminal = True # Integration is stopped if one of the crucial variables becomes negative. self.sol = solve_ivp(dydt, self.time_interval, self.initial_variable_values, method='BDF', max_step=self.parameters['max_step'], events=event_negative, args=(self.operating_inputs, self.parameters, self.solver_variable_names, self.control_variables)) # Recover the variable values calculated by the solver into the dictionary. self._recovery() # Calculate the cell voltage after computing the internal states of the cell. self.variables[\"Ucell\"].extend(calculate_cell_voltage(self.variables, self.operating_inputs, self.parameters))","title":"__init__"},{"location":"functions/model/AlphaPEM/#model.AlphaPEM.AlphaPEM.solver_variable_names_extension","text":"Several points are considered in each GDL and must be inserted into the solver_variable_names. Source code in model/AlphaPEM.py def solver_variable_names_extension(self): \"\"\"Several points are considered in each GDL and must be inserted into the solver_variable_names. \"\"\" new_points_location = ['C_v_agdl', 'C_v_cgdl', 's_agdl', 's_cgdl', 'C_H2_agdl', 'C_O2_cgdl'] for variable in new_points_location: index = self.solver_variable_names.index(variable) # Delete the previous points self.solver_variable_names.pop(index) # Increase the number of points self.solver_variable_names[index:index] = [f'{variable}_{i}' for i in range(1, self.parameters['n_gdl'] + 1)]","title":"solver_variable_names_extension"},{"location":"functions/model/auxiliaries/","text":"Auxiliaries This file represents all the flows passing through the auxiliaries. It is a component of the fuel cell model. auxiliaries(t, solver_variables, control_variables, i_fc, operating_inputs, parameters) This function calculates the flows passing through the auxiliaries. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. i_fc ( float ) \u2013 Fuel cell current density at time t (A.m-2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Jv_a_in ( float ) \u2013 Vapor flow at the anode gas channel inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Vapor flow at the anode gas channel outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Vapor flow at the cathode gas channel inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Vapor flow at the cathode gas channel outlet (mol.m-2.s-1). J_H2_in ( float ) \u2013 H2 flow at the anode gas channel inlet (mol.m-2.s-1). J_H2_out ( float ) \u2013 H2 flow at the anode gas channel outlet (mol.m-2.s-1). J_O2_in ( float ) \u2013 O2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_O2_out ( float ) \u2013 O2 flow at the cathode gas channel outlet (mol.m-2.s-1). J_N2_in ( float ) \u2013 N2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_N2_out ( float ) \u2013 N2 flow at the cathode gas channel outlet (mol.m-2.s-1). Wasm_in ( float ) \u2013 Anode side supply manifold inlet flow (kg.s-1). Wasm_out ( float ) \u2013 Anode side supply manifold outlet flow (kg.s-1). Waem_in ( float ) \u2013 Anode side external manifold inlet flow (kg.s-1). Waem_out ( float ) \u2013 Anode side external manifold outlet flow (kg.s-1). Wcsm_in ( float ) \u2013 Cathode side supply manifold inlet flow (kg.s-1). Wcsm_out ( float ) \u2013 Cathode side supply manifold outlet flow (kg.s-1). Wcem_in ( float ) \u2013 Cathode side external manifold inlet flow (kg.s-1). Wcem_out ( float ) \u2013 Cathode side external manifold outlet flow (kg.s-1). Ware ( float ) \u2013 Anode side recirculation flow (kg.s-1). Wv_asm_in ( float ) \u2013 Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out ( float ) \u2013 Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in ( float ) \u2013 Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out ( float ) \u2013 Vapor flow at the cathode external manifold outlet (mol.s-1). Source code in model/auxiliaries.py def auxiliaries(t, solver_variables, control_variables, i_fc, operating_inputs, parameters): \"\"\"This function calculates the flows passing through the auxiliaries. Parameters ---------- t : float Time (s). solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. i_fc : float Fuel cell current density at time t (A.m-2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Jv_a_in : float Vapor flow at the anode gas channel inlet (mol.m-2.s-1). Jv_a_out : float Vapor flow at the anode gas channel outlet (mol.m-2.s-1). Jv_c_in : float Vapor flow at the cathode gas channel inlet (mol.m-2.s-1). Jv_c_out : float Vapor flow at the cathode gas channel outlet (mol.m-2.s-1). J_H2_in : float H2 flow at the anode gas channel inlet (mol.m-2.s-1). J_H2_out : float H2 flow at the anode gas channel outlet (mol.m-2.s-1). J_O2_in : float O2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_O2_out : float O2 flow at the cathode gas channel outlet (mol.m-2.s-1). J_N2_in : float N2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_N2_out : float N2 flow at the cathode gas channel outlet (mol.m-2.s-1). Wasm_in : float Anode side supply manifold inlet flow (kg.s-1). Wasm_out : float Anode side supply manifold outlet flow (kg.s-1). Waem_in : float Anode side external manifold inlet flow (kg.s-1). Waem_out : float Anode side external manifold outlet flow (kg.s-1). Wcsm_in : float Cathode side supply manifold inlet flow (kg.s-1). Wcsm_out : float Cathode side supply manifold outlet flow (kg.s-1). Wcem_in : float Cathode side external manifold inlet flow (kg.s-1). Wcem_out : float Cathode side external manifold outlet flow (kg.s-1). Ware : float Anode side recirculation flow (kg.s-1). Wv_asm_in : float Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out : float Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in : float Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out : float Vapor flow at the cathode external manifold outlet (mol.s-1). \"\"\" # __________________________________________________Preliminaries___________________________________________________ # Extraction of the variables Pasm, Paem, Pcsm = solver_variables['Pasm'], solver_variables['Paem'], solver_variables['Pcsm'] Pcem, Phi_asm, Phi_aem = solver_variables['Pcem'], solver_variables['Phi_asm'], solver_variables['Phi_aem'] Phi_csm, Phi_cem = solver_variables['Phi_csm'], solver_variables['Phi_cem'] Wcp, Wa_inj, Wc_inj = solver_variables['Wcp'], solver_variables['Wa_inj'], solver_variables['Wc_inj'] # Extraction of the operating inputs and the parameters Tfc, Pa_des, Pc_des = operating_inputs['Tfc'], operating_inputs['Pa_des'], operating_inputs['Pc_des'] Sa, Sc = operating_inputs['Sa'], operating_inputs['Sc'] Phi_a_des, Phi_c_des = control_variables['Phi_a_des'], control_variables['Phi_c_des'] Aact, Hgc, Wgc = parameters['Aact'], parameters['Hgc'], parameters['Wgc'] type_auxiliary = parameters['type_auxiliary'] # Intermediate values Mext, Pagc, Pcgc, Phi_agc, Phi_cgc, y_cgc, Magc, Mcgc, Pr_aem, Pr_cem, \\ Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c, i_n = \\ auxiliaries_int_values(t, solver_variables, operating_inputs, parameters) # _________________________________________Inlet and outlet global flows____________________________________________ \"\"\"Global flows here refer to flows that integrate all the chemical species circulating together. Slight differences are to be noted in the expression of these flows depending on the type of auxiliary selected. \"\"\" # At the anode side if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": # Anode inlet Wasm_in = Ksm_in * (Pa_des - Pasm) # kg.s-1 Wasm_out = Ksm_out * (Pasm - Pagc) # kg.s-1 Ja_in = Wasm_out / (Hgc * Wgc * Masm) # mol.m-2.s-1 # Anode outlet Waem_in = Kem_in * (Pagc - Paem) # kg.s-1 Ware = n_cell * Maem * (Paem / (Paem - Phi_aem * Psat(Tfc))) * (Sa - 1) * (i_fc + i_n) / ( 2 * F) * Aact # kg.s-1 Waem_out = k_purge * C_D * A_T * Paem / np.sqrt(R * Tfc) * Pr_aem ** (1 / gamma_H2) * \\ np.sqrt(Magc * 2 * gamma_H2 / (gamma_H2 - 1) * (1 - Pr_aem ** ((gamma_H2 - 1) / gamma_H2))) # kg.s-1 Ja_out = Waem_in / (Hgc * Wgc * Magc) # mol.m-2.s-1 elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Anode inlet Wrd = n_cell * M_H2 * Sa * (i_fc + i_n) / (2 * F) * Aact # kg.s-1 Wasm_in = Wrd + Wa_inj # kg.s-1 Wasm_out = Ksm_out * (Pasm - Pagc) # kg.s-1 Ja_in = Wasm_out / (Hgc * Wgc * Masm) # mol.m-2.s-1 # Anode outlet Waem_in = Kem_in * (Pagc - Paem) # kg.s-1 Ware = 0 # kg.s-1 Waem_out = C_D * Abp_a * Paem / np.sqrt(R * Tfc) * Pr_aem ** (1 / gamma_H2) * \\ np.sqrt(Magc * 2 * gamma_H2 / (gamma_H2 - 1) * (1 - Pr_aem ** ((gamma_H2 - 1) / gamma_H2))) # kg.s-1 Ja_out = Waem_in / (Hgc * Wgc * Magc) # mol.m-2.s-1 else: # elif type_auxiliary == \"no_auxiliary\" (only 1 cell): # Anode inlet Wasm_in, Wasm_out = 0, 0 # kg.s-1 Ja_in = (1 + Phi_a_des * Psat(Tfc) / (Pagc - Phi_a_des * Psat(Tfc))) * \\ Sa * (i_fc + i_n) / (2 * F) * Aact / (Hgc * Wgc) # mol.m-2.s-1 # Anode outlet Waem_in, Ware, Waem_out = 0, 0, 0 # kg.s-1 Ja_out = Kem_in * (Pagc - Pa_des) / (Hgc * Wgc * Magc) # mol.m-2.s-1 # At the cathode side if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Cathode inlet Wcsm_in = Wcp + Wc_inj # kg.s-1 Wcsm_out = Ksm_out * (Pcsm - Pcgc) # kg.s-1 Jc_in = Wcsm_out / (Hgc * Wgc * Mcsm) # mol.m-2.s-1 # Cathode outlet Wcem_in = Kem_in * (Pcgc - Pcem) # kg.s-1 Wcem_out = C_D * Abp_c * Pcem / np.sqrt(R * Tfc) * Pr_cem ** (1 / gamma) * \\ np.sqrt(Mcgc * 2 * gamma / (gamma - 1) * (1 - Pr_cem ** ((gamma - 1) / gamma))) # kg.s-1 Jc_out = Wcem_in / (Hgc * Wgc * Mcgc) # mol.m-2.s-1 else: # elif type_auxiliary == \"no_auxiliary\" (only 1 cell): # Cathode inlet Wcsm_in, Wcsm_out = 0, 0 # kg.s-1 Jc_in = (1 + Phi_c_des * Psat(Tfc) / (Pcgc - Phi_c_des * Psat(Tfc))) * \\ 1 / yO2_ext * Sc * (i_fc + i_n) / (4 * F) * Aact / (Hgc * Wgc) # mol.m-2.s-1 # Cathode outlet Wcem_in, Wcem_out = 0, 0 # kg.s-1 Jc_out = Kem_in * (Pcgc - Pc_des) / (Hgc * Wgc * Mcgc) # mol.m-2.s-1 # ________________________________________Inlet and outlet specific flows___________________________________________ \"\"\"Specific flows here refer to flows that integrate only a single chemical species within the ensemble of species circulating together. For example, only the water vapor flow within the ensemble of hydrogen and water vapor. \"\"\" # Vapor flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": Jv_a_in = Phi_asm * Psat(Tfc) / Pasm * Ja_in Jv_c_in = Phi_csm * Psat(Tfc) / Pcsm * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": Jv_a_in = Phi_a_des * Psat(Tfc) / Pagc * Ja_in Jv_c_in = Phi_c_des * Psat(Tfc) / Pcgc * Jc_in Jv_a_out = Phi_agc * Psat(Tfc) / Pagc * Ja_out Jv_c_out = Phi_cgc * Psat(Tfc) / Pcgc * Jc_out # H2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_H2_in = (1 - Phi_asm * Psat(Tfc) / Pasm) * Ja_in else: # elif type_auxiliary == \"no_auxiliary\": J_H2_in = (1 - Phi_a_des * Psat(Tfc) / Pagc) * Ja_in J_H2_out = (1 - Phi_agc * Psat(Tfc) / Pagc) * Ja_out # O2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_O2_in = yO2_ext * (1 - Phi_csm * Psat(Tfc) / Pcsm) * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": J_O2_in = yO2_ext * (1 - Phi_c_des * Psat(Tfc) / Pcgc) * Jc_in J_O2_out = y_cgc * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * Jc_out # N2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_N2_in = (1 - yO2_ext) * (1 - Phi_csm * Psat(Tfc) / Pcsm) * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": J_N2_in = (1 - yO2_ext) * (1 - Phi_c_des * Psat(Tfc) / Pcgc) * Jc_in J_N2_out = (1 - y_cgc) * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * Jc_out # Vapor flows at the manifold (mol.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": Wv_asm_in = Phi_aem * Psat(Tfc) / Paem * (Ware / Maem) Wv_aem_out = Phi_aem * Psat(Tfc) / Paem * (Waem_out / Maem) Wv_csm_in = Phi_ext * Psat(Text) / Pext * (Wcp / Mext) + Wc_inj / M_H2O Wv_cem_out = Phi_cem * Psat(Tfc) / Pcem * (Wcem_out / Mcem) elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": Wv_asm_in = Wa_inj / M_H2O Wv_aem_out = Phi_aem * Psat(Tfc) / Paem * (Waem_out / Maem) Wv_csm_in = Phi_ext * Psat(Text) / Pext * (Wcp / Mext) + Wc_inj / M_H2O Wv_cem_out = Phi_cem * Psat(Tfc) / Pcem * (Wcem_out / Mcem) else: # elif type_auxiliary == \"no_auxiliary\": Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out = [0] * 4 return Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, \\ J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, \\ Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, \\ Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out","title":"Auxiliaries"},{"location":"functions/model/auxiliaries/#auxiliaries","text":"This file represents all the flows passing through the auxiliaries. It is a component of the fuel cell model.","title":"Auxiliaries"},{"location":"functions/model/auxiliaries/#model.auxiliaries.auxiliaries","text":"This function calculates the flows passing through the auxiliaries. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. i_fc ( float ) \u2013 Fuel cell current density at time t (A.m-2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Jv_a_in ( float ) \u2013 Vapor flow at the anode gas channel inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Vapor flow at the anode gas channel outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Vapor flow at the cathode gas channel inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Vapor flow at the cathode gas channel outlet (mol.m-2.s-1). J_H2_in ( float ) \u2013 H2 flow at the anode gas channel inlet (mol.m-2.s-1). J_H2_out ( float ) \u2013 H2 flow at the anode gas channel outlet (mol.m-2.s-1). J_O2_in ( float ) \u2013 O2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_O2_out ( float ) \u2013 O2 flow at the cathode gas channel outlet (mol.m-2.s-1). J_N2_in ( float ) \u2013 N2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_N2_out ( float ) \u2013 N2 flow at the cathode gas channel outlet (mol.m-2.s-1). Wasm_in ( float ) \u2013 Anode side supply manifold inlet flow (kg.s-1). Wasm_out ( float ) \u2013 Anode side supply manifold outlet flow (kg.s-1). Waem_in ( float ) \u2013 Anode side external manifold inlet flow (kg.s-1). Waem_out ( float ) \u2013 Anode side external manifold outlet flow (kg.s-1). Wcsm_in ( float ) \u2013 Cathode side supply manifold inlet flow (kg.s-1). Wcsm_out ( float ) \u2013 Cathode side supply manifold outlet flow (kg.s-1). Wcem_in ( float ) \u2013 Cathode side external manifold inlet flow (kg.s-1). Wcem_out ( float ) \u2013 Cathode side external manifold outlet flow (kg.s-1). Ware ( float ) \u2013 Anode side recirculation flow (kg.s-1). Wv_asm_in ( float ) \u2013 Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out ( float ) \u2013 Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in ( float ) \u2013 Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out ( float ) \u2013 Vapor flow at the cathode external manifold outlet (mol.s-1). Source code in model/auxiliaries.py def auxiliaries(t, solver_variables, control_variables, i_fc, operating_inputs, parameters): \"\"\"This function calculates the flows passing through the auxiliaries. Parameters ---------- t : float Time (s). solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. i_fc : float Fuel cell current density at time t (A.m-2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Jv_a_in : float Vapor flow at the anode gas channel inlet (mol.m-2.s-1). Jv_a_out : float Vapor flow at the anode gas channel outlet (mol.m-2.s-1). Jv_c_in : float Vapor flow at the cathode gas channel inlet (mol.m-2.s-1). Jv_c_out : float Vapor flow at the cathode gas channel outlet (mol.m-2.s-1). J_H2_in : float H2 flow at the anode gas channel inlet (mol.m-2.s-1). J_H2_out : float H2 flow at the anode gas channel outlet (mol.m-2.s-1). J_O2_in : float O2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_O2_out : float O2 flow at the cathode gas channel outlet (mol.m-2.s-1). J_N2_in : float N2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_N2_out : float N2 flow at the cathode gas channel outlet (mol.m-2.s-1). Wasm_in : float Anode side supply manifold inlet flow (kg.s-1). Wasm_out : float Anode side supply manifold outlet flow (kg.s-1). Waem_in : float Anode side external manifold inlet flow (kg.s-1). Waem_out : float Anode side external manifold outlet flow (kg.s-1). Wcsm_in : float Cathode side supply manifold inlet flow (kg.s-1). Wcsm_out : float Cathode side supply manifold outlet flow (kg.s-1). Wcem_in : float Cathode side external manifold inlet flow (kg.s-1). Wcem_out : float Cathode side external manifold outlet flow (kg.s-1). Ware : float Anode side recirculation flow (kg.s-1). Wv_asm_in : float Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out : float Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in : float Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out : float Vapor flow at the cathode external manifold outlet (mol.s-1). \"\"\" # __________________________________________________Preliminaries___________________________________________________ # Extraction of the variables Pasm, Paem, Pcsm = solver_variables['Pasm'], solver_variables['Paem'], solver_variables['Pcsm'] Pcem, Phi_asm, Phi_aem = solver_variables['Pcem'], solver_variables['Phi_asm'], solver_variables['Phi_aem'] Phi_csm, Phi_cem = solver_variables['Phi_csm'], solver_variables['Phi_cem'] Wcp, Wa_inj, Wc_inj = solver_variables['Wcp'], solver_variables['Wa_inj'], solver_variables['Wc_inj'] # Extraction of the operating inputs and the parameters Tfc, Pa_des, Pc_des = operating_inputs['Tfc'], operating_inputs['Pa_des'], operating_inputs['Pc_des'] Sa, Sc = operating_inputs['Sa'], operating_inputs['Sc'] Phi_a_des, Phi_c_des = control_variables['Phi_a_des'], control_variables['Phi_c_des'] Aact, Hgc, Wgc = parameters['Aact'], parameters['Hgc'], parameters['Wgc'] type_auxiliary = parameters['type_auxiliary'] # Intermediate values Mext, Pagc, Pcgc, Phi_agc, Phi_cgc, y_cgc, Magc, Mcgc, Pr_aem, Pr_cem, \\ Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c, i_n = \\ auxiliaries_int_values(t, solver_variables, operating_inputs, parameters) # _________________________________________Inlet and outlet global flows____________________________________________ \"\"\"Global flows here refer to flows that integrate all the chemical species circulating together. Slight differences are to be noted in the expression of these flows depending on the type of auxiliary selected. \"\"\" # At the anode side if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": # Anode inlet Wasm_in = Ksm_in * (Pa_des - Pasm) # kg.s-1 Wasm_out = Ksm_out * (Pasm - Pagc) # kg.s-1 Ja_in = Wasm_out / (Hgc * Wgc * Masm) # mol.m-2.s-1 # Anode outlet Waem_in = Kem_in * (Pagc - Paem) # kg.s-1 Ware = n_cell * Maem * (Paem / (Paem - Phi_aem * Psat(Tfc))) * (Sa - 1) * (i_fc + i_n) / ( 2 * F) * Aact # kg.s-1 Waem_out = k_purge * C_D * A_T * Paem / np.sqrt(R * Tfc) * Pr_aem ** (1 / gamma_H2) * \\ np.sqrt(Magc * 2 * gamma_H2 / (gamma_H2 - 1) * (1 - Pr_aem ** ((gamma_H2 - 1) / gamma_H2))) # kg.s-1 Ja_out = Waem_in / (Hgc * Wgc * Magc) # mol.m-2.s-1 elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Anode inlet Wrd = n_cell * M_H2 * Sa * (i_fc + i_n) / (2 * F) * Aact # kg.s-1 Wasm_in = Wrd + Wa_inj # kg.s-1 Wasm_out = Ksm_out * (Pasm - Pagc) # kg.s-1 Ja_in = Wasm_out / (Hgc * Wgc * Masm) # mol.m-2.s-1 # Anode outlet Waem_in = Kem_in * (Pagc - Paem) # kg.s-1 Ware = 0 # kg.s-1 Waem_out = C_D * Abp_a * Paem / np.sqrt(R * Tfc) * Pr_aem ** (1 / gamma_H2) * \\ np.sqrt(Magc * 2 * gamma_H2 / (gamma_H2 - 1) * (1 - Pr_aem ** ((gamma_H2 - 1) / gamma_H2))) # kg.s-1 Ja_out = Waem_in / (Hgc * Wgc * Magc) # mol.m-2.s-1 else: # elif type_auxiliary == \"no_auxiliary\" (only 1 cell): # Anode inlet Wasm_in, Wasm_out = 0, 0 # kg.s-1 Ja_in = (1 + Phi_a_des * Psat(Tfc) / (Pagc - Phi_a_des * Psat(Tfc))) * \\ Sa * (i_fc + i_n) / (2 * F) * Aact / (Hgc * Wgc) # mol.m-2.s-1 # Anode outlet Waem_in, Ware, Waem_out = 0, 0, 0 # kg.s-1 Ja_out = Kem_in * (Pagc - Pa_des) / (Hgc * Wgc * Magc) # mol.m-2.s-1 # At the cathode side if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Cathode inlet Wcsm_in = Wcp + Wc_inj # kg.s-1 Wcsm_out = Ksm_out * (Pcsm - Pcgc) # kg.s-1 Jc_in = Wcsm_out / (Hgc * Wgc * Mcsm) # mol.m-2.s-1 # Cathode outlet Wcem_in = Kem_in * (Pcgc - Pcem) # kg.s-1 Wcem_out = C_D * Abp_c * Pcem / np.sqrt(R * Tfc) * Pr_cem ** (1 / gamma) * \\ np.sqrt(Mcgc * 2 * gamma / (gamma - 1) * (1 - Pr_cem ** ((gamma - 1) / gamma))) # kg.s-1 Jc_out = Wcem_in / (Hgc * Wgc * Mcgc) # mol.m-2.s-1 else: # elif type_auxiliary == \"no_auxiliary\" (only 1 cell): # Cathode inlet Wcsm_in, Wcsm_out = 0, 0 # kg.s-1 Jc_in = (1 + Phi_c_des * Psat(Tfc) / (Pcgc - Phi_c_des * Psat(Tfc))) * \\ 1 / yO2_ext * Sc * (i_fc + i_n) / (4 * F) * Aact / (Hgc * Wgc) # mol.m-2.s-1 # Cathode outlet Wcem_in, Wcem_out = 0, 0 # kg.s-1 Jc_out = Kem_in * (Pcgc - Pc_des) / (Hgc * Wgc * Mcgc) # mol.m-2.s-1 # ________________________________________Inlet and outlet specific flows___________________________________________ \"\"\"Specific flows here refer to flows that integrate only a single chemical species within the ensemble of species circulating together. For example, only the water vapor flow within the ensemble of hydrogen and water vapor. \"\"\" # Vapor flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": Jv_a_in = Phi_asm * Psat(Tfc) / Pasm * Ja_in Jv_c_in = Phi_csm * Psat(Tfc) / Pcsm * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": Jv_a_in = Phi_a_des * Psat(Tfc) / Pagc * Ja_in Jv_c_in = Phi_c_des * Psat(Tfc) / Pcgc * Jc_in Jv_a_out = Phi_agc * Psat(Tfc) / Pagc * Ja_out Jv_c_out = Phi_cgc * Psat(Tfc) / Pcgc * Jc_out # H2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_H2_in = (1 - Phi_asm * Psat(Tfc) / Pasm) * Ja_in else: # elif type_auxiliary == \"no_auxiliary\": J_H2_in = (1 - Phi_a_des * Psat(Tfc) / Pagc) * Ja_in J_H2_out = (1 - Phi_agc * Psat(Tfc) / Pagc) * Ja_out # O2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_O2_in = yO2_ext * (1 - Phi_csm * Psat(Tfc) / Pcsm) * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": J_O2_in = yO2_ext * (1 - Phi_c_des * Psat(Tfc) / Pcgc) * Jc_in J_O2_out = y_cgc * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * Jc_out # N2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_N2_in = (1 - yO2_ext) * (1 - Phi_csm * Psat(Tfc) / Pcsm) * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": J_N2_in = (1 - yO2_ext) * (1 - Phi_c_des * Psat(Tfc) / Pcgc) * Jc_in J_N2_out = (1 - y_cgc) * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * Jc_out # Vapor flows at the manifold (mol.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": Wv_asm_in = Phi_aem * Psat(Tfc) / Paem * (Ware / Maem) Wv_aem_out = Phi_aem * Psat(Tfc) / Paem * (Waem_out / Maem) Wv_csm_in = Phi_ext * Psat(Text) / Pext * (Wcp / Mext) + Wc_inj / M_H2O Wv_cem_out = Phi_cem * Psat(Tfc) / Pcem * (Wcem_out / Mcem) elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": Wv_asm_in = Wa_inj / M_H2O Wv_aem_out = Phi_aem * Psat(Tfc) / Paem * (Waem_out / Maem) Wv_csm_in = Phi_ext * Psat(Text) / Pext * (Wcp / Mext) + Wc_inj / M_H2O Wv_cem_out = Phi_cem * Psat(Tfc) / Pcem * (Wcem_out / Mcem) else: # elif type_auxiliary == \"no_auxiliary\": Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out = [0] * 4 return Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, \\ J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, \\ Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, \\ Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out","title":"auxiliaries"},{"location":"functions/model/cell_voltage/","text":"Cell voltage This file represents the equations for calculating the cell voltage. It is a component of the fuel cell model. calculate_cell_voltage(variables, operating_inputs, parameters) This function calculates the cell voltage at each time step. Parameters: variables ( dict ) \u2013 The dictionary containing the variables calculated by the solver. operating_inputs ( dict ) \u2013 The dictionary containing the operating inputs. parameters ( dict ) \u2013 The dictionary containing the parameters. Returns: Ucell_t ( list ) \u2013 The cell voltage at each time step. Source code in model/cell_voltage.py def calculate_cell_voltage(variables, operating_inputs, parameters): \"\"\"This function calculates the cell voltage at each time step. Parameters ---------- variables : dict The dictionary containing the variables calculated by the solver. operating_inputs : dict The dictionary containing the operating inputs. parameters : dict The dictionary containing the parameters. Returns ------- Ucell_t : list The cell voltage at each time step. \"\"\" # Extraction of the variables t, lambda_mem_t, lambda_ccl_t = variables['t'], variables['lambda_mem'], variables['lambda_ccl'] C_H2_acl_t, C_O2_ccl_t, eta_c_t = variables['C_H2_acl'], variables['C_O2_ccl'], variables['eta_c'] # Extraction of the operating inputs and the parameters Tfc = operating_inputs['Tfc'] Hmem, Hcl, epsilon_mc, tau = parameters['Hmem'], parameters['Hcl'], parameters['epsilon_mc'], parameters['tau'] Re, kappa_co = parameters['Re'], parameters['kappa_co'] # Initialisation n = len(t) Ucell_t = [0] * n # Loop for having Ucell_t at each time step for i in range(n): # Recovery of the already calculated variable values at each time step lambda_mem, lambda_ccl = lambda_mem_t[i], lambda_ccl_t[i] C_H2_acl, C_O2_ccl = C_H2_acl_t[i], C_O2_ccl_t[i] eta_c = eta_c_t[i] # Current density value at this time step i_fc = operating_inputs['current_density'](t[i], parameters) # The equilibrium potential Ueq = E0 - 8.5e-4 * (Tfc - 298.15) + R * Tfc / (2 * F) * (np.log(R * Tfc * C_H2_acl / Pref) + 0.5 * np.log(R * Tfc * C_O2_ccl / Pref)) # The crossover current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # The proton resistance # The proton resistance at the membrane : Rmem if lambda_mem >= 1: Rmem = Hmem / ((0.5139 * lambda_mem - 0.326) * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) else: Rmem = Hmem / (0.1879 * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) # The proton resistance at the cathode catalyst layer : Rccl if lambda_ccl >= 1: Rccl = 1 / 3 * 1 / (epsilon_mc / tau) * \\ Hcl / ((0.5139 * lambda_ccl - 0.326) * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) else: Rccl = 1 / 3 * 1 / (epsilon_mc / tau) * \\ Hcl / (0.1879 * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) # The total proton resistance Rp = Rmem + Rccl # its value is around [4-7]e-6 ohm.m\u00b2. # The cell voltage Ucell_t[i] = Ueq - eta_c - (i_fc + i_n) * (Rp + Re) return Ucell_t calculate_eta_c_intermediate_values(solver_variables, operating_inputs, parameters) This function calculates the intermediate values needed for the calculation of the cathode overpotential dynamic evolution. Parameters: solver_variables ( dict ) \u2013 The dictionary containing the variables calculated by the solver. operating_inputs ( dict ) \u2013 The dictionary containing the operating inputs. parameters ( dict ) \u2013 The dictionary containing the parameters. Returns: dict \u2013 The dictionary containing the crossover current density i_n at time t, and the liquid water induced voltage drop function f_drop at time t. Source code in model/cell_voltage.py def calculate_eta_c_intermediate_values(solver_variables, operating_inputs, parameters): \"\"\"This function calculates the intermediate values needed for the calculation of the cathode overpotential dynamic evolution. Parameters ---------- solver_variables : dict The dictionary containing the variables calculated by the solver. operating_inputs : dict The dictionary containing the operating inputs. parameters : dict The dictionary containing the parameters. Returns ------- dict The dictionary containing the crossover current density i_n at time t, and the liquid water induced voltage drop function f_drop at time t. \"\"\" # Extraction of the variables s_ccl, lambda_mem = solver_variables['s_ccl'], solver_variables['lambda_mem'] C_H2_acl, C_O2_ccl = solver_variables['C_H2_acl'], solver_variables['C_O2_ccl'] # Extraction of the operating inputs and the parameters Tfc, Pc_des = operating_inputs['Tfc'], operating_inputs['Pc_des'] Hmem = parameters['Hmem'] i0_c_ref, kappa_co, kappa_c = parameters['i0_c_ref'], parameters['kappa_co'], parameters['kappa_c'] a_slim, b_slim, a_switch = parameters['a_slim'], parameters['b_slim'], parameters['a_switch'] # The crossover current density i_n i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # The liquid water induced voltage drop function f_drop slim = a_slim * (Pc_des / 1e5) + b_slim s_switch = a_switch * slim f_drop = 0.5 * (1.0 - np.tanh((4 * s_ccl - 2 * slim - 2 * s_switch) / (slim - s_switch))) return {'i_n': i_n, 'f_drop': f_drop}","title":"Cell voltage"},{"location":"functions/model/cell_voltage/#cell-voltage","text":"This file represents the equations for calculating the cell voltage. It is a component of the fuel cell model.","title":"Cell voltage"},{"location":"functions/model/cell_voltage/#model.cell_voltage.calculate_cell_voltage","text":"This function calculates the cell voltage at each time step. Parameters: variables ( dict ) \u2013 The dictionary containing the variables calculated by the solver. operating_inputs ( dict ) \u2013 The dictionary containing the operating inputs. parameters ( dict ) \u2013 The dictionary containing the parameters. Returns: Ucell_t ( list ) \u2013 The cell voltage at each time step. Source code in model/cell_voltage.py def calculate_cell_voltage(variables, operating_inputs, parameters): \"\"\"This function calculates the cell voltage at each time step. Parameters ---------- variables : dict The dictionary containing the variables calculated by the solver. operating_inputs : dict The dictionary containing the operating inputs. parameters : dict The dictionary containing the parameters. Returns ------- Ucell_t : list The cell voltage at each time step. \"\"\" # Extraction of the variables t, lambda_mem_t, lambda_ccl_t = variables['t'], variables['lambda_mem'], variables['lambda_ccl'] C_H2_acl_t, C_O2_ccl_t, eta_c_t = variables['C_H2_acl'], variables['C_O2_ccl'], variables['eta_c'] # Extraction of the operating inputs and the parameters Tfc = operating_inputs['Tfc'] Hmem, Hcl, epsilon_mc, tau = parameters['Hmem'], parameters['Hcl'], parameters['epsilon_mc'], parameters['tau'] Re, kappa_co = parameters['Re'], parameters['kappa_co'] # Initialisation n = len(t) Ucell_t = [0] * n # Loop for having Ucell_t at each time step for i in range(n): # Recovery of the already calculated variable values at each time step lambda_mem, lambda_ccl = lambda_mem_t[i], lambda_ccl_t[i] C_H2_acl, C_O2_ccl = C_H2_acl_t[i], C_O2_ccl_t[i] eta_c = eta_c_t[i] # Current density value at this time step i_fc = operating_inputs['current_density'](t[i], parameters) # The equilibrium potential Ueq = E0 - 8.5e-4 * (Tfc - 298.15) + R * Tfc / (2 * F) * (np.log(R * Tfc * C_H2_acl / Pref) + 0.5 * np.log(R * Tfc * C_O2_ccl / Pref)) # The crossover current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # The proton resistance # The proton resistance at the membrane : Rmem if lambda_mem >= 1: Rmem = Hmem / ((0.5139 * lambda_mem - 0.326) * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) else: Rmem = Hmem / (0.1879 * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) # The proton resistance at the cathode catalyst layer : Rccl if lambda_ccl >= 1: Rccl = 1 / 3 * 1 / (epsilon_mc / tau) * \\ Hcl / ((0.5139 * lambda_ccl - 0.326) * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) else: Rccl = 1 / 3 * 1 / (epsilon_mc / tau) * \\ Hcl / (0.1879 * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) # The total proton resistance Rp = Rmem + Rccl # its value is around [4-7]e-6 ohm.m\u00b2. # The cell voltage Ucell_t[i] = Ueq - eta_c - (i_fc + i_n) * (Rp + Re) return Ucell_t","title":"calculate_cell_voltage"},{"location":"functions/model/cell_voltage/#model.cell_voltage.calculate_eta_c_intermediate_values","text":"This function calculates the intermediate values needed for the calculation of the cathode overpotential dynamic evolution. Parameters: solver_variables ( dict ) \u2013 The dictionary containing the variables calculated by the solver. operating_inputs ( dict ) \u2013 The dictionary containing the operating inputs. parameters ( dict ) \u2013 The dictionary containing the parameters. Returns: dict \u2013 The dictionary containing the crossover current density i_n at time t, and the liquid water induced voltage drop function f_drop at time t. Source code in model/cell_voltage.py def calculate_eta_c_intermediate_values(solver_variables, operating_inputs, parameters): \"\"\"This function calculates the intermediate values needed for the calculation of the cathode overpotential dynamic evolution. Parameters ---------- solver_variables : dict The dictionary containing the variables calculated by the solver. operating_inputs : dict The dictionary containing the operating inputs. parameters : dict The dictionary containing the parameters. Returns ------- dict The dictionary containing the crossover current density i_n at time t, and the liquid water induced voltage drop function f_drop at time t. \"\"\" # Extraction of the variables s_ccl, lambda_mem = solver_variables['s_ccl'], solver_variables['lambda_mem'] C_H2_acl, C_O2_ccl = solver_variables['C_H2_acl'], solver_variables['C_O2_ccl'] # Extraction of the operating inputs and the parameters Tfc, Pc_des = operating_inputs['Tfc'], operating_inputs['Pc_des'] Hmem = parameters['Hmem'] i0_c_ref, kappa_co, kappa_c = parameters['i0_c_ref'], parameters['kappa_co'], parameters['kappa_c'] a_slim, b_slim, a_switch = parameters['a_slim'], parameters['b_slim'], parameters['a_switch'] # The crossover current density i_n i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # The liquid water induced voltage drop function f_drop slim = a_slim * (Pc_des / 1e5) + b_slim s_switch = a_switch * slim f_drop = 0.5 * (1.0 - np.tanh((4 * s_ccl - 2 * slim - 2 * s_switch) / (slim - s_switch))) return {'i_n': i_n, 'f_drop': f_drop}","title":"calculate_eta_c_intermediate_values"},{"location":"functions/model/control/","text":"Control This module contains the function that control the operating conditions of the MEA system. control_operating_conditions(t, solver_variables, operating_inputs, parameters, control_variables) This function controls the operating conditions of the MEA system, if required. This is an elementary rule-based control, serving as a demonstrator. It will need to be improved in the future. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Dictionary containing the solver variables. operating_inputs ( dict ) \u2013 Dictionary containing the operating inputs. parameters ( dict ) \u2013 Dictionary containing the parameters. control_variables ( dict ) \u2013 Dictionary containing the control variables. Source code in model/control.py def control_operating_conditions(t, solver_variables, operating_inputs, parameters, control_variables): \"\"\"This function controls the operating conditions of the MEA system, if required. This is an elementary rule-based control, serving as a demonstrator. It will need to be improved in the future. Parameters ---------- t : float Time (s). solver_variables : dict Dictionary containing the solver variables. operating_inputs : dict Dictionary containing the operating inputs. parameters : dict Dictionary containing the parameters. control_variables : dict Dictionary containing the control variables. \"\"\" if parameters[\"type_control\"] != \"Phi_des\": raise ValueError('You have to specify a type_control which is accepted.') elif parameters[\"type_control\"] == \"Phi_des\": # Initialisation delta_t_control_Phi = 20 # s. Every delta_t_control_Phi second the cell humidity is controlled. delta_Phi_des = 0.01 # Arbitrary value for the step change of Phi_des. slim = parameters['a_slim'] * (operating_inputs['Pc_des'] / 1e5) + parameters['b_slim'] s_ccl_max = 0.55 * slim # An arbitrary margin for s_ccl is established to ensure the CCL is not too flooded. # I may take s_switch instead of 0.55 ? lambda_mem_min = 8 # An arbitrary margin for lambda_mem is established to ensure the membrane is not too dry. # Control on Phi_des # Every delta_t_control_Phi second, Phi_a_des is monitored for controlling the cell humidity. if t > (control_variables['t_control_Phi'] + delta_t_control_Phi): # s. control_variables['t_control_Phi'] = control_variables['t_control_Phi'] + delta_t_control_Phi # Flooding is likely. if solver_variables['s_ccl'] > s_ccl_max and solver_variables['lambda_mem'] > lambda_mem_min: if control_variables['Phi_a_des'] - delta_Phi_des >= 0: control_variables['Phi_a_des'] = control_variables['Phi_a_des'] - delta_Phi_des if control_variables['Phi_c_des'] - delta_Phi_des >= 0: control_variables['Phi_c_des'] = control_variables['Phi_c_des'] - delta_Phi_des # Drying out is likely. elif solver_variables['lambda_mem'] < lambda_mem_min and solver_variables['s_ccl'] < s_ccl_max: if control_variables['Phi_a_des'] + delta_Phi_des <= 1: control_variables['Phi_a_des'] = control_variables['Phi_a_des'] + delta_Phi_des if control_variables['Phi_c_des'] + delta_Phi_des <= 1: control_variables['Phi_c_des'] = control_variables['Phi_c_des'] + delta_Phi_des # Both flooding and drying out are likely. Nothing can be done. elif solver_variables['s_ccl'] > s_ccl_max and solver_variables['lambda_mem'] < lambda_mem_min: pass # Both flooding and drying out are unlikely. It is the desired situation. else: # elif solver_variables['s_ccl'] < s_ccl_max and solver_variables['lambda_mem'] > lambda_mem_min: pass","title":"Control"},{"location":"functions/model/control/#control","text":"This module contains the function that control the operating conditions of the MEA system.","title":"Control"},{"location":"functions/model/control/#model.control.control_operating_conditions","text":"This function controls the operating conditions of the MEA system, if required. This is an elementary rule-based control, serving as a demonstrator. It will need to be improved in the future. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Dictionary containing the solver variables. operating_inputs ( dict ) \u2013 Dictionary containing the operating inputs. parameters ( dict ) \u2013 Dictionary containing the parameters. control_variables ( dict ) \u2013 Dictionary containing the control variables. Source code in model/control.py def control_operating_conditions(t, solver_variables, operating_inputs, parameters, control_variables): \"\"\"This function controls the operating conditions of the MEA system, if required. This is an elementary rule-based control, serving as a demonstrator. It will need to be improved in the future. Parameters ---------- t : float Time (s). solver_variables : dict Dictionary containing the solver variables. operating_inputs : dict Dictionary containing the operating inputs. parameters : dict Dictionary containing the parameters. control_variables : dict Dictionary containing the control variables. \"\"\" if parameters[\"type_control\"] != \"Phi_des\": raise ValueError('You have to specify a type_control which is accepted.') elif parameters[\"type_control\"] == \"Phi_des\": # Initialisation delta_t_control_Phi = 20 # s. Every delta_t_control_Phi second the cell humidity is controlled. delta_Phi_des = 0.01 # Arbitrary value for the step change of Phi_des. slim = parameters['a_slim'] * (operating_inputs['Pc_des'] / 1e5) + parameters['b_slim'] s_ccl_max = 0.55 * slim # An arbitrary margin for s_ccl is established to ensure the CCL is not too flooded. # I may take s_switch instead of 0.55 ? lambda_mem_min = 8 # An arbitrary margin for lambda_mem is established to ensure the membrane is not too dry. # Control on Phi_des # Every delta_t_control_Phi second, Phi_a_des is monitored for controlling the cell humidity. if t > (control_variables['t_control_Phi'] + delta_t_control_Phi): # s. control_variables['t_control_Phi'] = control_variables['t_control_Phi'] + delta_t_control_Phi # Flooding is likely. if solver_variables['s_ccl'] > s_ccl_max and solver_variables['lambda_mem'] > lambda_mem_min: if control_variables['Phi_a_des'] - delta_Phi_des >= 0: control_variables['Phi_a_des'] = control_variables['Phi_a_des'] - delta_Phi_des if control_variables['Phi_c_des'] - delta_Phi_des >= 0: control_variables['Phi_c_des'] = control_variables['Phi_c_des'] - delta_Phi_des # Drying out is likely. elif solver_variables['lambda_mem'] < lambda_mem_min and solver_variables['s_ccl'] < s_ccl_max: if control_variables['Phi_a_des'] + delta_Phi_des <= 1: control_variables['Phi_a_des'] = control_variables['Phi_a_des'] + delta_Phi_des if control_variables['Phi_c_des'] + delta_Phi_des <= 1: control_variables['Phi_c_des'] = control_variables['Phi_c_des'] + delta_Phi_des # Both flooding and drying out are likely. Nothing can be done. elif solver_variables['s_ccl'] > s_ccl_max and solver_variables['lambda_mem'] < lambda_mem_min: pass # Both flooding and drying out are unlikely. It is the desired situation. else: # elif solver_variables['s_ccl'] < s_ccl_max and solver_variables['lambda_mem'] > lambda_mem_min: pass","title":"control_operating_conditions"},{"location":"functions/model/dif_eq/","text":"Differential equations This file represents all the differential equations used for the fuel cell model. calculate_dyn_H2_O2_N2_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, J_H2_agc_agdl, J_H2_agdl_agdl, J_H2_agdl_acl, J_O2_ccl_cgdl, J_O2_cgdl_cgdl, J_O2_cgdl_cgc, S_H2_acl, S_O2_ccl, **kwargs) This function calculates the dynamic evolution of the hydrogen, oxygen and nitrogen in the gas channels, the gas diffusion layers and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). Hgc ( float ) \u2013 Thickness of the gas channel (m). Lgc ( float ) \u2013 Length of the gas channel (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. J_H2_in ( float ) \u2013 Hydrogen flow at the anode inlet (mol.m-2.s-1). J_H2_out ( float ) \u2013 Hydrogen flow at the anode outlet (mol.m-2.s-1). J_O2_in ( float ) \u2013 Oxygen flow at the cathode inlet (mol.m-2.s-1). J_O2_out ( float ) \u2013 Oxygen flow at the cathode outlet (mol.m-2.s-1). J_N2_in ( float ) \u2013 Nitrogen flow at the cathode inlet (mol.m-2.s-1). J_N2_out ( float ) \u2013 Nitrogen flow at the cathode outlet (mol.m-2.s-1). J_H2_agc_agdl ( float ) \u2013 Hydrogen flow between the anode gas channel and the anode GDL (mol.m-2.s-1). J_H2_agdl_agdl ( list ) \u2013 Hydrogen flow between two nodes of the anode GDL (mol.m-2.s-1). J_H2_agdl_acl ( float ) \u2013 Hydrogen flow between the anode GDL and the anode CL (mol.m-2.s-1). J_O2_ccl_cgdl ( float ) \u2013 Oxygen flow between the cathode CL and the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgdl ( list ) \u2013 Oxygen flow between two nodes of the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgc ( float ) \u2013 Oxygen flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). S_H2_acl ( float ) \u2013 Hydrogen consumed in the anode CL (mol.m-3.s-1). S_O2_ccl ( float ) \u2013 Oxygen consumed in the cathode CL (mol.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_H2_O2_N2_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, J_H2_agc_agdl, J_H2_agdl_agdl, J_H2_agdl_acl, J_O2_ccl_cgdl, J_O2_cgdl_cgdl, J_O2_cgdl_cgc, S_H2_acl, S_O2_ccl, **kwargs): \"\"\"This function calculates the dynamic evolution of the hydrogen, oxygen and nitrogen in the gas channels, the gas diffusion layers and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). Hgc : float Thickness of the gas channel (m). Lgc : float Length of the gas channel (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. J_H2_in : float Hydrogen flow at the anode inlet (mol.m-2.s-1). J_H2_out : float Hydrogen flow at the anode outlet (mol.m-2.s-1). J_O2_in : float Oxygen flow at the cathode inlet (mol.m-2.s-1). J_O2_out : float Oxygen flow at the cathode outlet (mol.m-2.s-1). J_N2_in : float Nitrogen flow at the cathode inlet (mol.m-2.s-1). J_N2_out : float Nitrogen flow at the cathode outlet (mol.m-2.s-1). J_H2_agc_agdl : float Hydrogen flow between the anode gas channel and the anode GDL (mol.m-2.s-1). J_H2_agdl_agdl : list Hydrogen flow between two nodes of the anode GDL (mol.m-2.s-1). J_H2_agdl_acl : float Hydrogen flow between the anode GDL and the anode CL (mol.m-2.s-1). J_O2_ccl_cgdl : float Oxygen flow between the cathode CL and the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgdl : list Oxygen flow between two nodes of the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgc : float Oxygen flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). S_H2_acl : float Hydrogen consumed in the anode CL (mol.m-3.s-1). S_O2_ccl : float Oxygen consumed in the cathode CL (mol.m-3.s-1). \"\"\" # At the anode side # Inside the AGC dif_eq['dC_H2_agc / dt'] = (J_H2_in - J_H2_out) / Lgc - J_H2_agc_agdl / Hgc # Inside the AGDL dif_eq['dC_H2_agdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_agdl_1'])) * \\ (J_H2_agc_agdl - J_H2_agdl_agdl[1]) / (Hgdl / n_gdl) for i in range(2, n_gdl): dif_eq[f'dC_H2_agdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{i}'])) * \\ (J_H2_agdl_agdl[i - 1] - J_H2_agdl_agdl[i]) / (Hgdl / n_gdl) dif_eq[f'dC_H2_agdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{n_gdl}'])) * \\ (J_H2_agdl_agdl[n_gdl - 1] - J_H2_agdl_acl) / (Hgdl / n_gdl) # Inside the ACL dif_eq['dC_H2_acl / dt'] = 1 / (epsilon_cl * (1 - sv['s_acl'])) * (J_H2_agdl_acl / Hcl + S_H2_acl) # At the cathode side # Inside the CCL dif_eq['dC_O2_ccl / dt'] = 1 / (epsilon_cl * (1 - sv['s_ccl'])) * (-J_O2_ccl_cgdl / Hcl + S_O2_ccl) # Inside the CGDL dif_eq['dC_O2_cgdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_cgdl_1'])) * \\ (J_O2_ccl_cgdl - J_O2_cgdl_cgdl[1]) / (Hgdl / n_gdl) for i in range(2, n_gdl): dif_eq[f'dC_O2_cgdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{i}'])) * \\ (J_O2_cgdl_cgdl[i - 1] - J_O2_cgdl_cgdl[i]) / (Hgdl / n_gdl) dif_eq[f'dC_O2_cgdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{n_gdl}'])) * \\ (J_O2_cgdl_cgdl[n_gdl - 1] - J_O2_cgdl_cgc) / (Hgdl / n_gdl) # Inside the CGC dif_eq['dC_O2_cgc / dt'] = (J_O2_in - J_O2_out) / Lgc + J_O2_cgdl_cgc / Hgc # Inside the whole cell dif_eq['dC_N2 / dt'] = (J_N2_in - J_N2_out) / Lgc calculate_dyn_air_compressor_and_humidifier_evolution(dif_eq, Wcp_des, Wa_inj_des, Wc_inj_des, type_auxiliary, Wcp, Wa_inj, Wc_inj, **kwargs) This function calculates the dynamic evolution of the air compressor and the humidifiers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Wcp_des ( float ) \u2013 Desired air compressor flow rate (kg.s-1). Wa_inj_des ( float ) \u2013 Desired anode humidifier flow rate (kg.s-1). Wc_inj_des ( float ) \u2013 Desired cathode humidifier flow rate (kg.s-1). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Wcp ( float ) \u2013 Air compressor flow rate (kg.s-1). Wa_inj ( float ) \u2013 Anode humidifier flow rate (kg.s-1). Wc_inj ( float ) \u2013 Cathode humidifier flow rate (kg.s-1). Source code in model/dif_eq.py def calculate_dyn_air_compressor_and_humidifier_evolution(dif_eq, Wcp_des, Wa_inj_des, Wc_inj_des, type_auxiliary, Wcp, Wa_inj, Wc_inj, **kwargs): \"\"\"This function calculates the dynamic evolution of the air compressor and the humidifiers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Wcp_des : float Desired air compressor flow rate (kg.s-1). Wa_inj_des : float Desired anode humidifier flow rate (kg.s-1). Wc_inj_des : float Desired cathode humidifier flow rate (kg.s-1). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Wcp : float Air compressor flow rate (kg.s-1). Wa_inj : float Anode humidifier flow rate (kg.s-1). Wc_inj : float Cathode humidifier flow rate (kg.s-1). \"\"\" # Air compressor evolution if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dWcp / dt'] = (Wcp_des - Wcp) / tau_cp # Estimation at the first order. elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dWcp / dt'] = (Wcp_des - Wcp) / tau_cp # Estimation at the first order. else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dWcp / dt'] = 0 # Anode and cathode humidifiers evolution if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dWa_inj / dt'] = 0 dif_eq['dWc_inj / dt'] = (Wc_inj_des - Wc_inj) / tau_hum # Estimation at the first order. elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dWa_inj / dt'] = (Wa_inj_des - Wa_inj) / tau_hum # Estimation at the first order. dif_eq['dWc_inj / dt'] = (Wc_inj_des - Wc_inj) / tau_hum # Estimation at the first order. else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dWa_inj / dt'], dif_eq['dWc_inj / dt'] = 0, 0 calculate_dyn_dissoved_water_evolution(dif_eq, Hmem, Hcl, epsilon_mc, S_sorp_acl, S_sorp_ccl, J_lambda_mem_acl, J_lambda_mem_ccl, Sp_acl, Sp_ccl, **kwargs) This function calculates the dynamic evolution of the dissolved water in the membrane and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Hmem ( float ) \u2013 Thickness of the membrane (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the catalyst layer. S_sorp_acl ( float ) \u2013 Water sorption in the anode catalyst layer (mol.m-3.s-1) S_sorp_ccl ( float ) \u2013 Water sorption in the cathode catalyst layer (mol.m-3.s-1) J_lambda_mem_acl ( float ) \u2013 Dissolved water flow between the membrane and the anode catalyst layer (mol.m-2.s-1) J_lambda_mem_ccl ( float ) \u2013 Dissolved water flow between the membrane and the cathode catalyst layer (mol.m-2.s-1) Sp_acl ( float ) \u2013 Water produced in the membrane at the ACL through the chemical reaction and crossover (mol.m-3.s-1) Sp_ccl ( float ) \u2013 Water produced in the membrane at the CCL through the chemical reaction and crossover (mol.m-3.s-1) Source code in model/dif_eq.py def calculate_dyn_dissoved_water_evolution(dif_eq, Hmem, Hcl, epsilon_mc, S_sorp_acl, S_sorp_ccl, J_lambda_mem_acl, J_lambda_mem_ccl, Sp_acl, Sp_ccl, **kwargs): \"\"\" This function calculates the dynamic evolution of the dissolved water in the membrane and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Hmem : float Thickness of the membrane (m). Hcl : float Thickness of the catalyst layer (m). epsilon_mc : float Volume fraction of ionomer in the catalyst layer. S_sorp_acl : float Water sorption in the anode catalyst layer (mol.m-3.s-1) S_sorp_ccl : float Water sorption in the cathode catalyst layer (mol.m-3.s-1) J_lambda_mem_acl : float Dissolved water flow between the membrane and the anode catalyst layer (mol.m-2.s-1) J_lambda_mem_ccl : float Dissolved water flow between the membrane and the cathode catalyst layer (mol.m-2.s-1) Sp_acl : float Water produced in the membrane at the ACL through the chemical reaction and crossover (mol.m-3.s-1) Sp_ccl : float Water produced in the membrane at the CCL through the chemical reaction and crossover (mol.m-3.s-1) \"\"\" dif_eq['dlambda_acl / dt'] = M_eq / (rho_mem * epsilon_mc) * (-J_lambda_mem_acl / Hcl + S_sorp_acl + Sp_acl) dif_eq['dlambda_mem / dt'] = M_eq / rho_mem * (J_lambda_mem_acl - J_lambda_mem_ccl) / Hmem dif_eq['dlambda_ccl / dt'] = M_eq / (rho_mem * epsilon_mc) * (J_lambda_mem_ccl / Hcl + S_sorp_ccl + Sp_ccl) calculate_dyn_liquid_water_evolution(dif_eq, rho_H2O, Hgdl, Hcl, epsilon_gdl, n_gdl, Jl_agdl_agdl, Jl_agdl_acl, Jl_ccl_cgdl, Jl_cgdl_cgdl, Sl_agdl, Sl_acl, Sl_ccl, Sl_cgdl, **kwargs) This function calculates the dynamic evolution of the liquid water in the gas diffusion and catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. rho_H2O ( float ) \u2013 Density of water (kg.m-3). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. Jl_agdl_agdl ( list ) \u2013 Liquid water flow between two nodes of the anode GDL (kg.m-2.s-1). Jl_agdl_acl ( float ) \u2013 Liquid water flow between the anode GDL and the anode CL (kg.m-2.s-1). Jl_ccl_cgdl ( float ) \u2013 Liquid water flow between the cathode CL and the cathode GDL (kg.m-2.s-1). Jl_cgdl_cgdl ( list ) \u2013 Liquid water flow between two nodes of the cathode GDL (kg.m-2.s-1). Sl_agdl ( list ) \u2013 Liquid water produced in the anode GDL (kg.m-3.s-1). Sl_acl ( float ) \u2013 Liquid water produced in the anode CL (kg.m-3.s-1). Sl_ccl ( float ) \u2013 Liquid water produced in the cathode CL (kg.m-3.s-1). Sl_cgdl ( list ) \u2013 Liquid water produced in the cathode GDL (kg.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_liquid_water_evolution(dif_eq, rho_H2O, Hgdl, Hcl, epsilon_gdl, n_gdl, Jl_agdl_agdl, Jl_agdl_acl, Jl_ccl_cgdl, Jl_cgdl_cgdl, Sl_agdl, Sl_acl, Sl_ccl, Sl_cgdl, **kwargs): \"\"\" This function calculates the dynamic evolution of the liquid water in the gas diffusion and catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. rho_H2O : float Density of water (kg.m-3). Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. Jl_agdl_agdl : list Liquid water flow between two nodes of the anode GDL (kg.m-2.s-1). Jl_agdl_acl : float Liquid water flow between the anode GDL and the anode CL (kg.m-2.s-1). Jl_ccl_cgdl : float Liquid water flow between the cathode CL and the cathode GDL (kg.m-2.s-1). Jl_cgdl_cgdl : list Liquid water flow between two nodes of the cathode GDL (kg.m-2.s-1). Sl_agdl : list Liquid water produced in the anode GDL (kg.m-3.s-1). Sl_acl : float Liquid water produced in the anode CL (kg.m-3.s-1). Sl_ccl : float Liquid water produced in the cathode CL (kg.m-3.s-1). Sl_cgdl : list Liquid water produced in the cathode GDL (kg.m-3.s-1). \"\"\" # At the anode side # Inside the AGDL dif_eq['ds_agdl_1 / dt'] = 0 # Dirichlet boundary condition. s_agdl_1 is initialized to 0 and remains constant. for i in range(2, n_gdl): dif_eq[f'ds_agdl_{i} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_agdl_agdl[i - 1] - Jl_agdl_agdl[i]) / (Hgdl / n_gdl) + M_H2O * Sl_agdl[i]) dif_eq[f'ds_agdl_{n_gdl} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_agdl_agdl[n_gdl - 1] - Jl_agdl_acl) / (Hgdl / n_gdl) + M_H2O * Sl_agdl[n_gdl]) # Inside the ACL dif_eq['ds_acl / dt'] = 1 / (rho_H2O * epsilon_cl) * (Jl_agdl_acl / Hcl + M_H2O * Sl_acl) # At the cathode side # Inside the CCL dif_eq['ds_ccl / dt'] = 1 / (rho_H2O * epsilon_cl) * (- Jl_ccl_cgdl / Hcl + M_H2O * Sl_ccl) # Inside the CGDL dif_eq['ds_cgdl_1 / dt'] = 1 / (rho_H2O * epsilon_gdl) * ((Jl_ccl_cgdl - Jl_cgdl_cgdl[1]) / (Hgdl / n_gdl) + M_H2O * Sl_cgdl[1]) for i in range(2, n_gdl): dif_eq[f'ds_cgdl_{i} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_cgdl_cgdl[i - 1] - Jl_cgdl_cgdl[i]) / (Hgdl / n_gdl) + M_H2O * Sl_cgdl[i]) dif_eq[f'ds_cgdl_{n_gdl} / dt'] = 0 # Dirichlet boundary condition. s_cgdl_n_gdl is initialized to 0 and remains calculate_dyn_manifold_pressure_and_humidity_evolution(dif_eq, Masm, Maem, Mcsm, Mcem, Tfc, Hgc, Wgc, type_auxiliary, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out, **kwargs) This function calculates the dynamic evolution of the pressure and humidity inside the manifolds. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Masm ( float ) \u2013 Molar mass of all the gaseous species inside the anode supply manifold (kg.mol-1). Maem ( float ) \u2013 Molar mass of all the gaseous species inside the anode exhaust manifold (kg.mol-1). Mcsm ( float ) \u2013 Molar mass of all the gaseous species inside the cathode supply manifold (kg.mol-1). Mcem ( float ) \u2013 Molar mass of all the gaseous species inside the cathode exhaust manifold (kg.mol-1). Tfc ( float ) \u2013 Fuel cell temperature (K). Hgc ( float ) \u2013 Thickness of the gas channel (m). Wgc ( float ) \u2013 Width of the gas channel (m). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Jv_a_in ( float ) \u2013 Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Water vapor flow at the cathode outlet (mol.m-2.s-1). Wasm_in ( float ) \u2013 Flow at the anode supply manifold inlet (kg.s-1). Wasm_out ( float ) \u2013 Flow at the anode supply manifold outlet (kg.s-1). Waem_in ( float ) \u2013 Flow at the anode exhaust manifold inlet (kg.s-1). Waem_out ( float ) \u2013 Flow at the anode exhaust manifold outlet (kg.s-1). Wcsm_in ( float ) \u2013 Flow at the cathode supply manifold inlet (kg.s-1). Wcsm_out ( float ) \u2013 Flow at the cathode supply manifold outlet (kg.s-1). Wcem_in ( float ) \u2013 Flow at the cathode exhaust manifold inlet (kg.s-1). Wcem_out ( float ) \u2013 Flow at the cathode exhaust manifold outlet (kg.s-1). Ware ( float ) \u2013 Anode side recirculation flow (kg.s-1). Wv_asm_in ( float ) \u2013 Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out ( float ) \u2013 Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in ( float ) \u2013 Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out ( float ) \u2013 Vapor flow at the cathode external manifold outlet (mol.s-1). Source code in model/dif_eq.py def calculate_dyn_manifold_pressure_and_humidity_evolution(dif_eq, Masm, Maem, Mcsm, Mcem, Tfc, Hgc, Wgc, type_auxiliary, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out, **kwargs): \"\"\"This function calculates the dynamic evolution of the pressure and humidity inside the manifolds. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Masm : float Molar mass of all the gaseous species inside the anode supply manifold (kg.mol-1). Maem : float Molar mass of all the gaseous species inside the anode exhaust manifold (kg.mol-1). Mcsm : float Molar mass of all the gaseous species inside the cathode supply manifold (kg.mol-1). Mcem : float Molar mass of all the gaseous species inside the cathode exhaust manifold (kg.mol-1). Tfc : float Fuel cell temperature (K). Hgc : float Thickness of the gas channel (m). Wgc : float Width of the gas channel (m). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Jv_a_in : float Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out : float Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in : float Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out : float Water vapor flow at the cathode outlet (mol.m-2.s-1). Wasm_in : float Flow at the anode supply manifold inlet (kg.s-1). Wasm_out : float Flow at the anode supply manifold outlet (kg.s-1). Waem_in : float Flow at the anode exhaust manifold inlet (kg.s-1). Waem_out : float Flow at the anode exhaust manifold outlet (kg.s-1). Wcsm_in : float Flow at the cathode supply manifold inlet (kg.s-1). Wcsm_out : float Flow at the cathode supply manifold outlet (kg.s-1). Wcem_in : float Flow at the cathode exhaust manifold inlet (kg.s-1). Wcem_out : float Flow at the cathode exhaust manifold outlet (kg.s-1). Ware : float Anode side recirculation flow (kg.s-1). Wv_asm_in : float Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out : float Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in : float Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out : float Vapor flow at the cathode external manifold outlet (mol.s-1). \"\"\" # Pressure evolution inside the manifolds if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dPasm / dt'] = (Wasm_in + Ware - n_cell * Wasm_out) / (Vsm * Masm) * R * Tfc dif_eq['dPaem / dt'] = (n_cell * Waem_in - Ware - Waem_out) / (Vem * Maem) * R * Tfc dif_eq['dPcsm / dt'] = (Wcsm_in - n_cell * Wcsm_out) / (Vsm * Mcsm) * R * Tfc dif_eq['dPcem / dt'] = (n_cell * Wcem_in - Wcem_out) / (Vem * Mcem) * R * Tfc elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dPasm / dt'] = (Wasm_in - n_cell * Wasm_out) / (Vsm * Masm) * R * Tfc dif_eq['dPaem / dt'] = (n_cell * Waem_in - Waem_out) / (Vem * Maem) * R * Tfc dif_eq['dPcsm / dt'] = (Wcsm_in - n_cell * Wcsm_out) / (Vsm * Mcsm) * R * Tfc dif_eq['dPcem / dt'] = (n_cell * Wcem_in - Wcem_out) / (Vem * Mcem) * R * Tfc else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dPasm / dt'], dif_eq['dPaem / dt'], dif_eq['dPcsm / dt'], dif_eq['dPcem / dt'] = 0, 0, 0, 0 # Humidity evolution inside the manifolds if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dPhi_asm / dt'] = (Wv_asm_in - Jv_a_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_aem / dt'] = (Jv_a_out * Hgc * Wgc * n_cell - Wv_asm_in - Wv_aem_out) / Vem * R * Tfc / Psat(Tfc) dif_eq['dPhi_csm / dt'] = (Wv_csm_in - Jv_c_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_cem / dt'] = (Jv_c_out * Hgc * Wgc * n_cell - Wv_cem_out) / Vem * R * Tfc / Psat(Tfc) elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dPhi_asm / dt'] = (Wv_asm_in - Jv_a_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_aem / dt'] = (Jv_a_out * Hgc * Wgc * n_cell - Wv_aem_out) / Vem * R * Tfc / Psat(Tfc) dif_eq['dPhi_csm / dt'] = (Wv_csm_in - Jv_c_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_cem / dt'] = (Jv_c_out * Hgc * Wgc * n_cell - Wv_cem_out) / Vem * R * Tfc / Psat(Tfc) else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dPhi_asm / dt'], dif_eq['dPhi_aem / dt'], dif_eq['dPhi_csm / dt'], dif_eq['dPhi_cem / dt'] = 0, 0, 0, 0 calculate_dyn_throttle_area_evolution(dif_eq, Pagc, Pcgc, type_auxiliary, Abp_a, Abp_c, Tfc, Pa_des, Pc_des, **kwargs) This function calculates the dynamic evolution of the throttle area inside the anode and cathode auxiliaries. This function has to be executed after 'calculate_dyn_vapor_evolution' and 'calculate_dyn_H2_O2_N2_evolution'. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Pagc ( float ) \u2013 Pressure inside the anode gas channel (Pa). Pcgc ( float ) \u2013 Pressure inside the cathode gas channel (Pa). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Abp_a ( float ) \u2013 Throttle area inside the anode auxiliaries (m2). Abp_c ( float ) \u2013 Throttle area inside the cathode auxiliaries (m2). Tfc ( float ) \u2013 Fuel cell temperature (K). Pa_des ( float ) \u2013 Desired pressure inside the anode gas channel (Pa). Pc_des ( float ) \u2013 Desired pressure inside the cathode gas channel (Pa). Source code in model/dif_eq.py def calculate_dyn_throttle_area_evolution(dif_eq, Pagc, Pcgc, type_auxiliary, Abp_a, Abp_c, Tfc, Pa_des, Pc_des, **kwargs): \"\"\"This function calculates the dynamic evolution of the throttle area inside the anode and cathode auxiliaries. This function has to be executed after 'calculate_dyn_vapor_evolution' and 'calculate_dyn_H2_O2_N2_evolution'. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Pagc : float Pressure inside the anode gas channel (Pa). Pcgc : float Pressure inside the cathode gas channel (Pa). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Abp_a : float Throttle area inside the anode auxiliaries (m2). Abp_c : float Throttle area inside the cathode auxiliaries (m2). Tfc : float Fuel cell temperature (K). Pa_des : float Desired pressure inside the anode gas channel (Pa). Pc_des : float Desired pressure inside the cathode gas channel (Pa). \"\"\" # Calculation of the pressure derivative inside the gas channels dPagcdt = (dif_eq['dC_v_agc / dt'] + dif_eq['dC_H2_agc / dt']) * R * Tfc dPcgcdt = (dif_eq['dC_v_cgc / dt'] + dif_eq['dC_O2_cgc / dt'] + dif_eq['dC_N2 / dt']) * R * Tfc # Throttle area evolution inside the anode auxiliaries if type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dAbp_a / dt'] = - Kp * (Pa_des - Pagc) + Kd * dPagcdt # PD controller if Abp_a > A_T and dif_eq['dAbp_a / dt'] > 0: # The throttle area cannot be higher than the maximum value dif_eq['dAbp_a / dt'] = 0 elif Abp_a < 0 and dif_eq['dAbp_a / dt'] < 0: # The throttle area cannot be lower than 0 dif_eq['dAbp_a / dt'] = 0 else: # elif type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ # type_auxiliary == \"no_auxiliary\": dif_eq['dAbp_a / dt'] = 0 # The throttle area is not considered # Throttle area evolution inside the cathode auxiliaries if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dAbp_c / dt'] = - Kp * (Pc_des - Pcgc) + Kd * dPcgcdt # PD controller if Abp_c > A_T and dif_eq['dAbp_c / dt'] > 0: # The throttle area cannot be higher than the maximum value dif_eq['dAbp_c / dt'] = 0 elif Abp_c < 0 and dif_eq['dAbp_c / dt'] < 0: # The throttle area cannot be lower than 0 dif_eq['dAbp_c / dt'] = 0 else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dAbp_a / dt'] = 0 # The throttle area is not considered calculate_dyn_vapor_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Jv_agc_agdl, Jv_agdl_agdl, Jv_agdl_acl, S_sorp_acl, S_sorp_ccl, Jv_ccl_cgdl, Jv_cgdl_cgdl, Jv_cgdl_cgc, Sv_agdl, Sv_acl, Sv_ccl, Sv_cgdl, **kwargs) This function calculates the dynamic evolution of the vapor in the gas channels, the gas diffusion layers and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). Hgc ( float ) \u2013 Thickness of the gas channel (m). Lgc ( float ) \u2013 Length of the gas channel (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. Jv_a_in ( float ) \u2013 Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Water vapor flow at the cathode outlet (mol.m-2.s-1). Jv_agc_agdl ( float ) \u2013 Water vapor flow between the anode gas channel and the anode GDL (mol.m-2.s-1). Jv_agdl_agdl ( list ) \u2013 Water vapor flow between two nodes of the anode GDL (mol.m-2.s-1). Jv_agdl_acl ( float ) \u2013 Water vapor flow between the anode GDL and the anode CL (mol.m-2.s-1). S_sorp_acl \u2013 Water vapor sorption in the anode CL (mol.m-3.s-1). S_sorp_ccl \u2013 Water vapor sorption in the cathode CL (mol.m-3.s-1). Jv_ccl_cgdl ( float ) \u2013 Water vapor flow between the cathode CL and the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgdl ( list ) \u2013 Water vapor flow between two nodes of the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgc ( float ) \u2013 Water vapor flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). Sv_agdl ( list ) \u2013 Water vapor produced in the anode GDL (mol.m-3.s-1). Sv_acl ( float ) \u2013 Water vapor produced in the anode CL (mol.m-3.s-1). Sv_ccl ( float ) \u2013 Water vapor produced in the cathode CL (mol.m-3.s-1). Sv_cgdl ( list ) \u2013 Water vapor produced in the cathode GDL (mol.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_vapor_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Jv_agc_agdl, Jv_agdl_agdl, Jv_agdl_acl, S_sorp_acl, S_sorp_ccl, Jv_ccl_cgdl, Jv_cgdl_cgdl, Jv_cgdl_cgc, Sv_agdl, Sv_acl, Sv_ccl, Sv_cgdl, **kwargs): \"\"\"This function calculates the dynamic evolution of the vapor in the gas channels, the gas diffusion layers and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). Hgc : float Thickness of the gas channel (m). Lgc : float Length of the gas channel (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. Jv_a_in : float Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out : float Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in : float Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out : float Water vapor flow at the cathode outlet (mol.m-2.s-1). Jv_agc_agdl : float Water vapor flow between the anode gas channel and the anode GDL (mol.m-2.s-1). Jv_agdl_agdl : list Water vapor flow between two nodes of the anode GDL (mol.m-2.s-1). Jv_agdl_acl : float Water vapor flow between the anode GDL and the anode CL (mol.m-2.s-1). S_sorp_acl: float Water vapor sorption in the anode CL (mol.m-3.s-1). S_sorp_ccl: float Water vapor sorption in the cathode CL (mol.m-3.s-1). Jv_ccl_cgdl : float Water vapor flow between the cathode CL and the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgdl : list Water vapor flow between two nodes of the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgc : float Water vapor flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). Sv_agdl : list Water vapor produced in the anode GDL (mol.m-3.s-1). Sv_acl : float Water vapor produced in the anode CL (mol.m-3.s-1). Sv_ccl : float Water vapor produced in the cathode CL (mol.m-3.s-1). Sv_cgdl : list Water vapor produced in the cathode GDL (mol.m-3.s-1). \"\"\" # At the anode side # Inside the AGC dif_eq['dC_v_agc / dt'] = (Jv_a_in - Jv_a_out) / Lgc - Jv_agc_agdl / Hgc # Inside the AGDL dif_eq['dC_v_agdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_agdl_1'])) * \\ ((Jv_agc_agdl - Jv_agdl_agdl[1]) / (Hgdl / n_gdl) + Sv_agdl[1]) for i in range(2, n_gdl): dif_eq[f'dC_v_agdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{i}'])) * \\ ((Jv_agdl_agdl[i - 1] - Jv_agdl_agdl[i]) / (Hgdl / n_gdl) + Sv_agdl[i]) dif_eq[f'dC_v_agdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{n_gdl}'])) * \\ ((Jv_agdl_agdl[n_gdl - 1] - Jv_agdl_acl) / (Hgdl / n_gdl) + Sv_agdl[n_gdl]) # Inside the ACL dif_eq['dC_v_acl / dt'] = 1 / (epsilon_cl * (1 - sv['s_acl'])) * (Jv_agdl_acl / Hcl - S_sorp_acl + Sv_acl) # At the cathode side # Inside the CCL dif_eq['dC_v_ccl / dt'] = 1 / (epsilon_cl * (1 - sv['s_ccl'])) * (- Jv_ccl_cgdl / Hcl - S_sorp_ccl + Sv_ccl) # Inside the CGDL dif_eq['dC_v_cgdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_cgdl_1'])) * \\ ((Jv_ccl_cgdl - Jv_cgdl_cgdl[1]) / (Hgdl / n_gdl) + Sv_cgdl[1]) for i in range(2, n_gdl): dif_eq[f'dC_v_cgdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{i}'])) * \\ ((Jv_cgdl_cgdl[i - 1] - Jv_cgdl_cgdl[i]) / (Hgdl / n_gdl) + Sv_cgdl[i]) dif_eq[f'dC_v_cgdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{n_gdl}'])) * \\ ((Jv_cgdl_cgdl[n_gdl - 1] - Jv_cgdl_cgc) / (Hgdl / n_gdl) + Sv_cgdl[n_gdl]) # Inside the CGC dif_eq['dC_v_cgc / dt'] = (Jv_c_in - Jv_c_out) / Lgc + Jv_cgdl_cgc / Hgc calculate_dyn_voltage_evolution(dif_eq, i_fc, C_O2_ccl, eta_c, Tfc, Hcl, i0_c_ref, kappa_c, C_scl, i_n, f_drop, **kwargs) This function calculates the dynamic evolution of the cell overpotential eta_c. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. i_fc ( float ) \u2013 Fuel cell current density (A.m-2). C_O2_ccl ( float ) \u2013 Oxygen concentration in the cathode catalyst layer (mol.m-3). eta_c ( float ) \u2013 Cell overpotential (V). Tfc ( float ) \u2013 Fuel cell temperature (K). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode (A.m-2). kappa_c ( float ) \u2013 Overpotential correction exponent. C_scl ( float ) \u2013 Volumetric space-charge layer capacitance (F.m-3). i_n ( float ) \u2013 Crossover current density (A.m-2). f_drop ( float ) \u2013 Liquid water induced voltage drop function. Source code in model/dif_eq.py def calculate_dyn_voltage_evolution(dif_eq, i_fc, C_O2_ccl, eta_c, Tfc, Hcl, i0_c_ref, kappa_c, C_scl, i_n, f_drop, **kwargs): \"\"\"This function calculates the dynamic evolution of the cell overpotential eta_c. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. i_fc : float Fuel cell current density (A.m-2). C_O2_ccl : float Oxygen concentration in the cathode catalyst layer (mol.m-3). eta_c : float Cell overpotential (V). Tfc : float Fuel cell temperature (K). Hcl : float Thickness of the catalyst layer (m). i0_c_ref : float Reference exchange current density at the cathode (A.m-2). kappa_c : float Overpotential correction exponent. C_scl : float Volumetric space-charge layer capacitance (F.m-3). i_n : float Crossover current density (A.m-2). f_drop : float Liquid water induced voltage drop function. \"\"\" dif_eq['deta_c / dt'] = 1 / (C_scl * Hcl) * ((i_fc + i_n) - i0_c_ref * (C_O2_ccl / C_O2ref) ** kappa_c * np.exp(f_drop * alpha_c * F / (R * Tfc) * eta_c)) dydt(t, y, operating_inputs, parameters, solver_variable_names, control_variables) This function gives the system of differential equations to solve. Parameters: t ( float ) \u2013 Time (s). y ( ndarray ) \u2013 Numpy list of the solver variables. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. solver_variable_names ( list ) \u2013 Names of the solver variables. control_variables ( dict ) \u2013 Variables controlled by the user. Returns: dydt ( list ) \u2013 List containing the derivative of the solver variables. Source code in model/dif_eq.py def dydt(t, y, operating_inputs, parameters, solver_variable_names, control_variables): \"\"\"This function gives the system of differential equations to solve. Parameters ---------- t : float Time (s). y : numpy.ndarray Numpy list of the solver variables. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. solver_variable_names : list Names of the solver variables. control_variables : dict Variables controlled by the user. Returns ------- dydt : list List containing the derivative of the solver variables. \"\"\" # Creation of the dif_eq dictionary. It is an intermediate calculation to simplify the writing of the code. dif_eq = {('d' + key + ' / dt'): 0 for key in solver_variable_names} # Creation of the solver_variables dict. It is an intermediate calculation to simplify the writing of the code. solver_variables = {} for index, key in enumerate(solver_variable_names): solver_variables[key] = y[index] # Modifications of the operating conditions in real time, if required. if parameters[\"type_control\"] != \"no_control\": control_operating_conditions(t, solver_variables, operating_inputs, parameters, control_variables) # Intermediate values i_fc = operating_inputs['current_density'](t, parameters) Mext, Pagc, Pcgc, i_n, Masm, Maem, Mcsm, Mcem, rho_H2O = dif_eq_int_values(solver_variables, control_variables, operating_inputs, parameters) Wcp_des, Wa_inj_des, Wc_inj_des = desired_flows(solver_variables, control_variables, i_n, i_fc, operating_inputs, parameters, Mext) eta_c_intermediate_values = calculate_eta_c_intermediate_values(solver_variables, operating_inputs, parameters) # Calculation of the flows flows_dico = calculate_flows(t, solver_variables, control_variables, i_fc, operating_inputs, parameters) # Calculation of the dynamic evolutions # Inside the cell calculate_dyn_dissoved_water_evolution(dif_eq, **parameters, **flows_dico) calculate_dyn_liquid_water_evolution(dif_eq, rho_H2O, **parameters, **flows_dico) calculate_dyn_vapor_evolution(dif_eq, solver_variables, **parameters, **flows_dico) calculate_dyn_H2_O2_N2_evolution(dif_eq, solver_variables, **parameters, **flows_dico) calculate_dyn_voltage_evolution(dif_eq, i_fc, **solver_variables, **operating_inputs, **parameters, **eta_c_intermediate_values) # Inside the auxiliary components calculate_dyn_manifold_pressure_and_humidity_evolution(dif_eq, Masm, Maem, Mcsm, Mcem, **solver_variables, **operating_inputs, **parameters, **flows_dico) calculate_dyn_air_compressor_and_humidifier_evolution(dif_eq, Wcp_des, Wa_inj_des, Wc_inj_des, **solver_variables, **parameters) calculate_dyn_throttle_area_evolution(dif_eq, Pagc, Pcgc, **solver_variables, **operating_inputs, **parameters) # dif_eq is converted to dydt because the solver requires an ordered list to work dydt = [] for key in solver_variable_names: dydt.append(dif_eq['d' + key + ' / dt']) return dydt","title":"Differentiel equations"},{"location":"functions/model/dif_eq/#differential-equations","text":"This file represents all the differential equations used for the fuel cell model.","title":"Differential equations"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_H2_O2_N2_evolution","text":"This function calculates the dynamic evolution of the hydrogen, oxygen and nitrogen in the gas channels, the gas diffusion layers and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). Hgc ( float ) \u2013 Thickness of the gas channel (m). Lgc ( float ) \u2013 Length of the gas channel (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. J_H2_in ( float ) \u2013 Hydrogen flow at the anode inlet (mol.m-2.s-1). J_H2_out ( float ) \u2013 Hydrogen flow at the anode outlet (mol.m-2.s-1). J_O2_in ( float ) \u2013 Oxygen flow at the cathode inlet (mol.m-2.s-1). J_O2_out ( float ) \u2013 Oxygen flow at the cathode outlet (mol.m-2.s-1). J_N2_in ( float ) \u2013 Nitrogen flow at the cathode inlet (mol.m-2.s-1). J_N2_out ( float ) \u2013 Nitrogen flow at the cathode outlet (mol.m-2.s-1). J_H2_agc_agdl ( float ) \u2013 Hydrogen flow between the anode gas channel and the anode GDL (mol.m-2.s-1). J_H2_agdl_agdl ( list ) \u2013 Hydrogen flow between two nodes of the anode GDL (mol.m-2.s-1). J_H2_agdl_acl ( float ) \u2013 Hydrogen flow between the anode GDL and the anode CL (mol.m-2.s-1). J_O2_ccl_cgdl ( float ) \u2013 Oxygen flow between the cathode CL and the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgdl ( list ) \u2013 Oxygen flow between two nodes of the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgc ( float ) \u2013 Oxygen flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). S_H2_acl ( float ) \u2013 Hydrogen consumed in the anode CL (mol.m-3.s-1). S_O2_ccl ( float ) \u2013 Oxygen consumed in the cathode CL (mol.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_H2_O2_N2_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, J_H2_agc_agdl, J_H2_agdl_agdl, J_H2_agdl_acl, J_O2_ccl_cgdl, J_O2_cgdl_cgdl, J_O2_cgdl_cgc, S_H2_acl, S_O2_ccl, **kwargs): \"\"\"This function calculates the dynamic evolution of the hydrogen, oxygen and nitrogen in the gas channels, the gas diffusion layers and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). Hgc : float Thickness of the gas channel (m). Lgc : float Length of the gas channel (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. J_H2_in : float Hydrogen flow at the anode inlet (mol.m-2.s-1). J_H2_out : float Hydrogen flow at the anode outlet (mol.m-2.s-1). J_O2_in : float Oxygen flow at the cathode inlet (mol.m-2.s-1). J_O2_out : float Oxygen flow at the cathode outlet (mol.m-2.s-1). J_N2_in : float Nitrogen flow at the cathode inlet (mol.m-2.s-1). J_N2_out : float Nitrogen flow at the cathode outlet (mol.m-2.s-1). J_H2_agc_agdl : float Hydrogen flow between the anode gas channel and the anode GDL (mol.m-2.s-1). J_H2_agdl_agdl : list Hydrogen flow between two nodes of the anode GDL (mol.m-2.s-1). J_H2_agdl_acl : float Hydrogen flow between the anode GDL and the anode CL (mol.m-2.s-1). J_O2_ccl_cgdl : float Oxygen flow between the cathode CL and the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgdl : list Oxygen flow between two nodes of the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgc : float Oxygen flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). S_H2_acl : float Hydrogen consumed in the anode CL (mol.m-3.s-1). S_O2_ccl : float Oxygen consumed in the cathode CL (mol.m-3.s-1). \"\"\" # At the anode side # Inside the AGC dif_eq['dC_H2_agc / dt'] = (J_H2_in - J_H2_out) / Lgc - J_H2_agc_agdl / Hgc # Inside the AGDL dif_eq['dC_H2_agdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_agdl_1'])) * \\ (J_H2_agc_agdl - J_H2_agdl_agdl[1]) / (Hgdl / n_gdl) for i in range(2, n_gdl): dif_eq[f'dC_H2_agdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{i}'])) * \\ (J_H2_agdl_agdl[i - 1] - J_H2_agdl_agdl[i]) / (Hgdl / n_gdl) dif_eq[f'dC_H2_agdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{n_gdl}'])) * \\ (J_H2_agdl_agdl[n_gdl - 1] - J_H2_agdl_acl) / (Hgdl / n_gdl) # Inside the ACL dif_eq['dC_H2_acl / dt'] = 1 / (epsilon_cl * (1 - sv['s_acl'])) * (J_H2_agdl_acl / Hcl + S_H2_acl) # At the cathode side # Inside the CCL dif_eq['dC_O2_ccl / dt'] = 1 / (epsilon_cl * (1 - sv['s_ccl'])) * (-J_O2_ccl_cgdl / Hcl + S_O2_ccl) # Inside the CGDL dif_eq['dC_O2_cgdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_cgdl_1'])) * \\ (J_O2_ccl_cgdl - J_O2_cgdl_cgdl[1]) / (Hgdl / n_gdl) for i in range(2, n_gdl): dif_eq[f'dC_O2_cgdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{i}'])) * \\ (J_O2_cgdl_cgdl[i - 1] - J_O2_cgdl_cgdl[i]) / (Hgdl / n_gdl) dif_eq[f'dC_O2_cgdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{n_gdl}'])) * \\ (J_O2_cgdl_cgdl[n_gdl - 1] - J_O2_cgdl_cgc) / (Hgdl / n_gdl) # Inside the CGC dif_eq['dC_O2_cgc / dt'] = (J_O2_in - J_O2_out) / Lgc + J_O2_cgdl_cgc / Hgc # Inside the whole cell dif_eq['dC_N2 / dt'] = (J_N2_in - J_N2_out) / Lgc","title":"calculate_dyn_H2_O2_N2_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_air_compressor_and_humidifier_evolution","text":"This function calculates the dynamic evolution of the air compressor and the humidifiers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Wcp_des ( float ) \u2013 Desired air compressor flow rate (kg.s-1). Wa_inj_des ( float ) \u2013 Desired anode humidifier flow rate (kg.s-1). Wc_inj_des ( float ) \u2013 Desired cathode humidifier flow rate (kg.s-1). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Wcp ( float ) \u2013 Air compressor flow rate (kg.s-1). Wa_inj ( float ) \u2013 Anode humidifier flow rate (kg.s-1). Wc_inj ( float ) \u2013 Cathode humidifier flow rate (kg.s-1). Source code in model/dif_eq.py def calculate_dyn_air_compressor_and_humidifier_evolution(dif_eq, Wcp_des, Wa_inj_des, Wc_inj_des, type_auxiliary, Wcp, Wa_inj, Wc_inj, **kwargs): \"\"\"This function calculates the dynamic evolution of the air compressor and the humidifiers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Wcp_des : float Desired air compressor flow rate (kg.s-1). Wa_inj_des : float Desired anode humidifier flow rate (kg.s-1). Wc_inj_des : float Desired cathode humidifier flow rate (kg.s-1). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Wcp : float Air compressor flow rate (kg.s-1). Wa_inj : float Anode humidifier flow rate (kg.s-1). Wc_inj : float Cathode humidifier flow rate (kg.s-1). \"\"\" # Air compressor evolution if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dWcp / dt'] = (Wcp_des - Wcp) / tau_cp # Estimation at the first order. elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dWcp / dt'] = (Wcp_des - Wcp) / tau_cp # Estimation at the first order. else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dWcp / dt'] = 0 # Anode and cathode humidifiers evolution if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dWa_inj / dt'] = 0 dif_eq['dWc_inj / dt'] = (Wc_inj_des - Wc_inj) / tau_hum # Estimation at the first order. elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dWa_inj / dt'] = (Wa_inj_des - Wa_inj) / tau_hum # Estimation at the first order. dif_eq['dWc_inj / dt'] = (Wc_inj_des - Wc_inj) / tau_hum # Estimation at the first order. else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dWa_inj / dt'], dif_eq['dWc_inj / dt'] = 0, 0","title":"calculate_dyn_air_compressor_and_humidifier_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_dissoved_water_evolution","text":"This function calculates the dynamic evolution of the dissolved water in the membrane and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Hmem ( float ) \u2013 Thickness of the membrane (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the catalyst layer. S_sorp_acl ( float ) \u2013 Water sorption in the anode catalyst layer (mol.m-3.s-1) S_sorp_ccl ( float ) \u2013 Water sorption in the cathode catalyst layer (mol.m-3.s-1) J_lambda_mem_acl ( float ) \u2013 Dissolved water flow between the membrane and the anode catalyst layer (mol.m-2.s-1) J_lambda_mem_ccl ( float ) \u2013 Dissolved water flow between the membrane and the cathode catalyst layer (mol.m-2.s-1) Sp_acl ( float ) \u2013 Water produced in the membrane at the ACL through the chemical reaction and crossover (mol.m-3.s-1) Sp_ccl ( float ) \u2013 Water produced in the membrane at the CCL through the chemical reaction and crossover (mol.m-3.s-1) Source code in model/dif_eq.py def calculate_dyn_dissoved_water_evolution(dif_eq, Hmem, Hcl, epsilon_mc, S_sorp_acl, S_sorp_ccl, J_lambda_mem_acl, J_lambda_mem_ccl, Sp_acl, Sp_ccl, **kwargs): \"\"\" This function calculates the dynamic evolution of the dissolved water in the membrane and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Hmem : float Thickness of the membrane (m). Hcl : float Thickness of the catalyst layer (m). epsilon_mc : float Volume fraction of ionomer in the catalyst layer. S_sorp_acl : float Water sorption in the anode catalyst layer (mol.m-3.s-1) S_sorp_ccl : float Water sorption in the cathode catalyst layer (mol.m-3.s-1) J_lambda_mem_acl : float Dissolved water flow between the membrane and the anode catalyst layer (mol.m-2.s-1) J_lambda_mem_ccl : float Dissolved water flow between the membrane and the cathode catalyst layer (mol.m-2.s-1) Sp_acl : float Water produced in the membrane at the ACL through the chemical reaction and crossover (mol.m-3.s-1) Sp_ccl : float Water produced in the membrane at the CCL through the chemical reaction and crossover (mol.m-3.s-1) \"\"\" dif_eq['dlambda_acl / dt'] = M_eq / (rho_mem * epsilon_mc) * (-J_lambda_mem_acl / Hcl + S_sorp_acl + Sp_acl) dif_eq['dlambda_mem / dt'] = M_eq / rho_mem * (J_lambda_mem_acl - J_lambda_mem_ccl) / Hmem dif_eq['dlambda_ccl / dt'] = M_eq / (rho_mem * epsilon_mc) * (J_lambda_mem_ccl / Hcl + S_sorp_ccl + Sp_ccl)","title":"calculate_dyn_dissoved_water_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_liquid_water_evolution","text":"This function calculates the dynamic evolution of the liquid water in the gas diffusion and catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. rho_H2O ( float ) \u2013 Density of water (kg.m-3). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. Jl_agdl_agdl ( list ) \u2013 Liquid water flow between two nodes of the anode GDL (kg.m-2.s-1). Jl_agdl_acl ( float ) \u2013 Liquid water flow between the anode GDL and the anode CL (kg.m-2.s-1). Jl_ccl_cgdl ( float ) \u2013 Liquid water flow between the cathode CL and the cathode GDL (kg.m-2.s-1). Jl_cgdl_cgdl ( list ) \u2013 Liquid water flow between two nodes of the cathode GDL (kg.m-2.s-1). Sl_agdl ( list ) \u2013 Liquid water produced in the anode GDL (kg.m-3.s-1). Sl_acl ( float ) \u2013 Liquid water produced in the anode CL (kg.m-3.s-1). Sl_ccl ( float ) \u2013 Liquid water produced in the cathode CL (kg.m-3.s-1). Sl_cgdl ( list ) \u2013 Liquid water produced in the cathode GDL (kg.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_liquid_water_evolution(dif_eq, rho_H2O, Hgdl, Hcl, epsilon_gdl, n_gdl, Jl_agdl_agdl, Jl_agdl_acl, Jl_ccl_cgdl, Jl_cgdl_cgdl, Sl_agdl, Sl_acl, Sl_ccl, Sl_cgdl, **kwargs): \"\"\" This function calculates the dynamic evolution of the liquid water in the gas diffusion and catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. rho_H2O : float Density of water (kg.m-3). Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. Jl_agdl_agdl : list Liquid water flow between two nodes of the anode GDL (kg.m-2.s-1). Jl_agdl_acl : float Liquid water flow between the anode GDL and the anode CL (kg.m-2.s-1). Jl_ccl_cgdl : float Liquid water flow between the cathode CL and the cathode GDL (kg.m-2.s-1). Jl_cgdl_cgdl : list Liquid water flow between two nodes of the cathode GDL (kg.m-2.s-1). Sl_agdl : list Liquid water produced in the anode GDL (kg.m-3.s-1). Sl_acl : float Liquid water produced in the anode CL (kg.m-3.s-1). Sl_ccl : float Liquid water produced in the cathode CL (kg.m-3.s-1). Sl_cgdl : list Liquid water produced in the cathode GDL (kg.m-3.s-1). \"\"\" # At the anode side # Inside the AGDL dif_eq['ds_agdl_1 / dt'] = 0 # Dirichlet boundary condition. s_agdl_1 is initialized to 0 and remains constant. for i in range(2, n_gdl): dif_eq[f'ds_agdl_{i} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_agdl_agdl[i - 1] - Jl_agdl_agdl[i]) / (Hgdl / n_gdl) + M_H2O * Sl_agdl[i]) dif_eq[f'ds_agdl_{n_gdl} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_agdl_agdl[n_gdl - 1] - Jl_agdl_acl) / (Hgdl / n_gdl) + M_H2O * Sl_agdl[n_gdl]) # Inside the ACL dif_eq['ds_acl / dt'] = 1 / (rho_H2O * epsilon_cl) * (Jl_agdl_acl / Hcl + M_H2O * Sl_acl) # At the cathode side # Inside the CCL dif_eq['ds_ccl / dt'] = 1 / (rho_H2O * epsilon_cl) * (- Jl_ccl_cgdl / Hcl + M_H2O * Sl_ccl) # Inside the CGDL dif_eq['ds_cgdl_1 / dt'] = 1 / (rho_H2O * epsilon_gdl) * ((Jl_ccl_cgdl - Jl_cgdl_cgdl[1]) / (Hgdl / n_gdl) + M_H2O * Sl_cgdl[1]) for i in range(2, n_gdl): dif_eq[f'ds_cgdl_{i} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_cgdl_cgdl[i - 1] - Jl_cgdl_cgdl[i]) / (Hgdl / n_gdl) + M_H2O * Sl_cgdl[i]) dif_eq[f'ds_cgdl_{n_gdl} / dt'] = 0 # Dirichlet boundary condition. s_cgdl_n_gdl is initialized to 0 and remains","title":"calculate_dyn_liquid_water_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_manifold_pressure_and_humidity_evolution","text":"This function calculates the dynamic evolution of the pressure and humidity inside the manifolds. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Masm ( float ) \u2013 Molar mass of all the gaseous species inside the anode supply manifold (kg.mol-1). Maem ( float ) \u2013 Molar mass of all the gaseous species inside the anode exhaust manifold (kg.mol-1). Mcsm ( float ) \u2013 Molar mass of all the gaseous species inside the cathode supply manifold (kg.mol-1). Mcem ( float ) \u2013 Molar mass of all the gaseous species inside the cathode exhaust manifold (kg.mol-1). Tfc ( float ) \u2013 Fuel cell temperature (K). Hgc ( float ) \u2013 Thickness of the gas channel (m). Wgc ( float ) \u2013 Width of the gas channel (m). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Jv_a_in ( float ) \u2013 Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Water vapor flow at the cathode outlet (mol.m-2.s-1). Wasm_in ( float ) \u2013 Flow at the anode supply manifold inlet (kg.s-1). Wasm_out ( float ) \u2013 Flow at the anode supply manifold outlet (kg.s-1). Waem_in ( float ) \u2013 Flow at the anode exhaust manifold inlet (kg.s-1). Waem_out ( float ) \u2013 Flow at the anode exhaust manifold outlet (kg.s-1). Wcsm_in ( float ) \u2013 Flow at the cathode supply manifold inlet (kg.s-1). Wcsm_out ( float ) \u2013 Flow at the cathode supply manifold outlet (kg.s-1). Wcem_in ( float ) \u2013 Flow at the cathode exhaust manifold inlet (kg.s-1). Wcem_out ( float ) \u2013 Flow at the cathode exhaust manifold outlet (kg.s-1). Ware ( float ) \u2013 Anode side recirculation flow (kg.s-1). Wv_asm_in ( float ) \u2013 Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out ( float ) \u2013 Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in ( float ) \u2013 Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out ( float ) \u2013 Vapor flow at the cathode external manifold outlet (mol.s-1). Source code in model/dif_eq.py def calculate_dyn_manifold_pressure_and_humidity_evolution(dif_eq, Masm, Maem, Mcsm, Mcem, Tfc, Hgc, Wgc, type_auxiliary, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out, **kwargs): \"\"\"This function calculates the dynamic evolution of the pressure and humidity inside the manifolds. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Masm : float Molar mass of all the gaseous species inside the anode supply manifold (kg.mol-1). Maem : float Molar mass of all the gaseous species inside the anode exhaust manifold (kg.mol-1). Mcsm : float Molar mass of all the gaseous species inside the cathode supply manifold (kg.mol-1). Mcem : float Molar mass of all the gaseous species inside the cathode exhaust manifold (kg.mol-1). Tfc : float Fuel cell temperature (K). Hgc : float Thickness of the gas channel (m). Wgc : float Width of the gas channel (m). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Jv_a_in : float Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out : float Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in : float Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out : float Water vapor flow at the cathode outlet (mol.m-2.s-1). Wasm_in : float Flow at the anode supply manifold inlet (kg.s-1). Wasm_out : float Flow at the anode supply manifold outlet (kg.s-1). Waem_in : float Flow at the anode exhaust manifold inlet (kg.s-1). Waem_out : float Flow at the anode exhaust manifold outlet (kg.s-1). Wcsm_in : float Flow at the cathode supply manifold inlet (kg.s-1). Wcsm_out : float Flow at the cathode supply manifold outlet (kg.s-1). Wcem_in : float Flow at the cathode exhaust manifold inlet (kg.s-1). Wcem_out : float Flow at the cathode exhaust manifold outlet (kg.s-1). Ware : float Anode side recirculation flow (kg.s-1). Wv_asm_in : float Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out : float Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in : float Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out : float Vapor flow at the cathode external manifold outlet (mol.s-1). \"\"\" # Pressure evolution inside the manifolds if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dPasm / dt'] = (Wasm_in + Ware - n_cell * Wasm_out) / (Vsm * Masm) * R * Tfc dif_eq['dPaem / dt'] = (n_cell * Waem_in - Ware - Waem_out) / (Vem * Maem) * R * Tfc dif_eq['dPcsm / dt'] = (Wcsm_in - n_cell * Wcsm_out) / (Vsm * Mcsm) * R * Tfc dif_eq['dPcem / dt'] = (n_cell * Wcem_in - Wcem_out) / (Vem * Mcem) * R * Tfc elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dPasm / dt'] = (Wasm_in - n_cell * Wasm_out) / (Vsm * Masm) * R * Tfc dif_eq['dPaem / dt'] = (n_cell * Waem_in - Waem_out) / (Vem * Maem) * R * Tfc dif_eq['dPcsm / dt'] = (Wcsm_in - n_cell * Wcsm_out) / (Vsm * Mcsm) * R * Tfc dif_eq['dPcem / dt'] = (n_cell * Wcem_in - Wcem_out) / (Vem * Mcem) * R * Tfc else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dPasm / dt'], dif_eq['dPaem / dt'], dif_eq['dPcsm / dt'], dif_eq['dPcem / dt'] = 0, 0, 0, 0 # Humidity evolution inside the manifolds if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dPhi_asm / dt'] = (Wv_asm_in - Jv_a_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_aem / dt'] = (Jv_a_out * Hgc * Wgc * n_cell - Wv_asm_in - Wv_aem_out) / Vem * R * Tfc / Psat(Tfc) dif_eq['dPhi_csm / dt'] = (Wv_csm_in - Jv_c_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_cem / dt'] = (Jv_c_out * Hgc * Wgc * n_cell - Wv_cem_out) / Vem * R * Tfc / Psat(Tfc) elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dPhi_asm / dt'] = (Wv_asm_in - Jv_a_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_aem / dt'] = (Jv_a_out * Hgc * Wgc * n_cell - Wv_aem_out) / Vem * R * Tfc / Psat(Tfc) dif_eq['dPhi_csm / dt'] = (Wv_csm_in - Jv_c_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_cem / dt'] = (Jv_c_out * Hgc * Wgc * n_cell - Wv_cem_out) / Vem * R * Tfc / Psat(Tfc) else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dPhi_asm / dt'], dif_eq['dPhi_aem / dt'], dif_eq['dPhi_csm / dt'], dif_eq['dPhi_cem / dt'] = 0, 0, 0, 0","title":"calculate_dyn_manifold_pressure_and_humidity_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_throttle_area_evolution","text":"This function calculates the dynamic evolution of the throttle area inside the anode and cathode auxiliaries. This function has to be executed after 'calculate_dyn_vapor_evolution' and 'calculate_dyn_H2_O2_N2_evolution'. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Pagc ( float ) \u2013 Pressure inside the anode gas channel (Pa). Pcgc ( float ) \u2013 Pressure inside the cathode gas channel (Pa). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Abp_a ( float ) \u2013 Throttle area inside the anode auxiliaries (m2). Abp_c ( float ) \u2013 Throttle area inside the cathode auxiliaries (m2). Tfc ( float ) \u2013 Fuel cell temperature (K). Pa_des ( float ) \u2013 Desired pressure inside the anode gas channel (Pa). Pc_des ( float ) \u2013 Desired pressure inside the cathode gas channel (Pa). Source code in model/dif_eq.py def calculate_dyn_throttle_area_evolution(dif_eq, Pagc, Pcgc, type_auxiliary, Abp_a, Abp_c, Tfc, Pa_des, Pc_des, **kwargs): \"\"\"This function calculates the dynamic evolution of the throttle area inside the anode and cathode auxiliaries. This function has to be executed after 'calculate_dyn_vapor_evolution' and 'calculate_dyn_H2_O2_N2_evolution'. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Pagc : float Pressure inside the anode gas channel (Pa). Pcgc : float Pressure inside the cathode gas channel (Pa). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Abp_a : float Throttle area inside the anode auxiliaries (m2). Abp_c : float Throttle area inside the cathode auxiliaries (m2). Tfc : float Fuel cell temperature (K). Pa_des : float Desired pressure inside the anode gas channel (Pa). Pc_des : float Desired pressure inside the cathode gas channel (Pa). \"\"\" # Calculation of the pressure derivative inside the gas channels dPagcdt = (dif_eq['dC_v_agc / dt'] + dif_eq['dC_H2_agc / dt']) * R * Tfc dPcgcdt = (dif_eq['dC_v_cgc / dt'] + dif_eq['dC_O2_cgc / dt'] + dif_eq['dC_N2 / dt']) * R * Tfc # Throttle area evolution inside the anode auxiliaries if type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dAbp_a / dt'] = - Kp * (Pa_des - Pagc) + Kd * dPagcdt # PD controller if Abp_a > A_T and dif_eq['dAbp_a / dt'] > 0: # The throttle area cannot be higher than the maximum value dif_eq['dAbp_a / dt'] = 0 elif Abp_a < 0 and dif_eq['dAbp_a / dt'] < 0: # The throttle area cannot be lower than 0 dif_eq['dAbp_a / dt'] = 0 else: # elif type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ # type_auxiliary == \"no_auxiliary\": dif_eq['dAbp_a / dt'] = 0 # The throttle area is not considered # Throttle area evolution inside the cathode auxiliaries if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dAbp_c / dt'] = - Kp * (Pc_des - Pcgc) + Kd * dPcgcdt # PD controller if Abp_c > A_T and dif_eq['dAbp_c / dt'] > 0: # The throttle area cannot be higher than the maximum value dif_eq['dAbp_c / dt'] = 0 elif Abp_c < 0 and dif_eq['dAbp_c / dt'] < 0: # The throttle area cannot be lower than 0 dif_eq['dAbp_c / dt'] = 0 else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dAbp_a / dt'] = 0 # The throttle area is not considered","title":"calculate_dyn_throttle_area_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_vapor_evolution","text":"This function calculates the dynamic evolution of the vapor in the gas channels, the gas diffusion layers and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). Hgc ( float ) \u2013 Thickness of the gas channel (m). Lgc ( float ) \u2013 Length of the gas channel (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. Jv_a_in ( float ) \u2013 Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Water vapor flow at the cathode outlet (mol.m-2.s-1). Jv_agc_agdl ( float ) \u2013 Water vapor flow between the anode gas channel and the anode GDL (mol.m-2.s-1). Jv_agdl_agdl ( list ) \u2013 Water vapor flow between two nodes of the anode GDL (mol.m-2.s-1). Jv_agdl_acl ( float ) \u2013 Water vapor flow between the anode GDL and the anode CL (mol.m-2.s-1). S_sorp_acl \u2013 Water vapor sorption in the anode CL (mol.m-3.s-1). S_sorp_ccl \u2013 Water vapor sorption in the cathode CL (mol.m-3.s-1). Jv_ccl_cgdl ( float ) \u2013 Water vapor flow between the cathode CL and the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgdl ( list ) \u2013 Water vapor flow between two nodes of the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgc ( float ) \u2013 Water vapor flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). Sv_agdl ( list ) \u2013 Water vapor produced in the anode GDL (mol.m-3.s-1). Sv_acl ( float ) \u2013 Water vapor produced in the anode CL (mol.m-3.s-1). Sv_ccl ( float ) \u2013 Water vapor produced in the cathode CL (mol.m-3.s-1). Sv_cgdl ( list ) \u2013 Water vapor produced in the cathode GDL (mol.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_vapor_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Jv_agc_agdl, Jv_agdl_agdl, Jv_agdl_acl, S_sorp_acl, S_sorp_ccl, Jv_ccl_cgdl, Jv_cgdl_cgdl, Jv_cgdl_cgc, Sv_agdl, Sv_acl, Sv_ccl, Sv_cgdl, **kwargs): \"\"\"This function calculates the dynamic evolution of the vapor in the gas channels, the gas diffusion layers and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). Hgc : float Thickness of the gas channel (m). Lgc : float Length of the gas channel (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. Jv_a_in : float Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out : float Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in : float Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out : float Water vapor flow at the cathode outlet (mol.m-2.s-1). Jv_agc_agdl : float Water vapor flow between the anode gas channel and the anode GDL (mol.m-2.s-1). Jv_agdl_agdl : list Water vapor flow between two nodes of the anode GDL (mol.m-2.s-1). Jv_agdl_acl : float Water vapor flow between the anode GDL and the anode CL (mol.m-2.s-1). S_sorp_acl: float Water vapor sorption in the anode CL (mol.m-3.s-1). S_sorp_ccl: float Water vapor sorption in the cathode CL (mol.m-3.s-1). Jv_ccl_cgdl : float Water vapor flow between the cathode CL and the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgdl : list Water vapor flow between two nodes of the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgc : float Water vapor flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). Sv_agdl : list Water vapor produced in the anode GDL (mol.m-3.s-1). Sv_acl : float Water vapor produced in the anode CL (mol.m-3.s-1). Sv_ccl : float Water vapor produced in the cathode CL (mol.m-3.s-1). Sv_cgdl : list Water vapor produced in the cathode GDL (mol.m-3.s-1). \"\"\" # At the anode side # Inside the AGC dif_eq['dC_v_agc / dt'] = (Jv_a_in - Jv_a_out) / Lgc - Jv_agc_agdl / Hgc # Inside the AGDL dif_eq['dC_v_agdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_agdl_1'])) * \\ ((Jv_agc_agdl - Jv_agdl_agdl[1]) / (Hgdl / n_gdl) + Sv_agdl[1]) for i in range(2, n_gdl): dif_eq[f'dC_v_agdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{i}'])) * \\ ((Jv_agdl_agdl[i - 1] - Jv_agdl_agdl[i]) / (Hgdl / n_gdl) + Sv_agdl[i]) dif_eq[f'dC_v_agdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{n_gdl}'])) * \\ ((Jv_agdl_agdl[n_gdl - 1] - Jv_agdl_acl) / (Hgdl / n_gdl) + Sv_agdl[n_gdl]) # Inside the ACL dif_eq['dC_v_acl / dt'] = 1 / (epsilon_cl * (1 - sv['s_acl'])) * (Jv_agdl_acl / Hcl - S_sorp_acl + Sv_acl) # At the cathode side # Inside the CCL dif_eq['dC_v_ccl / dt'] = 1 / (epsilon_cl * (1 - sv['s_ccl'])) * (- Jv_ccl_cgdl / Hcl - S_sorp_ccl + Sv_ccl) # Inside the CGDL dif_eq['dC_v_cgdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_cgdl_1'])) * \\ ((Jv_ccl_cgdl - Jv_cgdl_cgdl[1]) / (Hgdl / n_gdl) + Sv_cgdl[1]) for i in range(2, n_gdl): dif_eq[f'dC_v_cgdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{i}'])) * \\ ((Jv_cgdl_cgdl[i - 1] - Jv_cgdl_cgdl[i]) / (Hgdl / n_gdl) + Sv_cgdl[i]) dif_eq[f'dC_v_cgdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{n_gdl}'])) * \\ ((Jv_cgdl_cgdl[n_gdl - 1] - Jv_cgdl_cgc) / (Hgdl / n_gdl) + Sv_cgdl[n_gdl]) # Inside the CGC dif_eq['dC_v_cgc / dt'] = (Jv_c_in - Jv_c_out) / Lgc + Jv_cgdl_cgc / Hgc","title":"calculate_dyn_vapor_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_voltage_evolution","text":"This function calculates the dynamic evolution of the cell overpotential eta_c. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. i_fc ( float ) \u2013 Fuel cell current density (A.m-2). C_O2_ccl ( float ) \u2013 Oxygen concentration in the cathode catalyst layer (mol.m-3). eta_c ( float ) \u2013 Cell overpotential (V). Tfc ( float ) \u2013 Fuel cell temperature (K). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode (A.m-2). kappa_c ( float ) \u2013 Overpotential correction exponent. C_scl ( float ) \u2013 Volumetric space-charge layer capacitance (F.m-3). i_n ( float ) \u2013 Crossover current density (A.m-2). f_drop ( float ) \u2013 Liquid water induced voltage drop function. Source code in model/dif_eq.py def calculate_dyn_voltage_evolution(dif_eq, i_fc, C_O2_ccl, eta_c, Tfc, Hcl, i0_c_ref, kappa_c, C_scl, i_n, f_drop, **kwargs): \"\"\"This function calculates the dynamic evolution of the cell overpotential eta_c. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. i_fc : float Fuel cell current density (A.m-2). C_O2_ccl : float Oxygen concentration in the cathode catalyst layer (mol.m-3). eta_c : float Cell overpotential (V). Tfc : float Fuel cell temperature (K). Hcl : float Thickness of the catalyst layer (m). i0_c_ref : float Reference exchange current density at the cathode (A.m-2). kappa_c : float Overpotential correction exponent. C_scl : float Volumetric space-charge layer capacitance (F.m-3). i_n : float Crossover current density (A.m-2). f_drop : float Liquid water induced voltage drop function. \"\"\" dif_eq['deta_c / dt'] = 1 / (C_scl * Hcl) * ((i_fc + i_n) - i0_c_ref * (C_O2_ccl / C_O2ref) ** kappa_c * np.exp(f_drop * alpha_c * F / (R * Tfc) * eta_c))","title":"calculate_dyn_voltage_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.dydt","text":"This function gives the system of differential equations to solve. Parameters: t ( float ) \u2013 Time (s). y ( ndarray ) \u2013 Numpy list of the solver variables. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. solver_variable_names ( list ) \u2013 Names of the solver variables. control_variables ( dict ) \u2013 Variables controlled by the user. Returns: dydt ( list ) \u2013 List containing the derivative of the solver variables. Source code in model/dif_eq.py def dydt(t, y, operating_inputs, parameters, solver_variable_names, control_variables): \"\"\"This function gives the system of differential equations to solve. Parameters ---------- t : float Time (s). y : numpy.ndarray Numpy list of the solver variables. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. solver_variable_names : list Names of the solver variables. control_variables : dict Variables controlled by the user. Returns ------- dydt : list List containing the derivative of the solver variables. \"\"\" # Creation of the dif_eq dictionary. It is an intermediate calculation to simplify the writing of the code. dif_eq = {('d' + key + ' / dt'): 0 for key in solver_variable_names} # Creation of the solver_variables dict. It is an intermediate calculation to simplify the writing of the code. solver_variables = {} for index, key in enumerate(solver_variable_names): solver_variables[key] = y[index] # Modifications of the operating conditions in real time, if required. if parameters[\"type_control\"] != \"no_control\": control_operating_conditions(t, solver_variables, operating_inputs, parameters, control_variables) # Intermediate values i_fc = operating_inputs['current_density'](t, parameters) Mext, Pagc, Pcgc, i_n, Masm, Maem, Mcsm, Mcem, rho_H2O = dif_eq_int_values(solver_variables, control_variables, operating_inputs, parameters) Wcp_des, Wa_inj_des, Wc_inj_des = desired_flows(solver_variables, control_variables, i_n, i_fc, operating_inputs, parameters, Mext) eta_c_intermediate_values = calculate_eta_c_intermediate_values(solver_variables, operating_inputs, parameters) # Calculation of the flows flows_dico = calculate_flows(t, solver_variables, control_variables, i_fc, operating_inputs, parameters) # Calculation of the dynamic evolutions # Inside the cell calculate_dyn_dissoved_water_evolution(dif_eq, **parameters, **flows_dico) calculate_dyn_liquid_water_evolution(dif_eq, rho_H2O, **parameters, **flows_dico) calculate_dyn_vapor_evolution(dif_eq, solver_variables, **parameters, **flows_dico) calculate_dyn_H2_O2_N2_evolution(dif_eq, solver_variables, **parameters, **flows_dico) calculate_dyn_voltage_evolution(dif_eq, i_fc, **solver_variables, **operating_inputs, **parameters, **eta_c_intermediate_values) # Inside the auxiliary components calculate_dyn_manifold_pressure_and_humidity_evolution(dif_eq, Masm, Maem, Mcsm, Mcem, **solver_variables, **operating_inputs, **parameters, **flows_dico) calculate_dyn_air_compressor_and_humidifier_evolution(dif_eq, Wcp_des, Wa_inj_des, Wc_inj_des, **solver_variables, **parameters) calculate_dyn_throttle_area_evolution(dif_eq, Pagc, Pcgc, **solver_variables, **operating_inputs, **parameters) # dif_eq is converted to dydt because the solver requires an ordered list to work dydt = [] for key in solver_variable_names: dydt.append(dif_eq['d' + key + ' / dt']) return dydt","title":"dydt"},{"location":"functions/model/flows/","text":"Flows This file represents all the flows inside the fuel cell system. It is a component of the fuel cell model. calculate_flows(t, sv, control_variables, i_fc, operating_inputs, parameters) This function calculates the flows inside the fuel cell system. Parameters: t ( float ) \u2013 Time (s). sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. control_variables ( dict ) \u2013 Variables controlled by the user. i_fc ( float ) \u2013 Fuel cell current density at time t (A.m-2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: dict \u2013 Flows inside the fuel cell system. Source code in model/flows.py def calculate_flows(t, sv, control_variables, i_fc, operating_inputs, parameters): \"\"\"This function calculates the flows inside the fuel cell system. Parameters ---------- t : float Time (s). sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. control_variables : dict Variables controlled by the user. i_fc : float Fuel cell current density at time t (A.m-2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- dict Flows inside the fuel cell system. \"\"\" # ___________________________________________________Preliminaries__________________________________________________ # Extraction of the variables C_v_agc, C_v_acl, C_v_ccl, C_v_cgc = sv['C_v_agc'], sv['C_v_acl'], sv['C_v_ccl'], sv['C_v_cgc'] s_acl, s_ccl = sv['s_acl'], sv['s_ccl'] lambda_acl, lambda_mem, lambda_ccl = sv['lambda_acl'], sv['lambda_mem'], sv['lambda_ccl'] C_H2_agc, C_H2_acl, C_O2_ccl, C_O2_cgc = sv['C_H2_agc'], sv['C_H2_acl'], sv['C_O2_ccl'], sv['C_O2_cgc'] C_N2 = sv['C_N2'] # Extraction of the operating inputs and parameters Tfc, Pc_des = operating_inputs['Tfc'], operating_inputs['Pc_des'] Hgdl, Hmem, Hcl = parameters['Hgdl'], parameters['Hmem'], parameters['Hcl'] Hgc, Wgc = parameters['Hgc'], parameters['Wgc'] epsilon_gdl, epsilon_c = parameters['epsilon_gdl'], parameters['epsilon_c'] e, kappa_co, n_gdl = parameters['e'], parameters['kappa_co'], parameters['n_gdl'] a_slim, b_slim = parameters['a_slim'], parameters['b_slim'] # Intermediate values (Pagc, Pcgc, s_agdl_agdl, s_agdl_acl, s_ccl_cgdl, s_cgdl_cgdl, epsilon_mean, theta_c_mean, lambda_acl_mem, lambda_mem_ccl, Pagc_agdl, Pagdl_agdl, Pagdl_acl, Pccl_cgdl, Pcgdl_cgdl, Pcgdl_cgc, nu_l) \\ = flows_int_values(sv, operating_inputs, parameters) # Inlet and outlet flows Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, \\ Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, \\ Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out \\ = auxiliaries(t, sv, control_variables, i_fc, operating_inputs, parameters) # ________________________________________Dissolved water flows (mol.m-2.s-1)_______________________________________ # Anode side J_lambda_mem_acl = 2.5 / 22 * i_fc / F * lambda_acl_mem - 2 * rho_mem / M_eq * \\ D(lambda_acl_mem) * (lambda_mem - lambda_acl) / (Hmem + Hcl) # Cathode side J_lambda_mem_ccl = 2.5 / 22 * i_fc / F * lambda_mem_ccl - 2 * rho_mem / M_eq * \\ D(lambda_mem_ccl) * (lambda_ccl - lambda_mem) / (Hmem + Hcl) # _________________________________________Liquid water flows (kg.m-2.s-1)__________________________________________ # Anode side Jl_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jl_agdl_agdl[i] = - sigma(Tfc) * K0(epsilon_gdl, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_gdl)) * \\ (epsilon_gdl / K0(epsilon_gdl, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_agdl_agdl[i] ** e + 1e-7) * (1.417 - 4.24 * s_agdl_agdl[i] + 3.789 * s_agdl_agdl[i] ** 2) * \\ (sv[f's_agdl_{i + 1}'] - sv[f's_agdl_{i}']) / (Hgdl / n_gdl) Jl_agdl_acl = - 2 * sigma(Tfc) * K0(epsilon_mean, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_mean)) * \\ (epsilon_mean / K0(epsilon_mean, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_agdl_acl ** e + 1e-7) * (1.417 - 4.24 * s_agdl_acl + 3.789 * s_agdl_acl ** 2) * \\ (s_acl - sv[f's_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side Jl_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jl_cgdl_cgdl[i] = - sigma(Tfc) * K0(epsilon_gdl, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_gdl)) * \\ (epsilon_gdl / K0(epsilon_gdl, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_cgdl_cgdl[i] ** e + 1e-7) * (1.417 - 4.24 * s_cgdl_cgdl[i] + 3.789 * s_cgdl_cgdl[i] ** 2) * \\ (sv[f's_cgdl_{i + 1}'] - sv[f's_cgdl_{i}']) / (Hgdl / n_gdl) Jl_ccl_cgdl = - 2 * sigma(Tfc) * K0(epsilon_mean, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_mean)) * \\ (epsilon_mean / K0(epsilon_mean, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_ccl_cgdl ** e + 1e-7) * (1.417 - 4.24 * s_ccl_cgdl + 3.789 * s_ccl_cgdl ** 2) * \\ (sv['s_cgdl_1'] - s_ccl) / (Hgdl / n_gdl + Hcl) # _____________________________________________Vapor flows (mol.m-2.s-1)____________________________________________ # Convective vapor flows # Anode side Jv_agc_agdl = h_a(Pagc_agdl, Tfc, Wgc, Hgc) * (C_v_agc - sv['C_v_agdl_1']) # Cathode side Jv_cgdl_cgc = h_c(Pcgdl_cgc, Tfc, Wgc, Hgc) * (sv[f'C_v_cgdl_{n_gdl}'] - C_v_cgc) # Conductive vapor flows # Anode side Jv_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jv_agdl_agdl[i] = - Da_eff(s_agdl_agdl[i], epsilon_gdl, Pagdl_agdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_v_agdl_{i + 1}'] - sv[f'C_v_agdl_{i}']) / (Hgdl / n_gdl) Jv_agdl_acl = - 2 * Da_eff(s_agdl_acl, epsilon_mean, Pagdl_acl, Tfc, epsilon_c, epsilon_gdl) * \\ (C_v_acl - sv[f'C_v_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side Jv_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jv_cgdl_cgdl[i] = - Dc_eff(s_cgdl_cgdl[i], epsilon_gdl, Pcgdl_cgdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_v_cgdl_{i + 1}'] - sv[f'C_v_cgdl_{i}']) / (Hgdl / n_gdl) Jv_ccl_cgdl = - 2 * Dc_eff(s_ccl_cgdl, epsilon_mean, Pccl_cgdl, Tfc, epsilon_c, epsilon_gdl) * \\ (sv['C_v_cgdl_1'] - C_v_ccl) / (Hgdl / n_gdl + Hcl) # __________________________________________H2 and O2 flows (mol.m-2.s-1)___________________________________________ # Hydrogen and oxygen consumption # Anode side S_H2_acl = - i_fc / (2 * F * Hcl) - \\ R * Tfc / (Hmem * Hcl) * (k_H2(lambda_mem, Tfc, kappa_co) * C_H2_acl + 2 * k_O2(lambda_mem, Tfc, kappa_co) * C_O2_ccl) # Cathode side S_O2_ccl = - i_fc / (4 * F * Hcl) - \\ R * Tfc / (Hmem * Hcl) * (k_O2(lambda_mem, Tfc, kappa_co) * C_O2_ccl + 1 / 2 * k_H2(lambda_mem, Tfc, kappa_co) * C_H2_acl) # Conductive-convective H2 and O2 flows # Anode side J_H2_agc_agdl = h_a(Pagc_agdl, Tfc, Wgc, Hgc) * (C_H2_agc - sv['C_H2_agdl_1']) # Cathode side J_O2_cgdl_cgc = h_c(Pcgdl_cgc, Tfc, Wgc, Hgc) * (sv[f'C_O2_cgdl_{n_gdl}'] - C_O2_cgc) # Conductive H2 and O2 flows # Anode side J_H2_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): J_H2_agdl_agdl[i] = - Da_eff(s_agdl_agdl[i], epsilon_gdl, Pagdl_agdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_H2_agdl_{i + 1}'] - sv[f'C_H2_agdl_{i}']) / (Hgdl / n_gdl) J_H2_agdl_acl = - 2 * Da_eff(s_agdl_acl, epsilon_mean, Pagdl_acl, Tfc, epsilon_c, epsilon_gdl) * \\ (C_H2_acl - sv[f'C_H2_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side J_O2_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): J_O2_cgdl_cgdl[i] = - Dc_eff(s_cgdl_cgdl[i], epsilon_gdl, Pcgdl_cgdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_O2_cgdl_{i + 1}'] - sv[f'C_O2_cgdl_{i}']) / (Hgdl / n_gdl) J_O2_ccl_cgdl = - 2 * Dc_eff(s_ccl_cgdl, epsilon_mean, Pccl_cgdl, Tfc, epsilon_c, epsilon_gdl) * \\ (sv['C_O2_cgdl_1'] - C_O2_ccl) / (Hgdl / n_gdl + Hcl) # __________________________________________Water generated (mol.m-3.s-1)___________________________________________ # Water produced in the membrane at the CL through the chemical reaction and crossover # Anode side Sp_acl = 2 * k_O2(lambda_mem, Tfc, kappa_co) * R * Tfc / (Hmem * Hcl) * C_O2_ccl # Cathode side Sp_ccl = i_fc / (2 * F * Hcl) + k_H2(lambda_mem, Tfc, kappa_co) * R * Tfc / (Hmem * Hcl) * C_H2_acl # Water sorption in the CL: # Anode side S_sorp_acl = gamma_sorp(C_v_acl, s_acl, lambda_acl, Tfc, Hcl, Kshape) * rho_mem / M_eq * \\ (lambda_eq(C_v_acl, s_acl, Tfc, Kshape) - lambda_acl) # Cathode side S_sorp_ccl = gamma_sorp(C_v_ccl, s_ccl, lambda_ccl, Tfc, Hcl, Kshape) * rho_mem / M_eq * \\ (lambda_eq(C_v_ccl, s_ccl, Tfc, Kshape) - lambda_ccl) # Liquid water generated through vapor condensation or degenerated through evaporation # Anode side Sl_agdl = [None] + [Svl(sv[f's_agdl_{i}'], sv[f'C_v_agdl_{i}'], sv[f'C_v_agdl_{i}'] + sv[f'C_H2_agdl_{i}'], epsilon_gdl, Tfc, gamma_cond, gamma_evap) for i in range(1, n_gdl + 1)] Sl_acl = Svl(s_acl, C_v_acl, C_v_acl + C_H2_acl, epsilon_cl, Tfc, gamma_cond, gamma_evap) # Cathode side Sl_cgdl = [None] + [Svl(sv[f's_cgdl_{i}'], sv[f'C_v_cgdl_{i}'], sv[f'C_v_cgdl_{i}'] + sv[f'C_O2_cgdl_{i}'] + C_N2, epsilon_gdl, Tfc, gamma_cond, gamma_evap) for i in range(1, n_gdl + 1)] Sl_ccl = Svl(s_ccl, C_v_ccl, C_v_ccl + C_O2_ccl + C_N2, epsilon_cl, Tfc, gamma_cond, gamma_evap) # Vapor generated through liquid water evaporation or degenerated through condensation # Anode side Sv_agdl = [None] + [-x for x in Sl_agdl[1:]] Sv_acl = - Sl_acl # Cathode side Sv_cgdl = [None] + [-x for x in Sl_cgdl[1:]] Sv_ccl = - Sl_ccl return {'Jv_a_in': Jv_a_in, 'Jv_a_out': Jv_a_out, 'Jv_c_in': Jv_c_in, 'Jv_c_out': Jv_c_out, 'J_H2_in': J_H2_in, 'J_H2_out': J_H2_out, 'J_O2_in': J_O2_in, 'J_O2_out': J_O2_out, 'J_N2_in': J_N2_in, 'J_N2_out': J_N2_out, 'Jv_agc_agdl': Jv_agc_agdl, 'Jv_agdl_agdl': Jv_agdl_agdl, 'Jv_agdl_acl': Jv_agdl_acl, 'S_sorp_acl': S_sorp_acl, 'S_sorp_ccl': S_sorp_ccl, 'Jv_ccl_cgdl': Jv_ccl_cgdl, 'Jv_cgdl_cgdl': Jv_cgdl_cgdl, 'Jv_cgdl_cgc': Jv_cgdl_cgc, 'Jl_agdl_agdl': Jl_agdl_agdl, 'Jl_agdl_acl': Jl_agdl_acl, 'J_lambda_mem_acl': J_lambda_mem_acl, 'J_lambda_mem_ccl': J_lambda_mem_ccl, 'Jl_ccl_cgdl': Jl_ccl_cgdl, 'Jl_cgdl_cgdl': Jl_cgdl_cgdl, 'Sp_acl': Sp_acl, 'Sp_ccl': Sp_ccl, 'J_H2_agc_agdl': J_H2_agc_agdl, 'J_H2_agdl_agdl': J_H2_agdl_agdl, 'J_H2_agdl_acl': J_H2_agdl_acl, 'J_O2_ccl_cgdl': J_O2_ccl_cgdl, 'J_O2_cgdl_cgdl': J_O2_cgdl_cgdl, 'J_O2_cgdl_cgc': J_O2_cgdl_cgc, 'S_H2_acl': S_H2_acl, 'S_O2_ccl': S_O2_ccl, 'Sv_agdl': Sv_agdl, 'Sv_acl': Sv_acl, 'Sv_ccl': Sv_ccl, 'Sv_cgdl': Sv_cgdl, 'Sl_agdl': Sl_agdl, 'Sl_acl': Sl_acl, 'Sl_ccl': Sl_ccl, 'Sl_cgdl': Sl_cgdl, 'Pagc': Pagc, 'Pcgc': Pcgc, 'Wasm_in': Wasm_in, 'Wasm_out': Wasm_out, 'Waem_in': Waem_in, 'Waem_out': Waem_out, 'Wcsm_in': Wcsm_in, 'Wcsm_out': Wcsm_out, 'Wcem_in': Wcem_in, 'Wcem_out': Wcem_out, 'Ware': Ware, 'Wv_asm_in': Wv_asm_in, 'Wv_aem_out': Wv_aem_out, 'Wv_csm_in': Wv_csm_in, 'Wv_cem_out': Wv_cem_out}","title":"Flows"},{"location":"functions/model/flows/#flows","text":"This file represents all the flows inside the fuel cell system. It is a component of the fuel cell model.","title":"Flows"},{"location":"functions/model/flows/#model.flows.calculate_flows","text":"This function calculates the flows inside the fuel cell system. Parameters: t ( float ) \u2013 Time (s). sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. control_variables ( dict ) \u2013 Variables controlled by the user. i_fc ( float ) \u2013 Fuel cell current density at time t (A.m-2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: dict \u2013 Flows inside the fuel cell system. Source code in model/flows.py def calculate_flows(t, sv, control_variables, i_fc, operating_inputs, parameters): \"\"\"This function calculates the flows inside the fuel cell system. Parameters ---------- t : float Time (s). sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. control_variables : dict Variables controlled by the user. i_fc : float Fuel cell current density at time t (A.m-2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- dict Flows inside the fuel cell system. \"\"\" # ___________________________________________________Preliminaries__________________________________________________ # Extraction of the variables C_v_agc, C_v_acl, C_v_ccl, C_v_cgc = sv['C_v_agc'], sv['C_v_acl'], sv['C_v_ccl'], sv['C_v_cgc'] s_acl, s_ccl = sv['s_acl'], sv['s_ccl'] lambda_acl, lambda_mem, lambda_ccl = sv['lambda_acl'], sv['lambda_mem'], sv['lambda_ccl'] C_H2_agc, C_H2_acl, C_O2_ccl, C_O2_cgc = sv['C_H2_agc'], sv['C_H2_acl'], sv['C_O2_ccl'], sv['C_O2_cgc'] C_N2 = sv['C_N2'] # Extraction of the operating inputs and parameters Tfc, Pc_des = operating_inputs['Tfc'], operating_inputs['Pc_des'] Hgdl, Hmem, Hcl = parameters['Hgdl'], parameters['Hmem'], parameters['Hcl'] Hgc, Wgc = parameters['Hgc'], parameters['Wgc'] epsilon_gdl, epsilon_c = parameters['epsilon_gdl'], parameters['epsilon_c'] e, kappa_co, n_gdl = parameters['e'], parameters['kappa_co'], parameters['n_gdl'] a_slim, b_slim = parameters['a_slim'], parameters['b_slim'] # Intermediate values (Pagc, Pcgc, s_agdl_agdl, s_agdl_acl, s_ccl_cgdl, s_cgdl_cgdl, epsilon_mean, theta_c_mean, lambda_acl_mem, lambda_mem_ccl, Pagc_agdl, Pagdl_agdl, Pagdl_acl, Pccl_cgdl, Pcgdl_cgdl, Pcgdl_cgc, nu_l) \\ = flows_int_values(sv, operating_inputs, parameters) # Inlet and outlet flows Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, \\ Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, \\ Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out \\ = auxiliaries(t, sv, control_variables, i_fc, operating_inputs, parameters) # ________________________________________Dissolved water flows (mol.m-2.s-1)_______________________________________ # Anode side J_lambda_mem_acl = 2.5 / 22 * i_fc / F * lambda_acl_mem - 2 * rho_mem / M_eq * \\ D(lambda_acl_mem) * (lambda_mem - lambda_acl) / (Hmem + Hcl) # Cathode side J_lambda_mem_ccl = 2.5 / 22 * i_fc / F * lambda_mem_ccl - 2 * rho_mem / M_eq * \\ D(lambda_mem_ccl) * (lambda_ccl - lambda_mem) / (Hmem + Hcl) # _________________________________________Liquid water flows (kg.m-2.s-1)__________________________________________ # Anode side Jl_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jl_agdl_agdl[i] = - sigma(Tfc) * K0(epsilon_gdl, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_gdl)) * \\ (epsilon_gdl / K0(epsilon_gdl, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_agdl_agdl[i] ** e + 1e-7) * (1.417 - 4.24 * s_agdl_agdl[i] + 3.789 * s_agdl_agdl[i] ** 2) * \\ (sv[f's_agdl_{i + 1}'] - sv[f's_agdl_{i}']) / (Hgdl / n_gdl) Jl_agdl_acl = - 2 * sigma(Tfc) * K0(epsilon_mean, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_mean)) * \\ (epsilon_mean / K0(epsilon_mean, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_agdl_acl ** e + 1e-7) * (1.417 - 4.24 * s_agdl_acl + 3.789 * s_agdl_acl ** 2) * \\ (s_acl - sv[f's_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side Jl_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jl_cgdl_cgdl[i] = - sigma(Tfc) * K0(epsilon_gdl, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_gdl)) * \\ (epsilon_gdl / K0(epsilon_gdl, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_cgdl_cgdl[i] ** e + 1e-7) * (1.417 - 4.24 * s_cgdl_cgdl[i] + 3.789 * s_cgdl_cgdl[i] ** 2) * \\ (sv[f's_cgdl_{i + 1}'] - sv[f's_cgdl_{i}']) / (Hgdl / n_gdl) Jl_ccl_cgdl = - 2 * sigma(Tfc) * K0(epsilon_mean, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_mean)) * \\ (epsilon_mean / K0(epsilon_mean, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_ccl_cgdl ** e + 1e-7) * (1.417 - 4.24 * s_ccl_cgdl + 3.789 * s_ccl_cgdl ** 2) * \\ (sv['s_cgdl_1'] - s_ccl) / (Hgdl / n_gdl + Hcl) # _____________________________________________Vapor flows (mol.m-2.s-1)____________________________________________ # Convective vapor flows # Anode side Jv_agc_agdl = h_a(Pagc_agdl, Tfc, Wgc, Hgc) * (C_v_agc - sv['C_v_agdl_1']) # Cathode side Jv_cgdl_cgc = h_c(Pcgdl_cgc, Tfc, Wgc, Hgc) * (sv[f'C_v_cgdl_{n_gdl}'] - C_v_cgc) # Conductive vapor flows # Anode side Jv_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jv_agdl_agdl[i] = - Da_eff(s_agdl_agdl[i], epsilon_gdl, Pagdl_agdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_v_agdl_{i + 1}'] - sv[f'C_v_agdl_{i}']) / (Hgdl / n_gdl) Jv_agdl_acl = - 2 * Da_eff(s_agdl_acl, epsilon_mean, Pagdl_acl, Tfc, epsilon_c, epsilon_gdl) * \\ (C_v_acl - sv[f'C_v_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side Jv_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jv_cgdl_cgdl[i] = - Dc_eff(s_cgdl_cgdl[i], epsilon_gdl, Pcgdl_cgdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_v_cgdl_{i + 1}'] - sv[f'C_v_cgdl_{i}']) / (Hgdl / n_gdl) Jv_ccl_cgdl = - 2 * Dc_eff(s_ccl_cgdl, epsilon_mean, Pccl_cgdl, Tfc, epsilon_c, epsilon_gdl) * \\ (sv['C_v_cgdl_1'] - C_v_ccl) / (Hgdl / n_gdl + Hcl) # __________________________________________H2 and O2 flows (mol.m-2.s-1)___________________________________________ # Hydrogen and oxygen consumption # Anode side S_H2_acl = - i_fc / (2 * F * Hcl) - \\ R * Tfc / (Hmem * Hcl) * (k_H2(lambda_mem, Tfc, kappa_co) * C_H2_acl + 2 * k_O2(lambda_mem, Tfc, kappa_co) * C_O2_ccl) # Cathode side S_O2_ccl = - i_fc / (4 * F * Hcl) - \\ R * Tfc / (Hmem * Hcl) * (k_O2(lambda_mem, Tfc, kappa_co) * C_O2_ccl + 1 / 2 * k_H2(lambda_mem, Tfc, kappa_co) * C_H2_acl) # Conductive-convective H2 and O2 flows # Anode side J_H2_agc_agdl = h_a(Pagc_agdl, Tfc, Wgc, Hgc) * (C_H2_agc - sv['C_H2_agdl_1']) # Cathode side J_O2_cgdl_cgc = h_c(Pcgdl_cgc, Tfc, Wgc, Hgc) * (sv[f'C_O2_cgdl_{n_gdl}'] - C_O2_cgc) # Conductive H2 and O2 flows # Anode side J_H2_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): J_H2_agdl_agdl[i] = - Da_eff(s_agdl_agdl[i], epsilon_gdl, Pagdl_agdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_H2_agdl_{i + 1}'] - sv[f'C_H2_agdl_{i}']) / (Hgdl / n_gdl) J_H2_agdl_acl = - 2 * Da_eff(s_agdl_acl, epsilon_mean, Pagdl_acl, Tfc, epsilon_c, epsilon_gdl) * \\ (C_H2_acl - sv[f'C_H2_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side J_O2_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): J_O2_cgdl_cgdl[i] = - Dc_eff(s_cgdl_cgdl[i], epsilon_gdl, Pcgdl_cgdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_O2_cgdl_{i + 1}'] - sv[f'C_O2_cgdl_{i}']) / (Hgdl / n_gdl) J_O2_ccl_cgdl = - 2 * Dc_eff(s_ccl_cgdl, epsilon_mean, Pccl_cgdl, Tfc, epsilon_c, epsilon_gdl) * \\ (sv['C_O2_cgdl_1'] - C_O2_ccl) / (Hgdl / n_gdl + Hcl) # __________________________________________Water generated (mol.m-3.s-1)___________________________________________ # Water produced in the membrane at the CL through the chemical reaction and crossover # Anode side Sp_acl = 2 * k_O2(lambda_mem, Tfc, kappa_co) * R * Tfc / (Hmem * Hcl) * C_O2_ccl # Cathode side Sp_ccl = i_fc / (2 * F * Hcl) + k_H2(lambda_mem, Tfc, kappa_co) * R * Tfc / (Hmem * Hcl) * C_H2_acl # Water sorption in the CL: # Anode side S_sorp_acl = gamma_sorp(C_v_acl, s_acl, lambda_acl, Tfc, Hcl, Kshape) * rho_mem / M_eq * \\ (lambda_eq(C_v_acl, s_acl, Tfc, Kshape) - lambda_acl) # Cathode side S_sorp_ccl = gamma_sorp(C_v_ccl, s_ccl, lambda_ccl, Tfc, Hcl, Kshape) * rho_mem / M_eq * \\ (lambda_eq(C_v_ccl, s_ccl, Tfc, Kshape) - lambda_ccl) # Liquid water generated through vapor condensation or degenerated through evaporation # Anode side Sl_agdl = [None] + [Svl(sv[f's_agdl_{i}'], sv[f'C_v_agdl_{i}'], sv[f'C_v_agdl_{i}'] + sv[f'C_H2_agdl_{i}'], epsilon_gdl, Tfc, gamma_cond, gamma_evap) for i in range(1, n_gdl + 1)] Sl_acl = Svl(s_acl, C_v_acl, C_v_acl + C_H2_acl, epsilon_cl, Tfc, gamma_cond, gamma_evap) # Cathode side Sl_cgdl = [None] + [Svl(sv[f's_cgdl_{i}'], sv[f'C_v_cgdl_{i}'], sv[f'C_v_cgdl_{i}'] + sv[f'C_O2_cgdl_{i}'] + C_N2, epsilon_gdl, Tfc, gamma_cond, gamma_evap) for i in range(1, n_gdl + 1)] Sl_ccl = Svl(s_ccl, C_v_ccl, C_v_ccl + C_O2_ccl + C_N2, epsilon_cl, Tfc, gamma_cond, gamma_evap) # Vapor generated through liquid water evaporation or degenerated through condensation # Anode side Sv_agdl = [None] + [-x for x in Sl_agdl[1:]] Sv_acl = - Sl_acl # Cathode side Sv_cgdl = [None] + [-x for x in Sl_cgdl[1:]] Sv_ccl = - Sl_ccl return {'Jv_a_in': Jv_a_in, 'Jv_a_out': Jv_a_out, 'Jv_c_in': Jv_c_in, 'Jv_c_out': Jv_c_out, 'J_H2_in': J_H2_in, 'J_H2_out': J_H2_out, 'J_O2_in': J_O2_in, 'J_O2_out': J_O2_out, 'J_N2_in': J_N2_in, 'J_N2_out': J_N2_out, 'Jv_agc_agdl': Jv_agc_agdl, 'Jv_agdl_agdl': Jv_agdl_agdl, 'Jv_agdl_acl': Jv_agdl_acl, 'S_sorp_acl': S_sorp_acl, 'S_sorp_ccl': S_sorp_ccl, 'Jv_ccl_cgdl': Jv_ccl_cgdl, 'Jv_cgdl_cgdl': Jv_cgdl_cgdl, 'Jv_cgdl_cgc': Jv_cgdl_cgc, 'Jl_agdl_agdl': Jl_agdl_agdl, 'Jl_agdl_acl': Jl_agdl_acl, 'J_lambda_mem_acl': J_lambda_mem_acl, 'J_lambda_mem_ccl': J_lambda_mem_ccl, 'Jl_ccl_cgdl': Jl_ccl_cgdl, 'Jl_cgdl_cgdl': Jl_cgdl_cgdl, 'Sp_acl': Sp_acl, 'Sp_ccl': Sp_ccl, 'J_H2_agc_agdl': J_H2_agc_agdl, 'J_H2_agdl_agdl': J_H2_agdl_agdl, 'J_H2_agdl_acl': J_H2_agdl_acl, 'J_O2_ccl_cgdl': J_O2_ccl_cgdl, 'J_O2_cgdl_cgdl': J_O2_cgdl_cgdl, 'J_O2_cgdl_cgc': J_O2_cgdl_cgc, 'S_H2_acl': S_H2_acl, 'S_O2_ccl': S_O2_ccl, 'Sv_agdl': Sv_agdl, 'Sv_acl': Sv_acl, 'Sv_ccl': Sv_ccl, 'Sv_cgdl': Sv_cgdl, 'Sl_agdl': Sl_agdl, 'Sl_acl': Sl_acl, 'Sl_ccl': Sl_ccl, 'Sl_cgdl': Sl_cgdl, 'Pagc': Pagc, 'Pcgc': Pcgc, 'Wasm_in': Wasm_in, 'Wasm_out': Wasm_out, 'Waem_in': Waem_in, 'Waem_out': Waem_out, 'Wcsm_in': Wcsm_in, 'Wcsm_out': Wcsm_out, 'Wcem_in': Wcem_in, 'Wcem_out': Wcem_out, 'Ware': Ware, 'Wv_asm_in': Wv_asm_in, 'Wv_aem_out': Wv_aem_out, 'Wv_csm_in': Wv_csm_in, 'Wv_cem_out': Wv_cem_out}","title":"calculate_flows"},{"location":"functions/modules/GUI_modules/","text":"GUI modules This module contains some of the required functions for the GUI.py file. 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, choices_buttons) This function is called when the user selects a specific option from a dropdown menu for the type of fuel cell. Depending on the selected option, it either hides or displays specific input fields (labels or entry widgets) on the GUI. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choices_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def 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, choices_buttons): \"\"\"This function is called when the user selects a specific option from a dropdown menu for the type of fuel cell. Depending on the selected option, it either hides or displays specific input fields (labels or entry widgets) on the GUI. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. choices_buttons : dict A dictionary containing the button information. \"\"\" if choices_buttons['type_fuel_cell']['value'].get() != 'Enter your specifications': # Recovers the new settings recover_for_display_operating_inputs_and_physical_parameters(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choices_buttons) # Display the labels for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Label(operating_conditions_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Label(accessible_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Label(undetermined_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Label(current_density_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Label(computing_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) else: # choices_buttons['type_fuel_cell']['value'].get() == 'Enter your specifications': # Saves and displays the user entries for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Entry(operating_conditions_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Entry(accessible_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Entry(undetermined_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Entry(current_density_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Entry(computing_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) 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) This function displays labels on the GUI, representing operating conditions and physical parameters, without their actual values. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. Source code in modules/GUI_modules.py def 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): \"\"\"This function displays labels on the GUI, representing operating conditions and physical parameters, without their actual values. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # Display the titles ttk.Label(operating_conditions_frame, text='Operating conditions', font=('cmr10', 12, 'bold')). \\ grid(row=1, column=0, columnspan=6, ipady=15) ttk.Label(accessible_parameters_frame, text='Accessible physical parameters', font=('cmr10', 12, 'bold')). \\ grid(row=0, column=0, columnspan=6, ipady=15) # Display the labels for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Label(operating_conditions_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Label(accessible_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Label(undetermined_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Label(current_density_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # computing parameters for k, v in choice_computing_parameters.items(): ttk.Label(computing_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") 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) This function displays entry widgets on the GUI. There, the user can enter values for operating conditions and physical parameters. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. Source code in modules/GUI_modules.py def 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): \"\"\"This function displays entry widgets on the GUI. There, the user can enter values for operating conditions and physical parameters. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # Display the value for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Entry(operating_conditions_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Entry(accessible_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Entry(undetermined_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Entry(current_density_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Entry(computing_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) display_radiobuttons(model_possibilities_frame, choices_buttons) This function displays radiobuttons on the GUI, allowing the user to make choices for control, results display, plot style, etc. Parameters: model_possibilities_frame ( Frame ) \u2013 The frame where the graphical elements for the model possibilities and the choice of current density are placed. choices_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def display_radiobuttons(model_possibilities_frame, choices_buttons): \"\"\"This function displays radiobuttons on the GUI, allowing the user to make choices for control, results display, plot style, etc. Parameters ---------- model_possibilities_frame : ttk.Frame The frame where the graphical elements for the model possibilities and the choice of current density are placed. choices_buttons : dict A dictionary containing the button information. \"\"\" ttk.Label(model_possibilities_frame, text='Model possibilities', font=('cmr10', 12, 'bold')) \\ .grid(row=0, column=0, columnspan=6, ipady=15) # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Auxiliaries: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=0, columnspan=1, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No auxiliaries', value=0, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Forced-convective cathode\\nwith anodic recirculation', value=1, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Forced-convective cathode\\nwith flow-through anode', value=2, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Control: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_control']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No control', value=0, variable=choices_buttons['type_control']['value']). \\ grid(row=choices_buttons['type_control']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Humidity', value=1, variable=choices_buttons['type_control']['value']). \\ grid(row=choices_buttons['type_control']['label_row'], column=3, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Purge: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_purge']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No purge', value=0, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Periodic', value=1, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Constant', value=2, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Display: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_display']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No display', value=0, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Synthetic', value=1, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Multiple', value=2, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Plot: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_plot']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Fixed', value=0, variable=choices_buttons['type_plot']['value']). \\ grid(row=choices_buttons['type_plot']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Dynamic', value=1, variable=choices_buttons['type_plot']['value']). \\ grid(row=choices_buttons['type_plot']['label_row'], column=3, sticky=\"w\") launch_AlphaPEM_for_EIS_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) Launch the AlphaPEM simulator for an EIS current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_EIS_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for an EIS current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None t0_EIS, t_new_start, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # These are used for EIS max_step # actualization. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is a list of all the frequency tested. n = len(t_new_start) # It is the plot update number. time_interval = [0, t0_EIS] # It is the initial time interval. # A preliminary simulation run is necessary to equilibrate the internal variables of the cell at i_EIS # prior to initiating the EIS. Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization t0_EIS_temp = t0_EIS # It is the initial time for 1 EIS point. tf_EIS_temp = t_new_start[0] + delta_t_break_EIS[0] + delta_t_measurement_EIS[0] # It is the final time for # 1 EIS point. n_inf = np.where(t_new_start <= t0_EIS_temp)[0][-1] # It is the number of frequency changes which has been # made. max_step = 1 / (f[n_inf] * nb_points_EIS) # max_step is actualized according to the current frequency # for increased calculation time_interval = [t0_EIS_temp, tf_EIS_temp] # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_EIS_temp = Simulator.variables['t'][-1] # It is the initial time for 1 EIS point. tf_EIS_temp = t_new_start[i + 1] + delta_t_break_EIS[i + 1] + delta_t_measurement_EIS[i + 1] # It # is the final time for 1 EIS point. n_inf = np.where(t_new_start <= t0_EIS_temp)[0][-1] # It is the number of frequency changes which # has been made. max_step = 1 / (f[n_inf] * nb_points_EIS) # max_step is actualized according to the current # frequency for increased calculation time_interval = [t0_EIS_temp, tf_EIS_temp] # It is the time interval for 1 EIS point. # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3) launch_AlphaPEM_for_polarization_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) Launch the AlphaPEM simulator for a polarization current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_polarization_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for a polarization current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Dynamic display requires a dedicated use of the AlphaPEM class. if type_plot == \"dynamic\": # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola delta_t = delta_t_load_pola + delta_t_break_pola # s. It is the time of one load. tf = delta_t_ini_pola + int(i_max_pola_1 / delta_i_pola + 1) * delta_t # s. It is the polarization current # duration. n = int(tf / delta_t) # It is the plot update number. time_interval = [0, delta_t_ini_pola + delta_t] # It is the initial time interval. # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_interval = Simulator.variables['t'][-1] tf_interval = delta_t_ini_pola + (i + 2) * delta_t time_interval = [t0_interval, tf_interval] # Reset of the time interval # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) else: # elif type_plot == \"fixed\": # Simulation Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3) launch_AlphaPEM_for_step_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) Launch the AlphaPEM simulator for a step current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_step_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for a step current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Dynamic display requires a dedicated use of the AlphaPEM class. if type_plot == \"dynamic\": # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = t_step n = int(tf_step / delta_t_dyn_step) # It is the plot update number. time_interval = [0, delta_t_dyn_step] # It is the initial time interval. # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_interval = Simulator.variables['t'][-1] tf_interval = (i + 2) * delta_t_dyn_step time_interval = [t0_interval, tf_interval] # Reset of the time interval # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) else: # elif type_plot == \"fixed\": # Simulation Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3) recover_for_display_operating_inputs_and_physical_parameters(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons) This function retrieves parameter values for predefined stacks (e.g., \"EH-31 1.5 bar (2021)\", \"Biao Xie 1.0 bar (2015)\", etc.) and converts them to appropriate units for display on the GUI. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def recover_for_display_operating_inputs_and_physical_parameters(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons): \"\"\"This function retrieves parameter values for predefined stacks (e.g., \"EH-31 1.5 bar (2021)\", \"Biao Xie 1.0 bar (2015)\", etc.) and converts them to appropriate units for display on the GUI. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" if choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 1.5 bar (2021)\": type_fuel_cell = \"EH-31_1.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.0 bar (2021)\": type_fuel_cell = \"EH-31_2.0\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.25 bar (2021)\": type_fuel_cell = \"EH-31_2.25\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.5 bar (2021)\": type_fuel_cell = \"EH-31_2.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Linhao Fan (2010)\": type_fuel_cell = \"LF\" Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola = stored_operating_inputs(type_fuel_cell) Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, \\ a_slim, b_slim, a_switch, C_scl = \\ stored_physical_parameters(type_fuel_cell) # operating conditions recovery choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].set(np.round(Tfc - 273.15)) # \u00b0C choice_operating_conditions['Anode pressure - Pa (bar)']['value'].set(np.round(Pa_des / 1e5, 2)) # bar choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].set(np.round(Pc_des / 1e5, 2)) # bar choice_operating_conditions['Anode stoichiometry - Sa']['value'].set(np.round(Sa, 1)) choice_operating_conditions['Cathode stoichiometry - Sc']['value'].set(np.round(Sc, 1)) choice_operating_conditions['Anode humidity - \u03a6a']['value'].set(np.round(Phi_a_des, 1)) choice_operating_conditions['Cathode humidity - \u03a6c']['value'].set(np.round(Phi_c_des, 1)) # accessible physical parameters recovery choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].set(np.round(Aact * 1e4)) # cm\u00b2 choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].set(np.round(Hgdl * 1e6)) # \u00b5m choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].set(np.round(Hcl * 1e6)) # \u00b5m choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].set(np.round(Hmem * 1e6)) # \u00b5m choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].set(np.round(Hgc * 1e6)) # \u00b5m choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].set(np.round(Wgc * 1e6)) # \u00b5m choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].set(np.round(Lgc, 2)) # \u00b5m # undetermined physical parameters recovery choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].set(np.round(epsilon_gdl, 3)) choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].set(np.round(epsilon_mc, 3)) choice_undetermined_parameters['Tortuosity - \u03c4']['value'].set(np.round(tau, 3)) choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].set(np.round(epsilon_c, 3)) choice_undetermined_parameters['Capillary exponent - e']['value'].set(e) choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].set(np.round(Re * 1e6, 2)) # \u00b5\u03a9.m\u00b2 choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].set(np.round(i0_c_ref, 2)) # A.m-2 choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].set(np.round(kappa_co, 2)) # mol.m-1.s-1.Pa-1 choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].set(np.round(kappa_c, 2)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].set(np.round(a_slim, 7)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].set(np.round(b_slim, 7)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].set(np.round(a_switch, 7)) choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].set(np.round(C_scl * 1e-6, 2)) # F.cm-3 # i_max_pola recovery choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].set(np.round(i_max_pola / 1e4, 2)) # A/cm\u00b2 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) This function retrieves and converts the parameter values from the GUI into standard units for further calculations. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def 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): \"\"\"This function retrieves and converts the parameter values from the GUI into standard units for further calculations. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # operating conditions Tfc = choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].get() + 273.15 # K Pa_des = choice_operating_conditions['Anode pressure - Pa (bar)']['value'].get() * 1e5 # Pa Pc_des = choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() * 1e5 # Pa Sa = choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() Sc = choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() Phi_a_des = choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() Phi_c_des = choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() # accessible physical parameters Aact = choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].get() * 1e-4 # m\u00b2 Hgdl = choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() * 1e-6 # m Hcl = choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() * 1e-6 # m Hmem = choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() * 1e-6 # m Hgc = choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() * 1e-6 # m Wgc = choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() * 1e-6 # m Lgc = choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() # m # undetermined physical parameters epsilon_gdl = choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() epsilon_mc = choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() tau = choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() epsilon_c = choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() e = choice_undetermined_parameters['Capillary exponent - e']['value'].get() Re = choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() * 1e-6 # ohm.m\u00b2 i0_c_ref = choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() # A.m-2 kappa_co = choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() # mol.m-1.s-1.Pa-1 kappa_c = choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() a_slim = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() b_slim = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() a_switch = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() C_scl = choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() * 1e6 # F.m-3 # current density parameters t_step = (choice_current_density_parameters['Initial time - t0_step (s)']['value'].get(), choice_current_density_parameters['Final time - tf_step (s)']['value'].get(), choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get(), choice_computing_parameters['Time for dynamic\\ndisplay - \u0394t_dyn_step (s)']['value'].get()) # (s, s, s, s) i_step = (choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() * 1e4, choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get() * 1e4) # (A.m-2, A.m-2) i_max_pola = choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() * 1e4 # A.m-2 delta_pola = (choice_current_density_parameters['Loading time\\n- \u0394t_load_pola (s)']['value'].get(), choice_current_density_parameters['Breaking time\\n- \u0394t_break_pola (s)']['value'].get(), choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() * 1e4, choice_current_density_parameters['Initial breaking time\\n- \u0394t_ini_pola (s)']['value'].get()) # (s, s, A.m-2, s) i_EIS = choice_current_density_parameters['Static current\\n- i_EIS (A/cm\u00b2)']['value'].get() * 1e4 # (A.m-2) ratio_EIS = choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() / 100 f_EIS = (choice_current_density_parameters['Power of the\\ninitial frequency\\n- f_power_min_EIS']['value'].get(), choice_current_density_parameters['Power of the\\nfinal frequency\\n- f_power_max_EIS']['value'].get(), choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get(), choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get()) t_EIS = EIS_parameters(f_EIS) # Time parameters for the EIS_current density function. t_purge = choice_computing_parameters['Purge time - t_purge (s)']['value'].get() # s delta_t_purge = choice_computing_parameters['Time between two purges\\n- \u0394t_purge (s)']['value'].get() # s max_step = choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() # s n_gdl = choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get() if choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 1.5 bar (2021)\": type_fuel_cell = \"EH-31_1.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.0 bar (2021)\": type_fuel_cell = \"EH-31_2.0\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.25 bar (2021)\": type_fuel_cell = \"EH-31_2.25\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.5 bar (2021)\": type_fuel_cell = \"EH-31_2.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Linhao Fan (2010)\": type_fuel_cell = \"LF\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Enter your specifications\": type_fuel_cell = \"manual_setup\" if choice_buttons['type_auxiliary']['value'].get() == 0: type_auxiliary = \"no_auxiliary\" elif choice_buttons['type_auxiliary']['value'].get() == 1: type_auxiliary = \"forced-convective_cathode_with_anodic_recirculation\" else: type_auxiliary = \"forced-convective_cathode_with_flow-through_anode\" if choice_buttons['type_control']['value'].get() == 0: type_control = \"no_control\" else: type_control = \"Phi_des\" if choice_buttons['type_purge']['value'].get() == 0: type_purge = \"no_purge\" elif choice_buttons['type_purge']['value'].get() == 1: type_purge = \"periodic_purge\" else: type_purge = \"constant_purge\" if choice_buttons['type_display']['value'].get() == 0: type_display = \"no_display\" elif choice_buttons['type_display']['value'].get() == 1: type_display = \"synthetic\" else: type_display = \"multiple\" if choice_buttons['type_plot']['value'].get() == 0: type_plot = \"fixed\" else: type_plot = \"dynamic\" return (Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, Aact, Hgdl, Hcl, Hmem, Hgc, Wgc, Lgc, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, t_purge, delta_t_purge, max_step, n_gdl, type_fuel_cell, type_auxiliary, type_control, type_purge, type_display, type_plot) set_equal_width(frame1, frame2, frame3, frame4, frame5, frame6) Adjusts the width of the frames to be equal based on their maximum width. Parameters: frame1 ( Frame ) \u2013 The first frame to be resized. frame2 ( Frame ) \u2013 The second frame to be resized. frame3 ( Frame ) \u2013 The third frame to be resized. frame4 ( Frame ) \u2013 The fourth frame to be resized. frame5 ( Frame ) \u2013 The fifth frame to be resized. frame6 ( Frame ) \u2013 The sixth frame to be resized. Source code in modules/GUI_modules.py def set_equal_width(frame1, frame2, frame3, frame4, frame5, frame6): \"\"\" Adjusts the width of the frames to be equal based on their maximum width. Parameters ---------- frame1 : ttk.Frame The first frame to be resized. frame2 : ttk.Frame The second frame to be resized. frame3 : ttk.Frame The third frame to be resized. frame4 : ttk.Frame The fourth frame to be resized. frame5 : ttk.Frame The fifth frame to be resized. frame6 : ttk.Frame The sixth frame to be resized. \"\"\" # Initialisation of the list of widths widths = [] for frame in [frame1, frame2, frame3, frame4, frame5, frame6]: # Update the frame sizes frame.update_idletasks() # Get the current width of all frames widths.append(frame.winfo_width()) # Set all frames to the maximum width for frame in [frame1, frame2, frame3, frame4, frame5, frame6]: for i in range(6): frame.grid_columnconfigure(i, minsize=max(widths) / 5.5) # Set minimum width of all column to max_width / 5 value_control(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons, current_button) This function checks the integrity of the values entered by the user and returns an empty tuple if they are not valid. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in modules/GUI_modules.py def value_control(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons, current_button): \"\"\"This function checks the integrity of the values entered by the user and returns an empty tuple if they are not valid. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # The values entered by the user are checked for compliance if choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].get() < 0: messagebox.showerror(title='Temperatures', message='Negative temperatures do not exist in the Kelvin scale.') choices.clear() return if choice_operating_conditions['Anode pressure - Pa (bar)']['value'].get() < 0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() < 0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() > 5.0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() > 5.0: messagebox.showerror(title='Desired pressures', message='Desired pressure should be positive and bellow 5.0 ' 'bars.') choices.clear() return if choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() < 1 or \\ choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() > 5 or \\ choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() < 1 or \\ choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() > 5: messagebox.showerror(title='Stoichiometric ratios', message='The stoichiometric ratios Sa and Sc should be ' 'between 1 and 5.') choices.clear() return if choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() < 0 or \\ choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() > 1 or \\ choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() < 0 or \\ choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() > 1: messagebox.showerror(title='Desired humidity', message='The desired humidities should be between 0 and 1.') choices.clear() return if choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].get() < 0: messagebox.showerror(title='Active area', message='Negative active area is impossible.') choices.clear() return if choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() > 1000 or \\ choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() > 1000 or \\ choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() > 1000: messagebox.showerror(title='MEA thickness', message='All MEA components generally have a thickness between ' '1\u00b5m and 1mm.') choices.clear() return if choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() < 10 or \\ choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() > 10000 or \\ choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() < 10 or \\ choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() > 10000 or \\ choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() < 0 or \\ choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() > 100: messagebox.showerror(title='GC distances', message='GC generally have a thickness and a width between 10\u00b5m and ' '10mm. Also, GC length is generally between 0 and 100m') choices.clear() return if choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() < 0 or \\ choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() > 1 or \\ choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() < 0 or \\ choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() > 1: messagebox.showerror(title='Porosities', message='All porosities should be between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() < 1 or choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() > 4: messagebox.showerror(title='Pore structure coefficient', message='The pore structure coefficient should be ' 'between 1 and 4.') choices.clear() return if choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() < 0 or \\ choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() > 1: messagebox.showerror(title='Compression ratio', message='The compression ratio should be between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Capillary exponent - e']['value'].get() < 3 or choice_undetermined_parameters['Capillary exponent - e']['value'].get() > 5: messagebox.showerror(title='Capillary exponent', message='The capillary exponent should be between 3 and 5 and ' 'being an integer.') choices.clear() return if choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() < 0.5 or \\ choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() > 5: messagebox.showerror(title='Electron conduction resistance', message='The electron conduction resistance is ' 'generally between 0.5 and 5 \u00b5\u03a9.m\u00b2.') choices.clear() return if choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() < 0.001 or \\ choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() > 500: messagebox.showerror(title='Referenced exchange current density', message='The referenced exchange current ' 'density is generally between 0.001 ' 'and 500 A.m-2.') choices.clear() return if choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() < 0.01 or \\ choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() > 100: messagebox.showerror(title='Crossover correction coefficient', message='The crossover correction coefficient is' ' generally between 0.01 and 100 ' 'mol.m-1.s-1.Pa-1.') choices.clear() return if choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() < 0 or \\ choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() > 100: messagebox.showerror(title='Overpotential correction exponent', message='The overpotential correction exponent ' 'is generally between 0 and 100.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() > 1: messagebox.showerror(title='Slop of slim function', message='The slop of slim function is generally between 0 ' 'and 1.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() > 1: messagebox.showerror(title='Intercept of slim function', message='The intercept of slim function is generally ' 'between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() > 1: messagebox.showerror(title='Slop of switch function', message='The slop of switch function is generally between' ' 0 and 1.') choices.clear() return if choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() < 5 or \\ choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() > 100: messagebox.showerror(title='Double layer capacitance', message='I have not settled yet a range for C_scl.') choices.clear() return if choice_current_density_parameters['Initial time - t0_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Final time - tf_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get() < 0 or \\ choice_computing_parameters['Time for dynamic\\ndisplay - \u0394t_dyn_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Breaking time\\n- \u0394t_break_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Initial breaking time\\n- \u0394t_ini_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Initial time - t0_step (s)']['value'].get() > \\ choice_current_density_parameters['Final time - tf_step (s)']['value'].get() or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get() > \\ (choice_current_density_parameters['Final time - tf_step (s)']['value'].get() - choice_current_density_parameters['Initial time - t0_step (s)']['value'].get()): messagebox.showerror(title='Times', message='The times should be positive, t0_step < tf_step and ' 'delta_t_load_step < (tf_step - t0_step).') choices.clear() return if choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Static current\\n- i_EIS (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() > \\ choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() or \\ choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() > \\ choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get(): messagebox.showerror(title='Current densities', message='The current densities should be positive, ' 'delta_i_pola < i_max_pola and ' 'i_ini_step < i_final_step.') choices.clear() return if choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() < 0 or \\ choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() > 20: messagebox.showerror(title='Ratio EIS', message='Ratio EIS is a percentage of i_EIS and should be between 0 ' 'and 20 for plotting correct EIS.') choices.clear() return if choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get() < 0 or \\ choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get() < 0 or \\ type(choice_current_density_parameters['Power of the\\ninitial frequency\\n- f_power_min_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Power of the\\nfinal frequency\\n- f_power_max_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get()) != int: messagebox.showerror(title='f EIS', message='f_EIS parameters should be integer and number of points should ' 'be positive.') choices.clear() return if choice_computing_parameters['Purge time - t_purge (s)']['value'].get() < 0 or \\ choice_computing_parameters['Time between two purges\\n- \u0394t_purge (s)']['value'].get() < 0: messagebox.showerror(title='Purge times', message='Negative times does not characterise purges.') choices.clear() return if choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() < 0 or \\ choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() > 0.1: messagebox.showerror(title='Max step', message='The max step value for the solver should be positive and lower ' 'than 0.1 for normal use.') choices.clear() return if choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get() < 2 or \\ type(choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get()) != int: messagebox.showerror(title='n gdl', message='The n_gdl value should be an integer bigger than 2. ' 'A good compromise is 10.') choices.clear() return if current_button == 0 and choice_buttons['type_display']['value'].get() == 2 \\ and choice_buttons['type_plot']['value'].get() == 1 : messagebox.showerror(title='n gdl', message='dynamic plot is not thought to be used with step current and ' 'multiple display. There would be too much plots to handle.') choices.clear() return if current_button == 2 and choice_buttons['type_plot']['value'].get() == 0: messagebox.showerror(title='n gdl', message='EIS has to be plot with a dynamic type_plot setting, ' 'because max_step has to be adjusted at each frequency.') choices.clear() return","title":"GUI modules"},{"location":"functions/modules/GUI_modules/#gui-modules","text":"This module contains some of the required functions for the GUI.py file.","title":"GUI modules"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.changeValue","text":"This function is called when the user selects a specific option from a dropdown menu for the type of fuel cell. Depending on the selected option, it either hides or displays specific input fields (labels or entry widgets) on the GUI. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choices_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def 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, choices_buttons): \"\"\"This function is called when the user selects a specific option from a dropdown menu for the type of fuel cell. Depending on the selected option, it either hides or displays specific input fields (labels or entry widgets) on the GUI. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. choices_buttons : dict A dictionary containing the button information. \"\"\" if choices_buttons['type_fuel_cell']['value'].get() != 'Enter your specifications': # Recovers the new settings recover_for_display_operating_inputs_and_physical_parameters(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choices_buttons) # Display the labels for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Label(operating_conditions_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Label(accessible_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Label(undetermined_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Label(current_density_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Label(computing_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) else: # choices_buttons['type_fuel_cell']['value'].get() == 'Enter your specifications': # Saves and displays the user entries for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Entry(operating_conditions_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Entry(accessible_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Entry(undetermined_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Entry(current_density_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Entry(computing_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5)","title":"changeValue"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.display_parameter_labels","text":"This function displays labels on the GUI, representing operating conditions and physical parameters, without their actual values. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. Source code in modules/GUI_modules.py def 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): \"\"\"This function displays labels on the GUI, representing operating conditions and physical parameters, without their actual values. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # Display the titles ttk.Label(operating_conditions_frame, text='Operating conditions', font=('cmr10', 12, 'bold')). \\ grid(row=1, column=0, columnspan=6, ipady=15) ttk.Label(accessible_parameters_frame, text='Accessible physical parameters', font=('cmr10', 12, 'bold')). \\ grid(row=0, column=0, columnspan=6, ipady=15) # Display the labels for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Label(operating_conditions_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Label(accessible_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Label(undetermined_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Label(current_density_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # computing parameters for k, v in choice_computing_parameters.items(): ttk.Label(computing_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\")","title":"display_parameter_labels"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.display_parameters_value","text":"This function displays entry widgets on the GUI. There, the user can enter values for operating conditions and physical parameters. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. Source code in modules/GUI_modules.py def 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): \"\"\"This function displays entry widgets on the GUI. There, the user can enter values for operating conditions and physical parameters. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # Display the value for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Entry(operating_conditions_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Entry(accessible_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Entry(undetermined_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Entry(current_density_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Entry(computing_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5)","title":"display_parameters_value"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.display_radiobuttons","text":"This function displays radiobuttons on the GUI, allowing the user to make choices for control, results display, plot style, etc. Parameters: model_possibilities_frame ( Frame ) \u2013 The frame where the graphical elements for the model possibilities and the choice of current density are placed. choices_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def display_radiobuttons(model_possibilities_frame, choices_buttons): \"\"\"This function displays radiobuttons on the GUI, allowing the user to make choices for control, results display, plot style, etc. Parameters ---------- model_possibilities_frame : ttk.Frame The frame where the graphical elements for the model possibilities and the choice of current density are placed. choices_buttons : dict A dictionary containing the button information. \"\"\" ttk.Label(model_possibilities_frame, text='Model possibilities', font=('cmr10', 12, 'bold')) \\ .grid(row=0, column=0, columnspan=6, ipady=15) # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Auxiliaries: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=0, columnspan=1, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No auxiliaries', value=0, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Forced-convective cathode\\nwith anodic recirculation', value=1, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Forced-convective cathode\\nwith flow-through anode', value=2, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Control: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_control']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No control', value=0, variable=choices_buttons['type_control']['value']). \\ grid(row=choices_buttons['type_control']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Humidity', value=1, variable=choices_buttons['type_control']['value']). \\ grid(row=choices_buttons['type_control']['label_row'], column=3, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Purge: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_purge']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No purge', value=0, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Periodic', value=1, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Constant', value=2, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Display: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_display']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No display', value=0, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Synthetic', value=1, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Multiple', value=2, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Plot: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_plot']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Fixed', value=0, variable=choices_buttons['type_plot']['value']). \\ grid(row=choices_buttons['type_plot']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Dynamic', value=1, variable=choices_buttons['type_plot']['value']). \\ grid(row=choices_buttons['type_plot']['label_row'], column=3, sticky=\"w\")","title":"display_radiobuttons"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.launch_AlphaPEM_for_EIS_current","text":"Launch the AlphaPEM simulator for an EIS current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_EIS_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for an EIS current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None t0_EIS, t_new_start, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # These are used for EIS max_step # actualization. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is a list of all the frequency tested. n = len(t_new_start) # It is the plot update number. time_interval = [0, t0_EIS] # It is the initial time interval. # A preliminary simulation run is necessary to equilibrate the internal variables of the cell at i_EIS # prior to initiating the EIS. Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization t0_EIS_temp = t0_EIS # It is the initial time for 1 EIS point. tf_EIS_temp = t_new_start[0] + delta_t_break_EIS[0] + delta_t_measurement_EIS[0] # It is the final time for # 1 EIS point. n_inf = np.where(t_new_start <= t0_EIS_temp)[0][-1] # It is the number of frequency changes which has been # made. max_step = 1 / (f[n_inf] * nb_points_EIS) # max_step is actualized according to the current frequency # for increased calculation time_interval = [t0_EIS_temp, tf_EIS_temp] # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_EIS_temp = Simulator.variables['t'][-1] # It is the initial time for 1 EIS point. tf_EIS_temp = t_new_start[i + 1] + delta_t_break_EIS[i + 1] + delta_t_measurement_EIS[i + 1] # It # is the final time for 1 EIS point. n_inf = np.where(t_new_start <= t0_EIS_temp)[0][-1] # It is the number of frequency changes which # has been made. max_step = 1 / (f[n_inf] * nb_points_EIS) # max_step is actualized according to the current # frequency for increased calculation time_interval = [t0_EIS_temp, tf_EIS_temp] # It is the time interval for 1 EIS point. # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3)","title":"launch_AlphaPEM_for_EIS_current"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.launch_AlphaPEM_for_polarization_current","text":"Launch the AlphaPEM simulator for a polarization current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_polarization_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for a polarization current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Dynamic display requires a dedicated use of the AlphaPEM class. if type_plot == \"dynamic\": # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola delta_t = delta_t_load_pola + delta_t_break_pola # s. It is the time of one load. tf = delta_t_ini_pola + int(i_max_pola_1 / delta_i_pola + 1) * delta_t # s. It is the polarization current # duration. n = int(tf / delta_t) # It is the plot update number. time_interval = [0, delta_t_ini_pola + delta_t] # It is the initial time interval. # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_interval = Simulator.variables['t'][-1] tf_interval = delta_t_ini_pola + (i + 2) * delta_t time_interval = [t0_interval, tf_interval] # Reset of the time interval # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) else: # elif type_plot == \"fixed\": # Simulation Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3)","title":"launch_AlphaPEM_for_polarization_current"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.launch_AlphaPEM_for_step_current","text":"Launch the AlphaPEM simulator for a step current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_step_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for a step current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Dynamic display requires a dedicated use of the AlphaPEM class. if type_plot == \"dynamic\": # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = t_step n = int(tf_step / delta_t_dyn_step) # It is the plot update number. time_interval = [0, delta_t_dyn_step] # It is the initial time interval. # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_interval = Simulator.variables['t'][-1] tf_interval = (i + 2) * delta_t_dyn_step time_interval = [t0_interval, tf_interval] # Reset of the time interval # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) else: # elif type_plot == \"fixed\": # Simulation Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3)","title":"launch_AlphaPEM_for_step_current"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.recover_for_display_operating_inputs_and_physical_parameters","text":"This function retrieves parameter values for predefined stacks (e.g., \"EH-31 1.5 bar (2021)\", \"Biao Xie 1.0 bar (2015)\", etc.) and converts them to appropriate units for display on the GUI. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def recover_for_display_operating_inputs_and_physical_parameters(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons): \"\"\"This function retrieves parameter values for predefined stacks (e.g., \"EH-31 1.5 bar (2021)\", \"Biao Xie 1.0 bar (2015)\", etc.) and converts them to appropriate units for display on the GUI. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" if choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 1.5 bar (2021)\": type_fuel_cell = \"EH-31_1.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.0 bar (2021)\": type_fuel_cell = \"EH-31_2.0\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.25 bar (2021)\": type_fuel_cell = \"EH-31_2.25\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.5 bar (2021)\": type_fuel_cell = \"EH-31_2.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Linhao Fan (2010)\": type_fuel_cell = \"LF\" Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola = stored_operating_inputs(type_fuel_cell) Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, \\ a_slim, b_slim, a_switch, C_scl = \\ stored_physical_parameters(type_fuel_cell) # operating conditions recovery choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].set(np.round(Tfc - 273.15)) # \u00b0C choice_operating_conditions['Anode pressure - Pa (bar)']['value'].set(np.round(Pa_des / 1e5, 2)) # bar choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].set(np.round(Pc_des / 1e5, 2)) # bar choice_operating_conditions['Anode stoichiometry - Sa']['value'].set(np.round(Sa, 1)) choice_operating_conditions['Cathode stoichiometry - Sc']['value'].set(np.round(Sc, 1)) choice_operating_conditions['Anode humidity - \u03a6a']['value'].set(np.round(Phi_a_des, 1)) choice_operating_conditions['Cathode humidity - \u03a6c']['value'].set(np.round(Phi_c_des, 1)) # accessible physical parameters recovery choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].set(np.round(Aact * 1e4)) # cm\u00b2 choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].set(np.round(Hgdl * 1e6)) # \u00b5m choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].set(np.round(Hcl * 1e6)) # \u00b5m choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].set(np.round(Hmem * 1e6)) # \u00b5m choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].set(np.round(Hgc * 1e6)) # \u00b5m choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].set(np.round(Wgc * 1e6)) # \u00b5m choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].set(np.round(Lgc, 2)) # \u00b5m # undetermined physical parameters recovery choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].set(np.round(epsilon_gdl, 3)) choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].set(np.round(epsilon_mc, 3)) choice_undetermined_parameters['Tortuosity - \u03c4']['value'].set(np.round(tau, 3)) choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].set(np.round(epsilon_c, 3)) choice_undetermined_parameters['Capillary exponent - e']['value'].set(e) choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].set(np.round(Re * 1e6, 2)) # \u00b5\u03a9.m\u00b2 choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].set(np.round(i0_c_ref, 2)) # A.m-2 choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].set(np.round(kappa_co, 2)) # mol.m-1.s-1.Pa-1 choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].set(np.round(kappa_c, 2)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].set(np.round(a_slim, 7)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].set(np.round(b_slim, 7)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].set(np.round(a_switch, 7)) choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].set(np.round(C_scl * 1e-6, 2)) # F.cm-3 # i_max_pola recovery choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].set(np.round(i_max_pola / 1e4, 2)) # A/cm\u00b2","title":"recover_for_display_operating_inputs_and_physical_parameters"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.recover_for_use_operating_inputs_and_physical_parameters","text":"This function retrieves and converts the parameter values from the GUI into standard units for further calculations. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def 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): \"\"\"This function retrieves and converts the parameter values from the GUI into standard units for further calculations. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # operating conditions Tfc = choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].get() + 273.15 # K Pa_des = choice_operating_conditions['Anode pressure - Pa (bar)']['value'].get() * 1e5 # Pa Pc_des = choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() * 1e5 # Pa Sa = choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() Sc = choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() Phi_a_des = choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() Phi_c_des = choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() # accessible physical parameters Aact = choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].get() * 1e-4 # m\u00b2 Hgdl = choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() * 1e-6 # m Hcl = choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() * 1e-6 # m Hmem = choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() * 1e-6 # m Hgc = choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() * 1e-6 # m Wgc = choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() * 1e-6 # m Lgc = choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() # m # undetermined physical parameters epsilon_gdl = choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() epsilon_mc = choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() tau = choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() epsilon_c = choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() e = choice_undetermined_parameters['Capillary exponent - e']['value'].get() Re = choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() * 1e-6 # ohm.m\u00b2 i0_c_ref = choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() # A.m-2 kappa_co = choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() # mol.m-1.s-1.Pa-1 kappa_c = choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() a_slim = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() b_slim = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() a_switch = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() C_scl = choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() * 1e6 # F.m-3 # current density parameters t_step = (choice_current_density_parameters['Initial time - t0_step (s)']['value'].get(), choice_current_density_parameters['Final time - tf_step (s)']['value'].get(), choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get(), choice_computing_parameters['Time for dynamic\\ndisplay - \u0394t_dyn_step (s)']['value'].get()) # (s, s, s, s) i_step = (choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() * 1e4, choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get() * 1e4) # (A.m-2, A.m-2) i_max_pola = choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() * 1e4 # A.m-2 delta_pola = (choice_current_density_parameters['Loading time\\n- \u0394t_load_pola (s)']['value'].get(), choice_current_density_parameters['Breaking time\\n- \u0394t_break_pola (s)']['value'].get(), choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() * 1e4, choice_current_density_parameters['Initial breaking time\\n- \u0394t_ini_pola (s)']['value'].get()) # (s, s, A.m-2, s) i_EIS = choice_current_density_parameters['Static current\\n- i_EIS (A/cm\u00b2)']['value'].get() * 1e4 # (A.m-2) ratio_EIS = choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() / 100 f_EIS = (choice_current_density_parameters['Power of the\\ninitial frequency\\n- f_power_min_EIS']['value'].get(), choice_current_density_parameters['Power of the\\nfinal frequency\\n- f_power_max_EIS']['value'].get(), choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get(), choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get()) t_EIS = EIS_parameters(f_EIS) # Time parameters for the EIS_current density function. t_purge = choice_computing_parameters['Purge time - t_purge (s)']['value'].get() # s delta_t_purge = choice_computing_parameters['Time between two purges\\n- \u0394t_purge (s)']['value'].get() # s max_step = choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() # s n_gdl = choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get() if choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 1.5 bar (2021)\": type_fuel_cell = \"EH-31_1.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.0 bar (2021)\": type_fuel_cell = \"EH-31_2.0\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.25 bar (2021)\": type_fuel_cell = \"EH-31_2.25\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.5 bar (2021)\": type_fuel_cell = \"EH-31_2.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Linhao Fan (2010)\": type_fuel_cell = \"LF\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Enter your specifications\": type_fuel_cell = \"manual_setup\" if choice_buttons['type_auxiliary']['value'].get() == 0: type_auxiliary = \"no_auxiliary\" elif choice_buttons['type_auxiliary']['value'].get() == 1: type_auxiliary = \"forced-convective_cathode_with_anodic_recirculation\" else: type_auxiliary = \"forced-convective_cathode_with_flow-through_anode\" if choice_buttons['type_control']['value'].get() == 0: type_control = \"no_control\" else: type_control = \"Phi_des\" if choice_buttons['type_purge']['value'].get() == 0: type_purge = \"no_purge\" elif choice_buttons['type_purge']['value'].get() == 1: type_purge = \"periodic_purge\" else: type_purge = \"constant_purge\" if choice_buttons['type_display']['value'].get() == 0: type_display = \"no_display\" elif choice_buttons['type_display']['value'].get() == 1: type_display = \"synthetic\" else: type_display = \"multiple\" if choice_buttons['type_plot']['value'].get() == 0: type_plot = \"fixed\" else: type_plot = \"dynamic\" return (Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, Aact, Hgdl, Hcl, Hmem, Hgc, Wgc, Lgc, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, t_purge, delta_t_purge, max_step, n_gdl, type_fuel_cell, type_auxiliary, type_control, type_purge, type_display, type_plot)","title":"recover_for_use_operating_inputs_and_physical_parameters"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.set_equal_width","text":"Adjusts the width of the frames to be equal based on their maximum width. Parameters: frame1 ( Frame ) \u2013 The first frame to be resized. frame2 ( Frame ) \u2013 The second frame to be resized. frame3 ( Frame ) \u2013 The third frame to be resized. frame4 ( Frame ) \u2013 The fourth frame to be resized. frame5 ( Frame ) \u2013 The fifth frame to be resized. frame6 ( Frame ) \u2013 The sixth frame to be resized. Source code in modules/GUI_modules.py def set_equal_width(frame1, frame2, frame3, frame4, frame5, frame6): \"\"\" Adjusts the width of the frames to be equal based on their maximum width. Parameters ---------- frame1 : ttk.Frame The first frame to be resized. frame2 : ttk.Frame The second frame to be resized. frame3 : ttk.Frame The third frame to be resized. frame4 : ttk.Frame The fourth frame to be resized. frame5 : ttk.Frame The fifth frame to be resized. frame6 : ttk.Frame The sixth frame to be resized. \"\"\" # Initialisation of the list of widths widths = [] for frame in [frame1, frame2, frame3, frame4, frame5, frame6]: # Update the frame sizes frame.update_idletasks() # Get the current width of all frames widths.append(frame.winfo_width()) # Set all frames to the maximum width for frame in [frame1, frame2, frame3, frame4, frame5, frame6]: for i in range(6): frame.grid_columnconfigure(i, minsize=max(widths) / 5.5) # Set minimum width of all column to max_width / 5","title":"set_equal_width"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.value_control","text":"This function checks the integrity of the values entered by the user and returns an empty tuple if they are not valid. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in modules/GUI_modules.py def value_control(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons, current_button): \"\"\"This function checks the integrity of the values entered by the user and returns an empty tuple if they are not valid. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # The values entered by the user are checked for compliance if choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].get() < 0: messagebox.showerror(title='Temperatures', message='Negative temperatures do not exist in the Kelvin scale.') choices.clear() return if choice_operating_conditions['Anode pressure - Pa (bar)']['value'].get() < 0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() < 0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() > 5.0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() > 5.0: messagebox.showerror(title='Desired pressures', message='Desired pressure should be positive and bellow 5.0 ' 'bars.') choices.clear() return if choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() < 1 or \\ choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() > 5 or \\ choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() < 1 or \\ choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() > 5: messagebox.showerror(title='Stoichiometric ratios', message='The stoichiometric ratios Sa and Sc should be ' 'between 1 and 5.') choices.clear() return if choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() < 0 or \\ choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() > 1 or \\ choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() < 0 or \\ choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() > 1: messagebox.showerror(title='Desired humidity', message='The desired humidities should be between 0 and 1.') choices.clear() return if choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].get() < 0: messagebox.showerror(title='Active area', message='Negative active area is impossible.') choices.clear() return if choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() > 1000 or \\ choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() > 1000 or \\ choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() > 1000: messagebox.showerror(title='MEA thickness', message='All MEA components generally have a thickness between ' '1\u00b5m and 1mm.') choices.clear() return if choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() < 10 or \\ choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() > 10000 or \\ choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() < 10 or \\ choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() > 10000 or \\ choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() < 0 or \\ choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() > 100: messagebox.showerror(title='GC distances', message='GC generally have a thickness and a width between 10\u00b5m and ' '10mm. Also, GC length is generally between 0 and 100m') choices.clear() return if choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() < 0 or \\ choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() > 1 or \\ choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() < 0 or \\ choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() > 1: messagebox.showerror(title='Porosities', message='All porosities should be between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() < 1 or choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() > 4: messagebox.showerror(title='Pore structure coefficient', message='The pore structure coefficient should be ' 'between 1 and 4.') choices.clear() return if choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() < 0 or \\ choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() > 1: messagebox.showerror(title='Compression ratio', message='The compression ratio should be between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Capillary exponent - e']['value'].get() < 3 or choice_undetermined_parameters['Capillary exponent - e']['value'].get() > 5: messagebox.showerror(title='Capillary exponent', message='The capillary exponent should be between 3 and 5 and ' 'being an integer.') choices.clear() return if choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() < 0.5 or \\ choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() > 5: messagebox.showerror(title='Electron conduction resistance', message='The electron conduction resistance is ' 'generally between 0.5 and 5 \u00b5\u03a9.m\u00b2.') choices.clear() return if choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() < 0.001 or \\ choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() > 500: messagebox.showerror(title='Referenced exchange current density', message='The referenced exchange current ' 'density is generally between 0.001 ' 'and 500 A.m-2.') choices.clear() return if choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() < 0.01 or \\ choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() > 100: messagebox.showerror(title='Crossover correction coefficient', message='The crossover correction coefficient is' ' generally between 0.01 and 100 ' 'mol.m-1.s-1.Pa-1.') choices.clear() return if choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() < 0 or \\ choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() > 100: messagebox.showerror(title='Overpotential correction exponent', message='The overpotential correction exponent ' 'is generally between 0 and 100.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() > 1: messagebox.showerror(title='Slop of slim function', message='The slop of slim function is generally between 0 ' 'and 1.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() > 1: messagebox.showerror(title='Intercept of slim function', message='The intercept of slim function is generally ' 'between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() > 1: messagebox.showerror(title='Slop of switch function', message='The slop of switch function is generally between' ' 0 and 1.') choices.clear() return if choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() < 5 or \\ choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() > 100: messagebox.showerror(title='Double layer capacitance', message='I have not settled yet a range for C_scl.') choices.clear() return if choice_current_density_parameters['Initial time - t0_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Final time - tf_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get() < 0 or \\ choice_computing_parameters['Time for dynamic\\ndisplay - \u0394t_dyn_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Breaking time\\n- \u0394t_break_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Initial breaking time\\n- \u0394t_ini_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Initial time - t0_step (s)']['value'].get() > \\ choice_current_density_parameters['Final time - tf_step (s)']['value'].get() or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get() > \\ (choice_current_density_parameters['Final time - tf_step (s)']['value'].get() - choice_current_density_parameters['Initial time - t0_step (s)']['value'].get()): messagebox.showerror(title='Times', message='The times should be positive, t0_step < tf_step and ' 'delta_t_load_step < (tf_step - t0_step).') choices.clear() return if choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Static current\\n- i_EIS (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() > \\ choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() or \\ choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() > \\ choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get(): messagebox.showerror(title='Current densities', message='The current densities should be positive, ' 'delta_i_pola < i_max_pola and ' 'i_ini_step < i_final_step.') choices.clear() return if choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() < 0 or \\ choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() > 20: messagebox.showerror(title='Ratio EIS', message='Ratio EIS is a percentage of i_EIS and should be between 0 ' 'and 20 for plotting correct EIS.') choices.clear() return if choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get() < 0 or \\ choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get() < 0 or \\ type(choice_current_density_parameters['Power of the\\ninitial frequency\\n- f_power_min_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Power of the\\nfinal frequency\\n- f_power_max_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get()) != int: messagebox.showerror(title='f EIS', message='f_EIS parameters should be integer and number of points should ' 'be positive.') choices.clear() return if choice_computing_parameters['Purge time - t_purge (s)']['value'].get() < 0 or \\ choice_computing_parameters['Time between two purges\\n- \u0394t_purge (s)']['value'].get() < 0: messagebox.showerror(title='Purge times', message='Negative times does not characterise purges.') choices.clear() return if choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() < 0 or \\ choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() > 0.1: messagebox.showerror(title='Max step', message='The max step value for the solver should be positive and lower ' 'than 0.1 for normal use.') choices.clear() return if choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get() < 2 or \\ type(choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get()) != int: messagebox.showerror(title='n gdl', message='The n_gdl value should be an integer bigger than 2. ' 'A good compromise is 10.') choices.clear() return if current_button == 0 and choice_buttons['type_display']['value'].get() == 2 \\ and choice_buttons['type_plot']['value'].get() == 1 : messagebox.showerror(title='n gdl', message='dynamic plot is not thought to be used with step current and ' 'multiple display. There would be too much plots to handle.') choices.clear() return if current_button == 2 and choice_buttons['type_plot']['value'].get() == 0: messagebox.showerror(title='n gdl', message='EIS has to be plot with a dynamic type_plot setting, ' 'because max_step has to be adjusted at each frequency.') choices.clear() return","title":"value_control"},{"location":"functions/modules/auxiliaries_modules/","text":"Auxiliaries modules This module is used to calculate intermediate values for the auxiliaries flows calculation. auxiliaries_int_values(t, solver_variables, operating_inputs, parameters) This functions calculates intermediate values for the auxiliaries flows calculation. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). Phi_agc ( float ) \u2013 Relative humidity in the anode gas channel. Phi_cgc ( float ) \u2013 Relative humidity in the cathode gas channel. y_cgc ( float ) \u2013 Oxygen ratio in dry air in the cathode gas channel. Magc ( float ) \u2013 Molar mass of all the gas species in the anode gas channel (kg/mol). Mcgc ( float ) \u2013 Molar mass of all the gas species in the cathode gas channel (kg/mol). Pr_aem ( float ) \u2013 Pressure ratio in the anode external manifold. Pr_cem ( float ) \u2013 Pressure ratio in the cathode external manifold. Maem ( float ) \u2013 Molar mass of all the gas species in the anode external manifold (kg/mol). Masm ( float ) \u2013 Molar mass of all the gas species in the anode supply manifold (kg/mol). Mcem ( float ) \u2013 Molar mass of all the gas species in the cathode external manifold (kg/mol). Mcsm ( float ) \u2013 Molar mass of all the gas species in the cathode supply manifold (kg/mol). k_purge ( float ) \u2013 Purge coefficient. It is equal to 1 if the purge is active and 0 otherwise. Abp_a ( float ) \u2013 Area of the back pressure valve in the anode external manifold (m\u00b2). Abp_c ( float ) \u2013 Area of the back pressure valve in the cathode external manifold (m\u00b2). i_n ( float ) \u2013 Internal current density (A/m\u00b2). Source code in modules/auxiliaries_modules.py def auxiliaries_int_values(t, solver_variables, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the auxiliaries flows calculation. Parameters ---------- t : float Time (s). solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Mext : float Molar mass of the ambient air outside the stack (kg/mol). Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). Phi_agc : float Relative humidity in the anode gas channel. Phi_cgc : float Relative humidity in the cathode gas channel. y_cgc : float Oxygen ratio in dry air in the cathode gas channel. Magc : float Molar mass of all the gas species in the anode gas channel (kg/mol). Mcgc : float Molar mass of all the gas species in the cathode gas channel (kg/mol). Pr_aem : float Pressure ratio in the anode external manifold. Pr_cem : float Pressure ratio in the cathode external manifold. Maem : float Molar mass of all the gas species in the anode external manifold (kg/mol). Masm : float Molar mass of all the gas species in the anode supply manifold (kg/mol). Mcem : float Molar mass of all the gas species in the cathode external manifold (kg/mol). Mcsm : float Molar mass of all the gas species in the cathode supply manifold (kg/mol). k_purge : float Purge coefficient. It is equal to 1 if the purge is active and 0 otherwise. Abp_a : float Area of the back pressure valve in the anode external manifold (m\u00b2). Abp_c : float Area of the back pressure valve in the cathode external manifold (m\u00b2). i_n : float Internal current density (A/m\u00b2). \"\"\" # Extraction of the variables C_v_agc, C_v_cgc = solver_variables['C_v_agc'], solver_variables['C_v_cgc'] lambda_mem = solver_variables['lambda_mem'] C_H2_agc, C_H2_acl = solver_variables['C_H2_agc'], solver_variables['C_H2_acl'] C_N2, C_O2_ccl, C_O2_cgc = solver_variables['C_N2'], solver_variables['C_O2_ccl'], solver_variables['C_O2_cgc'] Pasm, Paem, Pcsm = solver_variables['Pasm'], solver_variables['Paem'], solver_variables['Pcsm'] Pcem, Phi_asm, Phi_aem = solver_variables['Pcem'], solver_variables['Phi_asm'], solver_variables['Phi_aem'] Phi_csm, Phi_cem = solver_variables['Phi_csm'], solver_variables['Phi_cem'] Abp_a, Abp_c = solver_variables['Abp_a'], solver_variables['Abp_c'] # Extraction of the operating inputs and the parameters Tfc, Pa_des, Pc_des = operating_inputs['Tfc'], operating_inputs['Pa_des'], operating_inputs['Pc_des'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] t_purge, type_purge = parameters['t_purge'], parameters['type_purge'] # Molar mass of the ambient air Mext = Phi_ext * Psat(Text) / Pext * M_H2O + \\ yO2_ext * (1 - Phi_ext * Psat(Text) / Pext) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_ext * Psat(Text) / Pext) * M_N2 # Physical quantities inside the stack # Pressures Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Humidities Phi_agc = C_v_agc / C_v_sat(Tfc) Phi_cgc = C_v_cgc / C_v_sat(Tfc) # Oxygen ratio in dry air y_cgc = C_O2_cgc / (C_O2_cgc + C_N2) # Molar masses Magc = C_v_agc * R * Tfc / Pagc * M_H2O + \\ C_H2_agc * R * Tfc / Pagc * M_H2 Mcgc = Phi_cgc * Psat(Tfc) / Pcgc * M_H2O + \\ y_cgc * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * M_O2 + \\ (1 - y_cgc) * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * M_N2 # Internal current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # Physical quantities in the auxiliary system if parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_anodic_recirculation\" or \\ parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_flow-through_anode\": # Pressure ratios Pr_aem = (Pext / Paem) Pr_cem = (Pext / Pcem) # Oxygen ratio in dry air y_cem = (Pcem - Phi_cem * Psat(Tfc) - C_N2 * R * Tfc) / (Pcem - Phi_cem * Psat(Tfc)) # Molar masses Maem = Phi_aem * Psat(Tfc) / Paem * M_H2O + \\ (1 - Phi_aem * Psat(Tfc) / Paem) * M_H2 Masm = Phi_asm * Psat(Tfc) / Pasm * M_H2O + \\ (1 - Phi_asm * Psat(Tfc) / Pasm) * M_H2 Mcem = Phi_cem * Psat(Tfc) / Pcem * M_H2O + \\ y_cem * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_O2 + \\ (1 - y_cem) * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_N2 Mcsm = Phi_csm * Psat(Tfc) / Pcsm * M_H2O + \\ yO2_ext * (1 - Phi_csm * Psat(Tfc) / Pcsm) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_csm * Psat(Tfc) / Pcsm) * M_N2 # Purge if type_purge == \"no_purge\": k_purge = 0 elif type_purge == \"constant_purge\": k_purge = 1 elif type_purge == \"periodic_purge\": purge_time, delta_purge = t_purge if (t - int(t / (purge_time + delta_purge)) * (purge_time + delta_purge)) <= purge_time: k_purge = 1 else: k_purge = 0 else: raise ValueError(\"The type_purge variable should be correctly referenced.\") # Back pressure valve area if Abp_a > A_T: Abp_a = A_T elif Abp_a < 0: Abp_a = 0 if Abp_c > A_T: Abp_c = A_T elif Abp_c < 0: Abp_c = 0 else: # parameters[\"type_auxiliary\"] == \"no_auxiliary\" Pr_aem, Pr_cem, Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c = [0] * 9 return (Mext, Pagc, Pcgc, Phi_agc, Phi_cgc, y_cgc, Magc, Mcgc, Pr_aem, Pr_cem, Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c, i_n)","title":"Auxiliaries modules"},{"location":"functions/modules/auxiliaries_modules/#auxiliaries-modules","text":"This module is used to calculate intermediate values for the auxiliaries flows calculation.","title":"Auxiliaries modules"},{"location":"functions/modules/auxiliaries_modules/#modules.auxiliaries_modules.auxiliaries_int_values","text":"This functions calculates intermediate values for the auxiliaries flows calculation. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). Phi_agc ( float ) \u2013 Relative humidity in the anode gas channel. Phi_cgc ( float ) \u2013 Relative humidity in the cathode gas channel. y_cgc ( float ) \u2013 Oxygen ratio in dry air in the cathode gas channel. Magc ( float ) \u2013 Molar mass of all the gas species in the anode gas channel (kg/mol). Mcgc ( float ) \u2013 Molar mass of all the gas species in the cathode gas channel (kg/mol). Pr_aem ( float ) \u2013 Pressure ratio in the anode external manifold. Pr_cem ( float ) \u2013 Pressure ratio in the cathode external manifold. Maem ( float ) \u2013 Molar mass of all the gas species in the anode external manifold (kg/mol). Masm ( float ) \u2013 Molar mass of all the gas species in the anode supply manifold (kg/mol). Mcem ( float ) \u2013 Molar mass of all the gas species in the cathode external manifold (kg/mol). Mcsm ( float ) \u2013 Molar mass of all the gas species in the cathode supply manifold (kg/mol). k_purge ( float ) \u2013 Purge coefficient. It is equal to 1 if the purge is active and 0 otherwise. Abp_a ( float ) \u2013 Area of the back pressure valve in the anode external manifold (m\u00b2). Abp_c ( float ) \u2013 Area of the back pressure valve in the cathode external manifold (m\u00b2). i_n ( float ) \u2013 Internal current density (A/m\u00b2). Source code in modules/auxiliaries_modules.py def auxiliaries_int_values(t, solver_variables, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the auxiliaries flows calculation. Parameters ---------- t : float Time (s). solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Mext : float Molar mass of the ambient air outside the stack (kg/mol). Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). Phi_agc : float Relative humidity in the anode gas channel. Phi_cgc : float Relative humidity in the cathode gas channel. y_cgc : float Oxygen ratio in dry air in the cathode gas channel. Magc : float Molar mass of all the gas species in the anode gas channel (kg/mol). Mcgc : float Molar mass of all the gas species in the cathode gas channel (kg/mol). Pr_aem : float Pressure ratio in the anode external manifold. Pr_cem : float Pressure ratio in the cathode external manifold. Maem : float Molar mass of all the gas species in the anode external manifold (kg/mol). Masm : float Molar mass of all the gas species in the anode supply manifold (kg/mol). Mcem : float Molar mass of all the gas species in the cathode external manifold (kg/mol). Mcsm : float Molar mass of all the gas species in the cathode supply manifold (kg/mol). k_purge : float Purge coefficient. It is equal to 1 if the purge is active and 0 otherwise. Abp_a : float Area of the back pressure valve in the anode external manifold (m\u00b2). Abp_c : float Area of the back pressure valve in the cathode external manifold (m\u00b2). i_n : float Internal current density (A/m\u00b2). \"\"\" # Extraction of the variables C_v_agc, C_v_cgc = solver_variables['C_v_agc'], solver_variables['C_v_cgc'] lambda_mem = solver_variables['lambda_mem'] C_H2_agc, C_H2_acl = solver_variables['C_H2_agc'], solver_variables['C_H2_acl'] C_N2, C_O2_ccl, C_O2_cgc = solver_variables['C_N2'], solver_variables['C_O2_ccl'], solver_variables['C_O2_cgc'] Pasm, Paem, Pcsm = solver_variables['Pasm'], solver_variables['Paem'], solver_variables['Pcsm'] Pcem, Phi_asm, Phi_aem = solver_variables['Pcem'], solver_variables['Phi_asm'], solver_variables['Phi_aem'] Phi_csm, Phi_cem = solver_variables['Phi_csm'], solver_variables['Phi_cem'] Abp_a, Abp_c = solver_variables['Abp_a'], solver_variables['Abp_c'] # Extraction of the operating inputs and the parameters Tfc, Pa_des, Pc_des = operating_inputs['Tfc'], operating_inputs['Pa_des'], operating_inputs['Pc_des'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] t_purge, type_purge = parameters['t_purge'], parameters['type_purge'] # Molar mass of the ambient air Mext = Phi_ext * Psat(Text) / Pext * M_H2O + \\ yO2_ext * (1 - Phi_ext * Psat(Text) / Pext) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_ext * Psat(Text) / Pext) * M_N2 # Physical quantities inside the stack # Pressures Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Humidities Phi_agc = C_v_agc / C_v_sat(Tfc) Phi_cgc = C_v_cgc / C_v_sat(Tfc) # Oxygen ratio in dry air y_cgc = C_O2_cgc / (C_O2_cgc + C_N2) # Molar masses Magc = C_v_agc * R * Tfc / Pagc * M_H2O + \\ C_H2_agc * R * Tfc / Pagc * M_H2 Mcgc = Phi_cgc * Psat(Tfc) / Pcgc * M_H2O + \\ y_cgc * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * M_O2 + \\ (1 - y_cgc) * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * M_N2 # Internal current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # Physical quantities in the auxiliary system if parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_anodic_recirculation\" or \\ parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_flow-through_anode\": # Pressure ratios Pr_aem = (Pext / Paem) Pr_cem = (Pext / Pcem) # Oxygen ratio in dry air y_cem = (Pcem - Phi_cem * Psat(Tfc) - C_N2 * R * Tfc) / (Pcem - Phi_cem * Psat(Tfc)) # Molar masses Maem = Phi_aem * Psat(Tfc) / Paem * M_H2O + \\ (1 - Phi_aem * Psat(Tfc) / Paem) * M_H2 Masm = Phi_asm * Psat(Tfc) / Pasm * M_H2O + \\ (1 - Phi_asm * Psat(Tfc) / Pasm) * M_H2 Mcem = Phi_cem * Psat(Tfc) / Pcem * M_H2O + \\ y_cem * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_O2 + \\ (1 - y_cem) * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_N2 Mcsm = Phi_csm * Psat(Tfc) / Pcsm * M_H2O + \\ yO2_ext * (1 - Phi_csm * Psat(Tfc) / Pcsm) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_csm * Psat(Tfc) / Pcsm) * M_N2 # Purge if type_purge == \"no_purge\": k_purge = 0 elif type_purge == \"constant_purge\": k_purge = 1 elif type_purge == \"periodic_purge\": purge_time, delta_purge = t_purge if (t - int(t / (purge_time + delta_purge)) * (purge_time + delta_purge)) <= purge_time: k_purge = 1 else: k_purge = 0 else: raise ValueError(\"The type_purge variable should be correctly referenced.\") # Back pressure valve area if Abp_a > A_T: Abp_a = A_T elif Abp_a < 0: Abp_a = 0 if Abp_c > A_T: Abp_c = A_T elif Abp_c < 0: Abp_c = 0 else: # parameters[\"type_auxiliary\"] == \"no_auxiliary\" Pr_aem, Pr_cem, Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c = [0] * 9 return (Mext, Pagc, Pcgc, Phi_agc, Phi_cgc, y_cgc, Magc, Mcgc, Pr_aem, Pr_cem, Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c, i_n)","title":"auxiliaries_int_values"},{"location":"functions/modules/calibration_modules/","text":"Calibration modules This module contains some of the functions required for the parameter calibration. calculate_simulation_error(Simulator1, U_exp1, i_exp1, Simulator2, U_exp2, i_exp2) This function is used to calculate the simulation maximal error between the experimental and the simulated polarization curves. Two simulations on different operating conditions and on the same stack, and so two set of experimental data, are considered as it is the minimum amount of data which is required for the calibration. Parameters: Simulator1 ( AlphaPEM object ) \u2013 PEM simulator which contains the simulation results for the first simulation. U_exp1 ( ndarray ) \u2013 Experimental values of the voltage for the first simulation. i_exp1 ( ndarray ) \u2013 Experimental values of the current density for the first simulation. Simulator2 ( AlphaPEM object ) \u2013 PEM simulator which contains the simulation results for the second simulation. U_exp2 ( ndarray ) \u2013 Experimental values of the voltage for the second simulation. i_exp2 ( ndarray ) \u2013 Experimental values of the current density for the second simulation. Returns: sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. Source code in modules/calibration_modules.py def calculate_simulation_error(Simulator1, U_exp1, i_exp1, Simulator2, U_exp2, i_exp2): \"\"\"This function is used to calculate the simulation maximal error between the experimental and the simulated polarization curves. Two simulations on different operating conditions and on the same stack, and so two set of experimental data, are considered as it is the minimum amount of data which is required for the calibration. Parameters ---------- Simulator1 : AlphaPEM object PEM simulator which contains the simulation results for the first simulation. U_exp1 : numpy.ndarray Experimental values of the voltage for the first simulation. i_exp1 : numpy.ndarray Experimental values of the current density for the first simulation. Simulator2 : AlphaPEM object PEM simulator which contains the simulation results for the second simulation. U_exp2 : numpy.ndarray Experimental values of the voltage for the second simulation. i_exp2 : numpy.ndarray Experimental values of the current density for the second simulation. Returns ------- sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. \"\"\" # Recovery of ifc_1 t1 = np.array(Simulator1.variables['t']) n1 = len(t1) ifc_t_1 = np.zeros(n1) for i in range(n1): # Creation of ifc_t and conversion in A/cm\u00b2 ifc_t_1[i] = Simulator1.operating_inputs['current_density'](t1[i], Simulator1.parameters) / 1e4 # Recovery of ifc_2 t2 = np.array(Simulator2.variables['t']) n2 = len(t2) ifc_t_2 = np.zeros(n2) for i in range(n2): # Creation of ifc_t and conversion in A/cm\u00b2 ifc_t_2[i] = Simulator2.operating_inputs['current_density'](t2[i], Simulator2.parameters) / 1e4 # Polarisation curve point recovery after stack stabilisation for Simulator1 delta_t_load, delta_t_break, delta_i, delta_t_ini = Simulator1.parameters['delta_pola'] nb_loads1 = int(Simulator1.parameters['i_pola'] / delta_i + 1) # Number of load which are made ifc_discretized1 = np.zeros(nb_loads1) Ucell_discretized1 = np.zeros(nb_loads1) for i in range(nb_loads1): t_load = delta_t_ini + (i + 1) * (delta_t_load + delta_t_break) - delta_t_break / 10 # time for the measurement idx1 = (np.abs(t1 - t_load)).argmin() # the corresponding index ifc_discretized1[i] = ifc_t_1[idx1] # the last value at the end of each load Ucell_discretized1[i] = Simulator1.variables['Ucell'][idx1] # the last value at the end of each load # Polarisation curve point recovery after stack stabilisation for Simulator2 delta_t_load, delta_t_break, delta_i, delta_t_ini = Simulator2.parameters['delta_pola'] nb_loads2 = int(Simulator2.parameters['i_pola'] / delta_i + 1) # Number of load which are made ifc_discretized2 = np.zeros(nb_loads2) Ucell_discretized2 = np.zeros(nb_loads2) for i in range(nb_loads2): t_load = delta_t_ini + (i + 1) * (delta_t_load + delta_t_break) - delta_t_break / 10 # time for the measurement idx2 = (np.abs(t2 - t_load)).argmin() # the corresponding index ifc_discretized2[i] = ifc_t_2[idx2] # the last value at the end of each load Ucell_discretized2[i] = Simulator2.variables['Ucell'][idx2] # the last value at the end of each load # Interpolation of experimental points to match model points for Simulator 1 i_fc_reduced1 = ifc_discretized1[(ifc_discretized1 >= i_exp1[0]) & (ifc_discretized1 <= i_exp1[-1])] Ucell_reduced1 = Ucell_discretized1[(ifc_discretized1 >= i_exp1[0]) & (ifc_discretized1 <= i_exp1[-1])] U_exp_interpolated1 = interp1d(i_exp1, U_exp1, kind='linear')(i_fc_reduced1) # Interpolation of experimental points to match model points for Simulator 2 i_fc_reduced2 = ifc_discretized2[(ifc_discretized2 >= i_exp2[0]) & (ifc_discretized2 <= i_exp2[-1])] Ucell_reduced2 = Ucell_discretized2[(ifc_discretized2 >= i_exp2[0]) & (ifc_discretized2 <= i_exp2[-1])] U_exp_interpolated2 = interp1d(i_exp2, U_exp2, kind='linear')(i_fc_reduced2) # Distance between the simulated and the experimental polarization curves. if np.isnan(Ucell_reduced1).any() or np.isnan(Ucell_reduced2).any(): sim_error = 1e5 # If the mass loss arrives before i_exp[-1], some value would be equal to NaN. else: sim_error = (np.max(np.abs(Ucell_reduced1 - U_exp_interpolated1) / U_exp_interpolated1 * 100) + np.max(np.abs(Ucell_reduced2 - U_exp_interpolated2) / U_exp_interpolated2 * 100)) / 2 # in %. return sim_error determined_parameters(type_fuel_cell) This function is used to determine the parameters of the fuel cell model for the calibration when a registered type_fuel_cell is considered. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_pola ( float ) \u2013 Maximum current density for the polarization curve. Aact ( float ) \u2013 Active area of the cell in m\u00b2. Hmem ( float ) \u2013 Thickness of the membrane in m. Hcl ( float ) \u2013 Thickness of the catalyst layer in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Wgc ( float ) \u2013 Width of the gas channel in m. Lgc ( float ) \u2013 Length of the gas channel in m. type_auxiliary ( str ) \u2013 Type of auxiliary system. type_control ( str ) \u2013 Type of control system. type_purge ( str ) \u2013 Type of purge system. type_display ( str ) \u2013 Type of display. type_plot ( str ) \u2013 Type of plot. type_current ( str ) \u2013 Type of current density function. current_density ( function ) \u2013 Current density evolution over time. It is a function of time and parameters dictionary. t_step ( tuple ) \u2013 Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load' and dynamic time for display 'delta_t_dyn'. i_step ( tuple ) \u2013 Current parameters for the step_current density function. It is a tuple containing the initial and final current density value 'i_ini' and 'i_final'. delta_pola ( tuple ) \u2013 Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load', the breaking time 'delta_t_break', the current density step 'delta_i', and the initial breaking time 'delta_t_ini'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added. ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve. t_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min': f_min = 10**f_power_min, the power of the final frequency 'f_power_max', the number of frequencies tested 'nb_f' and the number of points calculated per specific period 'nb_points'. t_purge ( tuple ) \u2013 Time parameters for purging the system. It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. max_step ( float ) \u2013 Maximum time step for the solver. n_gdl ( int ) \u2013 Number of points considered in the GDL. i_exp ( ndarray ) \u2013 Experimental values of the current density. U_exp ( ndarray ) \u2013 Experimental values of the voltage. Source code in modules/calibration_modules.py def determined_parameters(type_fuel_cell): \"\"\"This function is used to determine the parameters of the fuel cell model for the calibration when a registered type_fuel_cell is considered. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_pola : float Maximum current density for the polarization curve. Aact : float Active area of the cell in m\u00b2. Hmem : float Thickness of the membrane in m. Hcl : float Thickness of the catalyst layer in m. Hgc : float Thickness of the gas channel in m. Wgc : float Width of the gas channel in m. Lgc : float Length of the gas channel in m. type_auxiliary : str Type of auxiliary system. type_control : str Type of control system. type_purge : str Type of purge system. type_display : str Type of display. type_plot : str Type of plot. type_current : str Type of current density function. current_density : function Current density evolution over time. It is a function of time and parameters dictionary. t_step : tuple Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load' and dynamic time for display 'delta_t_dyn'. i_step : tuple Current parameters for the step_current density function. It is a tuple containing the initial and final current density value 'i_ini' and 'i_final'. delta_pola : tuple Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load', the breaking time 'delta_t_break', the current density step 'delta_i', and the initial breaking time 'delta_t_ini'. i_EIS : float Current for which a ratio_EIS perturbation is added. ratio_EIS : float Value of the perturbation on the current density for building the EIS curve. t_EIS : tuple EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min': f_min = 10**f_power_min, the power of the final frequency 'f_power_max', the number of frequencies tested 'nb_f' and the number of points calculated per specific period 'nb_points'. t_purge : tuple Time parameters for purging the system. It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. max_step : float Maximum time step for the solver. n_gdl : int Number of points considered in the GDL. i_exp : numpy.ndarray Experimental values of the current density. U_exp : numpy.ndarray Experimental values of the voltage. \"\"\" if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": # Given values by the author # Operating inputs Tfc = 74 + 273.15 # K. It is the temperature of the fuel cell. Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. if type_fuel_cell == \"EH-31_1.5\": Pa_des, Pc_des = 1.5e5, 1.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.3e4 elif type_fuel_cell == \"EH-31_2.0\": Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.5e4 elif type_fuel_cell == \"EH-31_2.25\": Pa_des, Pc_des = 2.25e5, 2.25e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.85e4 else: # type_fuel_cell == \"EH-31_2.5\": Pa_des, Pc_des = 2.5e5, 2.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 3.05e4 # Fuel cell physical parameters Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Extrapolated physical parameters Hmem = 2e-5 # m. It is the thickness of the membrane. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. Hgc = 5e-4 # m. It is the thickness of the gas channel. # Algorithm parameters for polarization curve generation type_auxiliary = \"forced-convective_cathode_with_flow-through_anode\" type_control = \"no_control\" type_purge = \"no_purge\" type_display = \"multiple\" type_plot = \"final\" type_current = \"polarization\" current_density = polarization_current t_step = np.nan, np.nan, np.nan, np.nan # It is the time parameters for the step_current density function. i_step = np.nan, np.nan # It is the current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 1 * 60 # It is the parameters for the polarization curve. i_EIS, ratio_EIS = np.nan, np.nan # (A/m\u00b2, ). i_EIS is the current for which a ratio_EIS perturbation is added. f_EIS, t_EIS = np.nan, np.nan # It is the EIS parameters. t_purge = 0.6, 15 # s It is the purge time and the distance between two purges. max_step = 0.05 # It is good enough for having graphs without instabilities. n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. elif type_fuel_cell == \"LF\": # Given values by the author # Operating inputs Tfc = 80 + 273.15 # K. It is the temperature of the fuel cell. Pa_des, Pc_des = 101325, 101325 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 2.0, 1.5 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.84, 0.59 # It is the desired relative humidity. i_pola = 1.45e4 # Fuel cell physical parameters Hmem = 5.08e-5 # m. It is the thickness of the membrane. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. Hgdl = 4.2e-4 # m. It is the thickness of the gas diffusion layer. Hgc = 1e-3 # m. It is the thickness of the gas channel. Wgc = 8e-4 # m. It is the width of the gas channel. # Extrapolated physical parameters Aact = 0.0025 # m\u00b2. It is the active area of the catalyst layer. Lgc = 1.6 # m. It is the length of the gas channel. # Algorithm parameters for polarization curve generation type_auxiliary = \"forced-convective_cathode_with_anodic_recirculation\" type_control = \"no_control\" type_purge = \"no_purge\" type_display = \"no_display\" type_plot = \"final\" type_current = \"polarization\" current_density = polarization_current t_step = np.nan # It is the time parameters for the step_current density function. i_step = np.nan, np.nan # It is the current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 60 * 60 # It is the parameters for the polarization curve. i_EIS, ratio_EIS = np.nan, np.nan # (A/m\u00b2, ). i_EIS is the current for which a ratio_EIS perturbation is added. f_EIS, t_EIS = np.nan, np.nan # It is the EIS parameters. t_purge = 0.6, 15 # s It is the purge time and the distance between two purges. max_step = 0.05 # It is good enough for having graphs without instabilities. n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. else: ValueError(\"A correct type_fuel_cell should be given.\") # Characteristic points of the experimental polarization curve i_exp, U_exp = pola_exp_values(type_fuel_cell) return (Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_pola, Aact, Hmem, Hcl, Hgdl, Hgc, Wgc, Lgc, type_auxiliary, type_control, type_purge, type_display, type_plot, type_current, current_density, t_step, i_step, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, t_purge, max_step, n_gdl, i_exp, U_exp) print_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error) This function is used to print the calibration results. Parameters: convergence ( dict ) \u2013 A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. epsilon_c ( float ) \u2013 Compression ratio of the GDL. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. Source code in modules/calibration_modules.py def print_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error): \"\"\"This function is used to print the calibration results. Parameters ---------- convergence : dict A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. epsilon_c : float Compression ratio of the GDL. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. \"\"\" print(\"The convergence is:\\n\", convergence) print(\"\\nThe optimized epsilon_gdl: \", epsilon_gdl) print(\"The optimized epsilon_mc: \", epsilon_mc) print(\"The optimized tau: \", tau) print(\"The optimized epsilon_c: \", epsilon_c) print(\"The optimized e: \", e) print(\"The optimized Re: \", Re) print(\"The optimized i0_c_ref: \", i0_c_ref) print(\"The optimized kappa_co: \", kappa_co) print(\"The optimized kappa_c: \", kappa_c) print(\"The optimized a_slim: \", a_slim) print(\"The optimized b_slim: \", b_slim) print(\"The optimized a_switch: \", a_switch) print(Fore.RED + \"\\nThe max simulation error is: \", sim_error, \"%\") print(Style.RESET_ALL) save_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error, type_fuel_cell) This function is used to save in a text file the calibration results. Parameters: convergence ( dict ) \u2013 A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. epsilon_c ( float ) \u2013 Compression ratio of the GDL. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Source code in modules/calibration_modules.py def save_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error, type_fuel_cell): \"\"\"This function is used to save in a text file the calibration results. Parameters ---------- convergence : dict A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. epsilon_c : float Compression ratio of the GDL. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. type_fuel_cell : str Type of fuel cell configuration. \"\"\" root_folder, filename = \"results\", \"parameter_calibration_1.txt\" subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 else type_fuel_cell counter = 1 # Create the folder if necessary folder_name = os.path.join(root_folder, subfolder_name) if not os.path.exists(folder_name): os.makedirs(folder_name) # Create the file without erasing the previous ones while os.path.isfile(os.path.join(folder_name, filename)): counter += 1 filename = \"parameter_calibration_\" + str(counter) + \".txt\" # Write information file_path = os.path.join(folder_name, filename) with open(file_path, \"w\") as file: file.write(\"The convergence is: \" + str(convergence) + \"\\nThe optimized epsilon_gdl: \" + str(epsilon_gdl) + \"\\nThe optimized epsilon_mc: \" + str(epsilon_mc) + \"\\nThe optimized tau: \" + str(tau) + \"\\nThe optimized epsilon_c: \" + str(epsilon_c) + \"\\nThe optimized e: \" + str(e) + \"\\nThe optimized Re: \" + str(Re) + \"\\nThe optimized i0_c_ref: \" + str(i0_c_ref) + \"\\nThe optimized kappa_co: \" + str(kappa_co) + \"\\nThe optimized kappa_c: \" + str(kappa_c) + \"\\nThe optimized a_slim: \" + str(a_slim) + \"\\nThe optimized b_slim: \" + str(b_slim) + \"\\nThe optimized a_switch: \" + str(a_switch) + \"\\nThe max simulation error is: \" + str(sim_error) + \"%\" + \"\\nHere the algorithm works with RG2&3 (global)\")","title":"Calibration modules"},{"location":"functions/modules/calibration_modules/#calibration-modules","text":"This module contains some of the functions required for the parameter calibration.","title":"Calibration modules"},{"location":"functions/modules/calibration_modules/#modules.calibration_modules.calculate_simulation_error","text":"This function is used to calculate the simulation maximal error between the experimental and the simulated polarization curves. Two simulations on different operating conditions and on the same stack, and so two set of experimental data, are considered as it is the minimum amount of data which is required for the calibration. Parameters: Simulator1 ( AlphaPEM object ) \u2013 PEM simulator which contains the simulation results for the first simulation. U_exp1 ( ndarray ) \u2013 Experimental values of the voltage for the first simulation. i_exp1 ( ndarray ) \u2013 Experimental values of the current density for the first simulation. Simulator2 ( AlphaPEM object ) \u2013 PEM simulator which contains the simulation results for the second simulation. U_exp2 ( ndarray ) \u2013 Experimental values of the voltage for the second simulation. i_exp2 ( ndarray ) \u2013 Experimental values of the current density for the second simulation. Returns: sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. Source code in modules/calibration_modules.py def calculate_simulation_error(Simulator1, U_exp1, i_exp1, Simulator2, U_exp2, i_exp2): \"\"\"This function is used to calculate the simulation maximal error between the experimental and the simulated polarization curves. Two simulations on different operating conditions and on the same stack, and so two set of experimental data, are considered as it is the minimum amount of data which is required for the calibration. Parameters ---------- Simulator1 : AlphaPEM object PEM simulator which contains the simulation results for the first simulation. U_exp1 : numpy.ndarray Experimental values of the voltage for the first simulation. i_exp1 : numpy.ndarray Experimental values of the current density for the first simulation. Simulator2 : AlphaPEM object PEM simulator which contains the simulation results for the second simulation. U_exp2 : numpy.ndarray Experimental values of the voltage for the second simulation. i_exp2 : numpy.ndarray Experimental values of the current density for the second simulation. Returns ------- sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. \"\"\" # Recovery of ifc_1 t1 = np.array(Simulator1.variables['t']) n1 = len(t1) ifc_t_1 = np.zeros(n1) for i in range(n1): # Creation of ifc_t and conversion in A/cm\u00b2 ifc_t_1[i] = Simulator1.operating_inputs['current_density'](t1[i], Simulator1.parameters) / 1e4 # Recovery of ifc_2 t2 = np.array(Simulator2.variables['t']) n2 = len(t2) ifc_t_2 = np.zeros(n2) for i in range(n2): # Creation of ifc_t and conversion in A/cm\u00b2 ifc_t_2[i] = Simulator2.operating_inputs['current_density'](t2[i], Simulator2.parameters) / 1e4 # Polarisation curve point recovery after stack stabilisation for Simulator1 delta_t_load, delta_t_break, delta_i, delta_t_ini = Simulator1.parameters['delta_pola'] nb_loads1 = int(Simulator1.parameters['i_pola'] / delta_i + 1) # Number of load which are made ifc_discretized1 = np.zeros(nb_loads1) Ucell_discretized1 = np.zeros(nb_loads1) for i in range(nb_loads1): t_load = delta_t_ini + (i + 1) * (delta_t_load + delta_t_break) - delta_t_break / 10 # time for the measurement idx1 = (np.abs(t1 - t_load)).argmin() # the corresponding index ifc_discretized1[i] = ifc_t_1[idx1] # the last value at the end of each load Ucell_discretized1[i] = Simulator1.variables['Ucell'][idx1] # the last value at the end of each load # Polarisation curve point recovery after stack stabilisation for Simulator2 delta_t_load, delta_t_break, delta_i, delta_t_ini = Simulator2.parameters['delta_pola'] nb_loads2 = int(Simulator2.parameters['i_pola'] / delta_i + 1) # Number of load which are made ifc_discretized2 = np.zeros(nb_loads2) Ucell_discretized2 = np.zeros(nb_loads2) for i in range(nb_loads2): t_load = delta_t_ini + (i + 1) * (delta_t_load + delta_t_break) - delta_t_break / 10 # time for the measurement idx2 = (np.abs(t2 - t_load)).argmin() # the corresponding index ifc_discretized2[i] = ifc_t_2[idx2] # the last value at the end of each load Ucell_discretized2[i] = Simulator2.variables['Ucell'][idx2] # the last value at the end of each load # Interpolation of experimental points to match model points for Simulator 1 i_fc_reduced1 = ifc_discretized1[(ifc_discretized1 >= i_exp1[0]) & (ifc_discretized1 <= i_exp1[-1])] Ucell_reduced1 = Ucell_discretized1[(ifc_discretized1 >= i_exp1[0]) & (ifc_discretized1 <= i_exp1[-1])] U_exp_interpolated1 = interp1d(i_exp1, U_exp1, kind='linear')(i_fc_reduced1) # Interpolation of experimental points to match model points for Simulator 2 i_fc_reduced2 = ifc_discretized2[(ifc_discretized2 >= i_exp2[0]) & (ifc_discretized2 <= i_exp2[-1])] Ucell_reduced2 = Ucell_discretized2[(ifc_discretized2 >= i_exp2[0]) & (ifc_discretized2 <= i_exp2[-1])] U_exp_interpolated2 = interp1d(i_exp2, U_exp2, kind='linear')(i_fc_reduced2) # Distance between the simulated and the experimental polarization curves. if np.isnan(Ucell_reduced1).any() or np.isnan(Ucell_reduced2).any(): sim_error = 1e5 # If the mass loss arrives before i_exp[-1], some value would be equal to NaN. else: sim_error = (np.max(np.abs(Ucell_reduced1 - U_exp_interpolated1) / U_exp_interpolated1 * 100) + np.max(np.abs(Ucell_reduced2 - U_exp_interpolated2) / U_exp_interpolated2 * 100)) / 2 # in %. return sim_error","title":"calculate_simulation_error"},{"location":"functions/modules/calibration_modules/#modules.calibration_modules.determined_parameters","text":"This function is used to determine the parameters of the fuel cell model for the calibration when a registered type_fuel_cell is considered. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_pola ( float ) \u2013 Maximum current density for the polarization curve. Aact ( float ) \u2013 Active area of the cell in m\u00b2. Hmem ( float ) \u2013 Thickness of the membrane in m. Hcl ( float ) \u2013 Thickness of the catalyst layer in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Wgc ( float ) \u2013 Width of the gas channel in m. Lgc ( float ) \u2013 Length of the gas channel in m. type_auxiliary ( str ) \u2013 Type of auxiliary system. type_control ( str ) \u2013 Type of control system. type_purge ( str ) \u2013 Type of purge system. type_display ( str ) \u2013 Type of display. type_plot ( str ) \u2013 Type of plot. type_current ( str ) \u2013 Type of current density function. current_density ( function ) \u2013 Current density evolution over time. It is a function of time and parameters dictionary. t_step ( tuple ) \u2013 Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load' and dynamic time for display 'delta_t_dyn'. i_step ( tuple ) \u2013 Current parameters for the step_current density function. It is a tuple containing the initial and final current density value 'i_ini' and 'i_final'. delta_pola ( tuple ) \u2013 Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load', the breaking time 'delta_t_break', the current density step 'delta_i', and the initial breaking time 'delta_t_ini'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added. ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve. t_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min': f_min = 10**f_power_min, the power of the final frequency 'f_power_max', the number of frequencies tested 'nb_f' and the number of points calculated per specific period 'nb_points'. t_purge ( tuple ) \u2013 Time parameters for purging the system. It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. max_step ( float ) \u2013 Maximum time step for the solver. n_gdl ( int ) \u2013 Number of points considered in the GDL. i_exp ( ndarray ) \u2013 Experimental values of the current density. U_exp ( ndarray ) \u2013 Experimental values of the voltage. Source code in modules/calibration_modules.py def determined_parameters(type_fuel_cell): \"\"\"This function is used to determine the parameters of the fuel cell model for the calibration when a registered type_fuel_cell is considered. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_pola : float Maximum current density for the polarization curve. Aact : float Active area of the cell in m\u00b2. Hmem : float Thickness of the membrane in m. Hcl : float Thickness of the catalyst layer in m. Hgc : float Thickness of the gas channel in m. Wgc : float Width of the gas channel in m. Lgc : float Length of the gas channel in m. type_auxiliary : str Type of auxiliary system. type_control : str Type of control system. type_purge : str Type of purge system. type_display : str Type of display. type_plot : str Type of plot. type_current : str Type of current density function. current_density : function Current density evolution over time. It is a function of time and parameters dictionary. t_step : tuple Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load' and dynamic time for display 'delta_t_dyn'. i_step : tuple Current parameters for the step_current density function. It is a tuple containing the initial and final current density value 'i_ini' and 'i_final'. delta_pola : tuple Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load', the breaking time 'delta_t_break', the current density step 'delta_i', and the initial breaking time 'delta_t_ini'. i_EIS : float Current for which a ratio_EIS perturbation is added. ratio_EIS : float Value of the perturbation on the current density for building the EIS curve. t_EIS : tuple EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min': f_min = 10**f_power_min, the power of the final frequency 'f_power_max', the number of frequencies tested 'nb_f' and the number of points calculated per specific period 'nb_points'. t_purge : tuple Time parameters for purging the system. It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. max_step : float Maximum time step for the solver. n_gdl : int Number of points considered in the GDL. i_exp : numpy.ndarray Experimental values of the current density. U_exp : numpy.ndarray Experimental values of the voltage. \"\"\" if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": # Given values by the author # Operating inputs Tfc = 74 + 273.15 # K. It is the temperature of the fuel cell. Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. if type_fuel_cell == \"EH-31_1.5\": Pa_des, Pc_des = 1.5e5, 1.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.3e4 elif type_fuel_cell == \"EH-31_2.0\": Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.5e4 elif type_fuel_cell == \"EH-31_2.25\": Pa_des, Pc_des = 2.25e5, 2.25e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.85e4 else: # type_fuel_cell == \"EH-31_2.5\": Pa_des, Pc_des = 2.5e5, 2.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 3.05e4 # Fuel cell physical parameters Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Extrapolated physical parameters Hmem = 2e-5 # m. It is the thickness of the membrane. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. Hgc = 5e-4 # m. It is the thickness of the gas channel. # Algorithm parameters for polarization curve generation type_auxiliary = \"forced-convective_cathode_with_flow-through_anode\" type_control = \"no_control\" type_purge = \"no_purge\" type_display = \"multiple\" type_plot = \"final\" type_current = \"polarization\" current_density = polarization_current t_step = np.nan, np.nan, np.nan, np.nan # It is the time parameters for the step_current density function. i_step = np.nan, np.nan # It is the current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 1 * 60 # It is the parameters for the polarization curve. i_EIS, ratio_EIS = np.nan, np.nan # (A/m\u00b2, ). i_EIS is the current for which a ratio_EIS perturbation is added. f_EIS, t_EIS = np.nan, np.nan # It is the EIS parameters. t_purge = 0.6, 15 # s It is the purge time and the distance between two purges. max_step = 0.05 # It is good enough for having graphs without instabilities. n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. elif type_fuel_cell == \"LF\": # Given values by the author # Operating inputs Tfc = 80 + 273.15 # K. It is the temperature of the fuel cell. Pa_des, Pc_des = 101325, 101325 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 2.0, 1.5 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.84, 0.59 # It is the desired relative humidity. i_pola = 1.45e4 # Fuel cell physical parameters Hmem = 5.08e-5 # m. It is the thickness of the membrane. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. Hgdl = 4.2e-4 # m. It is the thickness of the gas diffusion layer. Hgc = 1e-3 # m. It is the thickness of the gas channel. Wgc = 8e-4 # m. It is the width of the gas channel. # Extrapolated physical parameters Aact = 0.0025 # m\u00b2. It is the active area of the catalyst layer. Lgc = 1.6 # m. It is the length of the gas channel. # Algorithm parameters for polarization curve generation type_auxiliary = \"forced-convective_cathode_with_anodic_recirculation\" type_control = \"no_control\" type_purge = \"no_purge\" type_display = \"no_display\" type_plot = \"final\" type_current = \"polarization\" current_density = polarization_current t_step = np.nan # It is the time parameters for the step_current density function. i_step = np.nan, np.nan # It is the current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 60 * 60 # It is the parameters for the polarization curve. i_EIS, ratio_EIS = np.nan, np.nan # (A/m\u00b2, ). i_EIS is the current for which a ratio_EIS perturbation is added. f_EIS, t_EIS = np.nan, np.nan # It is the EIS parameters. t_purge = 0.6, 15 # s It is the purge time and the distance between two purges. max_step = 0.05 # It is good enough for having graphs without instabilities. n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. else: ValueError(\"A correct type_fuel_cell should be given.\") # Characteristic points of the experimental polarization curve i_exp, U_exp = pola_exp_values(type_fuel_cell) return (Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_pola, Aact, Hmem, Hcl, Hgdl, Hgc, Wgc, Lgc, type_auxiliary, type_control, type_purge, type_display, type_plot, type_current, current_density, t_step, i_step, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, t_purge, max_step, n_gdl, i_exp, U_exp)","title":"determined_parameters"},{"location":"functions/modules/calibration_modules/#modules.calibration_modules.print_calibration_results","text":"This function is used to print the calibration results. Parameters: convergence ( dict ) \u2013 A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. epsilon_c ( float ) \u2013 Compression ratio of the GDL. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. Source code in modules/calibration_modules.py def print_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error): \"\"\"This function is used to print the calibration results. Parameters ---------- convergence : dict A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. epsilon_c : float Compression ratio of the GDL. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. \"\"\" print(\"The convergence is:\\n\", convergence) print(\"\\nThe optimized epsilon_gdl: \", epsilon_gdl) print(\"The optimized epsilon_mc: \", epsilon_mc) print(\"The optimized tau: \", tau) print(\"The optimized epsilon_c: \", epsilon_c) print(\"The optimized e: \", e) print(\"The optimized Re: \", Re) print(\"The optimized i0_c_ref: \", i0_c_ref) print(\"The optimized kappa_co: \", kappa_co) print(\"The optimized kappa_c: \", kappa_c) print(\"The optimized a_slim: \", a_slim) print(\"The optimized b_slim: \", b_slim) print(\"The optimized a_switch: \", a_switch) print(Fore.RED + \"\\nThe max simulation error is: \", sim_error, \"%\") print(Style.RESET_ALL)","title":"print_calibration_results"},{"location":"functions/modules/calibration_modules/#modules.calibration_modules.save_calibration_results","text":"This function is used to save in a text file the calibration results. Parameters: convergence ( dict ) \u2013 A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. epsilon_c ( float ) \u2013 Compression ratio of the GDL. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Source code in modules/calibration_modules.py def save_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error, type_fuel_cell): \"\"\"This function is used to save in a text file the calibration results. Parameters ---------- convergence : dict A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. epsilon_c : float Compression ratio of the GDL. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. type_fuel_cell : str Type of fuel cell configuration. \"\"\" root_folder, filename = \"results\", \"parameter_calibration_1.txt\" subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 else type_fuel_cell counter = 1 # Create the folder if necessary folder_name = os.path.join(root_folder, subfolder_name) if not os.path.exists(folder_name): os.makedirs(folder_name) # Create the file without erasing the previous ones while os.path.isfile(os.path.join(folder_name, filename)): counter += 1 filename = \"parameter_calibration_\" + str(counter) + \".txt\" # Write information file_path = os.path.join(folder_name, filename) with open(file_path, \"w\") as file: file.write(\"The convergence is: \" + str(convergence) + \"\\nThe optimized epsilon_gdl: \" + str(epsilon_gdl) + \"\\nThe optimized epsilon_mc: \" + str(epsilon_mc) + \"\\nThe optimized tau: \" + str(tau) + \"\\nThe optimized epsilon_c: \" + str(epsilon_c) + \"\\nThe optimized e: \" + str(e) + \"\\nThe optimized Re: \" + str(Re) + \"\\nThe optimized i0_c_ref: \" + str(i0_c_ref) + \"\\nThe optimized kappa_co: \" + str(kappa_co) + \"\\nThe optimized kappa_c: \" + str(kappa_c) + \"\\nThe optimized a_slim: \" + str(a_slim) + \"\\nThe optimized b_slim: \" + str(b_slim) + \"\\nThe optimized a_switch: \" + str(a_switch) + \"\\nThe max simulation error is: \" + str(sim_error) + \"%\" + \"\\nHere the algorithm works with RG2&3 (global)\")","title":"save_calibration_results"},{"location":"functions/modules/dif_eq_modules/","text":"Differential equations modules This module is used to determine intermediate values for the calculation of the differential equations and to implement integration events. desired_flows(solver_variables, control_variables, i_n, i_fc, operating_inputs, parameters, Mext) This function calculates the desired flow for the air compressor and the humidifiers. These desired flow are different from the real ones as the corresponding machines takes time to reach the desired values. Parameters: solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. i_n ( float ) \u2013 Internal current density (A/m\u00b2). i_fc ( float ) \u2013 Fuel cell current density (A/m\u00b2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Returns: Wcp_des ( float ) \u2013 Desired air compressor flow rate (kg/s). Wa_inj_des ( float ) \u2013 Desired humidifier flow rate at the anode side (kg/s). Wc_inj_des ( float ) \u2013 Desired humidifier flow rate at the cathode side (kg/s). Source code in modules/dif_eq_modules.py def desired_flows(solver_variables, control_variables, i_n, i_fc, operating_inputs, parameters, Mext): \"\"\" This function calculates the desired flow for the air compressor and the humidifiers. These desired flow are different from the real ones as the corresponding machines takes time to reach the desired values. Parameters ---------- solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. i_n : float Internal current density (A/m\u00b2). i_fc : float Fuel cell current density (A/m\u00b2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Mext : float Molar mass of the ambient air outside the stack (kg/mol). Returns ------- Wcp_des : float Desired air compressor flow rate (kg/s). Wa_inj_des : float Desired humidifier flow rate at the anode side (kg/s). Wc_inj_des : float Desired humidifier flow rate at the cathode side (kg/s). \"\"\" # Extraction of the variables Pasm, Pcsm, Wcp = solver_variables['Pasm'], solver_variables['Pcsm'], solver_variables['Wcp'] # Extraction of the operating inputs and the parameters Tfc, Sa, Sc = operating_inputs['Tfc'], operating_inputs['Sa'], operating_inputs['Sc'] Phi_a_des, Phi_c_des = control_variables['Phi_a_des'], control_variables['Phi_c_des'] Aact, type_auxiliary = parameters['Aact'], parameters['type_auxiliary'] if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Intermediate values Prd = Pasm Pcp = Pcsm # The desired air compressor flow rate Wcp_des (kg.s-1) Wcp_des = n_cell * Mext * Pext / (Pext - Phi_ext * Psat(Text)) * \\ 1 / yO2_ext * Sc * (i_fc + i_n) / (4 * F) * Aact # The desired humidifier flow rate at the anode side Wa_v_inj_des (kg.s-1) Wrd = n_cell * M_H2 * Sa * (i_fc + i_n) / (2 * F) * Aact Wa_inj_des = (M_H2O * Phi_a_des * Psat(Tfc) / (Prd + Phi_a_des * Psat(Tfc)) / (1 - Phi_a_des * Psat(Tfc) / (Prd + Phi_a_des * Psat(Tfc))) * (Wrd / M_H2)) # The desired humidifier flow rate at the cathode side Wc_inj_des (kg.s-1) Wv_hum_in = M_H2O * Phi_ext * Psat(Text) / Pext * (Wcp / Mext) # Vapor flow rate from the outside Wc_v_des = M_H2O * Phi_c_des * Psat(Tfc) / Pcp * (Wcp / Mext) # Desired vapor flow rate Wc_inj_des = Wc_v_des - Wv_hum_in # Desired humidifier flow rate else: # elif type_auxiliary == \"no_auxiliary\": Wcp_des, Wa_inj_des, Wc_inj_des = 0, 0, 0 return Wcp_des, Wa_inj_des, Wc_inj_des dif_eq_int_values(solver_variables, control_variables, operating_inputs, parameters) This functions calculates intermediate values for the calculation of the differential equations Parameters: solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). i_n ( float ) \u2013 Internal current density (A/m\u00b2). Masm ( float ) \u2013 Molar mass of all the gas species in the anode supply manifold (kg/mol). Maem ( float ) \u2013 Molar mass of all the gas species in the anode external manifold (kg/mol). Mcsm ( float ) \u2013 Molar mass of all the gas species in the cathode supply manifold (kg/mol). Mcem ( float ) \u2013 Molar mass of all the gas species in the cathode external manifold (kg/mol). rho_H2O(Tfc) : float \u2013 Density of water vapor at the fuel cell temperature (kg/m\u00b3). Source code in modules/dif_eq_modules.py def dif_eq_int_values(solver_variables, control_variables, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the calculation of the differential equations Parameters ---------- solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Mext : float Molar mass of the ambient air outside the stack (kg/mol). Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). i_n : float Internal current density (A/m\u00b2). Masm : float Molar mass of all the gas species in the anode supply manifold (kg/mol). Maem : float Molar mass of all the gas species in the anode external manifold (kg/mol). Mcsm : float Molar mass of all the gas species in the cathode supply manifold (kg/mol). Mcem : float Molar mass of all the gas species in the cathode external manifold (kg/mol). rho_H2O(Tfc) : float Density of water vapor at the fuel cell temperature (kg/m\u00b3). \"\"\" # Extraction of the variables C_v_agc, C_v_cgc = solver_variables['C_v_agc'], solver_variables['C_v_cgc'] C_H2_agc, C_H2_acl = solver_variables['C_H2_agc'], solver_variables['C_H2_acl'] C_O2_ccl, C_O2_cgc, C_N2 = solver_variables['C_O2_ccl'], solver_variables['C_O2_cgc'], solver_variables['C_N2'] lambda_mem, Pasm = solver_variables['lambda_mem'], solver_variables['Pasm'] Paem, Pcsm, Pcem = solver_variables['Paem'], solver_variables['Pcsm'], solver_variables['Pcem'] # Extraction of the operating inputs and the parameters Tfc, Phi_c_des = operating_inputs['Tfc'], control_variables['Phi_c_des'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] # Physical quantities outside the stack # Molar masses Mext = Phi_ext * Psat(Text) / Pext * M_H2O + \\ yO2_ext * (1 - Phi_ext * Psat(Text) / Pext) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_ext * Psat(Text) / Pext) * M_N2 # Physical quantities inside the stack # Pressures Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Humidities Phi_agc = C_v_agc / C_v_sat(Tfc) Phi_cgc = C_v_cgc / C_v_sat(Tfc) # Oxygen ratio in dry air y_c = C_O2_cgc / (C_O2_cgc + C_N2) # Internal current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # Physical quantities inside the auxiliary system if parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_anodic_recirculation\" or \\ parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_flow-through_anode\": # Pressure Pp = Pasm # Humidities Phi_aem = Phi_agc * Paem / Pagc Phi_asm = Phi_aem * Pp / Paem Phi_cem = Phi_cgc * Pcem / Pcgc # Molar masses Masm = Phi_asm * Psat(Tfc) / Pasm * M_H2O + \\ (1 - Phi_asm * Psat(Tfc) / Pasm) * M_H2 Maem = Phi_aem * Psat(Tfc) / Paem * M_H2O + \\ (1 - Phi_aem * Psat(Tfc) / Paem) * M_H2 Mcsm = Phi_c_des * Psat(Tfc) / Pcsm * M_H2O + \\ yO2_ext * (1 - Phi_c_des * Psat(Tfc) / Pcsm) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_c_des * Psat(Tfc) / Pcsm) * M_N2 Mcem = Phi_cem * Psat(Tfc) / Pcem * M_H2O + \\ y_c * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_O2 + \\ (1 - y_c) * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_N2 else: # parameters[\"type_auxiliary\"] == \"no_auxiliary\" Masm, Maem, Mcsm, Mcem = [0] * 4 return Mext, Pagc, Pcgc, i_n, Masm, Maem, Mcsm, Mcem, rho_H2O(Tfc) event_negative(t, y, operating_inputs, parameters, solver_variable_names, control_variables) This function creates an event that will be checked at each step of solve_ivp integration. The integration stops if one of the crucial variables (C_v, lambda, C_O2, C_H2) becomes negative (or smaller than 1e-5). Parameters: t ( float ) \u2013 Time (s). y ( ndarray ) \u2013 Numpy list of the solver variables. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. solver_variable_names ( list ) \u2013 Names of the solver variables. control_variables ( dict ) \u2013 Variables controlled by the user. Returns: The difference between the minimum value of the crucial variables and 1e-5. \u2013 Source code in modules/dif_eq_modules.py def event_negative(t, y, operating_inputs, parameters, solver_variable_names, control_variables): \"\"\"This function creates an event that will be checked at each step of solve_ivp integration. The integration stops if one of the crucial variables (C_v, lambda, C_O2, C_H2) becomes negative (or smaller than 1e-5). Parameters ---------- t : float Time (s). y : numpy.ndarray Numpy list of the solver variables. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. solver_variable_names : list Names of the solver variables. control_variables : dict Variables controlled by the user. Returns ------- The difference between the minimum value of the crucial variables and 1e-5. \"\"\" negative_solver_variables = {} # Dictionary to store the crucial variables for index, key in enumerate(solver_variable_names): if (key.startswith(\"C_v_\")) or (key.startswith(\"lambda_\")) or \\ (key.startswith(\"C_O2_\")) or (key.startswith(\"C_H2_\")): negative_solver_variables[key] = y[index] return min(negative_solver_variables.values()) - 1e-5 # 1e-5 is a control parameter to stop the program before","title":"Differential equations modules"},{"location":"functions/modules/dif_eq_modules/#differential-equations-modules","text":"This module is used to determine intermediate values for the calculation of the differential equations and to implement integration events.","title":"Differential equations modules"},{"location":"functions/modules/dif_eq_modules/#modules.dif_eq_modules.desired_flows","text":"This function calculates the desired flow for the air compressor and the humidifiers. These desired flow are different from the real ones as the corresponding machines takes time to reach the desired values. Parameters: solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. i_n ( float ) \u2013 Internal current density (A/m\u00b2). i_fc ( float ) \u2013 Fuel cell current density (A/m\u00b2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Returns: Wcp_des ( float ) \u2013 Desired air compressor flow rate (kg/s). Wa_inj_des ( float ) \u2013 Desired humidifier flow rate at the anode side (kg/s). Wc_inj_des ( float ) \u2013 Desired humidifier flow rate at the cathode side (kg/s). Source code in modules/dif_eq_modules.py def desired_flows(solver_variables, control_variables, i_n, i_fc, operating_inputs, parameters, Mext): \"\"\" This function calculates the desired flow for the air compressor and the humidifiers. These desired flow are different from the real ones as the corresponding machines takes time to reach the desired values. Parameters ---------- solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. i_n : float Internal current density (A/m\u00b2). i_fc : float Fuel cell current density (A/m\u00b2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Mext : float Molar mass of the ambient air outside the stack (kg/mol). Returns ------- Wcp_des : float Desired air compressor flow rate (kg/s). Wa_inj_des : float Desired humidifier flow rate at the anode side (kg/s). Wc_inj_des : float Desired humidifier flow rate at the cathode side (kg/s). \"\"\" # Extraction of the variables Pasm, Pcsm, Wcp = solver_variables['Pasm'], solver_variables['Pcsm'], solver_variables['Wcp'] # Extraction of the operating inputs and the parameters Tfc, Sa, Sc = operating_inputs['Tfc'], operating_inputs['Sa'], operating_inputs['Sc'] Phi_a_des, Phi_c_des = control_variables['Phi_a_des'], control_variables['Phi_c_des'] Aact, type_auxiliary = parameters['Aact'], parameters['type_auxiliary'] if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Intermediate values Prd = Pasm Pcp = Pcsm # The desired air compressor flow rate Wcp_des (kg.s-1) Wcp_des = n_cell * Mext * Pext / (Pext - Phi_ext * Psat(Text)) * \\ 1 / yO2_ext * Sc * (i_fc + i_n) / (4 * F) * Aact # The desired humidifier flow rate at the anode side Wa_v_inj_des (kg.s-1) Wrd = n_cell * M_H2 * Sa * (i_fc + i_n) / (2 * F) * Aact Wa_inj_des = (M_H2O * Phi_a_des * Psat(Tfc) / (Prd + Phi_a_des * Psat(Tfc)) / (1 - Phi_a_des * Psat(Tfc) / (Prd + Phi_a_des * Psat(Tfc))) * (Wrd / M_H2)) # The desired humidifier flow rate at the cathode side Wc_inj_des (kg.s-1) Wv_hum_in = M_H2O * Phi_ext * Psat(Text) / Pext * (Wcp / Mext) # Vapor flow rate from the outside Wc_v_des = M_H2O * Phi_c_des * Psat(Tfc) / Pcp * (Wcp / Mext) # Desired vapor flow rate Wc_inj_des = Wc_v_des - Wv_hum_in # Desired humidifier flow rate else: # elif type_auxiliary == \"no_auxiliary\": Wcp_des, Wa_inj_des, Wc_inj_des = 0, 0, 0 return Wcp_des, Wa_inj_des, Wc_inj_des","title":"desired_flows"},{"location":"functions/modules/dif_eq_modules/#modules.dif_eq_modules.dif_eq_int_values","text":"This functions calculates intermediate values for the calculation of the differential equations Parameters: solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). i_n ( float ) \u2013 Internal current density (A/m\u00b2). Masm ( float ) \u2013 Molar mass of all the gas species in the anode supply manifold (kg/mol). Maem ( float ) \u2013 Molar mass of all the gas species in the anode external manifold (kg/mol). Mcsm ( float ) \u2013 Molar mass of all the gas species in the cathode supply manifold (kg/mol). Mcem ( float ) \u2013 Molar mass of all the gas species in the cathode external manifold (kg/mol). rho_H2O(Tfc) : float \u2013 Density of water vapor at the fuel cell temperature (kg/m\u00b3). Source code in modules/dif_eq_modules.py def dif_eq_int_values(solver_variables, control_variables, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the calculation of the differential equations Parameters ---------- solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Mext : float Molar mass of the ambient air outside the stack (kg/mol). Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). i_n : float Internal current density (A/m\u00b2). Masm : float Molar mass of all the gas species in the anode supply manifold (kg/mol). Maem : float Molar mass of all the gas species in the anode external manifold (kg/mol). Mcsm : float Molar mass of all the gas species in the cathode supply manifold (kg/mol). Mcem : float Molar mass of all the gas species in the cathode external manifold (kg/mol). rho_H2O(Tfc) : float Density of water vapor at the fuel cell temperature (kg/m\u00b3). \"\"\" # Extraction of the variables C_v_agc, C_v_cgc = solver_variables['C_v_agc'], solver_variables['C_v_cgc'] C_H2_agc, C_H2_acl = solver_variables['C_H2_agc'], solver_variables['C_H2_acl'] C_O2_ccl, C_O2_cgc, C_N2 = solver_variables['C_O2_ccl'], solver_variables['C_O2_cgc'], solver_variables['C_N2'] lambda_mem, Pasm = solver_variables['lambda_mem'], solver_variables['Pasm'] Paem, Pcsm, Pcem = solver_variables['Paem'], solver_variables['Pcsm'], solver_variables['Pcem'] # Extraction of the operating inputs and the parameters Tfc, Phi_c_des = operating_inputs['Tfc'], control_variables['Phi_c_des'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] # Physical quantities outside the stack # Molar masses Mext = Phi_ext * Psat(Text) / Pext * M_H2O + \\ yO2_ext * (1 - Phi_ext * Psat(Text) / Pext) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_ext * Psat(Text) / Pext) * M_N2 # Physical quantities inside the stack # Pressures Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Humidities Phi_agc = C_v_agc / C_v_sat(Tfc) Phi_cgc = C_v_cgc / C_v_sat(Tfc) # Oxygen ratio in dry air y_c = C_O2_cgc / (C_O2_cgc + C_N2) # Internal current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # Physical quantities inside the auxiliary system if parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_anodic_recirculation\" or \\ parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_flow-through_anode\": # Pressure Pp = Pasm # Humidities Phi_aem = Phi_agc * Paem / Pagc Phi_asm = Phi_aem * Pp / Paem Phi_cem = Phi_cgc * Pcem / Pcgc # Molar masses Masm = Phi_asm * Psat(Tfc) / Pasm * M_H2O + \\ (1 - Phi_asm * Psat(Tfc) / Pasm) * M_H2 Maem = Phi_aem * Psat(Tfc) / Paem * M_H2O + \\ (1 - Phi_aem * Psat(Tfc) / Paem) * M_H2 Mcsm = Phi_c_des * Psat(Tfc) / Pcsm * M_H2O + \\ yO2_ext * (1 - Phi_c_des * Psat(Tfc) / Pcsm) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_c_des * Psat(Tfc) / Pcsm) * M_N2 Mcem = Phi_cem * Psat(Tfc) / Pcem * M_H2O + \\ y_c * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_O2 + \\ (1 - y_c) * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_N2 else: # parameters[\"type_auxiliary\"] == \"no_auxiliary\" Masm, Maem, Mcsm, Mcem = [0] * 4 return Mext, Pagc, Pcgc, i_n, Masm, Maem, Mcsm, Mcem, rho_H2O(Tfc)","title":"dif_eq_int_values"},{"location":"functions/modules/dif_eq_modules/#modules.dif_eq_modules.event_negative","text":"This function creates an event that will be checked at each step of solve_ivp integration. The integration stops if one of the crucial variables (C_v, lambda, C_O2, C_H2) becomes negative (or smaller than 1e-5). Parameters: t ( float ) \u2013 Time (s). y ( ndarray ) \u2013 Numpy list of the solver variables. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. solver_variable_names ( list ) \u2013 Names of the solver variables. control_variables ( dict ) \u2013 Variables controlled by the user. Returns: The difference between the minimum value of the crucial variables and 1e-5. \u2013 Source code in modules/dif_eq_modules.py def event_negative(t, y, operating_inputs, parameters, solver_variable_names, control_variables): \"\"\"This function creates an event that will be checked at each step of solve_ivp integration. The integration stops if one of the crucial variables (C_v, lambda, C_O2, C_H2) becomes negative (or smaller than 1e-5). Parameters ---------- t : float Time (s). y : numpy.ndarray Numpy list of the solver variables. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. solver_variable_names : list Names of the solver variables. control_variables : dict Variables controlled by the user. Returns ------- The difference between the minimum value of the crucial variables and 1e-5. \"\"\" negative_solver_variables = {} # Dictionary to store the crucial variables for index, key in enumerate(solver_variable_names): if (key.startswith(\"C_v_\")) or (key.startswith(\"lambda_\")) or \\ (key.startswith(\"C_O2_\")) or (key.startswith(\"C_H2_\")): negative_solver_variables[key] = y[index] return min(negative_solver_variables.values()) - 1e-5 # 1e-5 is a control parameter to stop the program before","title":"event_negative"},{"location":"functions/modules/display_modules/","text":"Display modules This module is used to accurately plot the figures. calculate_simulation_error(Ucell, U_exp_t) This function calculates the simulation error between the simulated cell voltage and the experimental cell voltage. It is calculated as the maximum relative difference between the two voltages (in %). Parameters: Ucell ( ndarray ) \u2013 Simulated cell voltage. U_exp_t ( ndarray ) \u2013 Experimental cell voltage. Returns: float \u2013 Simulation error between the simulated cell voltage and the experimental cell voltage (in %). Source code in modules/display_modules.py def calculate_simulation_error(Ucell, U_exp_t): \"\"\"This function calculates the simulation error between the simulated cell voltage and the experimental cell voltage. It is calculated as the maximum relative difference between the two voltages (in %). Parameters ---------- Ucell : numpy.ndarray Simulated cell voltage. U_exp_t : numpy.ndarray Experimental cell voltage. Returns ------- float Simulation error between the simulated cell voltage and the experimental cell voltage (in %). \"\"\" return np.round(np.max(np.abs(Ucell - U_exp_t) / U_exp_t * 100), 2) # in %. make_Fourier_transformation(variables, operating_inputs, parameters) This function calculates the Fourier transformation of both cell voltage and current density. It will be used to display the Nyquist and Bode diagrams. To generate it at each frequency change, the cell voltage and the current density are recorded. The time for which these points are captured is determined using the following approach: at the beginning of each frequency change, a delta_t_break_EIS time is observed to ensure the dynamic stability of the stack's variables. Subsequently, a delta_t_measurement_EIS time is needed to record the cell voltage and the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: dict \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. Source code in modules/display_modules.py def make_Fourier_transformation(variables, operating_inputs, parameters): \"\"\" This function calculates the Fourier transformation of both cell voltage and current density. It will be used to display the Nyquist and Bode diagrams. To generate it at each frequency change, the cell voltage and the current density are recorded. The time for which these points are captured is determined using the following approach: at the beginning of each frequency change, a delta_t_break_EIS time is observed to ensure the dynamic stability of the stack's variables. Subsequently, a delta_t_measurement_EIS time is needed to record the cell voltage and the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), np.array(variables['Ucell']) # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] t_EIS, max_step = parameters['t_EIS'], parameters['max_step'] # Creation of ifc ifc_t = np.zeros(len(t)) for i in range(len(t)): ifc_t[i] = current_density(t[i], parameters) # Identify the areas where Ucell and ifc can be measured for the EIS: after equilibrium and at each frequency change t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS n_inf = np.where(t_new_start_EIS <= t[0])[0][-1] # The number of frequency changes which has been mad so far. Ucell_EIS_measured = Ucell_t[np.where((t > (t[0] + delta_t_break_EIS[n_inf])) & (t < (t[0] + delta_t_break_EIS[n_inf] + delta_t_measurement_EIS[n_inf])))] ifc_EIS_measured = ifc_t[np.where((t > (t[0] + delta_t_break_EIS[n_inf])) & (t < (t[0] + delta_t_break_EIS[n_inf] + delta_t_measurement_EIS[n_inf])))] # Determination of the Fourier transformation N = Ucell_EIS_measured.size # Number of points used for the Fourier transformation Ucell_Fourier = fft(Ucell_EIS_measured) # Ucell Fourier transformation ifc_Fourier = fft(ifc_EIS_measured) # ifc Fourier transformation A_period_t = np.concatenate( ([np.abs(Ucell_Fourier)[0] / N], np.abs(Ucell_Fourier[1:N // 2]) * 2 / N)) # Recovery of # all amplitude values calculated by fft A = max(A_period_t[1:]) # Amplitude at the frequency of the perturbation freq_t = fftfreq(N, max_step)[:N // 2] # Recovery of all frequency values used by fft f = freq_t[np.argmax(A_period_t == A)] # Recovery of the studied frequency return {'Ucell_Fourier': Ucell_Fourier, 'ifc_Fourier': ifc_Fourier, 'A_period_t': A_period_t, 'A': A, 'freq_t': freq_t, 'f': f, 'N': N} plot_Bode_amplitude_instructions(f_EIS, type_fuel_cell, ax) This function adds the instructions for amplitude Bode plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_Bode_amplitude_instructions(f_EIS, type_fuel_cell, ax): \"\"\"This function adds the instructions for amplitude Bode plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. ax.set_xscale('log') # set logarithmic scale for the x-axis # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(LogLocator(base=10.0, numticks=f_power_max_EIS - f_power_min_EIS + 1)) ax.xaxis.set_minor_locator(LogLocator(base=10.0, subs=np.arange(2, 10) * .1, numticks=(f_power_max_EIS - f_power_min_EIS + 1) * len(np.arange(2, 10)))) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(30)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(30 / 5)) ax.set_xlim([10**f_power_min_EIS, 10**f_power_max_EIS]) plot_Bode_phase_instructions(f_EIS, type_fuel_cell, ax) This function adds the instructions for phase Bode plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_Bode_phase_instructions(f_EIS, type_fuel_cell, ax): \"\"\"This function adds the instructions for phase Bode plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. ax.set_xscale('log') # set logarithmic scale for the x-axis if not ax.yaxis_inverted(): ax.invert_yaxis() # Invert the y-axis # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(LogLocator(base=10.0, numticks = f_power_max_EIS-f_power_min_EIS+1)) ax.xaxis.set_minor_locator(LogLocator(base=10.0, subs=np.arange(2, 10) * .1, numticks = (f_power_max_EIS-f_power_min_EIS+1)*len(np.arange(2, 10)))) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(5 / 5)) ax.set_xlim([10**f_power_min_EIS, 10**f_power_max_EIS]) plot_C_H2(variables, n_gdl, ax) This function plots the hydrogen concentration at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. ax ( Axes ) \u2013 Axes on which the hydrogen concentration will be plotted. Source code in modules/display_modules.py def plot_C_H2(variables, n_gdl, ax): \"\"\"This function plots the hydrogen concentration at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. ax : matplotlib.axes.Axes Axes on which the hydrogen concentration will be plotted. \"\"\" # Extraction of the variables t, C_H2_agc_t = variables['t'], variables['C_H2_agc'] C_H2_agdl_t, C_H2_acl_t = variables[f'C_H2_agdl_{n_gdl // 2}'], variables['C_H2_acl'] # Plot the hydrogen concentration at different spatial localisations: C_H2 ax.plot(t, C_H2_agc_t, color=colors(0)) ax.plot(t, C_H2_agdl_t, color=colors(1)) ax.plot(t, C_H2_acl_t, color=colors(2)) ax.legend([r'$\\mathregular{C_{H_{2},agc}}$', r'$\\mathregular{C_{H_{2},agdl}}$', r'$\\mathregular{C_{H_{2},acl}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Hydrogen}$ $\\mathbf{concentration}$ $\\mathbf{C_{H_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(55, 58) plot_C_N2(variables, ax) This function plots the nitrogen concentration as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the nitrogen concentration will be plotted. Source code in modules/display_modules.py def plot_C_N2(variables, ax): \"\"\"This function plots the nitrogen concentration as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the nitrogen concentration will be plotted. \"\"\" # Extraction of the variables t, C_N2_t = variables['t'], variables['C_N2'] # Plot C_N2 ax.plot(t, C_N2_t, color=colors(6)) ax.legend([r'$\\mathregular{C_{N_{2}}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Nitrogen}$ $\\mathbf{concentration}$ $\\mathbf{C_{N_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.set_ylim(47, 49) plot_C_O2(variables, n_gdl, ax) This function plots the oxygen concentration at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. ax ( Axes ) \u2013 Axes on which the oxygen concentration will be plotted. Source code in modules/display_modules.py def plot_C_O2(variables, n_gdl, ax): \"\"\"This function plots the oxygen concentration at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. ax : matplotlib.axes.Axes Axes on which the oxygen concentration will be plotted. \"\"\" # Extraction of the variables t, C_O2_ccl_t = variables['t'], variables['C_O2_ccl'] C_O2_cgdl_t, C_O2_cgc_t = variables[f'C_O2_cgdl_{n_gdl // 2}'], variables['C_O2_cgc'] # Plot the oxygen concentration at different spatial localisations: C_O2 ax.plot(t, C_O2_ccl_t, color=colors(4)) ax.plot(t, C_O2_cgdl_t, color=colors(5)) ax.plot(t, C_O2_cgc_t, color=colors(6)) ax.legend([r'$\\mathregular{C_{O_{2},ccl}}$', r'$\\mathregular{C_{O_{2},cgdl}}$', r'$\\mathregular{C_{O_{2},cgc}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Oxygen}$ $\\mathbf{concentration}$ $\\mathbf{C_{O_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(6, 11) plot_C_v(variables, n_gdl, C_v_sat, n, ax) This function plots the vapor concentrations at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. C_v_sat ( float ) \u2013 Saturation vapor concentration. n ( int ) \u2013 Number of points used to plot the vapor concentration. ax ( Axes ) \u2013 Axes on which the vapor concentration will be plotted. Source code in modules/display_modules.py def plot_C_v(variables, n_gdl, C_v_sat, n, ax): \"\"\"This function plots the vapor concentrations at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. C_v_sat : float Saturation vapor concentration. n : int Number of points used to plot the vapor concentration. ax : matplotlib.axes.Axes Axes on which the vapor concentration will be plotted. \"\"\" # Extraction of the variables t, C_v_agc_t, C_v_agdl_t = variables['t'], variables['C_v_agc'], variables[f'C_v_agdl_{n_gdl // 2}'] C_v_acl_t, C_v_ccl_t = variables['C_v_acl'], variables['C_v_ccl'] C_v_cgdl_t, C_v_cgc_t = variables[f'C_v_cgdl_{n_gdl // 2}'], variables['C_v_cgc'] # Plot the vapor concentrations at different spatial localisations Cv C_v_sat_t = np.ones(n) * C_v_sat ax.plot(t, C_v_agc_t, color=colors(0)) ax.plot(t, C_v_agdl_t, color=colors(1)) ax.plot(t, C_v_acl_t, color=colors(2)) ax.plot(t, C_v_ccl_t, color=colors(4)) ax.plot(t, C_v_cgdl_t, color=colors(5)) ax.plot(t, C_v_cgc_t, color=colors(6)) ax.plot(t, C_v_sat_t, color='k') ax.legend([r'$\\mathregular{C_{v,agc}}$', r'$\\mathregular{C_{v,agdl}}$', r'$\\mathregular{C_{v,acl}}$', r'$\\mathregular{C_{v,ccl}}$', r'$\\mathregular{C_{v,cgdl}}$', r'$\\mathregular{C_{v,cgc}}$', r'$\\mathregular{C_{v,sat}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r\"$\\mathbf{Vapor}$ $\\mathbf{concentration}$ $\\mathbf{C_{v}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$\", labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(11, 16) plot_EIS_Nyquist_instructions(type_fuel_cell, f_Fourier, x, y, ax) This function adds the instructions for EIS plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. f_Fourier ( ndarray ) \u2013 Frequency at which the EIS is simulated. x ( ndarray ) \u2013 x-axis values for plotting the annotation. y ( ndarray ) \u2013 y-axis values for plotting the annotation. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_EIS_Nyquist_instructions(type_fuel_cell, f_Fourier, x, y, ax): \"\"\"This function adds the instructions for EIS plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. f_Fourier : numpy.ndarray Frequency at which the EIS is simulated. x : numpy.ndarray x-axis values for plotting the annotation. y : numpy.ndarray y-axis values for plotting the annotation. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions ax.set_aspect('equal', adjustable='box') # Set orthonormal axis. # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": # Double charge transfer if (f_Fourier >= 70 and f_Fourier <= 80): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, -40), ha='center', fontsize=14, rotation=90, weight='bold') # Auxiliary system if (f_Fourier >= 0.14 and f_Fourier <= 0.16): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 7), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 1.2 and f_Fourier <= 1.4): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 10), ha='center', fontsize=14, rotation=90, weight='bold') # Diffusion if (f_Fourier >= 0.015 and f_Fourier <= 0.020): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(30, 0), ha='center', fontsize=14, rotation=0, weight='bold') if (f_Fourier >= 0.9 and f_Fourier <= 1.1): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 10), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 70 and f_Fourier <= 90): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, -40), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 10000 and f_Fourier <= 12000): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(35, 0), ha='center', fontsize=14, rotation=0, weight='bold') ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(20)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(20 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(10)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(10 / 5)) ax.set_xlim(30, 200) ax.set_ylim(-25, 55) plot_EIS_curve_Bode_amplitude(parameters, Fourier_results, ax) This function is used to plot the amplitude Bode diagram of the EIS curves. Parameters: parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the amplitude Bode diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Bode_amplitude(parameters, Fourier_results, ax): \"\"\"This function is used to plot the amplitude Bode diagram of the EIS curves. Parameters ---------- parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the amplitude Bode diagram will be plotted. \"\"\" # Extraction of the parameters i_EIS, ratio_EIS, f_EIS = parameters['i_EIS'], parameters['ratio_EIS'], parameters['f_EIS'] type_fuel_cell = parameters['type_fuel_cell'] # Extraction of the Fourier results A, f = Fourier_results['A'], Fourier_results['f'] # Calculation of the impedance of the perturbation Z0 = A / (ratio_EIS * (-i_EIS)) * 1e7 # in m\u03a9.cm\u00b2. The sign of i is inverted to comply with the standards of EIS, # which measure a device under load rather than a current source. # Plot the amplitude Bode diagram ax.plot(f, np.abs(Z0), 'o', color=colors(1), label='Amplitude Bode diagram') ax.set_xlabel(r'$\\mathbf{Frequency}$ $\\mathbf{(Hz,}$ $\\mathbf{logarithmic}$ $\\mathbf{scale)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Impedance}$ $\\mathbf{amplitude}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_Bode_amplitude_instructions(f_EIS, type_fuel_cell, ax) plot_EIS_curve_Bode_angle(parameters, Fourier_results, ax) This function is used to plot the angle Bode diagram. It only works with an entry signal made with a cosinus (not a sinus). Parameters: Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the angle Bode diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Bode_angle(parameters, Fourier_results, ax): \"\"\"This function is used to plot the angle Bode diagram. It only works with an entry signal made with a cosinus (not a sinus). Parameters ---------- Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the angle Bode diagram will be plotted. \"\"\" # Extraction of the parameters f_EIS, type_fuel_cell = parameters['f_EIS'], parameters['type_fuel_cell'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] A_period_t, A = Fourier_results['A_period_t'], Fourier_results['A'] f, N = Fourier_results['f'], Fourier_results['N'] # Calculation of the dephasing values at the frequency of the perturbation theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) + np.pi # Recovery of all dephasing values calculated by fft. # An angle of pi is added to comply with the standards of EIS, # which measure a device under load rather than a current source. theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation phi_U_i = ((theta_U - theta_i) * 180 / np.pi) % 360 # Dephasing between Ucell and ifc with a value between 0 and 360 if phi_U_i > 180: phi_U_i -= 360 # To have a value between -180 and 180 # Plot the angle Bode diagram ax.plot(f, phi_U_i, 'o', color=colors(2), label='Angle Bode diagram') ax.set_xlabel(r'$\\mathbf{Frequency}$ $\\mathbf{(Hz,}$ $\\mathbf{logarithmic}$ $\\mathbf{scale)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Phase}$ $\\mathbf{(^\\circ)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_Bode_phase_instructions(f_EIS, type_fuel_cell, ax) plot_EIS_curve_Nyquist(parameters, Fourier_results, ax) This function is used to plot the Nyquist diagram of the EIS curves. Parameters: parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the Nyquist diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Nyquist(parameters, Fourier_results, ax): \"\"\" This function is used to plot the Nyquist diagram of the EIS curves. Parameters ---------- parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the Nyquist diagram will be plotted. \"\"\" # Extraction of the parameters i_EIS, ratio_EIS, type_fuel_cell = parameters['i_EIS'], parameters['ratio_EIS'], parameters['type_fuel_cell'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] f_Fourier = Fourier_results['f'] A_period_t, A, N = Fourier_results['A_period_t'], Fourier_results['A'], Fourier_results['N'] # Calculation of the real and imaginary component of the impedance for each period Z0 = A / (ratio_EIS * (-i_EIS)) * 1e7 # Impedance of the perturbation in m\u03a9.cm\u00b2. The sign of i is inverted to # comply with the standards of EIS, which measure a device under load rather than a current source. theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation Z_real = Z0 * np.cos(theta_U - theta_i) # Real component of the impedance for each period Z_imag = Z0 * np.sin(theta_U - theta_i) # Imaginary component of the impedance for each period # Plot the Nyquist diagram ax.plot(Z_real, -Z_imag, 'o', color=colors(0), label='Nyquist diagram') ax.set_xlabel(r'$\\mathbf{Z_{real}}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{-Z_{imag}}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_EIS_Nyquist_instructions(type_fuel_cell, f_Fourier, Z_real, -Z_imag, ax) plot_EIS_curve_tests(variables, operating_inputs, parameters, Fourier_results) This function is used to test the accuracy of the EIS results. It compares the reconstructed Ucell_Fourier(t) from the Fourier transformation with the current density ifc(t), and displays Ucell(t) given by the model with the reconstructed Ucell_Fourier(t). Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. Source code in modules/display_modules.py def plot_EIS_curve_tests(variables, operating_inputs, parameters, Fourier_results): \"\"\"This function is used to test the accuracy of the EIS results. It compares the reconstructed Ucell_Fourier(t) from the Fourier transformation with the current density ifc(t), and displays Ucell(t) given by the model with the reconstructed Ucell_Fourier(t). Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), variables['Ucell'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] i_EIS, ratio_EIS = parameters['i_EIS'], parameters['ratio_EIS'] t_EIS, f_EIS = parameters['t_EIS'], parameters['f_EIS'] max_step = parameters['max_step'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] A_period_t, A = Fourier_results['A_period_t'], Fourier_results['A'] f, N = Fourier_results['f'], Fourier_results['N'] # Reconstructed Ucell with a cosinus form, and comparison of its form with the current density one. t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS n_inf = np.where(t_new_start_EIS <= t[0])[0][-1] # The number of frequency changes which has been made. f_current = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation print(\"Ucell:\", round(A_period_t[0], 4), ' + ', round(A, 6), \" * np.cos(2*np.pi*\", round(f, 4), \"*t + \", round(theta_U, 4), \"). \") print(\"Current:\", i_EIS, ' + ', ratio_EIS * i_EIS, \" * np.cos(2*np.pi*\", round(f_current[n_inf], 4), \"*t + \", round(theta_i, 4), \"). \\n\") # Display ifc(t) plt.figure(3) plt.subplot(2, 1, 1) # Creation of ifc_t n = len(t) ifc_t = np.zeros(n) for i in range(n): # Conversion in A/cm\u00b2 ifc_t[i] = current_density(t[i], parameters) / 1e4 # Plot of ifc_t plt.plot(t, ifc_t, color='blue', label='ifc') plt.xlabel('Time (s)') plt.ylabel('Current density (A/cm\u00b2)') plt.title('The current density\\nbehaviour over time') # Display Ucell(t) and compare it with the reconstructed Ucell_Fourier(t) from the Fourier transformation plt.subplot(2, 1, 2) Ucell_Fourier = A_period_t[0] + A * np.cos(2 * np.pi * f * t + theta_U) plt.plot(t, Ucell_t, color='blue', label='Ucell') plt.plot(t, Ucell_Fourier, color='black', label='Ucell_Fourier') plt.xlabel('Time (s)') plt.ylabel('Cell voltage (V)') plt.title('The cell voltage\\nbehaviour over time') plot_J(variables, parameters, ax) This function plots the sorption and dissolved water flows as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the flows will be plotted. Source code in modules/display_modules.py def plot_J(variables, parameters, ax): \"\"\"This function plots the sorption and dissolved water flows as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the flows will be plotted. \"\"\" # Extraction of the variables t, S_sorp_acl_t, S_sorp_ccl_t = variables['t'], variables['S_sorp_acl'], variables['S_sorp_ccl'], J_lambda_mem_acl_t, J_lambda_mem_ccl_t = variables['J_lambda_mem_acl'], variables['J_lambda_mem_ccl'] # Extraction of the operating inputs and the parameters Hcl = parameters['Hcl'] # Plot the sorption and dissolved water flows: J J_sorp_acl, J_sorp_ccl = [x * Hcl for x in S_sorp_acl_t], [x * Hcl for x in S_sorp_ccl_t] # Conversion in # mol.m\u207b\u00b2.s\u207b\u00b9 for comparison ax.plot(t, J_sorp_acl, color=colors(2)) ax.plot(t, J_lambda_mem_acl_t, color=colors(3)) ax.plot(t, J_sorp_ccl, color=colors(4)) ax.plot(t, J_lambda_mem_ccl_t, color=colors(7)) ax.legend([r'$\\mathregular{J_{sorp,acl}}$', r'$\\mathregular{J_{\\lambda,mem,acl}}$', r'$\\mathregular{J_{sorp,ccl}}$', r'$\\mathregular{J_{\\lambda,mem,ccl}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Flows}$ $\\mathbf{J}$ $\\mathbf{\\left( mol.m^{-2}.s^{-1} \\right)}$', labelpad=3) ax.ticklabel_format(style='scientific', axis='y', scilimits=(0, 0)) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.02)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.02 / 5)) plt.show() plot_P(variables, ax) This function plots the pressure at different spatial localisations as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the pressure will be plotted. Source code in modules/display_modules.py def plot_P(variables, ax): \"\"\"This function plots the pressure at different spatial localisations as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the pressure will be plotted. \"\"\" # Extraction of the variables t, Pagc_t, Pcgc_t = variables['t'], variables['Pagc'], variables['Pcgc'] Pasm_t, Paem_t, Pcsm_t, Pcem_t = variables['Pasm'], variables['Paem'], variables['Pcsm'], variables['Pcem'] # Conversion in atm Pagc_t, Pcgc_t, Pasm_t = [x / 1e5 for x in Pagc_t], [x / 1e5 for x in Pcgc_t], [x / 1e5 for x in Pasm_t] Paem_t, Pcsm_t, Pcem_t = [x / 1e5 for x in Paem_t], [x / 1e5 for x in Pcsm_t], [x / 1e5 for x in Pcem_t] # Plot the pressure at different spatial localisations: P ax.plot(t, Pagc_t, color=colors(0)) ax.plot(t, Pcgc_t, color=colors(6)) ax.plot(t, Pasm_t, color=colors(7)) ax.plot(t, Paem_t, color=colors(8)) ax.plot(t, Pcsm_t, color=colors(9)) ax.plot(t, Pcem_t, color=colors(3)) ax.legend([r'$\\mathregular{P_{agc}}$', r'$\\mathregular{P_{cgc}}$', r'$\\mathregular{P_{asm}}$', r'$\\mathregular{P_{aem}}$', r'$\\mathregular{P_{csm}}$', r'$\\mathregular{P_{cem}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Pressure}$ $\\mathbf{P}$ $\\mathbf{\\left( bar \\right)}$', labelpad=3) ax.ticklabel_format(style='scientific', axis='y', scilimits=(0, 0)) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5e-4)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5e-4 / 5)) ax.set_ylim(1.99980, 2.00015) plot_Phi_a(variables, operating_inputs, ax) This function plots the humidity at the anode side, at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_a(variables, operating_inputs, ax): \"\"\"This function plots the humidity at the anode side, at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t, C_v_agc_t = variables['t'], variables['C_v_agc'] Phi_asm_t, Phi_aem_t = variables['Phi_asm'], variables['Phi_aem'] # Extraction of the operating inputs Tfc, Phi_a_des = operating_inputs['Tfc'], operating_inputs['Phi_a_des'] # Calculate the humidity Phi Phi_agc_t = [0] * len(t) for i in range(len(t)): Phi_agc_t[i] = C_v_agc_t[i] * R * Tfc / Psat(Tfc) # Plot the humidity at different spatial localisations: Phi ax.plot(t, Phi_agc_t, color=colors(0), label=r'$\\mathregular{\\Phi_{agc}}$') ax.plot(t, Phi_asm_t, color=colors(1), label=r'$\\mathregular{\\Phi_{asm}}$') ax.plot(t, Phi_aem_t, color=colors(2), label=r'$\\mathregular{\\Phi_{aem}}$') ax.plot(t, [Phi_a_des]*len(t), color='black', label=r'$\\mathregular{\\Phi_{a,des}}$') ax.legend(loc='center right', bbox_to_anchor=(1, 0.67)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Humidity}$ $\\mathbf{at}$ $\\mathbf{the}$ $\\mathbf{anode}$ $\\mathbf{side}$ $\\mathbf{\\Phi}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) plot_Phi_c(variables, operating_inputs, ax) This function plots the humidity, at the cathode side, at different spatial localisations as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_c(variables, operating_inputs, ax): \"\"\"This function plots the humidity, at the cathode side, at different spatial localisations as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t, C_v_cgc_t = variables['t'], variables['C_v_cgc'] Phi_csm_t, Phi_cem_t = variables['Phi_csm'], variables['Phi_cem'] # Extraction of the operating inputs Tfc, Phi_c_des = operating_inputs['Tfc'], operating_inputs['Phi_c_des'] # Calculate the humidity Phi Phi_cgc_t = [0] * len(t) for i in range(len(t)): Phi_cgc_t[i] = C_v_cgc_t[i] * R * Tfc / Psat(Tfc) # Plot the humidity at different spatial localisations: Phi ax.plot(t, Phi_cgc_t, color=colors(0), label=r'$\\mathregular{\\Phi_{cgc}}$') ax.plot(t, Phi_csm_t, color=colors(1), label=r'$\\mathregular{\\Phi_{csm}}$') ax.plot(t, Phi_cem_t, color=colors(2), label=r'$\\mathregular{\\Phi_{cem}}$') ax.plot(t, [Phi_c_des]*len(t), color='black', label=r'$\\mathregular{\\Phi_{c,des}}$') ax.legend(loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Humidity}$ $\\mathbf{at}$ $\\mathbf{the}$ $\\mathbf{cathode}$ $\\mathbf{side}$ $\\mathbf{\\Phi}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) plot_Phi_des(variables, operating_inputs, parameters, ax) This function plots the controlled or uncontrolled desired humidity at the anode and cathode as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_des(variables, operating_inputs, parameters, ax): \"\"\"This function plots the controlled or uncontrolled desired humidity at the anode and cathode as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t = variables['t'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] if parameters['type_control'] == \"Phi_des\": Phi_a_des, Phi_c_des = variables['Phi_a_des'], variables['Phi_c_des'] ax.set_ylabel(r'$\\mathbf{Controlled}$ $\\mathbf{inlet}$ $\\mathbf{humidity}$ $\\mathbf{\\Phi_{des}}$', labelpad=3) else: Phi_a_des, Phi_c_des = [operating_inputs['Phi_a_des']] * len(t), [operating_inputs['Phi_c_des']] * len(t) ax.set_ylabel(r'$\\mathbf{Uncontrolled}$ $\\mathbf{inlet}$ $\\mathbf{humidity}$ $\\mathbf{\\Phi_{des}}$', labelpad=3) # Plot Phi_des n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of ifc_t ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, Phi_c_des, color=colors(6), label=r'$\\mathregular{\\Phi_{c,des}}$') ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) if parameters['type_auxiliary'] == \"forced-convective_cathode_with_flow-through_anode\" or \\ parameters['type_auxiliary'] == \"no_auxiliary\": ax.plot(t, Phi_a_des, color=colors(0), label=r'$\\mathregular{\\Phi_{a,des}}$') ax.legend([r'$\\mathregular{\\Phi_{a,des}}$', r'$\\mathregular{\\Phi_{c,des}}$'], loc='best') else: ax.legend([r'$\\mathregular{\\Phi_{c,des}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.2)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.2 / 5)) ax.set_xlim(0, 4.1) plot_Ucell(variables, ax) This function plots the cell voltage as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the cell voltage will be plotted. Source code in modules/display_modules.py def plot_Ucell(variables, ax): \"\"\"This function plots the cell voltage as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the cell voltage will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = variables['t'], variables['Ucell'] # Plot the cell voltage: Ucell ax.plot(t, Ucell_t, color=colors(0), label=r'$\\mathregular{U_{cell}}$') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Cell}$ $\\mathbf{voltage}$ $\\mathbf{U_{cell}}$ $\\mathbf{\\left( V \\right)}$', labelpad=3) ax.legend([r'$\\mathregular{U_{cell}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.05)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.05 / 5)) plot_cell_efficiency(variables, operating_inputs, parameters, n, ax) This function plots the fuel cell efficiency eta_fc as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the fuel cell efficiency. ax ( Axes ) \u2013 Axes on which the fuel cell efficiency will be plotted. Source code in modules/display_modules.py def plot_cell_efficiency(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the fuel cell efficiency eta_fc as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the fuel cell efficiency. ax : matplotlib.axes.Axes Axes on which the fuel cell efficiency will be plotted. \"\"\" # Extraction of the variables t, Ucell_t, lambda_mem_t = variables['t'], variables['Ucell'], variables['lambda_mem'] C_H2_acl_t, C_O2_ccl_t = variables['C_H2_acl'], variables['C_O2_ccl'] # Extraction of the operating inputs and the parameters current_density, Tfc = operating_inputs['current_density'], operating_inputs['Tfc'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control = parameters['type_control'] # Creation of the fuel cell efficiency: eta_fc ifc_t, Pfc_t, eta_fc_t = np.zeros(n), np.zeros(n), np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 Pfc_t[i] = Ucell_t[i] * ifc_t[i] Ueq = E0 - 8.5e-4 * (Tfc - 298.15) + R * Tfc / (2 * F) * (np.log(R * Tfc * C_H2_acl_t[i] / Pref) + 0.5 * np.log(R * Tfc * C_O2_ccl_t[i] / Pref)) i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl_t[i] * k_H2(lambda_mem_t[i], Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl_t[i] * k_O2(lambda_mem_t[i], Tfc, kappa_co) i_n = (i_H2 + i_O2) / 1e4 # Conversion in A/cm\u00b2 eta_fc_t[i] = Pfc_t[i] / (Ueq * (ifc_t[i] + i_n)) # Plot of the fuel cell efficiency: eta_fc plot_specific_line(ifc_t, eta_fc_t, type_fuel_cell, type_auxiliary, type_control, None, ax) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=0) ax.set_ylabel(r'$\\mathbf{Fuel}$ $\\mathbf{cell}$ $\\mathbf{efficiency}$ $\\mathbf{\\eta_{fc}}$', labelpad=0) ax.legend(loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) ax.set_xlim(0, 4.1) ax.set_ylim(0, 0.7) plot_general_instructions(ax) This function adds the common instructions for all the plots displayed by AlphaPEM to the ax object. Parameters: ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_general_instructions(ax): \"\"\"This function adds the common instructions for all the plots displayed by AlphaPEM to the ax object. Parameters ---------- ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" ax.tick_params(axis='both', which='major', size=10, width=1.5, direction='out') ax.tick_params(axis='both', which='minor', size=5, width=1.5, direction='out') plt.tight_layout() # Adjust layout to prevent overlap between labels and the figure plt.show() # Show the figure plot_ifc(variables, operating_inputs, parameters, n, ax) This function plots the current density as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the current density. ax ( Axes ) \u2013 Axes on which the current density will be plotted. Source code in modules/display_modules.py def plot_ifc(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the current density as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the current density. ax : matplotlib.axes.Axes Axes on which the current density will be plotted. \"\"\" # Extraction of the variables t = variables['t'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] # Plot the current density: ifc ifc_t = np.zeros(n) for i in range(n): # Creation of ifc_t ifc_t[i] = current_density(t[i], parameters) / 10000 # Conversion in A/cm\u00b2 ax.plot(t, ifc_t, color=colors(0), label=r'$\\mathregular{i_{fc}}$') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) ax.legend([r'$\\mathregular{i_{fc}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) plot_lambda(variables, operating_inputs, parameters, ax) This function plots the water content at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the water content will be plotted. Source code in modules/display_modules.py def plot_lambda(variables, operating_inputs, parameters, ax): \"\"\"This function plots the water content at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the water content will be plotted. \"\"\" # Extraction of the variables t, lambda_acl_t = variables['t'], variables['lambda_acl'] lambda_mem_t, lambda_ccl_t = variables['lambda_mem'], variables['lambda_ccl'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] type_current = parameters['type_current'] # Plot the water content at different spatial localisations: lambda if type_current == \"polarization\": n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of i_fc ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, lambda_acl_t, color=colors(2)) ax.plot(ifc_t, lambda_mem_t, color=colors(3)) ax.plot(ifc_t, lambda_ccl_t, color=colors(4)) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) else: ax.plot(t, lambda_acl_t, color=colors(2)) ax.plot(t, lambda_mem_t, color=colors(3)) ax.plot(t, lambda_ccl_t, color=colors(4)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Water}$ $\\mathbf{content}$ $\\mathbf{\\lambda}$', labelpad=3) ax.legend([r'$\\mathregular{\\lambda_{acl}}$', r'$\\mathregular{\\lambda_{mem}}$', r'$\\mathregular{\\lambda_{ccl}}$'], loc='best') # Plot instructions plot_general_instructions(ax) if type_current == \"polarization\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) else: ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(3)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(3 / 5)) plot_pola_instructions(type_fuel_cell, ax) This function adds the specific instructions for polarisation plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_pola_instructions(type_fuel_cell, ax): \"\"\"This function adds the specific instructions for polarisation plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) ax.set_xlim(0, 3.0) ax.set_ylim(0.4, 1.04) # For LF fuel cell elif type_fuel_cell == \"LF\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.4)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.4 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.2)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.2 / 5)) ax.set_xlim(-0.05, 1.6) ax.set_ylim(0, 1.0) # For other fuel cell else: pass plot_polarisation_curve(variables, operating_inputs, parameters, ax) This function plots the model polarisation curve, and compare it to the experimental one (if it exists). The polarisation curve is a classical representation of the cell performances, showing the cell voltage as a function of the current density. To generate it, the current density is increased step by step, and the cell voltage is recorded at each step. The time for which this point is captured is determined using the following approach: at the beginning of each load, a delta_t_load_pola time is needed to raise the current density to its next value. Subsequently, a delta_t_break_pola time is observed to ensure the dynamic stability of the stack's variables before initiating a new load. Ideally, each polarisation point should be recorded at the end of each delta_t_break_pola time. However, due to the design of the increments to minimize program instability (as observed in step_current function), the end of each delta_t_break_pola time corresponds to the beginning of a new load. To ensure a stationary operation and accurate polarisation point measurements, it is recommended to take the polarisation point just before by subtracting a delta_t value from it. This adjustment allows for stable and consistent measurements during the stationary period. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the polarisation curve will be plotted. Source code in modules/display_modules.py def plot_polarisation_curve(variables, operating_inputs, parameters, ax): \"\"\" This function plots the model polarisation curve, and compare it to the experimental one (if it exists). The polarisation curve is a classical representation of the cell performances, showing the cell voltage as a function of the current density. To generate it, the current density is increased step by step, and the cell voltage is recorded at each step. The time for which this point is captured is determined using the following approach: at the beginning of each load, a delta_t_load_pola time is needed to raise the current density to its next value. Subsequently, a delta_t_break_pola time is observed to ensure the dynamic stability of the stack's variables before initiating a new load. Ideally, each polarisation point should be recorded at the end of each delta_t_break_pola time. However, due to the design of the increments to minimize program instability (as observed in step_current function), the end of each delta_t_break_pola time corresponds to the beginning of a new load. To ensure a stationary operation and accurate polarisation point measurements, it is recommended to take the polarisation point just before by subtracting a delta_t value from it. This adjustment allows for stable and consistent measurements during the stationary period. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the polarisation curve will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), np.array(variables['Ucell']) # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] t_step, i_step, i_max_pola = parameters['t_step'], parameters['i_step'], parameters['i_max_pola'] delta_pola = parameters['delta_pola'] i_EIS, t_EIS, f_EIS = parameters['i_EIS'], parameters['t_EIS'], parameters['f_EIS'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control, type_plot = parameters['type_control'], parameters['type_plot'] if type_plot == \"fixed\": # Creation of ifc_t n = len(t) ifc_t = np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 # Recovery of ifc and Ucell from the model after each stack stabilisation delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola nb_loads = int(i_max_pola / delta_i_pola + 1) # Number of loads which are made ifc_discretized = np.zeros(nb_loads) Ucell_discretized = np.zeros(nb_loads) for i in range(nb_loads): t_load = delta_t_ini_pola + (i + 1) * (delta_t_load_pola + delta_t_break_pola) - delta_t_break_pola / 10 # # time for measurement idx = (np.abs(t - t_load)).argmin() # the corresponding index ifc_discretized[i] = ifc_t[idx] # the last value at the end of each load Ucell_discretized[i] = Ucell_t[idx] # the last value at the end of each load # Plot the experimental polarization curve and calculate the simulation error compared with experimental data if type_fuel_cell != \"manual_setup\" and \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Experimental points are accessible # Plot of the experimental polarization curve i_exp_t, U_exp_t = pola_exp_values(type_fuel_cell) plot_experimental_polarisation_curve(type_fuel_cell, i_exp_t, U_exp_t, ax) # Calculate the simulation error compared with experimental data # i_fc and Ucell are reduced to remain within experimental limits for comparison i_fc_reduced = ifc_discretized[(ifc_discretized >= i_exp_t[0]) & (ifc_discretized <= i_exp_t[-1])] Ucell_reduced = Ucell_discretized[(ifc_discretized >= i_exp_t[0]) & (ifc_discretized <= i_exp_t[-1])] # Experimental points are interpolated to correspond to the model points U_exp_interpolated = interp1d(i_exp_t, U_exp_t, kind='linear')(i_fc_reduced) sim_error = calculate_simulation_error(Ucell_reduced, U_exp_interpolated) else: sim_error = None # Plot the model polarisation curve plot_specific_line(ifc_discretized, Ucell_discretized, type_fuel_cell, type_auxiliary, type_control, sim_error, ax) plot_pola_instructions(type_fuel_cell, ax) else: # type_plot == \"dynamic\" # Plot of the polarisation curve produced by the model delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola idx = (np.abs(t - t[-1] + delta_t_break_pola / 10)).argmin() # index for polarisation measurement ifc = np.array(current_density(t[idx], parameters) / 1e4) # time for polarisation measurement Ucell = np.array(Ucell_t[idx]) # voltage measurement ax.plot(ifc, Ucell, 'og', markersize=2) # Add the common instructions for the plot ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Cell}$ $\\mathbf{voltage}$ $\\mathbf{U_{cell}}$ $\\mathbf{\\left( V \\right)}$', labelpad=3) plot_general_instructions(ax) if type_plot == \"fixed\": ax.legend(loc='best') plot_power_density_curve(variables, operating_inputs, parameters, n, ax) This function plots the power density curve Pfc, produced by a cell, as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the power density curve. ax ( Axes ) \u2013 Axes on which the power density curve will be plotted. Source code in modules/display_modules.py def plot_power_density_curve(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the power density curve Pfc, produced by a cell, as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the power density curve. ax : matplotlib.axes.Axes Axes on which the power density curve will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = variables['t'], variables['Ucell'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control = parameters['type_control'] # Creation of the power density function: Pfc ifc_t, Pfc_t = np.zeros(n), np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 Pfc_t[i] = Ucell_t[i] * ifc_t[i] # Plot of the power density function: Pfc plot_specific_line(ifc_t, Pfc_t, type_fuel_cell, type_auxiliary, type_control, None, ax) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=0) ax.set_ylabel(r'$\\mathbf{Fuel}$ $\\mathbf{cell}$ $\\mathbf{power}$ $\\mathbf{density}$ $\\mathbf{P_{fc}}$ $\\mathbf{\\left( W.cm^{-2} \\right)}$', labelpad=0) ax.legend(loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.3)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.3 / 5)) ax.set_xlim(0, 4.1) ax.set_ylim(0, 2.1) plot_s(variables, operating_inputs, parameters, ax) This function plots the liquid water saturation at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the liquid water saturation will be plotted. Source code in modules/display_modules.py def plot_s(variables, operating_inputs, parameters, ax): \"\"\"This function plots the liquid water saturation at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the liquid water saturation will be plotted. \"\"\" # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] n_gdl, type_current = parameters['n_gdl'], parameters['type_current'] # Extraction of the variables t, s_agdl_t, s_acl_t = variables['t'], variables[f's_agdl_{n_gdl // 2}'], variables['s_acl'] s_ccl_t, s_cgdl_t = variables['s_ccl'], variables[f's_cgdl_{n_gdl // 2}'] # Plot the liquid water saturation at different spatial localisations: s if type_current == \"polarization\": n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of i_fc ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, s_agdl_t, color=colors(1)) ax.plot(ifc_t, s_acl_t, color=colors(2)) ax.plot(ifc_t, s_ccl_t, color=colors(4)) ax.plot(ifc_t, s_cgdl_t, color=colors(5)) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) else: ax.plot(t, s_agdl_t, color=colors(1)) ax.plot(t, s_acl_t, color=colors(2)) ax.plot(t, s_ccl_t, color=colors(4)) ax.plot(t, s_cgdl_t, color=colors(5)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Liquid}$ $\\mathbf{water}$ $\\mathbf{saturation}$ $\\mathbf{s}$', labelpad=3) ax.legend([r'$\\mathregular{s_{agdl}}$', r'$\\mathregular{s_{acl}}$', r'$\\mathregular{s_{ccl}}$', r'$\\mathregular{s_{cgdl}}$'], loc='best') # Plot instructions plot_general_instructions(ax) if type_current == \"polarization\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) else: ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.04)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.04 / 5)) plot_specific_line(x, y, type_fuel_cell, type_auxiliary, type_control, sim_error, ax) This function adds the appropriate plot configuration according to the type_input to the ax object. Parameters: x ( ndarray ) \u2013 x-axis values. y ( ndarray ) \u2013 y-axis values. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. type_auxiliary ( str ) \u2013 Type of auxiliary system. type_control ( str ) \u2013 Type of control system. sim_error ( float ) \u2013 Simulation error between the simulated cell voltage and the experimental cell voltage (in %). ax ( Axes ) \u2013 Axes on which the line will be plotted. Source code in modules/display_modules.py def plot_specific_line(x, y, type_fuel_cell, type_auxiliary, type_control, sim_error, ax): \"\"\" This function adds the appropriate plot configuration according to the type_input to the ax object. Parameters ---------- x : numpy.ndarray x-axis values. y : numpy.ndarray y-axis values. type_fuel_cell : str Type of fuel cell configuration. type_auxiliary : str Type of auxiliary system. type_control : str Type of control system. sim_error : float Simulation error between the simulated cell voltage and the experimental cell voltage (in %). ax : matplotlib.axes.Axes Axes on which the line will be plotted. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": if type_fuel_cell == \"EH-31_1.5\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(0), label='Sim. - P = 1.5 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_1.5\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(0), label='Sim. - P = 1.5 bar') elif type_fuel_cell == \"EH-31_2.0\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, '--', color=colors(1), label='Sim. - P = 2.0 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.0\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": if type_control == \"Phi_des\": ax.plot(x, y, color=colors(5), label=r'Sim. - P = 2.0 bar - controlled $\\mathregular{\\Phi_{des}}$') else: ax.plot(x, y, color=colors(1), label=r'Sim. - P = 2.0 bar - uncontrolled $\\mathregular{\\Phi_{des}}$') elif type_fuel_cell == \"EH-31_2.25\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, '--', color=colors(2), label='Sim. - P = 2.25 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.25\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(2), label='Sim. - P = 2.25 bar') elif type_fuel_cell == \"EH-31_2.5\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(3), label='Sim - P = 2.5 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.5\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(3), label='Sim - P = 2.5 bar') # For LF fuel cell elif type_fuel_cell == \"LF\": ax.plot(x, y, color=colors(0), label='Simulation') # For other fuel cell else: ax.plot(x, y, color=colors(0), label='Simulation')","title":"Display modules"},{"location":"functions/modules/display_modules/#display-modules","text":"This module is used to accurately plot the figures.","title":"Display modules"},{"location":"functions/modules/display_modules/#modules.display_modules.calculate_simulation_error","text":"This function calculates the simulation error between the simulated cell voltage and the experimental cell voltage. It is calculated as the maximum relative difference between the two voltages (in %). Parameters: Ucell ( ndarray ) \u2013 Simulated cell voltage. U_exp_t ( ndarray ) \u2013 Experimental cell voltage. Returns: float \u2013 Simulation error between the simulated cell voltage and the experimental cell voltage (in %). Source code in modules/display_modules.py def calculate_simulation_error(Ucell, U_exp_t): \"\"\"This function calculates the simulation error between the simulated cell voltage and the experimental cell voltage. It is calculated as the maximum relative difference between the two voltages (in %). Parameters ---------- Ucell : numpy.ndarray Simulated cell voltage. U_exp_t : numpy.ndarray Experimental cell voltage. Returns ------- float Simulation error between the simulated cell voltage and the experimental cell voltage (in %). \"\"\" return np.round(np.max(np.abs(Ucell - U_exp_t) / U_exp_t * 100), 2) # in %.","title":"calculate_simulation_error"},{"location":"functions/modules/display_modules/#modules.display_modules.make_Fourier_transformation","text":"This function calculates the Fourier transformation of both cell voltage and current density. It will be used to display the Nyquist and Bode diagrams. To generate it at each frequency change, the cell voltage and the current density are recorded. The time for which these points are captured is determined using the following approach: at the beginning of each frequency change, a delta_t_break_EIS time is observed to ensure the dynamic stability of the stack's variables. Subsequently, a delta_t_measurement_EIS time is needed to record the cell voltage and the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: dict \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. Source code in modules/display_modules.py def make_Fourier_transformation(variables, operating_inputs, parameters): \"\"\" This function calculates the Fourier transformation of both cell voltage and current density. It will be used to display the Nyquist and Bode diagrams. To generate it at each frequency change, the cell voltage and the current density are recorded. The time for which these points are captured is determined using the following approach: at the beginning of each frequency change, a delta_t_break_EIS time is observed to ensure the dynamic stability of the stack's variables. Subsequently, a delta_t_measurement_EIS time is needed to record the cell voltage and the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), np.array(variables['Ucell']) # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] t_EIS, max_step = parameters['t_EIS'], parameters['max_step'] # Creation of ifc ifc_t = np.zeros(len(t)) for i in range(len(t)): ifc_t[i] = current_density(t[i], parameters) # Identify the areas where Ucell and ifc can be measured for the EIS: after equilibrium and at each frequency change t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS n_inf = np.where(t_new_start_EIS <= t[0])[0][-1] # The number of frequency changes which has been mad so far. Ucell_EIS_measured = Ucell_t[np.where((t > (t[0] + delta_t_break_EIS[n_inf])) & (t < (t[0] + delta_t_break_EIS[n_inf] + delta_t_measurement_EIS[n_inf])))] ifc_EIS_measured = ifc_t[np.where((t > (t[0] + delta_t_break_EIS[n_inf])) & (t < (t[0] + delta_t_break_EIS[n_inf] + delta_t_measurement_EIS[n_inf])))] # Determination of the Fourier transformation N = Ucell_EIS_measured.size # Number of points used for the Fourier transformation Ucell_Fourier = fft(Ucell_EIS_measured) # Ucell Fourier transformation ifc_Fourier = fft(ifc_EIS_measured) # ifc Fourier transformation A_period_t = np.concatenate( ([np.abs(Ucell_Fourier)[0] / N], np.abs(Ucell_Fourier[1:N // 2]) * 2 / N)) # Recovery of # all amplitude values calculated by fft A = max(A_period_t[1:]) # Amplitude at the frequency of the perturbation freq_t = fftfreq(N, max_step)[:N // 2] # Recovery of all frequency values used by fft f = freq_t[np.argmax(A_period_t == A)] # Recovery of the studied frequency return {'Ucell_Fourier': Ucell_Fourier, 'ifc_Fourier': ifc_Fourier, 'A_period_t': A_period_t, 'A': A, 'freq_t': freq_t, 'f': f, 'N': N}","title":"make_Fourier_transformation"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Bode_amplitude_instructions","text":"This function adds the instructions for amplitude Bode plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_Bode_amplitude_instructions(f_EIS, type_fuel_cell, ax): \"\"\"This function adds the instructions for amplitude Bode plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. ax.set_xscale('log') # set logarithmic scale for the x-axis # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(LogLocator(base=10.0, numticks=f_power_max_EIS - f_power_min_EIS + 1)) ax.xaxis.set_minor_locator(LogLocator(base=10.0, subs=np.arange(2, 10) * .1, numticks=(f_power_max_EIS - f_power_min_EIS + 1) * len(np.arange(2, 10)))) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(30)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(30 / 5)) ax.set_xlim([10**f_power_min_EIS, 10**f_power_max_EIS])","title":"plot_Bode_amplitude_instructions"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Bode_phase_instructions","text":"This function adds the instructions for phase Bode plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_Bode_phase_instructions(f_EIS, type_fuel_cell, ax): \"\"\"This function adds the instructions for phase Bode plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. ax.set_xscale('log') # set logarithmic scale for the x-axis if not ax.yaxis_inverted(): ax.invert_yaxis() # Invert the y-axis # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(LogLocator(base=10.0, numticks = f_power_max_EIS-f_power_min_EIS+1)) ax.xaxis.set_minor_locator(LogLocator(base=10.0, subs=np.arange(2, 10) * .1, numticks = (f_power_max_EIS-f_power_min_EIS+1)*len(np.arange(2, 10)))) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(5 / 5)) ax.set_xlim([10**f_power_min_EIS, 10**f_power_max_EIS])","title":"plot_Bode_phase_instructions"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_C_H2","text":"This function plots the hydrogen concentration at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. ax ( Axes ) \u2013 Axes on which the hydrogen concentration will be plotted. Source code in modules/display_modules.py def plot_C_H2(variables, n_gdl, ax): \"\"\"This function plots the hydrogen concentration at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. ax : matplotlib.axes.Axes Axes on which the hydrogen concentration will be plotted. \"\"\" # Extraction of the variables t, C_H2_agc_t = variables['t'], variables['C_H2_agc'] C_H2_agdl_t, C_H2_acl_t = variables[f'C_H2_agdl_{n_gdl // 2}'], variables['C_H2_acl'] # Plot the hydrogen concentration at different spatial localisations: C_H2 ax.plot(t, C_H2_agc_t, color=colors(0)) ax.plot(t, C_H2_agdl_t, color=colors(1)) ax.plot(t, C_H2_acl_t, color=colors(2)) ax.legend([r'$\\mathregular{C_{H_{2},agc}}$', r'$\\mathregular{C_{H_{2},agdl}}$', r'$\\mathregular{C_{H_{2},acl}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Hydrogen}$ $\\mathbf{concentration}$ $\\mathbf{C_{H_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(55, 58)","title":"plot_C_H2"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_C_N2","text":"This function plots the nitrogen concentration as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the nitrogen concentration will be plotted. Source code in modules/display_modules.py def plot_C_N2(variables, ax): \"\"\"This function plots the nitrogen concentration as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the nitrogen concentration will be plotted. \"\"\" # Extraction of the variables t, C_N2_t = variables['t'], variables['C_N2'] # Plot C_N2 ax.plot(t, C_N2_t, color=colors(6)) ax.legend([r'$\\mathregular{C_{N_{2}}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Nitrogen}$ $\\mathbf{concentration}$ $\\mathbf{C_{N_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.set_ylim(47, 49)","title":"plot_C_N2"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_C_O2","text":"This function plots the oxygen concentration at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. ax ( Axes ) \u2013 Axes on which the oxygen concentration will be plotted. Source code in modules/display_modules.py def plot_C_O2(variables, n_gdl, ax): \"\"\"This function plots the oxygen concentration at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. ax : matplotlib.axes.Axes Axes on which the oxygen concentration will be plotted. \"\"\" # Extraction of the variables t, C_O2_ccl_t = variables['t'], variables['C_O2_ccl'] C_O2_cgdl_t, C_O2_cgc_t = variables[f'C_O2_cgdl_{n_gdl // 2}'], variables['C_O2_cgc'] # Plot the oxygen concentration at different spatial localisations: C_O2 ax.plot(t, C_O2_ccl_t, color=colors(4)) ax.plot(t, C_O2_cgdl_t, color=colors(5)) ax.plot(t, C_O2_cgc_t, color=colors(6)) ax.legend([r'$\\mathregular{C_{O_{2},ccl}}$', r'$\\mathregular{C_{O_{2},cgdl}}$', r'$\\mathregular{C_{O_{2},cgc}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Oxygen}$ $\\mathbf{concentration}$ $\\mathbf{C_{O_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(6, 11)","title":"plot_C_O2"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_C_v","text":"This function plots the vapor concentrations at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. C_v_sat ( float ) \u2013 Saturation vapor concentration. n ( int ) \u2013 Number of points used to plot the vapor concentration. ax ( Axes ) \u2013 Axes on which the vapor concentration will be plotted. Source code in modules/display_modules.py def plot_C_v(variables, n_gdl, C_v_sat, n, ax): \"\"\"This function plots the vapor concentrations at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. C_v_sat : float Saturation vapor concentration. n : int Number of points used to plot the vapor concentration. ax : matplotlib.axes.Axes Axes on which the vapor concentration will be plotted. \"\"\" # Extraction of the variables t, C_v_agc_t, C_v_agdl_t = variables['t'], variables['C_v_agc'], variables[f'C_v_agdl_{n_gdl // 2}'] C_v_acl_t, C_v_ccl_t = variables['C_v_acl'], variables['C_v_ccl'] C_v_cgdl_t, C_v_cgc_t = variables[f'C_v_cgdl_{n_gdl // 2}'], variables['C_v_cgc'] # Plot the vapor concentrations at different spatial localisations Cv C_v_sat_t = np.ones(n) * C_v_sat ax.plot(t, C_v_agc_t, color=colors(0)) ax.plot(t, C_v_agdl_t, color=colors(1)) ax.plot(t, C_v_acl_t, color=colors(2)) ax.plot(t, C_v_ccl_t, color=colors(4)) ax.plot(t, C_v_cgdl_t, color=colors(5)) ax.plot(t, C_v_cgc_t, color=colors(6)) ax.plot(t, C_v_sat_t, color='k') ax.legend([r'$\\mathregular{C_{v,agc}}$', r'$\\mathregular{C_{v,agdl}}$', r'$\\mathregular{C_{v,acl}}$', r'$\\mathregular{C_{v,ccl}}$', r'$\\mathregular{C_{v,cgdl}}$', r'$\\mathregular{C_{v,cgc}}$', r'$\\mathregular{C_{v,sat}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r\"$\\mathbf{Vapor}$ $\\mathbf{concentration}$ $\\mathbf{C_{v}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$\", labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(11, 16)","title":"plot_C_v"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_EIS_Nyquist_instructions","text":"This function adds the instructions for EIS plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. f_Fourier ( ndarray ) \u2013 Frequency at which the EIS is simulated. x ( ndarray ) \u2013 x-axis values for plotting the annotation. y ( ndarray ) \u2013 y-axis values for plotting the annotation. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_EIS_Nyquist_instructions(type_fuel_cell, f_Fourier, x, y, ax): \"\"\"This function adds the instructions for EIS plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. f_Fourier : numpy.ndarray Frequency at which the EIS is simulated. x : numpy.ndarray x-axis values for plotting the annotation. y : numpy.ndarray y-axis values for plotting the annotation. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions ax.set_aspect('equal', adjustable='box') # Set orthonormal axis. # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": # Double charge transfer if (f_Fourier >= 70 and f_Fourier <= 80): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, -40), ha='center', fontsize=14, rotation=90, weight='bold') # Auxiliary system if (f_Fourier >= 0.14 and f_Fourier <= 0.16): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 7), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 1.2 and f_Fourier <= 1.4): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 10), ha='center', fontsize=14, rotation=90, weight='bold') # Diffusion if (f_Fourier >= 0.015 and f_Fourier <= 0.020): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(30, 0), ha='center', fontsize=14, rotation=0, weight='bold') if (f_Fourier >= 0.9 and f_Fourier <= 1.1): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 10), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 70 and f_Fourier <= 90): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, -40), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 10000 and f_Fourier <= 12000): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(35, 0), ha='center', fontsize=14, rotation=0, weight='bold') ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(20)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(20 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(10)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(10 / 5)) ax.set_xlim(30, 200) ax.set_ylim(-25, 55)","title":"plot_EIS_Nyquist_instructions"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_EIS_curve_Bode_amplitude","text":"This function is used to plot the amplitude Bode diagram of the EIS curves. Parameters: parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the amplitude Bode diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Bode_amplitude(parameters, Fourier_results, ax): \"\"\"This function is used to plot the amplitude Bode diagram of the EIS curves. Parameters ---------- parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the amplitude Bode diagram will be plotted. \"\"\" # Extraction of the parameters i_EIS, ratio_EIS, f_EIS = parameters['i_EIS'], parameters['ratio_EIS'], parameters['f_EIS'] type_fuel_cell = parameters['type_fuel_cell'] # Extraction of the Fourier results A, f = Fourier_results['A'], Fourier_results['f'] # Calculation of the impedance of the perturbation Z0 = A / (ratio_EIS * (-i_EIS)) * 1e7 # in m\u03a9.cm\u00b2. The sign of i is inverted to comply with the standards of EIS, # which measure a device under load rather than a current source. # Plot the amplitude Bode diagram ax.plot(f, np.abs(Z0), 'o', color=colors(1), label='Amplitude Bode diagram') ax.set_xlabel(r'$\\mathbf{Frequency}$ $\\mathbf{(Hz,}$ $\\mathbf{logarithmic}$ $\\mathbf{scale)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Impedance}$ $\\mathbf{amplitude}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_Bode_amplitude_instructions(f_EIS, type_fuel_cell, ax)","title":"plot_EIS_curve_Bode_amplitude"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_EIS_curve_Bode_angle","text":"This function is used to plot the angle Bode diagram. It only works with an entry signal made with a cosinus (not a sinus). Parameters: Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the angle Bode diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Bode_angle(parameters, Fourier_results, ax): \"\"\"This function is used to plot the angle Bode diagram. It only works with an entry signal made with a cosinus (not a sinus). Parameters ---------- Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the angle Bode diagram will be plotted. \"\"\" # Extraction of the parameters f_EIS, type_fuel_cell = parameters['f_EIS'], parameters['type_fuel_cell'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] A_period_t, A = Fourier_results['A_period_t'], Fourier_results['A'] f, N = Fourier_results['f'], Fourier_results['N'] # Calculation of the dephasing values at the frequency of the perturbation theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) + np.pi # Recovery of all dephasing values calculated by fft. # An angle of pi is added to comply with the standards of EIS, # which measure a device under load rather than a current source. theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation phi_U_i = ((theta_U - theta_i) * 180 / np.pi) % 360 # Dephasing between Ucell and ifc with a value between 0 and 360 if phi_U_i > 180: phi_U_i -= 360 # To have a value between -180 and 180 # Plot the angle Bode diagram ax.plot(f, phi_U_i, 'o', color=colors(2), label='Angle Bode diagram') ax.set_xlabel(r'$\\mathbf{Frequency}$ $\\mathbf{(Hz,}$ $\\mathbf{logarithmic}$ $\\mathbf{scale)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Phase}$ $\\mathbf{(^\\circ)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_Bode_phase_instructions(f_EIS, type_fuel_cell, ax)","title":"plot_EIS_curve_Bode_angle"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_EIS_curve_Nyquist","text":"This function is used to plot the Nyquist diagram of the EIS curves. Parameters: parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the Nyquist diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Nyquist(parameters, Fourier_results, ax): \"\"\" This function is used to plot the Nyquist diagram of the EIS curves. Parameters ---------- parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the Nyquist diagram will be plotted. \"\"\" # Extraction of the parameters i_EIS, ratio_EIS, type_fuel_cell = parameters['i_EIS'], parameters['ratio_EIS'], parameters['type_fuel_cell'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] f_Fourier = Fourier_results['f'] A_period_t, A, N = Fourier_results['A_period_t'], Fourier_results['A'], Fourier_results['N'] # Calculation of the real and imaginary component of the impedance for each period Z0 = A / (ratio_EIS * (-i_EIS)) * 1e7 # Impedance of the perturbation in m\u03a9.cm\u00b2. The sign of i is inverted to # comply with the standards of EIS, which measure a device under load rather than a current source. theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation Z_real = Z0 * np.cos(theta_U - theta_i) # Real component of the impedance for each period Z_imag = Z0 * np.sin(theta_U - theta_i) # Imaginary component of the impedance for each period # Plot the Nyquist diagram ax.plot(Z_real, -Z_imag, 'o', color=colors(0), label='Nyquist diagram') ax.set_xlabel(r'$\\mathbf{Z_{real}}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{-Z_{imag}}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_EIS_Nyquist_instructions(type_fuel_cell, f_Fourier, Z_real, -Z_imag, ax)","title":"plot_EIS_curve_Nyquist"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_EIS_curve_tests","text":"This function is used to test the accuracy of the EIS results. It compares the reconstructed Ucell_Fourier(t) from the Fourier transformation with the current density ifc(t), and displays Ucell(t) given by the model with the reconstructed Ucell_Fourier(t). Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. Source code in modules/display_modules.py def plot_EIS_curve_tests(variables, operating_inputs, parameters, Fourier_results): \"\"\"This function is used to test the accuracy of the EIS results. It compares the reconstructed Ucell_Fourier(t) from the Fourier transformation with the current density ifc(t), and displays Ucell(t) given by the model with the reconstructed Ucell_Fourier(t). Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), variables['Ucell'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] i_EIS, ratio_EIS = parameters['i_EIS'], parameters['ratio_EIS'] t_EIS, f_EIS = parameters['t_EIS'], parameters['f_EIS'] max_step = parameters['max_step'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] A_period_t, A = Fourier_results['A_period_t'], Fourier_results['A'] f, N = Fourier_results['f'], Fourier_results['N'] # Reconstructed Ucell with a cosinus form, and comparison of its form with the current density one. t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS n_inf = np.where(t_new_start_EIS <= t[0])[0][-1] # The number of frequency changes which has been made. f_current = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation print(\"Ucell:\", round(A_period_t[0], 4), ' + ', round(A, 6), \" * np.cos(2*np.pi*\", round(f, 4), \"*t + \", round(theta_U, 4), \"). \") print(\"Current:\", i_EIS, ' + ', ratio_EIS * i_EIS, \" * np.cos(2*np.pi*\", round(f_current[n_inf], 4), \"*t + \", round(theta_i, 4), \"). \\n\") # Display ifc(t) plt.figure(3) plt.subplot(2, 1, 1) # Creation of ifc_t n = len(t) ifc_t = np.zeros(n) for i in range(n): # Conversion in A/cm\u00b2 ifc_t[i] = current_density(t[i], parameters) / 1e4 # Plot of ifc_t plt.plot(t, ifc_t, color='blue', label='ifc') plt.xlabel('Time (s)') plt.ylabel('Current density (A/cm\u00b2)') plt.title('The current density\\nbehaviour over time') # Display Ucell(t) and compare it with the reconstructed Ucell_Fourier(t) from the Fourier transformation plt.subplot(2, 1, 2) Ucell_Fourier = A_period_t[0] + A * np.cos(2 * np.pi * f * t + theta_U) plt.plot(t, Ucell_t, color='blue', label='Ucell') plt.plot(t, Ucell_Fourier, color='black', label='Ucell_Fourier') plt.xlabel('Time (s)') plt.ylabel('Cell voltage (V)') plt.title('The cell voltage\\nbehaviour over time')","title":"plot_EIS_curve_tests"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_J","text":"This function plots the sorption and dissolved water flows as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the flows will be plotted. Source code in modules/display_modules.py def plot_J(variables, parameters, ax): \"\"\"This function plots the sorption and dissolved water flows as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the flows will be plotted. \"\"\" # Extraction of the variables t, S_sorp_acl_t, S_sorp_ccl_t = variables['t'], variables['S_sorp_acl'], variables['S_sorp_ccl'], J_lambda_mem_acl_t, J_lambda_mem_ccl_t = variables['J_lambda_mem_acl'], variables['J_lambda_mem_ccl'] # Extraction of the operating inputs and the parameters Hcl = parameters['Hcl'] # Plot the sorption and dissolved water flows: J J_sorp_acl, J_sorp_ccl = [x * Hcl for x in S_sorp_acl_t], [x * Hcl for x in S_sorp_ccl_t] # Conversion in # mol.m\u207b\u00b2.s\u207b\u00b9 for comparison ax.plot(t, J_sorp_acl, color=colors(2)) ax.plot(t, J_lambda_mem_acl_t, color=colors(3)) ax.plot(t, J_sorp_ccl, color=colors(4)) ax.plot(t, J_lambda_mem_ccl_t, color=colors(7)) ax.legend([r'$\\mathregular{J_{sorp,acl}}$', r'$\\mathregular{J_{\\lambda,mem,acl}}$', r'$\\mathregular{J_{sorp,ccl}}$', r'$\\mathregular{J_{\\lambda,mem,ccl}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Flows}$ $\\mathbf{J}$ $\\mathbf{\\left( mol.m^{-2}.s^{-1} \\right)}$', labelpad=3) ax.ticklabel_format(style='scientific', axis='y', scilimits=(0, 0)) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.02)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.02 / 5)) plt.show()","title":"plot_J"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_P","text":"This function plots the pressure at different spatial localisations as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the pressure will be plotted. Source code in modules/display_modules.py def plot_P(variables, ax): \"\"\"This function plots the pressure at different spatial localisations as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the pressure will be plotted. \"\"\" # Extraction of the variables t, Pagc_t, Pcgc_t = variables['t'], variables['Pagc'], variables['Pcgc'] Pasm_t, Paem_t, Pcsm_t, Pcem_t = variables['Pasm'], variables['Paem'], variables['Pcsm'], variables['Pcem'] # Conversion in atm Pagc_t, Pcgc_t, Pasm_t = [x / 1e5 for x in Pagc_t], [x / 1e5 for x in Pcgc_t], [x / 1e5 for x in Pasm_t] Paem_t, Pcsm_t, Pcem_t = [x / 1e5 for x in Paem_t], [x / 1e5 for x in Pcsm_t], [x / 1e5 for x in Pcem_t] # Plot the pressure at different spatial localisations: P ax.plot(t, Pagc_t, color=colors(0)) ax.plot(t, Pcgc_t, color=colors(6)) ax.plot(t, Pasm_t, color=colors(7)) ax.plot(t, Paem_t, color=colors(8)) ax.plot(t, Pcsm_t, color=colors(9)) ax.plot(t, Pcem_t, color=colors(3)) ax.legend([r'$\\mathregular{P_{agc}}$', r'$\\mathregular{P_{cgc}}$', r'$\\mathregular{P_{asm}}$', r'$\\mathregular{P_{aem}}$', r'$\\mathregular{P_{csm}}$', r'$\\mathregular{P_{cem}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Pressure}$ $\\mathbf{P}$ $\\mathbf{\\left( bar \\right)}$', labelpad=3) ax.ticklabel_format(style='scientific', axis='y', scilimits=(0, 0)) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5e-4)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5e-4 / 5)) ax.set_ylim(1.99980, 2.00015)","title":"plot_P"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Phi_a","text":"This function plots the humidity at the anode side, at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_a(variables, operating_inputs, ax): \"\"\"This function plots the humidity at the anode side, at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t, C_v_agc_t = variables['t'], variables['C_v_agc'] Phi_asm_t, Phi_aem_t = variables['Phi_asm'], variables['Phi_aem'] # Extraction of the operating inputs Tfc, Phi_a_des = operating_inputs['Tfc'], operating_inputs['Phi_a_des'] # Calculate the humidity Phi Phi_agc_t = [0] * len(t) for i in range(len(t)): Phi_agc_t[i] = C_v_agc_t[i] * R * Tfc / Psat(Tfc) # Plot the humidity at different spatial localisations: Phi ax.plot(t, Phi_agc_t, color=colors(0), label=r'$\\mathregular{\\Phi_{agc}}$') ax.plot(t, Phi_asm_t, color=colors(1), label=r'$\\mathregular{\\Phi_{asm}}$') ax.plot(t, Phi_aem_t, color=colors(2), label=r'$\\mathregular{\\Phi_{aem}}$') ax.plot(t, [Phi_a_des]*len(t), color='black', label=r'$\\mathregular{\\Phi_{a,des}}$') ax.legend(loc='center right', bbox_to_anchor=(1, 0.67)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Humidity}$ $\\mathbf{at}$ $\\mathbf{the}$ $\\mathbf{anode}$ $\\mathbf{side}$ $\\mathbf{\\Phi}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5))","title":"plot_Phi_a"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Phi_c","text":"This function plots the humidity, at the cathode side, at different spatial localisations as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_c(variables, operating_inputs, ax): \"\"\"This function plots the humidity, at the cathode side, at different spatial localisations as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t, C_v_cgc_t = variables['t'], variables['C_v_cgc'] Phi_csm_t, Phi_cem_t = variables['Phi_csm'], variables['Phi_cem'] # Extraction of the operating inputs Tfc, Phi_c_des = operating_inputs['Tfc'], operating_inputs['Phi_c_des'] # Calculate the humidity Phi Phi_cgc_t = [0] * len(t) for i in range(len(t)): Phi_cgc_t[i] = C_v_cgc_t[i] * R * Tfc / Psat(Tfc) # Plot the humidity at different spatial localisations: Phi ax.plot(t, Phi_cgc_t, color=colors(0), label=r'$\\mathregular{\\Phi_{cgc}}$') ax.plot(t, Phi_csm_t, color=colors(1), label=r'$\\mathregular{\\Phi_{csm}}$') ax.plot(t, Phi_cem_t, color=colors(2), label=r'$\\mathregular{\\Phi_{cem}}$') ax.plot(t, [Phi_c_des]*len(t), color='black', label=r'$\\mathregular{\\Phi_{c,des}}$') ax.legend(loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Humidity}$ $\\mathbf{at}$ $\\mathbf{the}$ $\\mathbf{cathode}$ $\\mathbf{side}$ $\\mathbf{\\Phi}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5))","title":"plot_Phi_c"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Phi_des","text":"This function plots the controlled or uncontrolled desired humidity at the anode and cathode as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_des(variables, operating_inputs, parameters, ax): \"\"\"This function plots the controlled or uncontrolled desired humidity at the anode and cathode as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t = variables['t'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] if parameters['type_control'] == \"Phi_des\": Phi_a_des, Phi_c_des = variables['Phi_a_des'], variables['Phi_c_des'] ax.set_ylabel(r'$\\mathbf{Controlled}$ $\\mathbf{inlet}$ $\\mathbf{humidity}$ $\\mathbf{\\Phi_{des}}$', labelpad=3) else: Phi_a_des, Phi_c_des = [operating_inputs['Phi_a_des']] * len(t), [operating_inputs['Phi_c_des']] * len(t) ax.set_ylabel(r'$\\mathbf{Uncontrolled}$ $\\mathbf{inlet}$ $\\mathbf{humidity}$ $\\mathbf{\\Phi_{des}}$', labelpad=3) # Plot Phi_des n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of ifc_t ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, Phi_c_des, color=colors(6), label=r'$\\mathregular{\\Phi_{c,des}}$') ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) if parameters['type_auxiliary'] == \"forced-convective_cathode_with_flow-through_anode\" or \\ parameters['type_auxiliary'] == \"no_auxiliary\": ax.plot(t, Phi_a_des, color=colors(0), label=r'$\\mathregular{\\Phi_{a,des}}$') ax.legend([r'$\\mathregular{\\Phi_{a,des}}$', r'$\\mathregular{\\Phi_{c,des}}$'], loc='best') else: ax.legend([r'$\\mathregular{\\Phi_{c,des}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.2)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.2 / 5)) ax.set_xlim(0, 4.1)","title":"plot_Phi_des"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Ucell","text":"This function plots the cell voltage as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the cell voltage will be plotted. Source code in modules/display_modules.py def plot_Ucell(variables, ax): \"\"\"This function plots the cell voltage as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the cell voltage will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = variables['t'], variables['Ucell'] # Plot the cell voltage: Ucell ax.plot(t, Ucell_t, color=colors(0), label=r'$\\mathregular{U_{cell}}$') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Cell}$ $\\mathbf{voltage}$ $\\mathbf{U_{cell}}$ $\\mathbf{\\left( V \\right)}$', labelpad=3) ax.legend([r'$\\mathregular{U_{cell}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.05)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.05 / 5))","title":"plot_Ucell"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_cell_efficiency","text":"This function plots the fuel cell efficiency eta_fc as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the fuel cell efficiency. ax ( Axes ) \u2013 Axes on which the fuel cell efficiency will be plotted. Source code in modules/display_modules.py def plot_cell_efficiency(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the fuel cell efficiency eta_fc as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the fuel cell efficiency. ax : matplotlib.axes.Axes Axes on which the fuel cell efficiency will be plotted. \"\"\" # Extraction of the variables t, Ucell_t, lambda_mem_t = variables['t'], variables['Ucell'], variables['lambda_mem'] C_H2_acl_t, C_O2_ccl_t = variables['C_H2_acl'], variables['C_O2_ccl'] # Extraction of the operating inputs and the parameters current_density, Tfc = operating_inputs['current_density'], operating_inputs['Tfc'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control = parameters['type_control'] # Creation of the fuel cell efficiency: eta_fc ifc_t, Pfc_t, eta_fc_t = np.zeros(n), np.zeros(n), np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 Pfc_t[i] = Ucell_t[i] * ifc_t[i] Ueq = E0 - 8.5e-4 * (Tfc - 298.15) + R * Tfc / (2 * F) * (np.log(R * Tfc * C_H2_acl_t[i] / Pref) + 0.5 * np.log(R * Tfc * C_O2_ccl_t[i] / Pref)) i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl_t[i] * k_H2(lambda_mem_t[i], Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl_t[i] * k_O2(lambda_mem_t[i], Tfc, kappa_co) i_n = (i_H2 + i_O2) / 1e4 # Conversion in A/cm\u00b2 eta_fc_t[i] = Pfc_t[i] / (Ueq * (ifc_t[i] + i_n)) # Plot of the fuel cell efficiency: eta_fc plot_specific_line(ifc_t, eta_fc_t, type_fuel_cell, type_auxiliary, type_control, None, ax) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=0) ax.set_ylabel(r'$\\mathbf{Fuel}$ $\\mathbf{cell}$ $\\mathbf{efficiency}$ $\\mathbf{\\eta_{fc}}$', labelpad=0) ax.legend(loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) ax.set_xlim(0, 4.1) ax.set_ylim(0, 0.7)","title":"plot_cell_efficiency"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_general_instructions","text":"This function adds the common instructions for all the plots displayed by AlphaPEM to the ax object. Parameters: ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_general_instructions(ax): \"\"\"This function adds the common instructions for all the plots displayed by AlphaPEM to the ax object. Parameters ---------- ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" ax.tick_params(axis='both', which='major', size=10, width=1.5, direction='out') ax.tick_params(axis='both', which='minor', size=5, width=1.5, direction='out') plt.tight_layout() # Adjust layout to prevent overlap between labels and the figure plt.show() # Show the figure","title":"plot_general_instructions"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_ifc","text":"This function plots the current density as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the current density. ax ( Axes ) \u2013 Axes on which the current density will be plotted. Source code in modules/display_modules.py def plot_ifc(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the current density as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the current density. ax : matplotlib.axes.Axes Axes on which the current density will be plotted. \"\"\" # Extraction of the variables t = variables['t'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] # Plot the current density: ifc ifc_t = np.zeros(n) for i in range(n): # Creation of ifc_t ifc_t[i] = current_density(t[i], parameters) / 10000 # Conversion in A/cm\u00b2 ax.plot(t, ifc_t, color=colors(0), label=r'$\\mathregular{i_{fc}}$') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) ax.legend([r'$\\mathregular{i_{fc}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5))","title":"plot_ifc"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_lambda","text":"This function plots the water content at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the water content will be plotted. Source code in modules/display_modules.py def plot_lambda(variables, operating_inputs, parameters, ax): \"\"\"This function plots the water content at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the water content will be plotted. \"\"\" # Extraction of the variables t, lambda_acl_t = variables['t'], variables['lambda_acl'] lambda_mem_t, lambda_ccl_t = variables['lambda_mem'], variables['lambda_ccl'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] type_current = parameters['type_current'] # Plot the water content at different spatial localisations: lambda if type_current == \"polarization\": n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of i_fc ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, lambda_acl_t, color=colors(2)) ax.plot(ifc_t, lambda_mem_t, color=colors(3)) ax.plot(ifc_t, lambda_ccl_t, color=colors(4)) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) else: ax.plot(t, lambda_acl_t, color=colors(2)) ax.plot(t, lambda_mem_t, color=colors(3)) ax.plot(t, lambda_ccl_t, color=colors(4)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Water}$ $\\mathbf{content}$ $\\mathbf{\\lambda}$', labelpad=3) ax.legend([r'$\\mathregular{\\lambda_{acl}}$', r'$\\mathregular{\\lambda_{mem}}$', r'$\\mathregular{\\lambda_{ccl}}$'], loc='best') # Plot instructions plot_general_instructions(ax) if type_current == \"polarization\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) else: ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(3)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(3 / 5))","title":"plot_lambda"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_pola_instructions","text":"This function adds the specific instructions for polarisation plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_pola_instructions(type_fuel_cell, ax): \"\"\"This function adds the specific instructions for polarisation plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) ax.set_xlim(0, 3.0) ax.set_ylim(0.4, 1.04) # For LF fuel cell elif type_fuel_cell == \"LF\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.4)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.4 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.2)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.2 / 5)) ax.set_xlim(-0.05, 1.6) ax.set_ylim(0, 1.0) # For other fuel cell else: pass","title":"plot_pola_instructions"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_polarisation_curve","text":"This function plots the model polarisation curve, and compare it to the experimental one (if it exists). The polarisation curve is a classical representation of the cell performances, showing the cell voltage as a function of the current density. To generate it, the current density is increased step by step, and the cell voltage is recorded at each step. The time for which this point is captured is determined using the following approach: at the beginning of each load, a delta_t_load_pola time is needed to raise the current density to its next value. Subsequently, a delta_t_break_pola time is observed to ensure the dynamic stability of the stack's variables before initiating a new load. Ideally, each polarisation point should be recorded at the end of each delta_t_break_pola time. However, due to the design of the increments to minimize program instability (as observed in step_current function), the end of each delta_t_break_pola time corresponds to the beginning of a new load. To ensure a stationary operation and accurate polarisation point measurements, it is recommended to take the polarisation point just before by subtracting a delta_t value from it. This adjustment allows for stable and consistent measurements during the stationary period. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the polarisation curve will be plotted. Source code in modules/display_modules.py def plot_polarisation_curve(variables, operating_inputs, parameters, ax): \"\"\" This function plots the model polarisation curve, and compare it to the experimental one (if it exists). The polarisation curve is a classical representation of the cell performances, showing the cell voltage as a function of the current density. To generate it, the current density is increased step by step, and the cell voltage is recorded at each step. The time for which this point is captured is determined using the following approach: at the beginning of each load, a delta_t_load_pola time is needed to raise the current density to its next value. Subsequently, a delta_t_break_pola time is observed to ensure the dynamic stability of the stack's variables before initiating a new load. Ideally, each polarisation point should be recorded at the end of each delta_t_break_pola time. However, due to the design of the increments to minimize program instability (as observed in step_current function), the end of each delta_t_break_pola time corresponds to the beginning of a new load. To ensure a stationary operation and accurate polarisation point measurements, it is recommended to take the polarisation point just before by subtracting a delta_t value from it. This adjustment allows for stable and consistent measurements during the stationary period. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the polarisation curve will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), np.array(variables['Ucell']) # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] t_step, i_step, i_max_pola = parameters['t_step'], parameters['i_step'], parameters['i_max_pola'] delta_pola = parameters['delta_pola'] i_EIS, t_EIS, f_EIS = parameters['i_EIS'], parameters['t_EIS'], parameters['f_EIS'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control, type_plot = parameters['type_control'], parameters['type_plot'] if type_plot == \"fixed\": # Creation of ifc_t n = len(t) ifc_t = np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 # Recovery of ifc and Ucell from the model after each stack stabilisation delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola nb_loads = int(i_max_pola / delta_i_pola + 1) # Number of loads which are made ifc_discretized = np.zeros(nb_loads) Ucell_discretized = np.zeros(nb_loads) for i in range(nb_loads): t_load = delta_t_ini_pola + (i + 1) * (delta_t_load_pola + delta_t_break_pola) - delta_t_break_pola / 10 # # time for measurement idx = (np.abs(t - t_load)).argmin() # the corresponding index ifc_discretized[i] = ifc_t[idx] # the last value at the end of each load Ucell_discretized[i] = Ucell_t[idx] # the last value at the end of each load # Plot the experimental polarization curve and calculate the simulation error compared with experimental data if type_fuel_cell != \"manual_setup\" and \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Experimental points are accessible # Plot of the experimental polarization curve i_exp_t, U_exp_t = pola_exp_values(type_fuel_cell) plot_experimental_polarisation_curve(type_fuel_cell, i_exp_t, U_exp_t, ax) # Calculate the simulation error compared with experimental data # i_fc and Ucell are reduced to remain within experimental limits for comparison i_fc_reduced = ifc_discretized[(ifc_discretized >= i_exp_t[0]) & (ifc_discretized <= i_exp_t[-1])] Ucell_reduced = Ucell_discretized[(ifc_discretized >= i_exp_t[0]) & (ifc_discretized <= i_exp_t[-1])] # Experimental points are interpolated to correspond to the model points U_exp_interpolated = interp1d(i_exp_t, U_exp_t, kind='linear')(i_fc_reduced) sim_error = calculate_simulation_error(Ucell_reduced, U_exp_interpolated) else: sim_error = None # Plot the model polarisation curve plot_specific_line(ifc_discretized, Ucell_discretized, type_fuel_cell, type_auxiliary, type_control, sim_error, ax) plot_pola_instructions(type_fuel_cell, ax) else: # type_plot == \"dynamic\" # Plot of the polarisation curve produced by the model delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola idx = (np.abs(t - t[-1] + delta_t_break_pola / 10)).argmin() # index for polarisation measurement ifc = np.array(current_density(t[idx], parameters) / 1e4) # time for polarisation measurement Ucell = np.array(Ucell_t[idx]) # voltage measurement ax.plot(ifc, Ucell, 'og', markersize=2) # Add the common instructions for the plot ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Cell}$ $\\mathbf{voltage}$ $\\mathbf{U_{cell}}$ $\\mathbf{\\left( V \\right)}$', labelpad=3) plot_general_instructions(ax) if type_plot == \"fixed\": ax.legend(loc='best')","title":"plot_polarisation_curve"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_power_density_curve","text":"This function plots the power density curve Pfc, produced by a cell, as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the power density curve. ax ( Axes ) \u2013 Axes on which the power density curve will be plotted. Source code in modules/display_modules.py def plot_power_density_curve(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the power density curve Pfc, produced by a cell, as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the power density curve. ax : matplotlib.axes.Axes Axes on which the power density curve will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = variables['t'], variables['Ucell'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control = parameters['type_control'] # Creation of the power density function: Pfc ifc_t, Pfc_t = np.zeros(n), np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 Pfc_t[i] = Ucell_t[i] * ifc_t[i] # Plot of the power density function: Pfc plot_specific_line(ifc_t, Pfc_t, type_fuel_cell, type_auxiliary, type_control, None, ax) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=0) ax.set_ylabel(r'$\\mathbf{Fuel}$ $\\mathbf{cell}$ $\\mathbf{power}$ $\\mathbf{density}$ $\\mathbf{P_{fc}}$ $\\mathbf{\\left( W.cm^{-2} \\right)}$', labelpad=0) ax.legend(loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.3)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.3 / 5)) ax.set_xlim(0, 4.1) ax.set_ylim(0, 2.1)","title":"plot_power_density_curve"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_s","text":"This function plots the liquid water saturation at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the liquid water saturation will be plotted. Source code in modules/display_modules.py def plot_s(variables, operating_inputs, parameters, ax): \"\"\"This function plots the liquid water saturation at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the liquid water saturation will be plotted. \"\"\" # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] n_gdl, type_current = parameters['n_gdl'], parameters['type_current'] # Extraction of the variables t, s_agdl_t, s_acl_t = variables['t'], variables[f's_agdl_{n_gdl // 2}'], variables['s_acl'] s_ccl_t, s_cgdl_t = variables['s_ccl'], variables[f's_cgdl_{n_gdl // 2}'] # Plot the liquid water saturation at different spatial localisations: s if type_current == \"polarization\": n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of i_fc ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, s_agdl_t, color=colors(1)) ax.plot(ifc_t, s_acl_t, color=colors(2)) ax.plot(ifc_t, s_ccl_t, color=colors(4)) ax.plot(ifc_t, s_cgdl_t, color=colors(5)) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) else: ax.plot(t, s_agdl_t, color=colors(1)) ax.plot(t, s_acl_t, color=colors(2)) ax.plot(t, s_ccl_t, color=colors(4)) ax.plot(t, s_cgdl_t, color=colors(5)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Liquid}$ $\\mathbf{water}$ $\\mathbf{saturation}$ $\\mathbf{s}$', labelpad=3) ax.legend([r'$\\mathregular{s_{agdl}}$', r'$\\mathregular{s_{acl}}$', r'$\\mathregular{s_{ccl}}$', r'$\\mathregular{s_{cgdl}}$'], loc='best') # Plot instructions plot_general_instructions(ax) if type_current == \"polarization\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) else: ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.04)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.04 / 5))","title":"plot_s"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_specific_line","text":"This function adds the appropriate plot configuration according to the type_input to the ax object. Parameters: x ( ndarray ) \u2013 x-axis values. y ( ndarray ) \u2013 y-axis values. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. type_auxiliary ( str ) \u2013 Type of auxiliary system. type_control ( str ) \u2013 Type of control system. sim_error ( float ) \u2013 Simulation error between the simulated cell voltage and the experimental cell voltage (in %). ax ( Axes ) \u2013 Axes on which the line will be plotted. Source code in modules/display_modules.py def plot_specific_line(x, y, type_fuel_cell, type_auxiliary, type_control, sim_error, ax): \"\"\" This function adds the appropriate plot configuration according to the type_input to the ax object. Parameters ---------- x : numpy.ndarray x-axis values. y : numpy.ndarray y-axis values. type_fuel_cell : str Type of fuel cell configuration. type_auxiliary : str Type of auxiliary system. type_control : str Type of control system. sim_error : float Simulation error between the simulated cell voltage and the experimental cell voltage (in %). ax : matplotlib.axes.Axes Axes on which the line will be plotted. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": if type_fuel_cell == \"EH-31_1.5\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(0), label='Sim. - P = 1.5 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_1.5\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(0), label='Sim. - P = 1.5 bar') elif type_fuel_cell == \"EH-31_2.0\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, '--', color=colors(1), label='Sim. - P = 2.0 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.0\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": if type_control == \"Phi_des\": ax.plot(x, y, color=colors(5), label=r'Sim. - P = 2.0 bar - controlled $\\mathregular{\\Phi_{des}}$') else: ax.plot(x, y, color=colors(1), label=r'Sim. - P = 2.0 bar - uncontrolled $\\mathregular{\\Phi_{des}}$') elif type_fuel_cell == \"EH-31_2.25\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, '--', color=colors(2), label='Sim. - P = 2.25 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.25\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(2), label='Sim. - P = 2.25 bar') elif type_fuel_cell == \"EH-31_2.5\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(3), label='Sim - P = 2.5 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.5\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(3), label='Sim - P = 2.5 bar') # For LF fuel cell elif type_fuel_cell == \"LF\": ax.plot(x, y, color=colors(0), label='Simulation') # For other fuel cell else: ax.plot(x, y, color=colors(0), label='Simulation')","title":"plot_specific_line"},{"location":"functions/modules/flows_modules/","text":"Flows modules This module is used to calculate intermediate values for the flows calculation. flows_int_values(sv, operating_inputs, parameters) This functions calculates intermediate values for the flows calculation. Parameters: sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). s_agdl_agdl ( list ) \u2013 Mean value of the saturated liquid water variable in the anode GDL between two adjacent GDL nodes. s_agdl_acl ( float ) \u2013 Mean value of the saturated liquid water variable between the last GDL node and the anode CL. s_ccl_cgdl ( float ) \u2013 Mean value of the saturated liquid water variable between the cathode CL and the first GDL node. s_cgdl_cgdl ( list ) \u2013 Mean value of the saturated liquid water variable in the cathode GDL between two adjacent GDL nodes. epsilon_mean ( float ) \u2013 Mean value of the porosity in the GDL and the CL. theta_c_mean ( float ) \u2013 Mean value of the contact angle in the GDL and the CL. lambda_acl_mem ( float ) \u2013 Mean value of the dissolved water variable between the anode CL and the membrane. lambda_mem_ccl ( float ) \u2013 Mean value of the dissolved water variable between the membrane and the cathode CL. Pagc_agdl ( float ) \u2013 Mean value of the pressure between the anode gas channel and the first GDL node. Pagdl_agdl ( list ) \u2013 Mean value of the pressure in the anode GDL between two adjacent GDL nodes. Pagdl_acl ( float ) \u2013 Mean value of the pressure between the last GDL node and the anode CL. Pccl_cgdl ( float ) \u2013 Mean value of the pressure between the cathode CL and the first GDL node. Pcgdl_cgdl ( list ) \u2013 Mean value of the pressure in the cathode GDL between two adjacent GDL nodes. Pcgdl_cgc ( float ) \u2013 Mean value of the pressure between the last GDL node and the cathode gas channel. nu_l ( float ) \u2013 Liquid water kinematic viscosity (m\u00b2.s-1). Source code in modules/flows_modules.py def flows_int_values(sv, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the flows calculation. Parameters ---------- sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). s_agdl_agdl : list Mean value of the saturated liquid water variable in the anode GDL between two adjacent GDL nodes. s_agdl_acl : float Mean value of the saturated liquid water variable between the last GDL node and the anode CL. s_ccl_cgdl : float Mean value of the saturated liquid water variable between the cathode CL and the first GDL node. s_cgdl_cgdl : list Mean value of the saturated liquid water variable in the cathode GDL between two adjacent GDL nodes. epsilon_mean : float Mean value of the porosity in the GDL and the CL. theta_c_mean : float Mean value of the contact angle in the GDL and the CL. lambda_acl_mem : float Mean value of the dissolved water variable between the anode CL and the membrane. lambda_mem_ccl : float Mean value of the dissolved water variable between the membrane and the cathode CL. Pagc_agdl : float Mean value of the pressure between the anode gas channel and the first GDL node. Pagdl_agdl : list Mean value of the pressure in the anode GDL between two adjacent GDL nodes. Pagdl_acl : float Mean value of the pressure between the last GDL node and the anode CL. Pccl_cgdl : float Mean value of the pressure between the cathode CL and the first GDL node. Pcgdl_cgdl : list Mean value of the pressure in the cathode GDL between two adjacent GDL nodes. Pcgdl_cgc : float Mean value of the pressure between the last GDL node and the cathode gas channel. nu_l : float Liquid water kinematic viscosity (m\u00b2.s-1). \"\"\" # Extraction of the variables C_v_agc, C_v_acl, C_v_ccl, C_v_cgc = sv['C_v_agc'], sv['C_v_acl'], sv['C_v_ccl'], sv['C_v_cgc'] s_acl, s_ccl = sv['s_acl'], sv['s_ccl'] lambda_acl, lambda_mem, lambda_ccl = sv['lambda_acl'], sv['lambda_mem'], sv['lambda_ccl'] C_H2_agc, C_H2_acl, C_O2_ccl, C_O2_cgc = sv['C_H2_agc'], sv['C_H2_acl'], sv['C_O2_ccl'], sv['C_O2_cgc'] C_N2 = sv['C_N2'] # Extraction of the operating inputs and the parameters Tfc = operating_inputs['Tfc'] epsilon_gdl, n_gdl = parameters['epsilon_gdl'], parameters['n_gdl'] # Pressures in the stack Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pagdl = [(sv[f'C_v_agdl_{i}'] + sv[f'C_H2_agdl_{i}']) * R * Tfc for i in range(1, n_gdl + 1)] Pacl = (C_v_acl + C_H2_acl) * R * Tfc Pccl = (C_v_ccl + C_O2_ccl + C_N2) * R * Tfc Pcgdl = [(sv[f'C_v_cgdl_{i}'] + sv[f'C_O2_cgdl_{i}'] + C_N2) * R * Tfc for i in range(1, n_gdl + 1)] Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Mean values ... # ... of the saturated liquid water variable s_agdl_agdl = [None] + [sv[f's_agdl_{i}'] / 2 + sv[f's_agdl_{i + 1}'] / 2 for i in range(1, n_gdl)] s_agdl_acl = sv[f's_agdl_{n_gdl}'] / 2 + s_acl / 2 s_ccl_cgdl = s_ccl / 2 + sv['s_cgdl_1'] / 2 s_cgdl_cgdl = [None] + [sv[f's_cgdl_{i}'] / 2 + sv[f's_cgdl_{i + 1}'] / 2 for i in range(1, n_gdl)] # ... of the porosity and the contact angle epsilon_mean = epsilon_gdl / 2 + epsilon_cl / 2 theta_c_mean = theta_c_gdl / 2 + theta_c_cl / 2 # ... of the dissolved water variable lambda_acl_mem = lambda_acl / 2 + lambda_mem / 2 lambda_mem_ccl = lambda_mem / 2 + lambda_ccl / 2 # ... of the pressure Pagc_agdl = Pagc / 2 + Pagdl[0] / 2 Pagdl_agdl = [None] + [Pagdl[i] / 2 + Pagdl[i + 1] / 2 for i in range(0, n_gdl - 1)] Pagdl_acl = Pagdl[-1] / 2 + Pacl / 2 Pccl_cgdl = Pccl / 2 + Pcgdl[0] / 2 Pcgdl_cgdl = [None] + [Pcgdl[i] / 2 + Pcgdl[i + 1] / 2 for i in range(0, n_gdl - 1)] Pcgdl_cgc = Pcgdl[n_gdl - 1] / 2 + Pcgc / 2 return (Pagc, Pcgc, s_agdl_agdl, s_agdl_acl, s_ccl_cgdl, s_cgdl_cgdl, epsilon_mean, theta_c_mean, lambda_acl_mem, lambda_mem_ccl, Pagc_agdl, Pagdl_agdl, Pagdl_acl, Pccl_cgdl, Pcgdl_cgdl, Pcgdl_cgc, nu_l(Tfc))","title":"Flows modules"},{"location":"functions/modules/flows_modules/#flows-modules","text":"This module is used to calculate intermediate values for the flows calculation.","title":"Flows modules"},{"location":"functions/modules/flows_modules/#modules.flows_modules.flows_int_values","text":"This functions calculates intermediate values for the flows calculation. Parameters: sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). s_agdl_agdl ( list ) \u2013 Mean value of the saturated liquid water variable in the anode GDL between two adjacent GDL nodes. s_agdl_acl ( float ) \u2013 Mean value of the saturated liquid water variable between the last GDL node and the anode CL. s_ccl_cgdl ( float ) \u2013 Mean value of the saturated liquid water variable between the cathode CL and the first GDL node. s_cgdl_cgdl ( list ) \u2013 Mean value of the saturated liquid water variable in the cathode GDL between two adjacent GDL nodes. epsilon_mean ( float ) \u2013 Mean value of the porosity in the GDL and the CL. theta_c_mean ( float ) \u2013 Mean value of the contact angle in the GDL and the CL. lambda_acl_mem ( float ) \u2013 Mean value of the dissolved water variable between the anode CL and the membrane. lambda_mem_ccl ( float ) \u2013 Mean value of the dissolved water variable between the membrane and the cathode CL. Pagc_agdl ( float ) \u2013 Mean value of the pressure between the anode gas channel and the first GDL node. Pagdl_agdl ( list ) \u2013 Mean value of the pressure in the anode GDL between two adjacent GDL nodes. Pagdl_acl ( float ) \u2013 Mean value of the pressure between the last GDL node and the anode CL. Pccl_cgdl ( float ) \u2013 Mean value of the pressure between the cathode CL and the first GDL node. Pcgdl_cgdl ( list ) \u2013 Mean value of the pressure in the cathode GDL between two adjacent GDL nodes. Pcgdl_cgc ( float ) \u2013 Mean value of the pressure between the last GDL node and the cathode gas channel. nu_l ( float ) \u2013 Liquid water kinematic viscosity (m\u00b2.s-1). Source code in modules/flows_modules.py def flows_int_values(sv, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the flows calculation. Parameters ---------- sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). s_agdl_agdl : list Mean value of the saturated liquid water variable in the anode GDL between two adjacent GDL nodes. s_agdl_acl : float Mean value of the saturated liquid water variable between the last GDL node and the anode CL. s_ccl_cgdl : float Mean value of the saturated liquid water variable between the cathode CL and the first GDL node. s_cgdl_cgdl : list Mean value of the saturated liquid water variable in the cathode GDL between two adjacent GDL nodes. epsilon_mean : float Mean value of the porosity in the GDL and the CL. theta_c_mean : float Mean value of the contact angle in the GDL and the CL. lambda_acl_mem : float Mean value of the dissolved water variable between the anode CL and the membrane. lambda_mem_ccl : float Mean value of the dissolved water variable between the membrane and the cathode CL. Pagc_agdl : float Mean value of the pressure between the anode gas channel and the first GDL node. Pagdl_agdl : list Mean value of the pressure in the anode GDL between two adjacent GDL nodes. Pagdl_acl : float Mean value of the pressure between the last GDL node and the anode CL. Pccl_cgdl : float Mean value of the pressure between the cathode CL and the first GDL node. Pcgdl_cgdl : list Mean value of the pressure in the cathode GDL between two adjacent GDL nodes. Pcgdl_cgc : float Mean value of the pressure between the last GDL node and the cathode gas channel. nu_l : float Liquid water kinematic viscosity (m\u00b2.s-1). \"\"\" # Extraction of the variables C_v_agc, C_v_acl, C_v_ccl, C_v_cgc = sv['C_v_agc'], sv['C_v_acl'], sv['C_v_ccl'], sv['C_v_cgc'] s_acl, s_ccl = sv['s_acl'], sv['s_ccl'] lambda_acl, lambda_mem, lambda_ccl = sv['lambda_acl'], sv['lambda_mem'], sv['lambda_ccl'] C_H2_agc, C_H2_acl, C_O2_ccl, C_O2_cgc = sv['C_H2_agc'], sv['C_H2_acl'], sv['C_O2_ccl'], sv['C_O2_cgc'] C_N2 = sv['C_N2'] # Extraction of the operating inputs and the parameters Tfc = operating_inputs['Tfc'] epsilon_gdl, n_gdl = parameters['epsilon_gdl'], parameters['n_gdl'] # Pressures in the stack Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pagdl = [(sv[f'C_v_agdl_{i}'] + sv[f'C_H2_agdl_{i}']) * R * Tfc for i in range(1, n_gdl + 1)] Pacl = (C_v_acl + C_H2_acl) * R * Tfc Pccl = (C_v_ccl + C_O2_ccl + C_N2) * R * Tfc Pcgdl = [(sv[f'C_v_cgdl_{i}'] + sv[f'C_O2_cgdl_{i}'] + C_N2) * R * Tfc for i in range(1, n_gdl + 1)] Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Mean values ... # ... of the saturated liquid water variable s_agdl_agdl = [None] + [sv[f's_agdl_{i}'] / 2 + sv[f's_agdl_{i + 1}'] / 2 for i in range(1, n_gdl)] s_agdl_acl = sv[f's_agdl_{n_gdl}'] / 2 + s_acl / 2 s_ccl_cgdl = s_ccl / 2 + sv['s_cgdl_1'] / 2 s_cgdl_cgdl = [None] + [sv[f's_cgdl_{i}'] / 2 + sv[f's_cgdl_{i + 1}'] / 2 for i in range(1, n_gdl)] # ... of the porosity and the contact angle epsilon_mean = epsilon_gdl / 2 + epsilon_cl / 2 theta_c_mean = theta_c_gdl / 2 + theta_c_cl / 2 # ... of the dissolved water variable lambda_acl_mem = lambda_acl / 2 + lambda_mem / 2 lambda_mem_ccl = lambda_mem / 2 + lambda_ccl / 2 # ... of the pressure Pagc_agdl = Pagc / 2 + Pagdl[0] / 2 Pagdl_agdl = [None] + [Pagdl[i] / 2 + Pagdl[i + 1] / 2 for i in range(0, n_gdl - 1)] Pagdl_acl = Pagdl[-1] / 2 + Pacl / 2 Pccl_cgdl = Pccl / 2 + Pcgdl[0] / 2 Pcgdl_cgdl = [None] + [Pcgdl[i] / 2 + Pcgdl[i + 1] / 2 for i in range(0, n_gdl - 1)] Pcgdl_cgc = Pcgdl[n_gdl - 1] / 2 + Pcgc / 2 return (Pagc, Pcgc, s_agdl_agdl, s_agdl_acl, s_ccl_cgdl, s_cgdl_cgdl, epsilon_mean, theta_c_mean, lambda_acl_mem, lambda_mem_ccl, Pagc_agdl, Pagdl_agdl, Pagdl_acl, Pccl_cgdl, Pcgdl_cgdl, Pcgdl_cgc, nu_l(Tfc))","title":"flows_int_values"},{"location":"functions/modules/main_modules/","text":"Main modules This module contains some of the required functions for the main.py file. figures_preparation(type_current, type_display) This function create the required figures and axes according to the type_current and type_display. Parameters: type_current ( str ) \u2013 Type of current density function. type_display ( str ) \u2013 Type of display. Returns: fig1 ( Figure ) \u2013 Figure for the first plot. ax1 ( AxesSubplot ) \u2013 Axes for the first plot. fig2 ( Figure ) \u2013 Figure for the second plot. ax2 ( AxesSubplot ) \u2013 Axes for the second plot. Source code in modules/main_modules.py def figures_preparation(type_current, type_display): \"\"\" This function create the required figures and axes according to the type_current and type_display. Parameters ---------- type_current : str Type of current density function. type_display : str Type of display. Returns ------- fig1 : matplotlib.figure.Figure Figure for the first plot. ax1 : matplotlib.axes._subplots.AxesSubplot Axes for the first plot. fig2 : matplotlib.figure.Figure Figure for the second plot. ax2 : matplotlib.axes._subplots.AxesSubplot Axes for the second plot. \"\"\" mpl.rcParams['font.family'] = 'cmr10' # 'cmr10' for English characters and 'DejaVu Serif' for French ones mpl.rcParams['axes.formatter.use_mathtext'] = True # For the scientific notation mpl.rcParams['lines.linewidth'] = 2.0 mpl.rcParams['lines.markersize'] = 5.0 if type_display == \"no_display\": fig1, ax1 = None, None fig2, ax2 = None, None fig3, ax3 = None, None # For the step current if type_current == \"step\": if type_display == \"multiple\": # saving instruction is directly implemented within AlphaPEM.Display here. mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = None, None # Here, additional plots are unnecessary fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 13 # Font size for all text fig1, ax1 = plt.subplots(3, 3, figsize=(14, 14)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) # For the polarization curve elif type_current == \"polarization\": if type_display == \"multiple\": mpl.rcParams['font.size'] = 11 # Font size for all text fig1, ax1 = plt.subplots(1, 3, figsize=(14, 4.7)) fig2, ax2 = plt.subplots(1, 3, figsize=(14, 4.7)) fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = plt.subplots(figsize=(8, 8)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary # For the EIS curve elif type_current == \"EIS\": if type_display == \"multiple\": mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = plt.subplots(figsize=(8, 8)) fig2, ax2 = plt.subplots(figsize=(8, 8)) fig3, ax3 = plt.subplots(figsize=(8, 8)) elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 13 # Font size for all text fig1, ax1 = plt.subplots(1, 3, figsize=(14, 4.7)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) return fig1, ax1, fig2, ax2, fig3, ax3 plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3) This function saves the plots in the mentioned folder. The names of the files are automatically generated according to the type_current and the type_display. Parameters: type_fuel_cell ( str ) \u2013 Type of the fuel cell. type_current ( str ) \u2013 Type of current density function. type_display ( str ) \u2013 Type of display. fig1 ( Figure ) \u2013 Figure for the first plot. fig2 ( Figure ) \u2013 Figure for the second plot. Source code in modules/main_modules.py def plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3): \"\"\"This function saves the plots in the mentioned folder. The names of the files are automatically generated according to the type_current and the type_display. Parameters ---------- type_fuel_cell : str Type of the fuel cell. type_current : str Type of current density function. type_display : str Type of display. fig1 : matplotlib.figure.Figure Figure for the first plot. fig2 : matplotlib.figure.Figure Figure for the second plot. \"\"\" # Folder name subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 else type_fuel_cell # For the step current if type_current == \"step\": if type_display == \"multiple\": pass # saving instruction is directly implemented within AlphaPEM.Display for this situation. if type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"step_current_syn_1.pdf\", fig1) # For the polarization curve elif type_current == \"polarization\": if type_display == \"multiple\": saving_instructions(\"results\", subfolder_name, \"global_indicators_1.pdf\", fig1) saving_instructions(\"results\", subfolder_name, \"pola_curve_syn_1.pdf\", fig2) elif type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"pola_curve_1.pdf\", fig1) # For the EIS curve elif type_current == \"EIS\": if type_display == \"multiple\": saving_instructions(\"results\", subfolder_name, \"Nyquist_plot_1.pdf\", fig1) saving_instructions(\"results\", subfolder_name, \"Bode_amplitude_curve_1.pdf\", fig2) saving_instructions(\"results\", subfolder_name, \"Bode_angle_curve_1.pdf\", fig3) elif type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"Nyquist_plot_syn_1.pdf\", fig1) saving_instructions(root_folder, subfolder_name, filename, fig) This function gives the saving instructions for the figures. Parameters: root_folder ( str ) \u2013 The root folder for the saving. subfolder_name ( str ) \u2013 The subfolder name for the saving. filename ( str ) \u2013 The filename for the saving. fig ( Figure ) \u2013 The figure to be saved. Source code in modules/main_modules.py def saving_instructions(root_folder, subfolder_name, filename, fig): \"\"\"This function gives the saving instructions for the figures. Parameters ---------- root_folder : str The root folder for the saving. subfolder_name : str The subfolder name for the saving. filename : str The filename for the saving. fig : matplotlib.figure.Figure The figure to be saved. \"\"\" # Create the folder if necessary folder_name = os.path.join(root_folder, subfolder_name) if not os.path.exists(folder_name): os.makedirs(folder_name) # Create the filename without erasing the previous ones counter = 1 while os.path.isfile(os.path.join(folder_name, filename)): counter += 1 if filename[-6] == \"_\": # for the numbers between 1 and 9 filename = filename[:-5] + str(counter) + \".pdf\" elif filename[-7] == \"_\": # for the numbers between 10 and 99. filename = filename[:-6] + str(counter) + \".pdf\" else: # for the numbers between 100 and 999. The bigger numbers are not considered. filename = filename[:-7] + str(counter) + \".pdf\" # Save the figure file_path = os.path.join(folder_name, filename) fig.savefig(file_path, dpi=900, transparent=False, bbox_inches='tight')","title":"Main modules"},{"location":"functions/modules/main_modules/#main-modules","text":"This module contains some of the required functions for the main.py file.","title":"Main modules"},{"location":"functions/modules/main_modules/#modules.main_modules.figures_preparation","text":"This function create the required figures and axes according to the type_current and type_display. Parameters: type_current ( str ) \u2013 Type of current density function. type_display ( str ) \u2013 Type of display. Returns: fig1 ( Figure ) \u2013 Figure for the first plot. ax1 ( AxesSubplot ) \u2013 Axes for the first plot. fig2 ( Figure ) \u2013 Figure for the second plot. ax2 ( AxesSubplot ) \u2013 Axes for the second plot. Source code in modules/main_modules.py def figures_preparation(type_current, type_display): \"\"\" This function create the required figures and axes according to the type_current and type_display. Parameters ---------- type_current : str Type of current density function. type_display : str Type of display. Returns ------- fig1 : matplotlib.figure.Figure Figure for the first plot. ax1 : matplotlib.axes._subplots.AxesSubplot Axes for the first plot. fig2 : matplotlib.figure.Figure Figure for the second plot. ax2 : matplotlib.axes._subplots.AxesSubplot Axes for the second plot. \"\"\" mpl.rcParams['font.family'] = 'cmr10' # 'cmr10' for English characters and 'DejaVu Serif' for French ones mpl.rcParams['axes.formatter.use_mathtext'] = True # For the scientific notation mpl.rcParams['lines.linewidth'] = 2.0 mpl.rcParams['lines.markersize'] = 5.0 if type_display == \"no_display\": fig1, ax1 = None, None fig2, ax2 = None, None fig3, ax3 = None, None # For the step current if type_current == \"step\": if type_display == \"multiple\": # saving instruction is directly implemented within AlphaPEM.Display here. mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = None, None # Here, additional plots are unnecessary fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 13 # Font size for all text fig1, ax1 = plt.subplots(3, 3, figsize=(14, 14)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) # For the polarization curve elif type_current == \"polarization\": if type_display == \"multiple\": mpl.rcParams['font.size'] = 11 # Font size for all text fig1, ax1 = plt.subplots(1, 3, figsize=(14, 4.7)) fig2, ax2 = plt.subplots(1, 3, figsize=(14, 4.7)) fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = plt.subplots(figsize=(8, 8)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary # For the EIS curve elif type_current == \"EIS\": if type_display == \"multiple\": mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = plt.subplots(figsize=(8, 8)) fig2, ax2 = plt.subplots(figsize=(8, 8)) fig3, ax3 = plt.subplots(figsize=(8, 8)) elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 13 # Font size for all text fig1, ax1 = plt.subplots(1, 3, figsize=(14, 4.7)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) return fig1, ax1, fig2, ax2, fig3, ax3","title":"figures_preparation"},{"location":"functions/modules/main_modules/#modules.main_modules.plot_saving","text":"This function saves the plots in the mentioned folder. The names of the files are automatically generated according to the type_current and the type_display. Parameters: type_fuel_cell ( str ) \u2013 Type of the fuel cell. type_current ( str ) \u2013 Type of current density function. type_display ( str ) \u2013 Type of display. fig1 ( Figure ) \u2013 Figure for the first plot. fig2 ( Figure ) \u2013 Figure for the second plot. Source code in modules/main_modules.py def plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3): \"\"\"This function saves the plots in the mentioned folder. The names of the files are automatically generated according to the type_current and the type_display. Parameters ---------- type_fuel_cell : str Type of the fuel cell. type_current : str Type of current density function. type_display : str Type of display. fig1 : matplotlib.figure.Figure Figure for the first plot. fig2 : matplotlib.figure.Figure Figure for the second plot. \"\"\" # Folder name subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 else type_fuel_cell # For the step current if type_current == \"step\": if type_display == \"multiple\": pass # saving instruction is directly implemented within AlphaPEM.Display for this situation. if type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"step_current_syn_1.pdf\", fig1) # For the polarization curve elif type_current == \"polarization\": if type_display == \"multiple\": saving_instructions(\"results\", subfolder_name, \"global_indicators_1.pdf\", fig1) saving_instructions(\"results\", subfolder_name, \"pola_curve_syn_1.pdf\", fig2) elif type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"pola_curve_1.pdf\", fig1) # For the EIS curve elif type_current == \"EIS\": if type_display == \"multiple\": saving_instructions(\"results\", subfolder_name, \"Nyquist_plot_1.pdf\", fig1) saving_instructions(\"results\", subfolder_name, \"Bode_amplitude_curve_1.pdf\", fig2) saving_instructions(\"results\", subfolder_name, \"Bode_angle_curve_1.pdf\", fig3) elif type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"Nyquist_plot_syn_1.pdf\", fig1)","title":"plot_saving"},{"location":"functions/modules/main_modules/#modules.main_modules.saving_instructions","text":"This function gives the saving instructions for the figures. Parameters: root_folder ( str ) \u2013 The root folder for the saving. subfolder_name ( str ) \u2013 The subfolder name for the saving. filename ( str ) \u2013 The filename for the saving. fig ( Figure ) \u2013 The figure to be saved. Source code in modules/main_modules.py def saving_instructions(root_folder, subfolder_name, filename, fig): \"\"\"This function gives the saving instructions for the figures. Parameters ---------- root_folder : str The root folder for the saving. subfolder_name : str The subfolder name for the saving. filename : str The filename for the saving. fig : matplotlib.figure.Figure The figure to be saved. \"\"\" # Create the folder if necessary folder_name = os.path.join(root_folder, subfolder_name) if not os.path.exists(folder_name): os.makedirs(folder_name) # Create the filename without erasing the previous ones counter = 1 while os.path.isfile(os.path.join(folder_name, filename)): counter += 1 if filename[-6] == \"_\": # for the numbers between 1 and 9 filename = filename[:-5] + str(counter) + \".pdf\" elif filename[-7] == \"_\": # for the numbers between 10 and 99. filename = filename[:-6] + str(counter) + \".pdf\" else: # for the numbers between 100 and 999. The bigger numbers are not considered. filename = filename[:-7] + str(counter) + \".pdf\" # Save the figure file_path = os.path.join(folder_name, filename) fig.savefig(file_path, dpi=900, transparent=False, bbox_inches='tight')","title":"saving_instructions"},{"location":"functions/modules/settings_modules/","text":"Settings modules This modul contains some of the required functions for the settings. EIS_parameters(f_EIS) This function gives the time parameters for the EIS_current density function. Parameters: f_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Returns: t_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. Source code in modules/settings_modules.py def EIS_parameters(f_EIS): \"\"\"This function gives the time parameters for the EIS_current density function. Parameters ---------- f_EIS : tuple EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Returns ------- t_EIS : tuple EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. \"\"\" # Initialisation # Frequencies f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is the tested frequencies nb_period_break_EIS, nb_period_measurement_EIS = 50, 50 # They are the number of temporal periods which are used # for break and for measurement. It is more accurate to use # periods than time as the frequency range is big. # Time parameters delta_t_break_EIS = np.array([]) # It is the estimated time for reaching equilibrium at each frequency. delta_t_measurement_EIS = np.array([]) # It is the estimated time for measuring the voltage response. # Time parameters calculation t0_EIS = 1 / f[0] # s. It is the simulation starting time. # [0, t0_EIS] is used to let the stack equilibrate to i_EIS. t_new_start_EIS = np.array([t0_EIS]) # It is a list of time parameters which gives the beginning of each frequency # change. for i in range(nb_f_EIS): # The goal is to measure nb_f_EIS periods of the signal in order to have precise enough values. T_i = 1 / (f[i]) # s. It is the period of the signal. if i < (nb_f_EIS - 1): delta_t_break_EIS = np.concatenate((delta_t_break_EIS, [nb_period_break_EIS * T_i])) delta_t_measurement_EIS = np.concatenate((delta_t_measurement_EIS, [nb_period_measurement_EIS * T_i])) next_start_EIS = t_new_start_EIS[i] + delta_t_break_EIS[i] + delta_t_measurement_EIS[i] t_new_start_EIS = np.concatenate((t_new_start_EIS, [next_start_EIS])) else: delta_t_break_EIS = np.concatenate((delta_t_break_EIS, [nb_period_break_EIS * T_i])) delta_t_measurement_EIS = np.concatenate((delta_t_measurement_EIS, [nb_period_measurement_EIS * T_i])) tf_EIS = t_new_start_EIS[-1] + delta_t_break_EIS[-1] + delta_t_measurement_EIS[-1] # s. It is the # simulation ending time t_EIS = t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS return t_EIS stored_operating_inputs(type_fuel_cell) This function gives the operating inputs which correspond to the given type_fuel_cell. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve. Source code in modules/settings_modules.py def stored_operating_inputs(type_fuel_cell): \"\"\"This function gives the operating inputs which correspond to the given type_fuel_cell. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_max_pola : float Maximum current density for the polarization curve. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 1.5e5, 1.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.0\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.25\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.25e5, 2.25e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.5\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.5e5, 2.5e5 # Pa. It is the desired pressures of the fuel gas. Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. # For LF fuel cell elif type_fuel_cell == \"LF\": Tfc = 80 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 101325, 101325 # Pa. It is the desired pressures of the fuel gas. Sa, Sc = 2.0, 1.5 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.84, 0.59 # It is the desired relative humidity. i_max_pola = 1.6e4 # A.m-2. It is the maximum current density for the polarization curve. # For other fuel cells else: raise ValueError('the type_fuel_cell given is not valid.') return Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola stored_physical_parameters(type_fuel_cell) This function gives the physical parameters which correspond to the given type_fuel_cell. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Hcl ( float ) \u2013 Thickness of the catalyst layer in m. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. Hmem ( float ) \u2013 Thickness of the membrane in m. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. Hgc ( float ) \u2013 Thickness of the gas channel in m. Wgc ( float ) \u2013 Width of the gas channel in m. Lgc ( float ) \u2013 Length of the gas channel in m. Aact ( float ) \u2013 Active area of the cell in m\u00b2. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl ( float ) \u2013 Volumetric double layer capacitance in F.m-3. Source code in modules/settings_modules.py def stored_physical_parameters(type_fuel_cell): \"\"\"This function gives the physical parameters which correspond to the given type_fuel_cell. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Hcl : float Thickness of the catalyst layer in m. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. Hmem : float Thickness of the membrane in m. Hgdl : float Thickness of the gas diffusion layer in m. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_c : float Compression ratio of the GDL. Hgc : float Thickness of the gas channel in m. Wgc : float Width of the gas channel in m. Lgc : float Length of the gas channel in m. Aact : float Active area of the cell in m\u00b2. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl : float Volumetric double layer capacitance in F.m-3. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": # Catalyst layer Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.399 # It is the volume fraction of ionomer in the CL. tau = 1.016 # It is the pore structure coefficient, without units. # Membrane Hmem = 2e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.701 # It is the anode/cathode GDL porosity. epsilon_c = 0.271 # It is the compression ratio of the GDL. # Gas channel Hgc = 5e-4 # m. It is the thickness of the gas channel. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Interaction parameters between water and PEMFC structure e = 5.0 # It is the capillary exponent # Voltage polarization Re = 5.70e-07 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 2.79 # A.m-2.It is the reference exchange current density at the cathode. kappa_co = 27.2 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.61 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0.05553, 0.10514, 0.63654 # It is the limit liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. # For LF fuel cell elif type_fuel_cell == \"LF\": # Catalyst layer Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.27 # It is the volume fraction of ionomer in the CL. tau = 1.2 # It is the pore structure coefficient, without units. # Membrane Hmem = 5.08e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 4.2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.6 # It is the anode/cathode GDL porosity. epsilon_c = 0.21 # It is the compression ratio of the GDL. # Gas channel. Hgc = 1e-3 # m. It is the thickness of the gas channel. Wgc = 8e-4 # m. It is the width of the gas channel. Wrib = 7e-4 # m. It is the rib of the gas channel. L1gc = 0.1 # m. It is the length of 1 channel. Ngc = 16 # . It is the number of channels in the gas channel. It is taken to have Aact = 25cm\u00b2. Lgc = (L1gc + Wrib) * Ngc # m. It is the length of the gas channel. Aact = (L1gc + 2 * Wrib) * (Wgc + Wrib) * Ngc + (L1gc + 2 * Wrib) * 7e-4 # m\u00b2. It is the CL active area. # Interaction parameters between water and PEMFC structure e = 3.0 # It is the capillary exponent # Voltage polarization Re = 1e-6 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 10 # A.m-2.It is the reference exchange current density at the cathode. kappa_co = 25 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.5 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0, 1, 1 # It is the limit liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. # For other fuel cells else: raise ValueError('the type_input given is not valid.') return Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, \\ Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl","title":"Settings modules"},{"location":"functions/modules/settings_modules/#settings-modules","text":"This modul contains some of the required functions for the settings.","title":"Settings modules"},{"location":"functions/modules/settings_modules/#modules.settings_modules.EIS_parameters","text":"This function gives the time parameters for the EIS_current density function. Parameters: f_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Returns: t_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. Source code in modules/settings_modules.py def EIS_parameters(f_EIS): \"\"\"This function gives the time parameters for the EIS_current density function. Parameters ---------- f_EIS : tuple EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Returns ------- t_EIS : tuple EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. \"\"\" # Initialisation # Frequencies f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is the tested frequencies nb_period_break_EIS, nb_period_measurement_EIS = 50, 50 # They are the number of temporal periods which are used # for break and for measurement. It is more accurate to use # periods than time as the frequency range is big. # Time parameters delta_t_break_EIS = np.array([]) # It is the estimated time for reaching equilibrium at each frequency. delta_t_measurement_EIS = np.array([]) # It is the estimated time for measuring the voltage response. # Time parameters calculation t0_EIS = 1 / f[0] # s. It is the simulation starting time. # [0, t0_EIS] is used to let the stack equilibrate to i_EIS. t_new_start_EIS = np.array([t0_EIS]) # It is a list of time parameters which gives the beginning of each frequency # change. for i in range(nb_f_EIS): # The goal is to measure nb_f_EIS periods of the signal in order to have precise enough values. T_i = 1 / (f[i]) # s. It is the period of the signal. if i < (nb_f_EIS - 1): delta_t_break_EIS = np.concatenate((delta_t_break_EIS, [nb_period_break_EIS * T_i])) delta_t_measurement_EIS = np.concatenate((delta_t_measurement_EIS, [nb_period_measurement_EIS * T_i])) next_start_EIS = t_new_start_EIS[i] + delta_t_break_EIS[i] + delta_t_measurement_EIS[i] t_new_start_EIS = np.concatenate((t_new_start_EIS, [next_start_EIS])) else: delta_t_break_EIS = np.concatenate((delta_t_break_EIS, [nb_period_break_EIS * T_i])) delta_t_measurement_EIS = np.concatenate((delta_t_measurement_EIS, [nb_period_measurement_EIS * T_i])) tf_EIS = t_new_start_EIS[-1] + delta_t_break_EIS[-1] + delta_t_measurement_EIS[-1] # s. It is the # simulation ending time t_EIS = t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS return t_EIS","title":"EIS_parameters"},{"location":"functions/modules/settings_modules/#modules.settings_modules.stored_operating_inputs","text":"This function gives the operating inputs which correspond to the given type_fuel_cell. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve. Source code in modules/settings_modules.py def stored_operating_inputs(type_fuel_cell): \"\"\"This function gives the operating inputs which correspond to the given type_fuel_cell. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_max_pola : float Maximum current density for the polarization curve. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 1.5e5, 1.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.0\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.25\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.25e5, 2.25e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.5\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.5e5, 2.5e5 # Pa. It is the desired pressures of the fuel gas. Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. # For LF fuel cell elif type_fuel_cell == \"LF\": Tfc = 80 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 101325, 101325 # Pa. It is the desired pressures of the fuel gas. Sa, Sc = 2.0, 1.5 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.84, 0.59 # It is the desired relative humidity. i_max_pola = 1.6e4 # A.m-2. It is the maximum current density for the polarization curve. # For other fuel cells else: raise ValueError('the type_fuel_cell given is not valid.') return Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola","title":"stored_operating_inputs"},{"location":"functions/modules/settings_modules/#modules.settings_modules.stored_physical_parameters","text":"This function gives the physical parameters which correspond to the given type_fuel_cell. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Hcl ( float ) \u2013 Thickness of the catalyst layer in m. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. Hmem ( float ) \u2013 Thickness of the membrane in m. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. Hgc ( float ) \u2013 Thickness of the gas channel in m. Wgc ( float ) \u2013 Width of the gas channel in m. Lgc ( float ) \u2013 Length of the gas channel in m. Aact ( float ) \u2013 Active area of the cell in m\u00b2. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl ( float ) \u2013 Volumetric double layer capacitance in F.m-3. Source code in modules/settings_modules.py def stored_physical_parameters(type_fuel_cell): \"\"\"This function gives the physical parameters which correspond to the given type_fuel_cell. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Hcl : float Thickness of the catalyst layer in m. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. Hmem : float Thickness of the membrane in m. Hgdl : float Thickness of the gas diffusion layer in m. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_c : float Compression ratio of the GDL. Hgc : float Thickness of the gas channel in m. Wgc : float Width of the gas channel in m. Lgc : float Length of the gas channel in m. Aact : float Active area of the cell in m\u00b2. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl : float Volumetric double layer capacitance in F.m-3. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": # Catalyst layer Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.399 # It is the volume fraction of ionomer in the CL. tau = 1.016 # It is the pore structure coefficient, without units. # Membrane Hmem = 2e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.701 # It is the anode/cathode GDL porosity. epsilon_c = 0.271 # It is the compression ratio of the GDL. # Gas channel Hgc = 5e-4 # m. It is the thickness of the gas channel. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Interaction parameters between water and PEMFC structure e = 5.0 # It is the capillary exponent # Voltage polarization Re = 5.70e-07 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 2.79 # A.m-2.It is the reference exchange current density at the cathode. kappa_co = 27.2 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.61 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0.05553, 0.10514, 0.63654 # It is the limit liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. # For LF fuel cell elif type_fuel_cell == \"LF\": # Catalyst layer Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.27 # It is the volume fraction of ionomer in the CL. tau = 1.2 # It is the pore structure coefficient, without units. # Membrane Hmem = 5.08e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 4.2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.6 # It is the anode/cathode GDL porosity. epsilon_c = 0.21 # It is the compression ratio of the GDL. # Gas channel. Hgc = 1e-3 # m. It is the thickness of the gas channel. Wgc = 8e-4 # m. It is the width of the gas channel. Wrib = 7e-4 # m. It is the rib of the gas channel. L1gc = 0.1 # m. It is the length of 1 channel. Ngc = 16 # . It is the number of channels in the gas channel. It is taken to have Aact = 25cm\u00b2. Lgc = (L1gc + Wrib) * Ngc # m. It is the length of the gas channel. Aact = (L1gc + 2 * Wrib) * (Wgc + Wrib) * Ngc + (L1gc + 2 * Wrib) * 7e-4 # m\u00b2. It is the CL active area. # Interaction parameters between water and PEMFC structure e = 3.0 # It is the capillary exponent # Voltage polarization Re = 1e-6 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 10 # A.m-2.It is the reference exchange current density at the cathode. kappa_co = 25 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.5 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0, 1, 1 # It is the limit liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. # For other fuel cells else: raise ValueError('the type_input given is not valid.') return Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, \\ Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl","title":"stored_physical_parameters"},{"location":"functions/modules/transitory_functions/","text":"Transitory functions This module contains transitory functions which all have a specific physical meaning for modeling the PEM fuel cell. C_v_sat(T) This function calculates the saturated vapor concentration for a perfect gas, in mol.m-3, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Saturated vapor concentration for a perfect gas in mol.m-3. Source code in modules/transitory_functions.py def C_v_sat(T): \"\"\"This function calculates the saturated vapor concentration for a perfect gas, in mol.m-3, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Saturated vapor concentration for a perfect gas in mol.m-3. \"\"\" return Psat(T) / (R * T) D(lambdaa) This function calculates the diffusion coefficient of water in the membrane, in m\u00b2.s-1. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. Returns: float \u2013 Diffusion coefficient of water in the membrane in m\u00b2.s-1. Source code in modules/transitory_functions.py def D(lambdaa): \"\"\"This function calculates the diffusion coefficient of water in the membrane, in m\u00b2.s-1. Parameters ---------- lambdaa : float Water content in the membrane. Returns ------- float Diffusion coefficient of water in the membrane in m\u00b2.s-1. \"\"\" return 4.1e-10 * (lambdaa / 25.0) ** 0.15 * (1.0 + np.tanh((lambdaa - 2.5) / 1.4)) Da(P, T) This function calculates the diffusion coefficient at the anode, in m\u00b2.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Returns: float \u2013 Diffusion coefficient at the anode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Da(P, T): \"\"\"This function calculates the diffusion coefficient at the anode, in m\u00b2.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Returns ------- float Diffusion coefficient at the anode in m\u00b2.s-1. \"\"\" return 1.644e-4 * (T / 333) ** 2.334 * (101325 / P) Da_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl) This function calculates the effective diffusion coefficient at the anode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: s ( float ) \u2013 Liquid water saturation variable. epsilon ( float ) \u2013 Porosity. P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Effective diffusion coefficient at the anode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Da_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl): \"\"\"This function calculates the effective diffusion coefficient at the anode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- s : float Liquid water saturation variable. epsilon : float Porosity. P : float Pressure in Pa. T : float Temperature in K. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Effective diffusion coefficient at the anode in m\u00b2.s-1. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta2 = -1.59 elif 0.67 <= epsilon_gdl < 0.8: beta2 = -0.90 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon * ((epsilon - 0.11) / (1 - 0.11)) ** 0.785 * np.exp(beta2 * epsilon_c) * (1 - s) ** 2 * Da(P, T) Dc(P, T) This function calculates the diffusion coefficient at the cathode, in m\u00b2.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Returns: float \u2013 Diffusion coefficient at the cathode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Dc(P, T): \"\"\"This function calculates the diffusion coefficient at the cathode, in m\u00b2.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Returns ------- float Diffusion coefficient at the cathode in m\u00b2.s-1. \"\"\" return 3.242e-5 * (T / 333) ** 2.334 * (101325 / P) Dc_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl) This function calculates the effective diffusion coefficient at the cathode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: s ( float ) \u2013 Liquid water saturation variable. epsilon ( float ) \u2013 Porosity. P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Effective diffusion coefficient at the cathode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Dc_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl): \"\"\"This function calculates the effective diffusion coefficient at the cathode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- s : float Liquid water saturation variable. epsilon : float Porosity. P : float Pressure in Pa. T : float Temperature in K. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Effective diffusion coefficient at the cathode in m\u00b2.s-1. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta2 = -1.59 elif 0.67 <= epsilon_gdl < 0.8: beta2 = -0.90 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon * ((epsilon - 0.11) / (1 - 0.11)) ** 0.785 * np.exp(beta2 * epsilon_c) * (1 - s) ** 2 * Dc(P, T) K0(epsilon, epsilon_c, epsilon_gdl) This function calculates the intrinsic permeability, in m\u00b2, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: epsilon ( float ) \u2013 Porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Intrinsic permeability in m\u00b2. Source code in modules/transitory_functions.py def K0(epsilon, epsilon_c, epsilon_gdl): \"\"\"This function calculates the intrinsic permeability, in m\u00b2, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- epsilon : float Porosity. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Intrinsic permeability in m\u00b2. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta1 = -3.60 elif 0.67 <= epsilon_gdl < 0.8: beta1 = -2.60 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon / (8 * np.log(epsilon) ** 2) * (epsilon - 0.11) ** (0.785 + 2) * \\ 4.6e-6 ** 2 / ((1 - 0.11) ** 0.785 * ((0.785 + 1) * epsilon - 0.11) ** 2) * np.exp(beta1 * epsilon_c) Psat(T) This function calculates the saturated partial pressure of vapor, in Pa, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Saturated partial pressure of vapor in Pa. Source code in modules/transitory_functions.py def Psat(T): \"\"\"This function calculates the saturated partial pressure of vapor, in Pa, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Saturated partial pressure of vapor in Pa. \"\"\" return 101325 * 10 ** (-2.1794 + 0.02953 * (T - 273.15) - 9.1837e-5 * (T - 273.15) ** 2 + 1.4454e-7 * (T - 273.15) ** 3) Svl(s, C_v, Ctot, epsilon, T, gamma_cond, gamma_evap) This function calculates the phase transfer rate of water condensation or evaporation, in mol.m-3.s-1. Parameters: s ( float ) \u2013 Liquid water saturation variable. C_v ( float ) \u2013 Water concentration variable in mol.m-3. Ctot ( float ) \u2013 Total gas concentration in mol.m-3. epsilon ( float ) \u2013 Porosity. T ( float ) \u2013 Temperature in K. gamma_cond ( float ) \u2013 Overall condensation rate constant for water in s-1. gamma_evap ( float ) \u2013 Overall evaporation rate constant for water in Pa-1.s-1. Returns: float \u2013 Phase transfer rate of water condensation or evaporation in mol.m-3.s-1. Source code in modules/transitory_functions.py def Svl(s, C_v, Ctot, epsilon, T, gamma_cond, gamma_evap): \"\"\"This function calculates the phase transfer rate of water condensation or evaporation, in mol.m-3.s-1. Parameters ---------- s : float Liquid water saturation variable. C_v : float Water concentration variable in mol.m-3. Ctot : float Total gas concentration in mol.m-3. epsilon : float Porosity. T : float Temperature in K. gamma_cond : float Overall condensation rate constant for water in s-1. gamma_evap : float Overall evaporation rate constant for water in Pa-1.s-1. Returns ------- float Phase transfer rate of water condensation or evaporation in mol.m-3.s-1. \"\"\" if C_v > C_v_sat(T): # condensation return gamma_cond * epsilon * (1 - s) * (C_v / Ctot) * (C_v - C_v_sat(T)) else: # evaporation return -gamma_evap * epsilon * s * rho_H2O(T) / M_H2O * R * T * (C_v_sat(T) - C_v) gamma_sorp(C_v, s, lambdaa, T, Hcl, Kshape) This function calculates the sorption rate of water in the membrane, in s-1. Parameters: C_v ( float ) \u2013 Water concentration variable in mol.m-3. s ( float ) \u2013 Liquid water saturation variable. lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. Hcl ( float ) \u2013 Thickness of the CL layer. Kshape ( float ) \u2013 Mathematical factor governing lambda_eq smoothing Returns: float \u2013 Sorption rate of water in the membrane in s-1. Source code in modules/transitory_functions.py def gamma_sorp(C_v, s, lambdaa, T, Hcl, Kshape): \"\"\"This function calculates the sorption rate of water in the membrane, in s-1. Parameters ---------- C_v : float Water concentration variable in mol.m-3. s : float Liquid water saturation variable. lambdaa : float Water content in the membrane. T : float Temperature in K. Hcl : float Thickness of the CL layer. Kshape : float Mathematical factor governing lambda_eq smoothing Returns ------- float Sorption rate of water in the membrane in s-1. \"\"\" fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) # water volume fraction of # the membrane if lambda_eq(C_v, s, T, Kshape) >= lambdaa: # type_flow = absorption return (1.14e-5 * fv) / Hcl * np.exp(2416 * (1 / 303 - 1 / T)) else: # type_flow = desorption return (4.59e-5 * fv) / Hcl * np.exp(2416 * (1 / 303 - 1 / T)) h_a(P, T, Wgc, Hgc) This function calculates the effective convective-conductive mass transfer coefficient at the anode, in m.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Wgc ( float ) \u2013 Width of the gas channel in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Returns: float \u2013 Effective convective-conductive mass transfer coefficient at the anode in m.s-1. Source code in modules/transitory_functions.py def h_a(P, T, Wgc, Hgc): \"\"\"This function calculates the effective convective-conductive mass transfer coefficient at the anode, in m.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Wgc : float Width of the gas channel in m. Hgc : float Thickness of the gas channel in m. Returns ------- float Effective convective-conductive mass transfer coefficient at the anode in m.s-1. \"\"\" Sh = 0.9247 * np.log(Wgc / Hgc) + 2.3787 # Sherwood coefficient. return Sh * Da(P, T) / Hgc h_c(P, T, Wgc, Hgc) This function calculates the effective convective-conductive mass transfer coefficient at the cathode, in m.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Wgc ( float ) \u2013 Width of the gas channel in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Returns: float \u2013 Effective convective-conductive mass transfer coefficient at the cathode in m.s-1. Source code in modules/transitory_functions.py def h_c(P, T, Wgc, Hgc): \"\"\"This function calculates the effective convective-conductive mass transfer coefficient at the cathode, in m.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Wgc : float Width of the gas channel in m. Hgc : float Thickness of the gas channel in m. Returns ------- float Effective convective-conductive mass transfer coefficient at the cathode in m.s-1. \"\"\" Sh = 0.9247 * np.log(Wgc / Hgc) + 2.3787 # Sherwood coefficient. return Sh * Dc(P, T) / Hgc k_H2(lambdaa, T, kappa_co) This function calculates the permeability coefficient of the membrane for hydrogen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns: float \u2013 Permeability coefficient of the membrane for hydrogen in mol.m\u22121.s\u22121.Pa\u22121. Source code in modules/transitory_functions.py def k_H2(lambdaa, T, kappa_co): \"\"\"This function calculates the permeability coefficient of the membrane for hydrogen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters ---------- lambdaa : float Water content in the membrane. T : float Temperature in K. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns ------- float Permeability coefficient of the membrane for hydrogen in mol.m\u22121.s\u22121.Pa\u22121. \"\"\" # Initialisation of the constants E_H2_v = 2.1e4 # J.mol-1. It is the activation energy of H2 for crossover in the under saturated membrane. E_H2_l = 1.8e4 # J.mol-1. It is the activation energy of H2 for crossover in the liquide-equilibrated membrane. Tref = 303.15 # K. # Calculation of the permeability coefficient of the membrane for hydrogen if lambdaa < 17.6: fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) return kappa_co * (0.29 + 2.2 * fv) * 1e-14 * np.exp(E_H2_v / R * (1 / Tref - 1 / T)) else: return kappa_co * 1.8 * 1e-14 * np.exp(E_H2_l / R * (1 / Tref - 1 / T)) k_O2(lambdaa, T, kappa_co) This function calculates the permeability coefficient of the membrane for oxygen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns: float \u2013 Permeability coefficient of the membrane for oxygen in mol.m\u22121.s\u22121.Pa\u22121. Source code in modules/transitory_functions.py def k_O2(lambdaa, T, kappa_co): \"\"\"This function calculates the permeability coefficient of the membrane for oxygen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters ---------- lambdaa : float Water content in the membrane. T : float Temperature in K. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns ------- float Permeability coefficient of the membrane for oxygen in mol.m\u22121.s\u22121.Pa\u22121. \"\"\" # Initialisation of the constants E_O2_v = 2.2e4 # J.mol-1. It is the activation energy of oxygen for crossover in the under saturated membrane. E_O2_l = 2.0e4 # J.mol-1. It is the activation energy of oxygen for crossover in the liquide-equilibrated membrane. Tref = 303.15 # K. # Calculation of the permeability coefficient of the membrane for oxygen if lambdaa < 17.6: fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) return kappa_co * (0.11 + 1.9 * fv) * 1e-14 * np.exp(E_O2_v / R * (1 / Tref - 1 / T)) else: return kappa_co * 1.2 * 1e-14 * np.exp(E_O2_l / R * (1 / Tref - 1 / T)) lambda_eq(C_v, s, T, Kshape) This function calculates the equilibrium water content in the membrane. Hinatsu's expression modified with Bao's formulation has been selected. Parameters: C_v ( float ) \u2013 Water concentration variable in mol.m-3. s ( float ) \u2013 Liquid water saturation variable. T ( float ) \u2013 Temperature in K. Kshape ( float ) \u2013 Mathematical factor governing lambda_eq smoothing Returns: float \u2013 Equilibrium water content in the membrane. Source code in modules/transitory_functions.py def lambda_eq(C_v, s, T, Kshape): \"\"\"This function calculates the equilibrium water content in the membrane. Hinatsu's expression modified with Bao's formulation has been selected. Parameters ---------- C_v : float Water concentration variable in mol.m-3. s : float Liquid water saturation variable. T : float Temperature in K. Kshape : float Mathematical factor governing lambda_eq smoothing Returns ------- float Equilibrium water content in the membrane. \"\"\" a_w = C_v / C_v_sat(T) + 2 * s # water activity return 0.5 * (0.300 + 10.8 * a_w - 16.0 * a_w ** 2 + 14.1 * a_w ** 3) * (1 - np.tanh(100 * (a_w - 1))) \\ + 0.5 * (9.2 + 8.6 * (1 - np.exp(-Kshape * (a_w - 1)))) * (1 + np.tanh(100 * (a_w - 1))) nu_l(T) This function calculates the liquid water kinematic viscosity, in m\u00b2.s-1, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Liquid water kinematic viscosity in m\u00b2.s-1. Source code in modules/transitory_functions.py def nu_l(T): \"\"\"This function calculates the liquid water kinematic viscosity, in m\u00b2.s-1, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Liquid water kinematic viscosity in m\u00b2.s-1. \"\"\" mu_l = 2.414 * 10 ** (-5 + 247.8 / (T - 140.0)) # Pa.s. It is the liquid water dynamic viscosity. return mu_l / rho_H2O(T) rho_H2O(T) This function calculates the water density, in kg.m-3, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Water density in kg.m-3. Source code in modules/transitory_functions.py def rho_H2O(T): \"\"\"This function calculates the water density, in kg.m-3, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Water density in kg.m-3. \"\"\" return ((999.83952 + 16.945176 * (T - 273.15) - 7.9870401e-3 * (T - 273.15) ** 2 - 46.170461e-6 * (T - 273.15) ** 3 + 105.56302e-9 * (T - 273.15) ** 4 - 280.54253e-12 * (T - 273.15) ** 5) / (1 + 16.879850e-3 * (T - 273.15))) sigma(T) This function calculates the water surface tension, in N.m-1, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Water surface tension in N.m-1. Source code in modules/transitory_functions.py def sigma(T): \"\"\"This function calculates the water surface tension, in N.m-1, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Water surface tension in N.m-1. \"\"\" return 235.8e-3 * ((647.15 - T) / 647.15) ** 1.256 * (1 - 0.625 * (647.15 - T) / 647.15)","title":"Transitory functions"},{"location":"functions/modules/transitory_functions/#transitory-functions","text":"This module contains transitory functions which all have a specific physical meaning for modeling the PEM fuel cell.","title":"Transitory functions"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.C_v_sat","text":"This function calculates the saturated vapor concentration for a perfect gas, in mol.m-3, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Saturated vapor concentration for a perfect gas in mol.m-3. Source code in modules/transitory_functions.py def C_v_sat(T): \"\"\"This function calculates the saturated vapor concentration for a perfect gas, in mol.m-3, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Saturated vapor concentration for a perfect gas in mol.m-3. \"\"\" return Psat(T) / (R * T)","title":"C_v_sat"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.D","text":"This function calculates the diffusion coefficient of water in the membrane, in m\u00b2.s-1. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. Returns: float \u2013 Diffusion coefficient of water in the membrane in m\u00b2.s-1. Source code in modules/transitory_functions.py def D(lambdaa): \"\"\"This function calculates the diffusion coefficient of water in the membrane, in m\u00b2.s-1. Parameters ---------- lambdaa : float Water content in the membrane. Returns ------- float Diffusion coefficient of water in the membrane in m\u00b2.s-1. \"\"\" return 4.1e-10 * (lambdaa / 25.0) ** 0.15 * (1.0 + np.tanh((lambdaa - 2.5) / 1.4))","title":"D"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Da","text":"This function calculates the diffusion coefficient at the anode, in m\u00b2.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Returns: float \u2013 Diffusion coefficient at the anode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Da(P, T): \"\"\"This function calculates the diffusion coefficient at the anode, in m\u00b2.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Returns ------- float Diffusion coefficient at the anode in m\u00b2.s-1. \"\"\" return 1.644e-4 * (T / 333) ** 2.334 * (101325 / P)","title":"Da"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Da_eff","text":"This function calculates the effective diffusion coefficient at the anode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: s ( float ) \u2013 Liquid water saturation variable. epsilon ( float ) \u2013 Porosity. P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Effective diffusion coefficient at the anode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Da_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl): \"\"\"This function calculates the effective diffusion coefficient at the anode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- s : float Liquid water saturation variable. epsilon : float Porosity. P : float Pressure in Pa. T : float Temperature in K. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Effective diffusion coefficient at the anode in m\u00b2.s-1. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta2 = -1.59 elif 0.67 <= epsilon_gdl < 0.8: beta2 = -0.90 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon * ((epsilon - 0.11) / (1 - 0.11)) ** 0.785 * np.exp(beta2 * epsilon_c) * (1 - s) ** 2 * Da(P, T)","title":"Da_eff"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Dc","text":"This function calculates the diffusion coefficient at the cathode, in m\u00b2.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Returns: float \u2013 Diffusion coefficient at the cathode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Dc(P, T): \"\"\"This function calculates the diffusion coefficient at the cathode, in m\u00b2.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Returns ------- float Diffusion coefficient at the cathode in m\u00b2.s-1. \"\"\" return 3.242e-5 * (T / 333) ** 2.334 * (101325 / P)","title":"Dc"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Dc_eff","text":"This function calculates the effective diffusion coefficient at the cathode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: s ( float ) \u2013 Liquid water saturation variable. epsilon ( float ) \u2013 Porosity. P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Effective diffusion coefficient at the cathode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Dc_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl): \"\"\"This function calculates the effective diffusion coefficient at the cathode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- s : float Liquid water saturation variable. epsilon : float Porosity. P : float Pressure in Pa. T : float Temperature in K. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Effective diffusion coefficient at the cathode in m\u00b2.s-1. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta2 = -1.59 elif 0.67 <= epsilon_gdl < 0.8: beta2 = -0.90 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon * ((epsilon - 0.11) / (1 - 0.11)) ** 0.785 * np.exp(beta2 * epsilon_c) * (1 - s) ** 2 * Dc(P, T)","title":"Dc_eff"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.K0","text":"This function calculates the intrinsic permeability, in m\u00b2, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: epsilon ( float ) \u2013 Porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Intrinsic permeability in m\u00b2. Source code in modules/transitory_functions.py def K0(epsilon, epsilon_c, epsilon_gdl): \"\"\"This function calculates the intrinsic permeability, in m\u00b2, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- epsilon : float Porosity. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Intrinsic permeability in m\u00b2. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta1 = -3.60 elif 0.67 <= epsilon_gdl < 0.8: beta1 = -2.60 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon / (8 * np.log(epsilon) ** 2) * (epsilon - 0.11) ** (0.785 + 2) * \\ 4.6e-6 ** 2 / ((1 - 0.11) ** 0.785 * ((0.785 + 1) * epsilon - 0.11) ** 2) * np.exp(beta1 * epsilon_c)","title":"K0"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Psat","text":"This function calculates the saturated partial pressure of vapor, in Pa, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Saturated partial pressure of vapor in Pa. Source code in modules/transitory_functions.py def Psat(T): \"\"\"This function calculates the saturated partial pressure of vapor, in Pa, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Saturated partial pressure of vapor in Pa. \"\"\" return 101325 * 10 ** (-2.1794 + 0.02953 * (T - 273.15) - 9.1837e-5 * (T - 273.15) ** 2 + 1.4454e-7 * (T - 273.15) ** 3)","title":"Psat"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Svl","text":"This function calculates the phase transfer rate of water condensation or evaporation, in mol.m-3.s-1. Parameters: s ( float ) \u2013 Liquid water saturation variable. C_v ( float ) \u2013 Water concentration variable in mol.m-3. Ctot ( float ) \u2013 Total gas concentration in mol.m-3. epsilon ( float ) \u2013 Porosity. T ( float ) \u2013 Temperature in K. gamma_cond ( float ) \u2013 Overall condensation rate constant for water in s-1. gamma_evap ( float ) \u2013 Overall evaporation rate constant for water in Pa-1.s-1. Returns: float \u2013 Phase transfer rate of water condensation or evaporation in mol.m-3.s-1. Source code in modules/transitory_functions.py def Svl(s, C_v, Ctot, epsilon, T, gamma_cond, gamma_evap): \"\"\"This function calculates the phase transfer rate of water condensation or evaporation, in mol.m-3.s-1. Parameters ---------- s : float Liquid water saturation variable. C_v : float Water concentration variable in mol.m-3. Ctot : float Total gas concentration in mol.m-3. epsilon : float Porosity. T : float Temperature in K. gamma_cond : float Overall condensation rate constant for water in s-1. gamma_evap : float Overall evaporation rate constant for water in Pa-1.s-1. Returns ------- float Phase transfer rate of water condensation or evaporation in mol.m-3.s-1. \"\"\" if C_v > C_v_sat(T): # condensation return gamma_cond * epsilon * (1 - s) * (C_v / Ctot) * (C_v - C_v_sat(T)) else: # evaporation return -gamma_evap * epsilon * s * rho_H2O(T) / M_H2O * R * T * (C_v_sat(T) - C_v)","title":"Svl"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.gamma_sorp","text":"This function calculates the sorption rate of water in the membrane, in s-1. Parameters: C_v ( float ) \u2013 Water concentration variable in mol.m-3. s ( float ) \u2013 Liquid water saturation variable. lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. Hcl ( float ) \u2013 Thickness of the CL layer. Kshape ( float ) \u2013 Mathematical factor governing lambda_eq smoothing Returns: float \u2013 Sorption rate of water in the membrane in s-1. Source code in modules/transitory_functions.py def gamma_sorp(C_v, s, lambdaa, T, Hcl, Kshape): \"\"\"This function calculates the sorption rate of water in the membrane, in s-1. Parameters ---------- C_v : float Water concentration variable in mol.m-3. s : float Liquid water saturation variable. lambdaa : float Water content in the membrane. T : float Temperature in K. Hcl : float Thickness of the CL layer. Kshape : float Mathematical factor governing lambda_eq smoothing Returns ------- float Sorption rate of water in the membrane in s-1. \"\"\" fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) # water volume fraction of # the membrane if lambda_eq(C_v, s, T, Kshape) >= lambdaa: # type_flow = absorption return (1.14e-5 * fv) / Hcl * np.exp(2416 * (1 / 303 - 1 / T)) else: # type_flow = desorption return (4.59e-5 * fv) / Hcl * np.exp(2416 * (1 / 303 - 1 / T))","title":"gamma_sorp"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.h_a","text":"This function calculates the effective convective-conductive mass transfer coefficient at the anode, in m.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Wgc ( float ) \u2013 Width of the gas channel in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Returns: float \u2013 Effective convective-conductive mass transfer coefficient at the anode in m.s-1. Source code in modules/transitory_functions.py def h_a(P, T, Wgc, Hgc): \"\"\"This function calculates the effective convective-conductive mass transfer coefficient at the anode, in m.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Wgc : float Width of the gas channel in m. Hgc : float Thickness of the gas channel in m. Returns ------- float Effective convective-conductive mass transfer coefficient at the anode in m.s-1. \"\"\" Sh = 0.9247 * np.log(Wgc / Hgc) + 2.3787 # Sherwood coefficient. return Sh * Da(P, T) / Hgc","title":"h_a"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.h_c","text":"This function calculates the effective convective-conductive mass transfer coefficient at the cathode, in m.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Wgc ( float ) \u2013 Width of the gas channel in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Returns: float \u2013 Effective convective-conductive mass transfer coefficient at the cathode in m.s-1. Source code in modules/transitory_functions.py def h_c(P, T, Wgc, Hgc): \"\"\"This function calculates the effective convective-conductive mass transfer coefficient at the cathode, in m.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Wgc : float Width of the gas channel in m. Hgc : float Thickness of the gas channel in m. Returns ------- float Effective convective-conductive mass transfer coefficient at the cathode in m.s-1. \"\"\" Sh = 0.9247 * np.log(Wgc / Hgc) + 2.3787 # Sherwood coefficient. return Sh * Dc(P, T) / Hgc","title":"h_c"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.k_H2","text":"This function calculates the permeability coefficient of the membrane for hydrogen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns: float \u2013 Permeability coefficient of the membrane for hydrogen in mol.m\u22121.s\u22121.Pa\u22121. Source code in modules/transitory_functions.py def k_H2(lambdaa, T, kappa_co): \"\"\"This function calculates the permeability coefficient of the membrane for hydrogen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters ---------- lambdaa : float Water content in the membrane. T : float Temperature in K. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns ------- float Permeability coefficient of the membrane for hydrogen in mol.m\u22121.s\u22121.Pa\u22121. \"\"\" # Initialisation of the constants E_H2_v = 2.1e4 # J.mol-1. It is the activation energy of H2 for crossover in the under saturated membrane. E_H2_l = 1.8e4 # J.mol-1. It is the activation energy of H2 for crossover in the liquide-equilibrated membrane. Tref = 303.15 # K. # Calculation of the permeability coefficient of the membrane for hydrogen if lambdaa < 17.6: fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) return kappa_co * (0.29 + 2.2 * fv) * 1e-14 * np.exp(E_H2_v / R * (1 / Tref - 1 / T)) else: return kappa_co * 1.8 * 1e-14 * np.exp(E_H2_l / R * (1 / Tref - 1 / T))","title":"k_H2"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.k_O2","text":"This function calculates the permeability coefficient of the membrane for oxygen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns: float \u2013 Permeability coefficient of the membrane for oxygen in mol.m\u22121.s\u22121.Pa\u22121. Source code in modules/transitory_functions.py def k_O2(lambdaa, T, kappa_co): \"\"\"This function calculates the permeability coefficient of the membrane for oxygen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters ---------- lambdaa : float Water content in the membrane. T : float Temperature in K. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns ------- float Permeability coefficient of the membrane for oxygen in mol.m\u22121.s\u22121.Pa\u22121. \"\"\" # Initialisation of the constants E_O2_v = 2.2e4 # J.mol-1. It is the activation energy of oxygen for crossover in the under saturated membrane. E_O2_l = 2.0e4 # J.mol-1. It is the activation energy of oxygen for crossover in the liquide-equilibrated membrane. Tref = 303.15 # K. # Calculation of the permeability coefficient of the membrane for oxygen if lambdaa < 17.6: fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) return kappa_co * (0.11 + 1.9 * fv) * 1e-14 * np.exp(E_O2_v / R * (1 / Tref - 1 / T)) else: return kappa_co * 1.2 * 1e-14 * np.exp(E_O2_l / R * (1 / Tref - 1 / T))","title":"k_O2"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.lambda_eq","text":"This function calculates the equilibrium water content in the membrane. Hinatsu's expression modified with Bao's formulation has been selected. Parameters: C_v ( float ) \u2013 Water concentration variable in mol.m-3. s ( float ) \u2013 Liquid water saturation variable. T ( float ) \u2013 Temperature in K. Kshape ( float ) \u2013 Mathematical factor governing lambda_eq smoothing Returns: float \u2013 Equilibrium water content in the membrane. Source code in modules/transitory_functions.py def lambda_eq(C_v, s, T, Kshape): \"\"\"This function calculates the equilibrium water content in the membrane. Hinatsu's expression modified with Bao's formulation has been selected. Parameters ---------- C_v : float Water concentration variable in mol.m-3. s : float Liquid water saturation variable. T : float Temperature in K. Kshape : float Mathematical factor governing lambda_eq smoothing Returns ------- float Equilibrium water content in the membrane. \"\"\" a_w = C_v / C_v_sat(T) + 2 * s # water activity return 0.5 * (0.300 + 10.8 * a_w - 16.0 * a_w ** 2 + 14.1 * a_w ** 3) * (1 - np.tanh(100 * (a_w - 1))) \\ + 0.5 * (9.2 + 8.6 * (1 - np.exp(-Kshape * (a_w - 1)))) * (1 + np.tanh(100 * (a_w - 1)))","title":"lambda_eq"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.nu_l","text":"This function calculates the liquid water kinematic viscosity, in m\u00b2.s-1, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Liquid water kinematic viscosity in m\u00b2.s-1. Source code in modules/transitory_functions.py def nu_l(T): \"\"\"This function calculates the liquid water kinematic viscosity, in m\u00b2.s-1, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Liquid water kinematic viscosity in m\u00b2.s-1. \"\"\" mu_l = 2.414 * 10 ** (-5 + 247.8 / (T - 140.0)) # Pa.s. It is the liquid water dynamic viscosity. return mu_l / rho_H2O(T)","title":"nu_l"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.rho_H2O","text":"This function calculates the water density, in kg.m-3, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Water density in kg.m-3. Source code in modules/transitory_functions.py def rho_H2O(T): \"\"\"This function calculates the water density, in kg.m-3, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Water density in kg.m-3. \"\"\" return ((999.83952 + 16.945176 * (T - 273.15) - 7.9870401e-3 * (T - 273.15) ** 2 - 46.170461e-6 * (T - 273.15) ** 3 + 105.56302e-9 * (T - 273.15) ** 4 - 280.54253e-12 * (T - 273.15) ** 5) / (1 + 16.879850e-3 * (T - 273.15)))","title":"rho_H2O"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.sigma","text":"This function calculates the water surface tension, in N.m-1, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Water surface tension in N.m-1. Source code in modules/transitory_functions.py def sigma(T): \"\"\"This function calculates the water surface tension, in N.m-1, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Water surface tension in N.m-1. \"\"\" return 235.8e-3 * ((647.15 - T) / 647.15) ** 1.256 * (1 - 0.625 * (647.15 - T) / 647.15)","title":"sigma"}]}
\ No newline at end of file
+{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"AlphaPEM AlphaPEM is an open-source software package for simulating proton exchange membrane fuel cell (PEMFC) systems for embedded applications. It is based on a physics-based, one-dimensional (1D), dynamic, two-phase, and 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. A detailed presentation of this program was published in the peer-reviewed journal SoftwareX. Improvements to AlphaPEM , such as the addition of heat transfer modelling and spatial extension to 1D+1D, will be available in the future. Table of Contents Installation Major updates Related publications Installation To install AlphaPEM , follow these steps in a shell: Clone the repository: git clone https://github.com/gassraphael/AlphaPEM.git Navigate to the project directory: cd AlphaPEM Update the Python package manager, pip, to the latest available version: pip install --upgrade pip Install the required dependencies (eventually in a specific environment): pip install numpy scipy matplotlib colorama geneticalgorithm2 python3 -m pip install git+https://github.com/RedFantom/ttkthemes Major updates V1.0 - 2024.09.05 - This version of AlphaPEM corresponds to the one developed during Rapha\u00ebl Gass's PhD from 2021 to 2024. Work in progress The polarization curves from the EH-31 fuel cells, provided by default, are no longer calibrated due to recent modifications made to the equations. A calibration of the indeterminate parameters will be performed in the future to correct this issue. Related publications The detailed model description and simulation results can be found in the following articles and thesis. Submitted journal papers: AlphaPEM: An Open-Source Dynamic 1D Physics-Based Pem Fuel Cell Model for Embedded Applications In the journal SoftwareX, in arXiv , in HAL or in SSRN (preprint). The objective of this work is to highlight the AlphaPEM software, which has been published as open-source on GitHub. The first version of this PEM fuel cell simulator is based on the dynamic 1D model developed during 2021-2024. An Advanced 1D Physics-Based Model for PEM Hydrogen Fuel Cells With Enhanced Overvoltage Prediction In the International Journal of Hydrogen Energy, in arXiv or in HAL (preprint). The aim of this study was to introduce the dynamic 1D model developed during 2021-2024, emphasizing the adjustment of the equations for this specific model and their numerical resolution. Furthermore, a novel coefficient is proposed to establish a physical relationship between the voltage drop at high currents, the quantity of liquid water in the cell, and operating conditions. Published journal papers: A Critical Review of Proton Exchange Membrane Fuel Cells Matter Transports and Voltage Polarisation for Modelling In the Journal of the Electrochemical Society or in HAL (postprint). The aim of this work was to compile, within a single article, all the equations required for the physical modeling of a fuel cell. Each equation is complemented with explanations, critical analysis, and suggestions for potential enhancements. Thesis: to complete.","title":"Home"},{"location":"#alphapem","text":"AlphaPEM is an open-source software package for simulating proton exchange membrane fuel cell (PEMFC) systems for embedded applications. It is based on a physics-based, one-dimensional (1D), dynamic, two-phase, and 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. A detailed presentation of this program was published in the peer-reviewed journal SoftwareX. Improvements to AlphaPEM , such as the addition of heat transfer modelling and spatial extension to 1D+1D, will be available in the future.","title":"AlphaPEM"},{"location":"#table-of-contents","text":"Installation Major updates Related publications","title":"Table of Contents"},{"location":"#installation","text":"To install AlphaPEM , follow these steps in a shell: Clone the repository: git clone https://github.com/gassraphael/AlphaPEM.git Navigate to the project directory: cd AlphaPEM Update the Python package manager, pip, to the latest available version: pip install --upgrade pip Install the required dependencies (eventually in a specific environment): pip install numpy scipy matplotlib colorama geneticalgorithm2 python3 -m pip install git+https://github.com/RedFantom/ttkthemes","title":"Installation"},{"location":"#major-updates","text":"V1.0 - 2024.09.05 - This version of AlphaPEM corresponds to the one developed during Rapha\u00ebl Gass's PhD from 2021 to 2024.","title":"Major updates"},{"location":"#work-in-progress","text":"The polarization curves from the EH-31 fuel cells, provided by default, are no longer calibrated due to recent modifications made to the equations. A calibration of the indeterminate parameters will be performed in the future to correct this issue.","title":"Work in progress"},{"location":"#related-publications","text":"The detailed model description and simulation results can be found in the following articles and thesis. Submitted journal papers: AlphaPEM: An Open-Source Dynamic 1D Physics-Based Pem Fuel Cell Model for Embedded Applications In the journal SoftwareX, in arXiv , in HAL or in SSRN (preprint). The objective of this work is to highlight the AlphaPEM software, which has been published as open-source on GitHub. The first version of this PEM fuel cell simulator is based on the dynamic 1D model developed during 2021-2024. An Advanced 1D Physics-Based Model for PEM Hydrogen Fuel Cells With Enhanced Overvoltage Prediction In the International Journal of Hydrogen Energy, in arXiv or in HAL (preprint). The aim of this study was to introduce the dynamic 1D model developed during 2021-2024, emphasizing the adjustment of the equations for this specific model and their numerical resolution. Furthermore, a novel coefficient is proposed to establish a physical relationship between the voltage drop at high currents, the quantity of liquid water in the cell, and operating conditions. Published journal papers: A Critical Review of Proton Exchange Membrane Fuel Cells Matter Transports and Voltage Polarisation for Modelling In the Journal of the Electrochemical Society or in HAL (postprint). The aim of this work was to compile, within a single article, all the equations required for the physical modeling of a fuel cell. Each equation is complemented with explanations, critical analysis, and suggestions for potential enhancements. Thesis: to complete.","title":"Related publications"},{"location":"about/","text":"Contributions Authors AlphaPEM is firstly developed by Rapha\u00ebl Gass during his PhD thesis from 2021 to 2024, supervised by Prof. Zhongliang Li, Prof. Rachid Outbib, Prof. Samir Jemei and Prof. Daniel Hissel. Financial support This work has been supported: - from 2021 to 2024 by French National Research Agency via project DEAL (Grant no. ANR-20-CE05-0016-01), the Region Provence-Alpes-C\u00f4te d\u2019Azur, the EIPHI Graduate School (contract ANR-17-EURE-0002) and the Region Bourgogne Franche-Comt\u00e9. Licenses AlphaPEM is licensed under the GNU GPL 3.0. See the LICENSE file for more details. It also includes components licensed under the MIT license : calibration/parameter_calibration.py from geneticalgorithm2 . New contributors Contributions from the community are welcome! If you would like to contribute to AlphaPEM , please follow these steps: Fork the repository. Create a new branch ( git checkout -b feature/YourFeature ). Commit your changes ( git commit -am 'Add some feature' ). Push to the branch ( git push origin feature/YourFeature ). Create a new Pull Request. Contact For any questions or support, please contact me at gassraphael@proton.me .","title":"About"},{"location":"about/#contributions","text":"","title":"Contributions"},{"location":"about/#authors","text":"AlphaPEM is firstly developed by Rapha\u00ebl Gass during his PhD thesis from 2021 to 2024, supervised by Prof. Zhongliang Li, Prof. Rachid Outbib, Prof. Samir Jemei and Prof. Daniel Hissel.","title":"Authors"},{"location":"about/#financial-support","text":"This work has been supported: - from 2021 to 2024 by French National Research Agency via project DEAL (Grant no. ANR-20-CE05-0016-01), the Region Provence-Alpes-C\u00f4te d\u2019Azur, the EIPHI Graduate School (contract ANR-17-EURE-0002) and the Region Bourgogne Franche-Comt\u00e9.","title":"Financial support"},{"location":"about/#licenses","text":"AlphaPEM is licensed under the GNU GPL 3.0. See the LICENSE file for more details. It also includes components licensed under the MIT license : calibration/parameter_calibration.py from geneticalgorithm2 .","title":"Licenses"},{"location":"about/#new-contributors","text":"Contributions from the community are welcome! If you would like to contribute to AlphaPEM , please follow these steps: Fork the repository. Create a new branch ( git checkout -b feature/YourFeature ). Commit your changes ( git commit -am 'Add some feature' ). Push to the branch ( git push origin feature/YourFeature ). Create a new Pull Request.","title":"New contributors"},{"location":"about/#contact","text":"For any questions or support, please contact me at gassraphael@proton.me .","title":"Contact"},{"location":"functions/GUI/","text":"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 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. \\nIt is based on a physics-based, \" \\ \"one-dimensional (1D), dynamic, two-phase, and 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.\" \\ \"\\n\\nAlphaPEM is firstly developed by Rapha\u00ebl Gass during his PhD thesis from 2021 to 2024, supervised by \" \\ \"Prof. Zhongliang Li, Prof. Rachid Outbib, Prof. Samir Jemei and Prof. Daniel Hissel. \\nIt has been \" \\ \"supported by French National Research Agency via project DEAL (Grant no. ANR-20-CE05-0016-01), the Region \" \\ \"Provence-Alpes-C\u00f4te d\u2019Azur, the EIPHI Graduate School (contract ANR-17-EURE-0002) and the Region \" \\ \"Bourgogne Franche-Comt\u00e9.\" \\ \"\\n\\nIt is related to the following articles:\" \\ \"\\n - Gass et al 2024 J. Electrochem. Soc. https://doi.org/10.1149/1945-7111/ad305a,\" \\ \"\\n - Gass et al 2024 SSRN http://dx.doi.org/10.2139/ssrn.4812343.\" \\ \"\\n\\nMore information can be found in:\" \\ \"\\n - GitHub webpage: https://github.com/gassraphael/AlphaPEM\" \\ \"\\n - Documentation webpage: to do\" \\ \"\\n\\nIf you want to contact me, please send an email to: gassraphael@proton.me.\" # 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 ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in GUI.py 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 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 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) # Create the choice dictionaries choice_operating_conditions = \\ {'Temperature - Tfc (\u00b0C)': {'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 - \u03a6a': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 4, 'label_column': 1}, 'Cathode humidity - \u03a6c': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 4, 'label_column': 3}} choice_accessible_parameters = \\ {'GDL thickness - Hgdl (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 1}, 'CL thickness - Hcl (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 3}, 'Membrane thickness - Hmem (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 5}, 'GC thickness - Hgc (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 1}, 'GC width - Wgc (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 3}, 'GC cumulated length - Lgc (m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 5}, 'Active area - Aact (cm\u00b2)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 3, 'label_column': 1}} choice_undetermined_parameters = \\ {'GDL porosity - \u03b5_gdl': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.6), 'label_row': 0, 'label_column': 1}, 'Ionomer volume fraction\\n- \u03b5_mc': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.25), 'label_row': 0, 'label_column': 3}, 'Tortuosity - \u03c4': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.5), 'label_row': 0, 'label_column': 5}, 'Compression ratio - \u03b5_c': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.2), 'label_row': 1, 'label_column': 1}, 'Capillary exponent - e': {'value': tk.IntVar(undetermined_parameters_frame, 4), 'label_row': 1, 'label_column': 3}, 'Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.0), 'label_row': 1, 'label_column': 5}, 'Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)': {'value': tk.DoubleVar(undetermined_parameters_frame, 3.0), 'label_row': 2, 'label_column': 1}, 'Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.0), 'label_row': 2, 'label_column': 3}, 'Overpotential correction\\nexponent - \u03ba_c': {'value': tk.DoubleVar(undetermined_parameters_frame, 2.0), 'label_row': 2, 'label_column': 5}, 'Limit liquid saturation\\ncoefficient - a_slim': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.05), 'label_row': 3, 'label_column': 1}, 'Limit liquid saturation\\ncoefficient - b_slim': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.1), 'label_row': 3, 'label_column': 3}, 'Limit liquid saturation\\ncoefficient - a_switch': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.7), 'label_row': 3, 'label_column': 5}, 'Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)': {'value': tk.DoubleVar(undetermined_parameters_frame, 20), 'label_row': 4, 'label_column': 1}} choice_current_density_parameters = \\ {'Initial time - t0_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 0), 'label_row': 0, 'label_column': 1}, 'Final time - tf_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 1000), 'label_row': 0, 'label_column': 3}, 'Loading time\\n- \u0394t_load_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 50), 'label_row': 0, 'label_column': 5}, 'Initial current density\\n- i_ini_step (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 1, 'label_column': 1}, 'Final current density\\n- i_final_step (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 1.5), 'label_row': 1, 'label_column': 3}, 'Loading time\\n- \u0394t_load_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 30), 'label_row': 2, 'label_column': 1}, 'Breaking time\\n- \u0394t_break_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 30), 'label_row': 2, 'label_column': 3}, 'Initial breaking time\\n- \u0394t_ini_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 60), 'label_row': 2, 'label_column': 5}, 'Maximum current density\\n- i_max_pola (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 3, 'label_column': 1}, 'Current density step\\n- \u0394i_pola (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.1), 'label_row': 3, 'label_column': 3}, 'Static current\\n- i_EIS (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 4, 'label_column': 1}, 'Current ratio\\n- ratio_EIS (%)': {'value': tk.DoubleVar(current_density_parameters_frame, 5), 'label_row': 4, 'label_column': 3}, 'Number of points\\ncalculated - nb_points_EIS': {'value': tk.IntVar(current_density_parameters_frame, 50), 'label_row': 4, 'label_column': 5}, 'Power of the\\ninitial frequency\\n- f_power_min_EIS': {'value': tk.IntVar(current_density_parameters_frame, -3), 'label_row': 5, 'label_column': 1}, 'Power of the\\nfinal frequency\\n- f_power_max_EIS': {'value': tk.IntVar(current_density_parameters_frame, 5), 'label_row': 5, 'label_column': 3}, 'Number of frequencies\\ntested - nb_f_EIS': {'value': tk.IntVar(current_density_parameters_frame, 60), 'label_row': 5, 'label_column': 5}} choice_computing_parameters = \\ {'Time for dynamic\\ndisplay - \u0394t_dyn_step (s)': {'value': tk.DoubleVar(computing_parameters_frame, 10), '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- \u0394t_purge (s)': {'value': tk.DoubleVar(computing_parameters_frame, 15), 'label_row': 0, 'label_column': 5}, 'Maximum time step\\n- max_step (s)': {'value': tk.DoubleVar(computing_parameters_frame, 0.1), 'label_row': 1, 'label_column': 1}, 'Number of GDL nodes - n_gdl': {'value': tk.IntVar(computing_parameters_frame, 10), 'label_row': 1, '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}, 'type_control': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 2}, 'type_purge': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 3}, 'type_display': {'value': tk.IntVar(model_possibilities_frame, 1), 'label_row': 4}, 'type_plot': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 5}} # 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)', 'Linhao Fan (2010)', 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=6, 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=6, 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=6, column=4, padx=10, pady=20) # About button ttk.Button(model_possibilities_frame, text='About', style='Black.TButton', command=about) \\ .grid(row=6, 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 ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in GUI.py 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. Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, Aact, Hgdl, Hcl, Hmem, Hgc, Wgc, Lgc, epsilon_gdl, \\ epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, t_step, \\ i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, t_purge, delta_t_purge, max_step, n_gdl, \\ type_fuel_cell, 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) if current_button == 0: type_current = \"step\" current_density = step_current launch_AlphaPEM_for_step_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) if current_button == 1: type_current = \"polarization\" current_density = polarization_current launch_AlphaPEM_for_polarization_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) if current_button == 2: type_current = \"EIS\" current_density = EIS_current launch_AlphaPEM_for_EIS_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) 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 ) \u2013 The frame to show or hide. show_info ( BooleanVar ) \u2013 A boolean variable to track the current visibility state. canvas ( Canvas ) \u2013 The canvas to update the scroll region. Source code in GUI.py 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'))","title":"GUI"},{"location":"functions/GUI/#gui","text":"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.","title":"GUI"},{"location":"functions/GUI/#GUI.about","text":"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 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. \\nIt is based on a physics-based, \" \\ \"one-dimensional (1D), dynamic, two-phase, and 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.\" \\ \"\\n\\nAlphaPEM is firstly developed by Rapha\u00ebl Gass during his PhD thesis from 2021 to 2024, supervised by \" \\ \"Prof. Zhongliang Li, Prof. Rachid Outbib, Prof. Samir Jemei and Prof. Daniel Hissel. \\nIt has been \" \\ \"supported by French National Research Agency via project DEAL (Grant no. ANR-20-CE05-0016-01), the Region \" \\ \"Provence-Alpes-C\u00f4te d\u2019Azur, the EIPHI Graduate School (contract ANR-17-EURE-0002) and the Region \" \\ \"Bourgogne Franche-Comt\u00e9.\" \\ \"\\n\\nIt is related to the following articles:\" \\ \"\\n - Gass et al 2024 J. Electrochem. Soc. https://doi.org/10.1149/1945-7111/ad305a,\" \\ \"\\n - Gass et al 2024 SSRN http://dx.doi.org/10.2139/ssrn.4812343.\" \\ \"\\n\\nMore information can be found in:\" \\ \"\\n - GitHub webpage: https://github.com/gassraphael/AlphaPEM\" \\ \"\\n - Documentation webpage: to do\" \\ \"\\n\\nIf you want to contact me, please send an email to: gassraphael@proton.me.\" # 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)","title":"about"},{"location":"functions/GUI/#GUI.control_current_button","text":"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 ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in GUI.py 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)","title":"control_current_button"},{"location":"functions/GUI/#GUI.create_application","text":"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 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()","title":"create_application"},{"location":"functions/GUI/#GUI.main_frame","text":"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 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) # Create the choice dictionaries choice_operating_conditions = \\ {'Temperature - Tfc (\u00b0C)': {'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 - \u03a6a': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 4, 'label_column': 1}, 'Cathode humidity - \u03a6c': {'value': tk.DoubleVar(operating_conditions_frame), 'label_row': 4, 'label_column': 3}} choice_accessible_parameters = \\ {'GDL thickness - Hgdl (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 1}, 'CL thickness - Hcl (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 3}, 'Membrane thickness - Hmem (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 1, 'label_column': 5}, 'GC thickness - Hgc (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 1}, 'GC width - Wgc (\u00b5m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 3}, 'GC cumulated length - Lgc (m)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 2, 'label_column': 5}, 'Active area - Aact (cm\u00b2)': {'value': tk.DoubleVar(accessible_parameters_frame), 'label_row': 3, 'label_column': 1}} choice_undetermined_parameters = \\ {'GDL porosity - \u03b5_gdl': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.6), 'label_row': 0, 'label_column': 1}, 'Ionomer volume fraction\\n- \u03b5_mc': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.25), 'label_row': 0, 'label_column': 3}, 'Tortuosity - \u03c4': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.5), 'label_row': 0, 'label_column': 5}, 'Compression ratio - \u03b5_c': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.2), 'label_row': 1, 'label_column': 1}, 'Capillary exponent - e': {'value': tk.IntVar(undetermined_parameters_frame, 4), 'label_row': 1, 'label_column': 3}, 'Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.0), 'label_row': 1, 'label_column': 5}, 'Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)': {'value': tk.DoubleVar(undetermined_parameters_frame, 3.0), 'label_row': 2, 'label_column': 1}, 'Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))': {'value': tk.DoubleVar(undetermined_parameters_frame, 1.0), 'label_row': 2, 'label_column': 3}, 'Overpotential correction\\nexponent - \u03ba_c': {'value': tk.DoubleVar(undetermined_parameters_frame, 2.0), 'label_row': 2, 'label_column': 5}, 'Limit liquid saturation\\ncoefficient - a_slim': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.05), 'label_row': 3, 'label_column': 1}, 'Limit liquid saturation\\ncoefficient - b_slim': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.1), 'label_row': 3, 'label_column': 3}, 'Limit liquid saturation\\ncoefficient - a_switch': {'value': tk.DoubleVar(undetermined_parameters_frame, 0.7), 'label_row': 3, 'label_column': 5}, 'Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)': {'value': tk.DoubleVar(undetermined_parameters_frame, 20), 'label_row': 4, 'label_column': 1}} choice_current_density_parameters = \\ {'Initial time - t0_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 0), 'label_row': 0, 'label_column': 1}, 'Final time - tf_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 1000), 'label_row': 0, 'label_column': 3}, 'Loading time\\n- \u0394t_load_step (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 50), 'label_row': 0, 'label_column': 5}, 'Initial current density\\n- i_ini_step (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 1, 'label_column': 1}, 'Final current density\\n- i_final_step (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 1.5), 'label_row': 1, 'label_column': 3}, 'Loading time\\n- \u0394t_load_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 30), 'label_row': 2, 'label_column': 1}, 'Breaking time\\n- \u0394t_break_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 30), 'label_row': 2, 'label_column': 3}, 'Initial breaking time\\n- \u0394t_ini_pola (s)': {'value': tk.DoubleVar(current_density_parameters_frame, 60), 'label_row': 2, 'label_column': 5}, 'Maximum current density\\n- i_max_pola (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 3, 'label_column': 1}, 'Current density step\\n- \u0394i_pola (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.1), 'label_row': 3, 'label_column': 3}, 'Static current\\n- i_EIS (A/cm\u00b2)': {'value': tk.DoubleVar(current_density_parameters_frame, 0.5), 'label_row': 4, 'label_column': 1}, 'Current ratio\\n- ratio_EIS (%)': {'value': tk.DoubleVar(current_density_parameters_frame, 5), 'label_row': 4, 'label_column': 3}, 'Number of points\\ncalculated - nb_points_EIS': {'value': tk.IntVar(current_density_parameters_frame, 50), 'label_row': 4, 'label_column': 5}, 'Power of the\\ninitial frequency\\n- f_power_min_EIS': {'value': tk.IntVar(current_density_parameters_frame, -3), 'label_row': 5, 'label_column': 1}, 'Power of the\\nfinal frequency\\n- f_power_max_EIS': {'value': tk.IntVar(current_density_parameters_frame, 5), 'label_row': 5, 'label_column': 3}, 'Number of frequencies\\ntested - nb_f_EIS': {'value': tk.IntVar(current_density_parameters_frame, 60), 'label_row': 5, 'label_column': 5}} choice_computing_parameters = \\ {'Time for dynamic\\ndisplay - \u0394t_dyn_step (s)': {'value': tk.DoubleVar(computing_parameters_frame, 10), '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- \u0394t_purge (s)': {'value': tk.DoubleVar(computing_parameters_frame, 15), 'label_row': 0, 'label_column': 5}, 'Maximum time step\\n- max_step (s)': {'value': tk.DoubleVar(computing_parameters_frame, 0.1), 'label_row': 1, 'label_column': 1}, 'Number of GDL nodes - n_gdl': {'value': tk.IntVar(computing_parameters_frame, 10), 'label_row': 1, '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}, 'type_control': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 2}, 'type_purge': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 3}, 'type_display': {'value': tk.IntVar(model_possibilities_frame, 1), 'label_row': 4}, 'type_plot': {'value': tk.IntVar(model_possibilities_frame, 0), 'label_row': 5}} # 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)', 'Linhao Fan (2010)', 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=6, 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=6, 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=6, column=4, padx=10, pady=20) # About button ttk.Button(model_possibilities_frame, text='About', style='Black.TButton', command=about) \\ .grid(row=6, 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)","title":"main_frame"},{"location":"functions/GUI/#GUI.show_current_button","text":"This function determines the action to be performed based on the button_type. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in GUI.py 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. Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, Aact, Hgdl, Hcl, Hmem, Hgc, Wgc, Lgc, epsilon_gdl, \\ epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, t_step, \\ i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, t_purge, delta_t_purge, max_step, n_gdl, \\ type_fuel_cell, 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) if current_button == 0: type_current = \"step\" current_density = step_current launch_AlphaPEM_for_step_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) if current_button == 1: type_current = \"polarization\" current_density = polarization_current launch_AlphaPEM_for_polarization_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) if current_button == 2: type_current = \"EIS\" current_density = EIS_current launch_AlphaPEM_for_EIS_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot)","title":"show_current_button"},{"location":"functions/GUI/#GUI.toggle_info","text":"Toggles the visibility of the given frame and updates the scroll region of the given canvas. Parameters: frame ( Frame ) \u2013 The frame to show or hide. show_info ( BooleanVar ) \u2013 A boolean variable to track the current visibility state. canvas ( Canvas ) \u2013 The canvas to update the scroll region. Source code in GUI.py 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'))","title":"toggle_info"},{"location":"functions/main/","text":"main This file is designated for executing the AlphaPEM software package. Most of it should remain unaltered for regular program usage. In the section \"AlphaPEM settings\", users can select various preconfigured configurations for execution: the fuel cell, current density, auxiliary system, control strategy, purge, display and plot used. Adjustments to these configurations can be made within setting.py or current_densities.py and their associated files.","title":"Main"},{"location":"functions/main/#main","text":"This file is designated for executing the AlphaPEM software package. Most of it should remain unaltered for regular program usage. In the section \"AlphaPEM settings\", users can select various preconfigured configurations for execution: the fuel cell, current density, auxiliary system, control strategy, purge, display and plot used. Adjustments to these configurations can be made within setting.py or current_densities.py and their associated files.","title":"main"},{"location":"functions/calibration/experimental_values/","text":"Experimental values This file is designated for executing the AlphaPEM software package. plot_experimental_polarisation_curve(type_fuel_cell, i_fc_t, U_exp_t, ax) This function plots the experimental polarisation curve on the same graph as the model results. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. i_fc_t ( ndarray ) \u2013 Current density values. U_exp_t ( ndarray ) \u2013 Experimental values of the voltage. ax ( Axes ) \u2013 Axes object on which the experimental data is plotted. Source code in calibration/experimental_values.py def plot_experimental_polarisation_curve(type_fuel_cell, i_fc_t, U_exp_t, ax): \"\"\" This function plots the experimental polarisation curve on the same graph as the model results. Parameters ---------- type_fuel_cell : str Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. i_fc_t : numpy.ndarray Current density values. U_exp_t : numpy.ndarray Experimental values of the voltage. ax : matplotlib.axes.Axes Axes object on which the experimental data is plotted. \"\"\" if type_fuel_cell == \"EH-31_1.5\": # at 1.5 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"s\", color=\"black\", label=\"Exp. - P = 1.5 bar\") elif type_fuel_cell == \"EH-31_2.0\": # at 2.0 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"o\", color=\"black\", label=\"Exp. - P = 2.0 bar\") elif type_fuel_cell == \"EH-31_2.25\": # at 2.25 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"^\", color=\"black\", label=\"Exp. - P = 2.25 bar\") elif type_fuel_cell == \"EH-31_2.5\": # at 2.5 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=(5, 1), color=\"black\", label=\"Exp. - P = 2.5 bar\") elif type_fuel_cell == \"BX_1.0\": # at 1.0 atm ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"^\", color=\"black\", label=\"Exp. - P = 1.0 atm\") elif type_fuel_cell == \"BX_1.35\": # at 1.35 atm ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"s\", color=\"black\", label=\"Exp. - P = 1.35 atm\") elif type_fuel_cell == \"LF\": ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"s\", color=\"black\", label=\"Experimental data\") ax.legend(loc='best', markerscale=0.5) pola_exp_values(type_fuel_cell) This function returns the experimental values of polarisation curves made on different fuel cells at different operating conditions. The experimental values are used to compare the model results with the experimental data. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. Returns: i_exp_t ( ndarray ) \u2013 Experimental values of the current density. U_exp_t ( ndarray ) \u2013 Experimental values of the voltage. Source code in calibration/experimental_values.py def pola_exp_values(type_fuel_cell): \"\"\" This function returns the experimental values of polarisation curves made on different fuel cells at different operating conditions. The experimental values are used to compare the model results with the experimental data. Parameters ---------- type_fuel_cell : str Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. Returns ------- i_exp_t : numpy.ndarray Experimental values of the current density. U_exp_t : numpy.ndarray Experimental values of the voltage. \"\"\" if type_fuel_cell == \"EH-31_1.5\": # at 1.5 bar # Current density i_exp_t = np.zeros(37) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.050, 0.068, 0.089, 0.110, 0.147 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.185, 0.233, 0.293, 0.352, 0.395 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.455, 0.510, 0.556, 0.620, 0.672 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.738, 0.799, 0.850, 0.892, 0.942 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 1.039, 1.139, 1.212, 1.269, 1.360 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.432, 1.525, 1.604, 1.683, 1.765 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.878, 1.966, 2.050, 2.109, 2.151 i_exp_t[35], i_exp_t[36] = 2.188, 2.246 # Voltage U_exp_t = np.zeros(37) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.882, 0.865, 0.850, 0.834 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.823, 0.811, 0.794, 0.781, 0.772 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.761, 0.752, 0.745, 0.735, 0.728 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.719, 0.712, 0.706, 0.700, 0.694 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.681, 0.668, 0.660, 0.653, 0.641 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.634, 0.622, 0.610, 0.599, 0.586 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.570, 0.556, 0.540, 0.530, 0.521 U_exp_t[35], U_exp_t[36] = 0.513, 0.500 elif type_fuel_cell == \"EH-31_2.0\": # at 2.0 bar # Current density i_exp_t = np.zeros(49) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.050, 0.057, 0.079, 0.106, 0.135 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.171, 0.206, 0.242, 0.302, 0.346 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.395, 0.434, 0.476, 0.531, 0.570 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.623, 0.681, 0.731, 0.779, 0.822 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.868, 0.930, 0.976, 1.031, 1.090 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.134, 1.205, 1.242, 1.312, 1.358 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.403, 1.453, 1.501, 1.569, 1.634, i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.725, 1.786, 1.857, 1.924, 1.979 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.050, 2.125, 2.168, 2.214, 2.258 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48] = 2.308, 2.348, 2.413, 2.459 # Voltage U_exp_t = np.zeros(49) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.889, 0.874, 0.860, 0.853 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.845, 0.837, 0.830, 0.817, 0.808 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.800, 0.792, 0.786, 0.779, 0.772 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.765, 0.759, 0.753, 0.747, 0.742, U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.737, 0.730, 0.726, 0.720, 0.714, U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.710, 0.702, 0.698, 0.690, 0.684 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.679, 0.673, 0.668, 0.659, 0.651 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.640, 0.631, 0.620, 0.608, 0.598 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.586, 0.573, 0.565, 0.557, 0.548 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48] = 0.537, 0.528, 0.513, 0.502 elif type_fuel_cell == \"EH-31_2.25\": # at 2.25 bar # Current density i_exp_t = np.zeros(54) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.056, 0.095, 0.120, 0.138, 0.160 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.183, 0.218, 0.248, 0.279, 0.315 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.364, 0.409, 0.477, 0.536, 0.594 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.641, 0.697, 0.748, 0.809, 0.866 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.944, 1.011, 1.074, 1.142, 1.193 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.252, 1.322, 1.381, 1.442, 1.496 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.545, 1.599, 1.675, 1.746, 1.827 i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.868, 1.918, 2.004, 2.053, 2.114 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.156, 2.209, 2.257, 2.310, 2.356 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48], i_exp_t[49] = 2.403, 2.468, 2.513, 2.552, 2.600 i_exp_t[50], i_exp_t[51], i_exp_t[52], i_exp_t[53] = 2.636, 2.679, 2.728, 2.794 # Voltage U_exp_t = np.zeros(54) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.894, 0.882, 0.873, 0.867, 0.861 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.854, 0.847, 0.840, 0.834, 0.827 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.819, 0.812, 0.801, 0.793, 0.786 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.781, 0.775, 0.771, 0.764, 0.759 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.751, 0.746, 0.740, 0.734, 0.728 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.723, 0.715, 0.709, 0.703, 0.698 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.692, 0.686, 0.678, 0.670, 0.660 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.654, 0.647, 0.635, 0.628, 0.618 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.613, 0.604, 0.596, 0.587, 0.580 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48], U_exp_t[49] = 0.570, 0.559, 0.551, 0.545, 0.536 U_exp_t[50], U_exp_t[51], U_exp_t[52], U_exp_t[53] = 0.528, 0.520, 0.511, 0.497 elif type_fuel_cell == \"EH-31_2.5\": # at 2.5 bar # Current density i_exp_t = np.zeros(56) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.057, 0.070, 0.082, 0.101, 0.127 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.145, 0.168, 0.200, 0.234, 0.267 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.296, 0.331, 0.355, 0.388, 0.423 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.467, 0.527, 0.577, 0.632, 0.685 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.740, 0.789, 0.845, 0.898, 0.953 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.030, 1.124, 1.192, 1.254, 1.314 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.364, 1.434, 1.514, 1.587, 1.643 i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.707, 1.769, 1.826, 1.892, 1.972 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.040, 2.124, 2.192, 2.265, 2.358 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48], i_exp_t[49] = 2.429, 2.508, 2.572, 2.624, 2.691 i_exp_t[50], i_exp_t[51], i_exp_t[52], i_exp_t[53], i_exp_t[54] = 2.750, 2.822, 2.879, 2.918, 2.956 i_exp_t[55] = 2.988 # Voltage U_exp_t = np.zeros(56) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.892, 0.884, 0.875, 0.866 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.861, 0.856, 0.850, 0.845, 0.840 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.835, 0.829, 0.824, 0.820, 0.814 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.807, 0.800, 0.793, 0.787, 0.783 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.778, 0.775, 0.771, 0.767, 0.763 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.758, 0.750, 0.744, 0.738, 0.732 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.726, 0.719, 0.712, 0.703, 0.697 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.691, 0.685, 0.679, 0.672, 0.663 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.657, 0.648, 0.640, 0.632, 0.621 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48], U_exp_t[49] = 0.610, 0.600, 0.591, 0.584, 0.575 U_exp_t[50], U_exp_t[51], U_exp_t[52], U_exp_t[53], U_exp_t[54] = 0.566, 0.555, 0.546, 0.537, 0.531 U_exp_t[55] = 0.524 elif type_fuel_cell == \"BX_1.0\": # at 1.0 atm # Current density i_exp_t = np.zeros(9) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.00, 0.07, 0.17, 0.31, 0.48 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8] = 0.63, 0.74, 0.88, 0.99 # Voltage U_exp_t = np.zeros(9) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.97, 0.80, 0.75, 0.70, 0.65 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8] = 0.60, 0.55, 0.50, 0.44 elif type_fuel_cell == \"BX_1.35\": # at 1.35 atm # Current density i_exp_t = np.zeros(7) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3] = 0.00, 0.07, 0.23, 0.52 i_exp_t[4], i_exp_t[5], i_exp_t[6] = 0.86, 1.13, 1.35 # Voltage U_exp_t = np.zeros(7) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3] = 0.94, 0.80, 0.75, 0.70 U_exp_t[4], U_exp_t[5], U_exp_t[6] = 0.65, 0.60, 0.55 elif type_fuel_cell == \"LF\": # Current density i_exp_t = np.zeros(13) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.00, 0.04, 0.08, 0.16, 0.25 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.32, 0.39, 0.48, 0.64, 0.80 i_exp_t[10], i_exp_t[11], i_exp_t[12] = 1.00, 1.20, 1.40 # Voltage U_exp_t = np.zeros(13) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.98, 0.87, 0.84, 0.80, 0.77 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.74, 0.72, 0.69, 0.65, 0.60 U_exp_t[10], U_exp_t[11], U_exp_t[12] = 0.54, 0.46, 0.32 return i_exp_t, U_exp_t","title":"Experimental values"},{"location":"functions/calibration/experimental_values/#experimental-values","text":"This file is designated for executing the AlphaPEM software package.","title":"Experimental values"},{"location":"functions/calibration/experimental_values/#calibration.experimental_values.plot_experimental_polarisation_curve","text":"This function plots the experimental polarisation curve on the same graph as the model results. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. i_fc_t ( ndarray ) \u2013 Current density values. U_exp_t ( ndarray ) \u2013 Experimental values of the voltage. ax ( Axes ) \u2013 Axes object on which the experimental data is plotted. Source code in calibration/experimental_values.py def plot_experimental_polarisation_curve(type_fuel_cell, i_fc_t, U_exp_t, ax): \"\"\" This function plots the experimental polarisation curve on the same graph as the model results. Parameters ---------- type_fuel_cell : str Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. i_fc_t : numpy.ndarray Current density values. U_exp_t : numpy.ndarray Experimental values of the voltage. ax : matplotlib.axes.Axes Axes object on which the experimental data is plotted. \"\"\" if type_fuel_cell == \"EH-31_1.5\": # at 1.5 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"s\", color=\"black\", label=\"Exp. - P = 1.5 bar\") elif type_fuel_cell == \"EH-31_2.0\": # at 2.0 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"o\", color=\"black\", label=\"Exp. - P = 2.0 bar\") elif type_fuel_cell == \"EH-31_2.25\": # at 2.25 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=\"^\", color=\"black\", label=\"Exp. - P = 2.25 bar\") elif type_fuel_cell == \"EH-31_2.5\": # at 2.5 bar ax.scatter(i_fc_t, U_exp_t, linewidths=1.5, marker=(5, 1), color=\"black\", label=\"Exp. - P = 2.5 bar\") elif type_fuel_cell == \"BX_1.0\": # at 1.0 atm ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"^\", color=\"black\", label=\"Exp. - P = 1.0 atm\") elif type_fuel_cell == \"BX_1.35\": # at 1.35 atm ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"s\", color=\"black\", label=\"Exp. - P = 1.35 atm\") elif type_fuel_cell == \"LF\": ax.scatter(i_fc_t, U_exp_t, linewidths=3.5, marker=\"s\", color=\"black\", label=\"Experimental data\") ax.legend(loc='best', markerscale=0.5)","title":"plot_experimental_polarisation_curve"},{"location":"functions/calibration/experimental_values/#calibration.experimental_values.pola_exp_values","text":"This function returns the experimental values of polarisation curves made on different fuel cells at different operating conditions. The experimental values are used to compare the model results with the experimental data. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. Returns: i_exp_t ( ndarray ) \u2013 Experimental values of the current density. U_exp_t ( ndarray ) \u2013 Experimental values of the voltage. Source code in calibration/experimental_values.py def pola_exp_values(type_fuel_cell): \"\"\" This function returns the experimental values of polarisation curves made on different fuel cells at different operating conditions. The experimental values are used to compare the model results with the experimental data. Parameters ---------- type_fuel_cell : str Type of fuel cell used in the model. This parameter includes the fuel cell used in the model and the corresponding operating conditions. Returns ------- i_exp_t : numpy.ndarray Experimental values of the current density. U_exp_t : numpy.ndarray Experimental values of the voltage. \"\"\" if type_fuel_cell == \"EH-31_1.5\": # at 1.5 bar # Current density i_exp_t = np.zeros(37) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.050, 0.068, 0.089, 0.110, 0.147 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.185, 0.233, 0.293, 0.352, 0.395 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.455, 0.510, 0.556, 0.620, 0.672 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.738, 0.799, 0.850, 0.892, 0.942 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 1.039, 1.139, 1.212, 1.269, 1.360 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.432, 1.525, 1.604, 1.683, 1.765 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.878, 1.966, 2.050, 2.109, 2.151 i_exp_t[35], i_exp_t[36] = 2.188, 2.246 # Voltage U_exp_t = np.zeros(37) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.882, 0.865, 0.850, 0.834 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.823, 0.811, 0.794, 0.781, 0.772 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.761, 0.752, 0.745, 0.735, 0.728 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.719, 0.712, 0.706, 0.700, 0.694 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.681, 0.668, 0.660, 0.653, 0.641 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.634, 0.622, 0.610, 0.599, 0.586 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.570, 0.556, 0.540, 0.530, 0.521 U_exp_t[35], U_exp_t[36] = 0.513, 0.500 elif type_fuel_cell == \"EH-31_2.0\": # at 2.0 bar # Current density i_exp_t = np.zeros(49) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.050, 0.057, 0.079, 0.106, 0.135 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.171, 0.206, 0.242, 0.302, 0.346 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.395, 0.434, 0.476, 0.531, 0.570 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.623, 0.681, 0.731, 0.779, 0.822 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.868, 0.930, 0.976, 1.031, 1.090 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.134, 1.205, 1.242, 1.312, 1.358 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.403, 1.453, 1.501, 1.569, 1.634, i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.725, 1.786, 1.857, 1.924, 1.979 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.050, 2.125, 2.168, 2.214, 2.258 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48] = 2.308, 2.348, 2.413, 2.459 # Voltage U_exp_t = np.zeros(49) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.889, 0.874, 0.860, 0.853 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.845, 0.837, 0.830, 0.817, 0.808 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.800, 0.792, 0.786, 0.779, 0.772 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.765, 0.759, 0.753, 0.747, 0.742, U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.737, 0.730, 0.726, 0.720, 0.714, U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.710, 0.702, 0.698, 0.690, 0.684 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.679, 0.673, 0.668, 0.659, 0.651 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.640, 0.631, 0.620, 0.608, 0.598 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.586, 0.573, 0.565, 0.557, 0.548 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48] = 0.537, 0.528, 0.513, 0.502 elif type_fuel_cell == \"EH-31_2.25\": # at 2.25 bar # Current density i_exp_t = np.zeros(54) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.056, 0.095, 0.120, 0.138, 0.160 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.183, 0.218, 0.248, 0.279, 0.315 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.364, 0.409, 0.477, 0.536, 0.594 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.641, 0.697, 0.748, 0.809, 0.866 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.944, 1.011, 1.074, 1.142, 1.193 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.252, 1.322, 1.381, 1.442, 1.496 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.545, 1.599, 1.675, 1.746, 1.827 i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.868, 1.918, 2.004, 2.053, 2.114 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.156, 2.209, 2.257, 2.310, 2.356 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48], i_exp_t[49] = 2.403, 2.468, 2.513, 2.552, 2.600 i_exp_t[50], i_exp_t[51], i_exp_t[52], i_exp_t[53] = 2.636, 2.679, 2.728, 2.794 # Voltage U_exp_t = np.zeros(54) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.894, 0.882, 0.873, 0.867, 0.861 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.854, 0.847, 0.840, 0.834, 0.827 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.819, 0.812, 0.801, 0.793, 0.786 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.781, 0.775, 0.771, 0.764, 0.759 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.751, 0.746, 0.740, 0.734, 0.728 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.723, 0.715, 0.709, 0.703, 0.698 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.692, 0.686, 0.678, 0.670, 0.660 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.654, 0.647, 0.635, 0.628, 0.618 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.613, 0.604, 0.596, 0.587, 0.580 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48], U_exp_t[49] = 0.570, 0.559, 0.551, 0.545, 0.536 U_exp_t[50], U_exp_t[51], U_exp_t[52], U_exp_t[53] = 0.528, 0.520, 0.511, 0.497 elif type_fuel_cell == \"EH-31_2.5\": # at 2.5 bar # Current density i_exp_t = np.zeros(56) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.057, 0.070, 0.082, 0.101, 0.127 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.145, 0.168, 0.200, 0.234, 0.267 i_exp_t[10], i_exp_t[11], i_exp_t[12], i_exp_t[13], i_exp_t[14] = 0.296, 0.331, 0.355, 0.388, 0.423 i_exp_t[15], i_exp_t[16], i_exp_t[17], i_exp_t[18], i_exp_t[19] = 0.467, 0.527, 0.577, 0.632, 0.685 i_exp_t[20], i_exp_t[21], i_exp_t[22], i_exp_t[23], i_exp_t[24] = 0.740, 0.789, 0.845, 0.898, 0.953 i_exp_t[25], i_exp_t[26], i_exp_t[27], i_exp_t[28], i_exp_t[29] = 1.030, 1.124, 1.192, 1.254, 1.314 i_exp_t[30], i_exp_t[31], i_exp_t[32], i_exp_t[33], i_exp_t[34] = 1.364, 1.434, 1.514, 1.587, 1.643 i_exp_t[35], i_exp_t[36], i_exp_t[37], i_exp_t[38], i_exp_t[39] = 1.707, 1.769, 1.826, 1.892, 1.972 i_exp_t[40], i_exp_t[41], i_exp_t[42], i_exp_t[43], i_exp_t[44] = 2.040, 2.124, 2.192, 2.265, 2.358 i_exp_t[45], i_exp_t[46], i_exp_t[47], i_exp_t[48], i_exp_t[49] = 2.429, 2.508, 2.572, 2.624, 2.691 i_exp_t[50], i_exp_t[51], i_exp_t[52], i_exp_t[53], i_exp_t[54] = 2.750, 2.822, 2.879, 2.918, 2.956 i_exp_t[55] = 2.988 # Voltage U_exp_t = np.zeros(56) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.900, 0.892, 0.884, 0.875, 0.866 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.861, 0.856, 0.850, 0.845, 0.840 U_exp_t[10], U_exp_t[11], U_exp_t[12], U_exp_t[13], U_exp_t[14] = 0.835, 0.829, 0.824, 0.820, 0.814 U_exp_t[15], U_exp_t[16], U_exp_t[17], U_exp_t[18], U_exp_t[19] = 0.807, 0.800, 0.793, 0.787, 0.783 U_exp_t[20], U_exp_t[21], U_exp_t[22], U_exp_t[23], U_exp_t[24] = 0.778, 0.775, 0.771, 0.767, 0.763 U_exp_t[25], U_exp_t[26], U_exp_t[27], U_exp_t[28], U_exp_t[29] = 0.758, 0.750, 0.744, 0.738, 0.732 U_exp_t[30], U_exp_t[31], U_exp_t[32], U_exp_t[33], U_exp_t[34] = 0.726, 0.719, 0.712, 0.703, 0.697 U_exp_t[35], U_exp_t[36], U_exp_t[37], U_exp_t[38], U_exp_t[39] = 0.691, 0.685, 0.679, 0.672, 0.663 U_exp_t[40], U_exp_t[41], U_exp_t[42], U_exp_t[43], U_exp_t[44] = 0.657, 0.648, 0.640, 0.632, 0.621 U_exp_t[45], U_exp_t[46], U_exp_t[47], U_exp_t[48], U_exp_t[49] = 0.610, 0.600, 0.591, 0.584, 0.575 U_exp_t[50], U_exp_t[51], U_exp_t[52], U_exp_t[53], U_exp_t[54] = 0.566, 0.555, 0.546, 0.537, 0.531 U_exp_t[55] = 0.524 elif type_fuel_cell == \"BX_1.0\": # at 1.0 atm # Current density i_exp_t = np.zeros(9) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.00, 0.07, 0.17, 0.31, 0.48 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8] = 0.63, 0.74, 0.88, 0.99 # Voltage U_exp_t = np.zeros(9) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.97, 0.80, 0.75, 0.70, 0.65 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8] = 0.60, 0.55, 0.50, 0.44 elif type_fuel_cell == \"BX_1.35\": # at 1.35 atm # Current density i_exp_t = np.zeros(7) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3] = 0.00, 0.07, 0.23, 0.52 i_exp_t[4], i_exp_t[5], i_exp_t[6] = 0.86, 1.13, 1.35 # Voltage U_exp_t = np.zeros(7) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3] = 0.94, 0.80, 0.75, 0.70 U_exp_t[4], U_exp_t[5], U_exp_t[6] = 0.65, 0.60, 0.55 elif type_fuel_cell == \"LF\": # Current density i_exp_t = np.zeros(13) i_exp_t[0], i_exp_t[1], i_exp_t[2], i_exp_t[3], i_exp_t[4] = 0.00, 0.04, 0.08, 0.16, 0.25 i_exp_t[5], i_exp_t[6], i_exp_t[7], i_exp_t[8], i_exp_t[9] = 0.32, 0.39, 0.48, 0.64, 0.80 i_exp_t[10], i_exp_t[11], i_exp_t[12] = 1.00, 1.20, 1.40 # Voltage U_exp_t = np.zeros(13) U_exp_t[0], U_exp_t[1], U_exp_t[2], U_exp_t[3], U_exp_t[4] = 0.98, 0.87, 0.84, 0.80, 0.77 U_exp_t[5], U_exp_t[6], U_exp_t[7], U_exp_t[8], U_exp_t[9] = 0.74, 0.72, 0.69, 0.65, 0.60 U_exp_t[10], U_exp_t[11], U_exp_t[12] = 0.54, 0.46, 0.32 return i_exp_t, U_exp_t","title":"pola_exp_values"},{"location":"functions/calibration/parameter_calibration/","text":"Parameter Calibration This file is designated for executing the undetermined parameters' calibration. Most of it should remain unaltered for regular program usage. Users can select here the fuel cell to calibrate, along with the undetermined parameters to modify, and the parameters for the Genetic Algorithm. The experimental fuel cell data are stored in the files calibration_modules.py and experimental_values.py. The parameters employed for the Genetic Algorithm here have proven to be effective, though not necessarily optimal.","title":"Parameter calibration"},{"location":"functions/calibration/parameter_calibration/#parameter-calibration","text":"This file is designated for executing the undetermined parameters' calibration. Most of it should remain unaltered for regular program usage. Users can select here the fuel cell to calibrate, along with the undetermined parameters to modify, and the parameters for the Genetic Algorithm. The experimental fuel cell data are stored in the files calibration_modules.py and experimental_values.py. The parameters employed for the Genetic Algorithm here have proven to be effective, though not necessarily optimal.","title":"Parameter Calibration"},{"location":"functions/configuration/current_densities/","text":"Current densities This file contains the functions that generate the current densities for the simulation. EIS_current(t, parameters) Represents a current density used for creating an EIS curve and Bode diagrams. The current density is first equilibrated at i_EIS A.m-2 from 0 to t0_EIS seconds using a step increase. Then, a sinusoidal perturbation is added to the current density. This perturbation has an amplitude of (ratio_EIS * i_EIS) A.m-2 and a frequency of f[n_inf] Hz. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The polarization current density at time t. Source code in configuration/current_densities.py def EIS_current(t, parameters): \"\"\" Represents a current density used for creating an EIS curve and Bode diagrams. The current density is first equilibrated at i_EIS A.m-2 from 0 to t0_EIS seconds using a step increase. Then, a sinusoidal perturbation is added to the current density. This perturbation has an amplitude of (ratio_EIS * i_EIS) A.m-2 and a frequency of f[n_inf] Hz. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The polarization current density at time t. \"\"\" # Initialisation i_EIS, ratio_EIS = parameters['i_EIS'], parameters['ratio_EIS'] # (A/m\u00b2, ). i_EIS is the current for which a # ratio_EIS perturbation is added. t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = parameters['t_EIS'] # It is the initial # EIS time after stack equilibrium, a list of time parameters which gives the beginning of each frequency # change, the final time, a list of time parameters which gives the estimated time for reaching equilibrium # at each frequency, and a list of time parameters which gives the estimated time for measuring the voltage # response at each frequency. f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = parameters['f_EIS'] # It is the power of the initial # frequency: f_min_EIS = 10**f_power_min_EIS, the power of the final frequency, the number of frequencies # tested and the number of points calculated per specific period. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is a list of all the frequency tested, # ranged logarithmically. # Current density for the EIS curve if t < t0_EIS: delta_t_ini = t0_EIS / 4 # s. It is the required time for elevating i_fc from 0 to i_EIS without starving the # cell. i_fc = i_EIS * (1.0 + np.tanh(4 * (t - 2 * (delta_t_ini / 2)) / delta_t_ini)) / 2 else: n_inf = np.where(t_new_start_EIS <= t)[0][-1] # It is the number of frequency changes which has been made so far. i_disruption = (ratio_EIS * i_EIS) * np.cos(2 * np.pi * f[n_inf] * t) i_fc = i_EIS + i_disruption return i_fc polarization_current(t, parameters) Represents a current density used for creating a polarization curve. Starting from 0, the current density increases by the value of delta_i_pola every delta_t, following C\u221e step current increments, until it reaches i_max_pola. Each increment lasts for delta_t_load_pola seconds. After each increment, there is a pause of delta_t_break_pola seconds to allow the stack to reach equilibrium. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The polarization current density at time t. Source code in configuration/current_densities.py def polarization_current(t, parameters): \"\"\"Represents a current density used for creating a polarization curve. Starting from 0, the current density increases by the value of delta_i_pola every delta_t, following C\u221e step current increments, until it reaches i_max_pola. Each increment lasts for delta_t_load_pola seconds. After each increment, there is a pause of delta_t_break_pola seconds to allow the stack to reach equilibrium. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The polarization current density at time t. \"\"\" # Initialisation delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = parameters['delta_pola'] # (s, s, A.m-2, s). It is the loading time, the breaking time, the current density # step, and the initial breaking time. i_max_pola = parameters['i_max_pola'] # A.m-2. It is the maximum current density for the polarization curve. delta_t = delta_t_load_pola + delta_t_break_pola # s. It is the time of one load. tf = delta_t_ini_pola + int(i_max_pola / delta_i_pola + 1) * delta_t # s. It is the duration of this polarization current. n = int(tf / delta_t) # . It is the number of loads made for this polarization current. # Current density for the polarization curve i_fc = 0 # A.m-2. Initialisation of the current density. if t < delta_t_ini_pola: # It is the initial break for having homogeneity inside the cell i_fc = 0 # before starting the measurements. else: for i in range(n): t_switch = delta_t * i # The current density value changes around this time. i_fc += delta_i_pola * (1.0 + np.tanh(4 * (t - delta_t_ini_pola - delta_t - t_switch - (delta_t_load_pola / 2)) / delta_t_load_pola)) / 2 return i_fc step_current(t, parameters) Represents a step change in current density. The current starts at 0 and smoothly stabilizes at i_ini_step A.m-2 in delta_t_load seconds. Around t_switch seconds, the current increases smoothly and stabilizes at i_final_step A.m-2 in delta_t_load seconds. This is a C\u221e function, which is advantageous for enhancing the overall stability of the results. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The step current density at time t. Source code in configuration/current_densities.py def step_current(t, parameters): \"\"\"Represents a step change in current density. The current starts at 0 and smoothly stabilizes at i_ini_step A.m-2 in delta_t_load seconds. Around t_switch seconds, the current increases smoothly and stabilizes at i_final_step A.m-2 in delta_t_load seconds. This is a C\u221e function, which is advantageous for enhancing the overall stability of the results. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The step current density at time t. \"\"\" # Initialisation t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = parameters['t_step'] # (s, s, s, s). It is the initial, final, # loading and dynamic time for display. i_ini_step, i_final_step = parameters['i_step'] # (A.m-2, A.m-2). It is the initial and final current density values. t_switch = tf_step // 2 # The current density value changes around this time. # Step current density i_fc = i_ini_step * (1.0 + np.tanh(4 * (t - 2 * (delta_t_load_step / 2)) / delta_t_load_step)) / 2 + \\ + (i_final_step - i_ini_step) * (1.0 + np.tanh(4 * (t - t_switch - (delta_t_load_step / 2)) / delta_t_load_step)) / 2 return i_fc","title":"Current densities"},{"location":"functions/configuration/current_densities/#current-densities","text":"This file contains the functions that generate the current densities for the simulation.","title":"Current densities"},{"location":"functions/configuration/current_densities/#configuration.current_densities.EIS_current","text":"Represents a current density used for creating an EIS curve and Bode diagrams. The current density is first equilibrated at i_EIS A.m-2 from 0 to t0_EIS seconds using a step increase. Then, a sinusoidal perturbation is added to the current density. This perturbation has an amplitude of (ratio_EIS * i_EIS) A.m-2 and a frequency of f[n_inf] Hz. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The polarization current density at time t. Source code in configuration/current_densities.py def EIS_current(t, parameters): \"\"\" Represents a current density used for creating an EIS curve and Bode diagrams. The current density is first equilibrated at i_EIS A.m-2 from 0 to t0_EIS seconds using a step increase. Then, a sinusoidal perturbation is added to the current density. This perturbation has an amplitude of (ratio_EIS * i_EIS) A.m-2 and a frequency of f[n_inf] Hz. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The polarization current density at time t. \"\"\" # Initialisation i_EIS, ratio_EIS = parameters['i_EIS'], parameters['ratio_EIS'] # (A/m\u00b2, ). i_EIS is the current for which a # ratio_EIS perturbation is added. t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = parameters['t_EIS'] # It is the initial # EIS time after stack equilibrium, a list of time parameters which gives the beginning of each frequency # change, the final time, a list of time parameters which gives the estimated time for reaching equilibrium # at each frequency, and a list of time parameters which gives the estimated time for measuring the voltage # response at each frequency. f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = parameters['f_EIS'] # It is the power of the initial # frequency: f_min_EIS = 10**f_power_min_EIS, the power of the final frequency, the number of frequencies # tested and the number of points calculated per specific period. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is a list of all the frequency tested, # ranged logarithmically. # Current density for the EIS curve if t < t0_EIS: delta_t_ini = t0_EIS / 4 # s. It is the required time for elevating i_fc from 0 to i_EIS without starving the # cell. i_fc = i_EIS * (1.0 + np.tanh(4 * (t - 2 * (delta_t_ini / 2)) / delta_t_ini)) / 2 else: n_inf = np.where(t_new_start_EIS <= t)[0][-1] # It is the number of frequency changes which has been made so far. i_disruption = (ratio_EIS * i_EIS) * np.cos(2 * np.pi * f[n_inf] * t) i_fc = i_EIS + i_disruption return i_fc","title":"EIS_current"},{"location":"functions/configuration/current_densities/#configuration.current_densities.polarization_current","text":"Represents a current density used for creating a polarization curve. Starting from 0, the current density increases by the value of delta_i_pola every delta_t, following C\u221e step current increments, until it reaches i_max_pola. Each increment lasts for delta_t_load_pola seconds. After each increment, there is a pause of delta_t_break_pola seconds to allow the stack to reach equilibrium. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The polarization current density at time t. Source code in configuration/current_densities.py def polarization_current(t, parameters): \"\"\"Represents a current density used for creating a polarization curve. Starting from 0, the current density increases by the value of delta_i_pola every delta_t, following C\u221e step current increments, until it reaches i_max_pola. Each increment lasts for delta_t_load_pola seconds. After each increment, there is a pause of delta_t_break_pola seconds to allow the stack to reach equilibrium. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The polarization current density at time t. \"\"\" # Initialisation delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = parameters['delta_pola'] # (s, s, A.m-2, s). It is the loading time, the breaking time, the current density # step, and the initial breaking time. i_max_pola = parameters['i_max_pola'] # A.m-2. It is the maximum current density for the polarization curve. delta_t = delta_t_load_pola + delta_t_break_pola # s. It is the time of one load. tf = delta_t_ini_pola + int(i_max_pola / delta_i_pola + 1) * delta_t # s. It is the duration of this polarization current. n = int(tf / delta_t) # . It is the number of loads made for this polarization current. # Current density for the polarization curve i_fc = 0 # A.m-2. Initialisation of the current density. if t < delta_t_ini_pola: # It is the initial break for having homogeneity inside the cell i_fc = 0 # before starting the measurements. else: for i in range(n): t_switch = delta_t * i # The current density value changes around this time. i_fc += delta_i_pola * (1.0 + np.tanh(4 * (t - delta_t_ini_pola - delta_t - t_switch - (delta_t_load_pola / 2)) / delta_t_load_pola)) / 2 return i_fc","title":"polarization_current"},{"location":"functions/configuration/current_densities/#configuration.current_densities.step_current","text":"Represents a step change in current density. The current starts at 0 and smoothly stabilizes at i_ini_step A.m-2 in delta_t_load seconds. Around t_switch seconds, the current increases smoothly and stabilizes at i_final_step A.m-2 in delta_t_load seconds. This is a C\u221e function, which is advantageous for enhancing the overall stability of the results. Parameters: t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: i_fc : float The step current density at time t. Source code in configuration/current_densities.py def step_current(t, parameters): \"\"\"Represents a step change in current density. The current starts at 0 and smoothly stabilizes at i_ini_step A.m-2 in delta_t_load seconds. Around t_switch seconds, the current increases smoothly and stabilizes at i_final_step A.m-2 in delta_t_load seconds. This is a C\u221e function, which is advantageous for enhancing the overall stability of the results. Parameters: ---------- t : float Time in seconds. parameters : dict A dictionary containing the parameters for the current density function. Returns: ------- i_fc : float The step current density at time t. \"\"\" # Initialisation t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = parameters['t_step'] # (s, s, s, s). It is the initial, final, # loading and dynamic time for display. i_ini_step, i_final_step = parameters['i_step'] # (A.m-2, A.m-2). It is the initial and final current density values. t_switch = tf_step // 2 # The current density value changes around this time. # Step current density i_fc = i_ini_step * (1.0 + np.tanh(4 * (t - 2 * (delta_t_load_step / 2)) / delta_t_load_step)) / 2 + \\ + (i_final_step - i_ini_step) * (1.0 + np.tanh(4 * (t - t_switch - (delta_t_load_step / 2)) / delta_t_load_step)) / 2 return i_fc","title":"step_current"},{"location":"functions/configuration/settings/","text":"Settings This file is used to set the parameters of the fuel cell system. computing_parameters(type_current, Hgdl, Hcl) This function is used to set the computing parameters of the fuel cell system. Parameters: type_current ( str ) \u2013 Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in meters. Hcl ( float ) \u2013 Thickness of the anode or cathode catalyst layer in meters. Returns: max_step ( float ) \u2013 Maximum time step for the resolution of the system of differential equations. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. t_purge ( tuple ) \u2013 Time parameters for purging the system. It is a tuple containing the purge time 'purge_time' in seconds, and the time between two purges 'delta_purge' in seconds. Source code in configuration/settings.py def computing_parameters(type_current, Hgdl, Hcl): \"\"\"This function is used to set the computing parameters of the fuel cell system. Parameters ---------- type_current : str Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Hgdl : float Thickness of the gas diffusion layer in meters. Hcl : float Thickness of the anode or cathode catalyst layer in meters. Returns ------- max_step : float Maximum time step for the resolution of the system of differential equations. n_gdl : int Number of model nodes placed inside each GDL. t_purge : tuple Time parameters for purging the system. It is a tuple containing the purge time 'purge_time' in seconds, and the time between two purges 'delta_purge' in seconds. \"\"\" if type_current == \"polarization\": max_step = 0.1 # Once the undetermined parameters are at their optimal values, this max_step can be used. elif type_current == \"step\": max_step = 0.1 # it is good enough for having graphs without instabilities. else: max_step = 0.1 n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. # A good value is int(Hgdl/Hcl/2), which is usually around 10. t_purge = 0.6, 15 # (s, s). It is the time parameters for purging the system. return max_step, n_gdl, t_purge current_density_parameters(type_current) This function is used to set the parameters of the current density which is imposed to the fuel cell system. Parameters: type_current ( str ) \u2013 Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Returns: t_step ( tuple ) \u2013 Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step' in seconds, final time 'tf_step' in seconds, loading time 'delta_t_load_step' in seconds, and time for dynamic display 'delta_t_dyn_step' in seconds. i_step ( tuple ) \u2013 Current parameters for the step_current density function. It is a tuple containing the initial and final current density values 'i_ini_step' and 'i_final_step', both in A.m-2. delta_pola ( tuple ) \u2013 Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load_pola' in seconds, the breaking time 'delta_t_break_pola' in seconds, the current density step 'delta_i_pola' in A.m-2, and the initial breaking time 'delta_t_ini_pola' in seconds. i_EIS ( float ) \u2013 Parameters for the EIS curve. It is the current for which a perturbation is added. ratio_EIS ( float ) \u2013 Parameters for the EIS curve. It is the ratio of the current for which a perturbation is added. f_EIS ( tuple ) \u2013 Frequency parameters for the EIS_current density function. It is a tuple containing the power of the initial frequency 'f_power_min_EIS' (f_min_EIS = 10**f_power_min_EIS), the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS', and the number of points calculated per specific period 'nb_points_EIS'. t_EIS ( tuple ) \u2013 Time parameters for the EIS_current density function. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS' in seconds, a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS' in seconds, the final time 'tf_EIS' in seconds, a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS' in seconds, and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS' in seconds. current_density ( function ) \u2013 Current density function. Source code in configuration/settings.py def current_density_parameters(type_current): \"\"\"This function is used to set the parameters of the current density which is imposed to the fuel cell system. Parameters ---------- type_current : str Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Returns ------- t_step : tuple Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step' in seconds, final time 'tf_step' in seconds, loading time 'delta_t_load_step' in seconds, and time for dynamic display 'delta_t_dyn_step' in seconds. i_step : tuple Current parameters for the step_current density function. It is a tuple containing the initial and final current density values 'i_ini_step' and 'i_final_step', both in A.m-2. delta_pola : tuple Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load_pola' in seconds, the breaking time 'delta_t_break_pola' in seconds, the current density step 'delta_i_pola' in A.m-2, and the initial breaking time 'delta_t_ini_pola' in seconds. i_EIS : float Parameters for the EIS curve. It is the current for which a perturbation is added. ratio_EIS : float Parameters for the EIS curve. It is the ratio of the current for which a perturbation is added. f_EIS : tuple Frequency parameters for the EIS_current density function. It is a tuple containing the power of the initial frequency 'f_power_min_EIS' (f_min_EIS = 10**f_power_min_EIS), the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS', and the number of points calculated per specific period 'nb_points_EIS'. t_EIS : tuple Time parameters for the EIS_current density function. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS' in seconds, a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS' in seconds, the final time 'tf_EIS' in seconds, a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS' in seconds, and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS' in seconds. current_density : function Current density function. \"\"\" t_step = 0, 1000, 50, 10 # (s, s, s, s). Time parameters for the step_current density function. i_step = 0.5e4, 1.5e4 # (A.m-2, A.m-2). Current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 1 * 60 # (s, s, A.m-2, s). Parameters for the polarization curve. i_EIS, ratio_EIS = 1.0e4, 5/100 # (A/m\u00b2, ). Parameters for the EIS curve. f_EIS = -3, 5, 90, 50 # Frequency parameters for the EIS_current density function. t_EIS = EIS_parameters(f_EIS) # Time parameters for the EIS_current density function. if type_current == \"step\": current_density = step_current # It is the current density function. elif type_current == \"polarization\": current_density = polarization_current # It is the current density function. elif type_current == \"EIS\": current_density = EIS_current # It is the current density function. else: raise ValueError('You have to specify a type_current which is on the list.') return t_step, i_step, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, current_density operating_inputs(type_fuel_cell) This function is used to set the operating inputs of the fuel cell system. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve. Source code in configuration/settings.py def operating_inputs(type_fuel_cell): \"\"\"This function is used to set the operating inputs of the fuel cell system. Parameters ---------- type_fuel_cell : str Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_max_pola : float Maximum current density for the polarization curve. \"\"\" if type_fuel_cell == \"manual_setup\": # Setup which are not stored in \"stored_operating_inputs\". Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. else: # Stored setup in \"stored_operating_inputs\". Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola = stored_operating_inputs(type_fuel_cell) return Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola physical_parameters(type_fuel_cell) This function is used to set the physical parameters of the fuel cell system. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns: Hcl ( float ) \u2013 Thickness of the anode or cathode catalyst layer in meters. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the catalyst layer. tau ( float ) \u2013 Pore structure coefficient. Hmem ( float ) \u2013 Thickness of the membrane in meters. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in meters. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. Hgc ( float ) \u2013 Thickness of the gas channel in meters. Wgc ( float ) \u2013 Width of the gas channel in meters. Lgc ( float ) \u2013 Length of the gas channel in meters. Aact ( float ) \u2013 Active area of the catalyst layer in meters squared. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl ( float ) \u2013 Volumetric double layer capacitance in F.m-3. Source code in configuration/settings.py def physical_parameters(type_fuel_cell): \"\"\"This function is used to set the physical parameters of the fuel cell system. Parameters ---------- type_fuel_cell : str Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns ------- Hcl : float Thickness of the anode or cathode catalyst layer in meters. epsilon_mc : float Volume fraction of ionomer in the catalyst layer. tau : float Pore structure coefficient. Hmem : float Thickness of the membrane in meters. Hgdl : float Thickness of the gas diffusion layer in meters. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_c : float Compression ratio of the GDL. Hgc : float Thickness of the gas channel in meters. Wgc : float Width of the gas channel in meters. Lgc : float Length of the gas channel in meters. Aact : float Active area of the catalyst layer in meters squared. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl : float Volumetric double layer capacitance in F.m-3. \"\"\" if type_fuel_cell == \"manual_setup\": # Setup which are not stored in \"stored_physical_parameters\". # Fuel cell physical parameters: \ud835\udf14 (which are not controllable by the system) # Catalyst layer Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.3949198274842546 # It is the volume fraction of ionomer in the CL. tau = 1.015639135686993 # It is the pore structure coefficient, without units. # Membrane Hmem = 2e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.7011156494971454 # It is the anode/cathode GDL porosity. epsilon_c = 0.27052745219052654 # It is the compression ratio of the GDL. # Gas channel Hgc = 5e-4 # m. It is the thickness of the gas channel. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Interaction parameters between water and PEMFC structure e = 5.0 # It is the capillary exponent # Voltage polarization Re = 5.694464714060734e-07 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 2.787917581303015 # A.m-2. It is the reference exchange current density at the cathode. kappa_co = 29.793535549174077 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.6136446641573106 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0.0555312850726664, 0.10514269908118055, 0.6365424991141914 # It is the limit # liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. else: # Stored setup in \"stored_physical_parameters\". (Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl) = stored_physical_parameters(type_fuel_cell) return (Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl)","title":"Settings"},{"location":"functions/configuration/settings/#settings","text":"This file is used to set the parameters of the fuel cell system.","title":"Settings"},{"location":"functions/configuration/settings/#configuration.settings.computing_parameters","text":"This function is used to set the computing parameters of the fuel cell system. Parameters: type_current ( str ) \u2013 Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in meters. Hcl ( float ) \u2013 Thickness of the anode or cathode catalyst layer in meters. Returns: max_step ( float ) \u2013 Maximum time step for the resolution of the system of differential equations. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. t_purge ( tuple ) \u2013 Time parameters for purging the system. It is a tuple containing the purge time 'purge_time' in seconds, and the time between two purges 'delta_purge' in seconds. Source code in configuration/settings.py def computing_parameters(type_current, Hgdl, Hcl): \"\"\"This function is used to set the computing parameters of the fuel cell system. Parameters ---------- type_current : str Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Hgdl : float Thickness of the gas diffusion layer in meters. Hcl : float Thickness of the anode or cathode catalyst layer in meters. Returns ------- max_step : float Maximum time step for the resolution of the system of differential equations. n_gdl : int Number of model nodes placed inside each GDL. t_purge : tuple Time parameters for purging the system. It is a tuple containing the purge time 'purge_time' in seconds, and the time between two purges 'delta_purge' in seconds. \"\"\" if type_current == \"polarization\": max_step = 0.1 # Once the undetermined parameters are at their optimal values, this max_step can be used. elif type_current == \"step\": max_step = 0.1 # it is good enough for having graphs without instabilities. else: max_step = 0.1 n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. # A good value is int(Hgdl/Hcl/2), which is usually around 10. t_purge = 0.6, 15 # (s, s). It is the time parameters for purging the system. return max_step, n_gdl, t_purge","title":"computing_parameters"},{"location":"functions/configuration/settings/#configuration.settings.current_density_parameters","text":"This function is used to set the parameters of the current density which is imposed to the fuel cell system. Parameters: type_current ( str ) \u2013 Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Returns: t_step ( tuple ) \u2013 Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step' in seconds, final time 'tf_step' in seconds, loading time 'delta_t_load_step' in seconds, and time for dynamic display 'delta_t_dyn_step' in seconds. i_step ( tuple ) \u2013 Current parameters for the step_current density function. It is a tuple containing the initial and final current density values 'i_ini_step' and 'i_final_step', both in A.m-2. delta_pola ( tuple ) \u2013 Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load_pola' in seconds, the breaking time 'delta_t_break_pola' in seconds, the current density step 'delta_i_pola' in A.m-2, and the initial breaking time 'delta_t_ini_pola' in seconds. i_EIS ( float ) \u2013 Parameters for the EIS curve. It is the current for which a perturbation is added. ratio_EIS ( float ) \u2013 Parameters for the EIS curve. It is the ratio of the current for which a perturbation is added. f_EIS ( tuple ) \u2013 Frequency parameters for the EIS_current density function. It is a tuple containing the power of the initial frequency 'f_power_min_EIS' (f_min_EIS = 10**f_power_min_EIS), the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS', and the number of points calculated per specific period 'nb_points_EIS'. t_EIS ( tuple ) \u2013 Time parameters for the EIS_current density function. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS' in seconds, a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS' in seconds, the final time 'tf_EIS' in seconds, a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS' in seconds, and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS' in seconds. current_density ( function ) \u2013 Current density function. Source code in configuration/settings.py def current_density_parameters(type_current): \"\"\"This function is used to set the parameters of the current density which is imposed to the fuel cell system. Parameters ---------- type_current : str Type of current density which is imposed to the fuel cell system. It can be \"step\", \"polarization\" or \"EIS\". Returns ------- t_step : tuple Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step' in seconds, final time 'tf_step' in seconds, loading time 'delta_t_load_step' in seconds, and time for dynamic display 'delta_t_dyn_step' in seconds. i_step : tuple Current parameters for the step_current density function. It is a tuple containing the initial and final current density values 'i_ini_step' and 'i_final_step', both in A.m-2. delta_pola : tuple Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load_pola' in seconds, the breaking time 'delta_t_break_pola' in seconds, the current density step 'delta_i_pola' in A.m-2, and the initial breaking time 'delta_t_ini_pola' in seconds. i_EIS : float Parameters for the EIS curve. It is the current for which a perturbation is added. ratio_EIS : float Parameters for the EIS curve. It is the ratio of the current for which a perturbation is added. f_EIS : tuple Frequency parameters for the EIS_current density function. It is a tuple containing the power of the initial frequency 'f_power_min_EIS' (f_min_EIS = 10**f_power_min_EIS), the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS', and the number of points calculated per specific period 'nb_points_EIS'. t_EIS : tuple Time parameters for the EIS_current density function. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS' in seconds, a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS' in seconds, the final time 'tf_EIS' in seconds, a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS' in seconds, and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS' in seconds. current_density : function Current density function. \"\"\" t_step = 0, 1000, 50, 10 # (s, s, s, s). Time parameters for the step_current density function. i_step = 0.5e4, 1.5e4 # (A.m-2, A.m-2). Current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 1 * 60 # (s, s, A.m-2, s). Parameters for the polarization curve. i_EIS, ratio_EIS = 1.0e4, 5/100 # (A/m\u00b2, ). Parameters for the EIS curve. f_EIS = -3, 5, 90, 50 # Frequency parameters for the EIS_current density function. t_EIS = EIS_parameters(f_EIS) # Time parameters for the EIS_current density function. if type_current == \"step\": current_density = step_current # It is the current density function. elif type_current == \"polarization\": current_density = polarization_current # It is the current density function. elif type_current == \"EIS\": current_density = EIS_current # It is the current density function. else: raise ValueError('You have to specify a type_current which is on the list.') return t_step, i_step, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, current_density","title":"current_density_parameters"},{"location":"functions/configuration/settings/#configuration.settings.operating_inputs","text":"This function is used to set the operating inputs of the fuel cell system. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve. Source code in configuration/settings.py def operating_inputs(type_fuel_cell): \"\"\"This function is used to set the operating inputs of the fuel cell system. Parameters ---------- type_fuel_cell : str Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_max_pola : float Maximum current density for the polarization curve. \"\"\" if type_fuel_cell == \"manual_setup\": # Setup which are not stored in \"stored_operating_inputs\". Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. else: # Stored setup in \"stored_operating_inputs\". Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola = stored_operating_inputs(type_fuel_cell) return Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola","title":"operating_inputs"},{"location":"functions/configuration/settings/#configuration.settings.physical_parameters","text":"This function is used to set the physical parameters of the fuel cell system. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns: Hcl ( float ) \u2013 Thickness of the anode or cathode catalyst layer in meters. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the catalyst layer. tau ( float ) \u2013 Pore structure coefficient. Hmem ( float ) \u2013 Thickness of the membrane in meters. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in meters. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. Hgc ( float ) \u2013 Thickness of the gas channel in meters. Wgc ( float ) \u2013 Width of the gas channel in meters. Lgc ( float ) \u2013 Length of the gas channel in meters. Aact ( float ) \u2013 Active area of the catalyst layer in meters squared. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl ( float ) \u2013 Volumetric double layer capacitance in F.m-3. Source code in configuration/settings.py def physical_parameters(type_fuel_cell): \"\"\"This function is used to set the physical parameters of the fuel cell system. Parameters ---------- type_fuel_cell : str Type of fuel cell system. It can be \"EH-31_1.5\", \"EH-31_2.0\", \"EH-31_2.25\", \"EH-31_2.5\", \"LF\", or \"manual_setup\". Returns ------- Hcl : float Thickness of the anode or cathode catalyst layer in meters. epsilon_mc : float Volume fraction of ionomer in the catalyst layer. tau : float Pore structure coefficient. Hmem : float Thickness of the membrane in meters. Hgdl : float Thickness of the gas diffusion layer in meters. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_c : float Compression ratio of the GDL. Hgc : float Thickness of the gas channel in meters. Wgc : float Width of the gas channel in meters. Lgc : float Length of the gas channel in meters. Aact : float Active area of the catalyst layer in meters squared. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl : float Volumetric double layer capacitance in F.m-3. \"\"\" if type_fuel_cell == \"manual_setup\": # Setup which are not stored in \"stored_physical_parameters\". # Fuel cell physical parameters: \ud835\udf14 (which are not controllable by the system) # Catalyst layer Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.3949198274842546 # It is the volume fraction of ionomer in the CL. tau = 1.015639135686993 # It is the pore structure coefficient, without units. # Membrane Hmem = 2e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.7011156494971454 # It is the anode/cathode GDL porosity. epsilon_c = 0.27052745219052654 # It is the compression ratio of the GDL. # Gas channel Hgc = 5e-4 # m. It is the thickness of the gas channel. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Interaction parameters between water and PEMFC structure e = 5.0 # It is the capillary exponent # Voltage polarization Re = 5.694464714060734e-07 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 2.787917581303015 # A.m-2. It is the reference exchange current density at the cathode. kappa_co = 29.793535549174077 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.6136446641573106 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0.0555312850726664, 0.10514269908118055, 0.6365424991141914 # It is the limit # liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. else: # Stored setup in \"stored_physical_parameters\". (Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl) = stored_physical_parameters(type_fuel_cell) return (Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl)","title":"physical_parameters"},{"location":"functions/model/AlphaPEM/","text":"AlphaPEM Objectives: Create an open-source software package to simulate the PEM fuel cell for control system applications. Authors: Rapha\u00ebl GASS, Zhongliang LI, Rachid OUTBIB, Samir JEMEI and Daniel HISSEL. This file describes the AlphaPEM class, which is a PEM fuel cell system simulator. The model is one-dimensional, dynamic, biphasic, and isothermal. It has been published in the following articles: - Gass et al 2024 J. Electrochem. Soc. https://doi.org/10.1149/1945-7111/ad305a - Gass et al 2024 SSRN http://dx.doi.org/10.2139/ssrn.4812343 AlphaPEM Source code in model/AlphaPEM.py class AlphaPEM: def __init__(self, current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values=None, time_interval=None): \"\"\"Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). initial_variable_values : list, optional Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval : list, optional Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. \"\"\" # Initialize the operating inputs and parameters dictionaries. self.operating_inputs = {'current_density': current_density, 'Tfc': Tfc, 'Pa_des': Pa_des, 'Pc_des': Pc_des, 'Sa': Sa, 'Sc': Sc, 'Phi_a_des': Phi_a_des, 'Phi_c_des': Phi_c_des} self.current_parameters = {'t_step': t_step, 'i_step': i_step, 'delta_pola': delta_pola, 'i_max_pola': i_max_pola, 'i_EIS': i_EIS, 'ratio_EIS': ratio_EIS, 't_EIS': t_EIS, 'f_EIS': f_EIS} self.accessible_physical_parameters = {'Aact': Aact, 'Hgdl': Hgdl, 'Hmem': Hmem, 'Hcl': Hcl, 'Hgc': Hgc, 'Wgc': Wgc, 'Lgc': Lgc} self.undetermined_physical_parameters = {'epsilon_gdl': epsilon_gdl, 'tau': tau, 'epsilon_mc': epsilon_mc, 'epsilon_c': epsilon_c, 'e': e, 'kappa_co': kappa_co, 'Re': Re, 'i0_c_ref': i0_c_ref, 'kappa_c': kappa_c, 'a_slim': a_slim, 'b_slim': b_slim, 'a_switch': a_switch, 'C_scl': C_scl} self.computing_parameters = {'max_step': max_step, 'n_gdl': n_gdl, 't_purge': t_purge, 'type_fuel_cell': type_fuel_cell, 'type_current': type_current, 'type_auxiliary': type_auxiliary, 'type_control': type_control, 'type_purge': type_purge, 'type_display': type_display, 'type_plot': type_plot} self.parameters = {**self.current_parameters, **self.accessible_physical_parameters, **self.undetermined_physical_parameters, **self.computing_parameters} if self.operating_inputs['Pa_des'] < Pext or self.operating_inputs['Pc_des'] < Pext: raise ValueError('The desired pressure is too low. It cannot be lower than the pressure outside the stack.') # Initialize the variables' dictionary. self.solver_variable_names = ['C_v_agc', 'C_v_agdl', 'C_v_acl', 'C_v_ccl', 'C_v_cgdl', 'C_v_cgc', 's_agdl', 's_acl', 's_ccl', 's_cgdl', 'lambda_acl', 'lambda_mem', 'lambda_ccl', 'C_H2_agc', 'C_H2_agdl', 'C_H2_acl', 'C_O2_ccl', 'C_O2_cgdl', 'C_O2_cgc', 'C_N2', 'eta_c', 'Pasm', 'Paem', 'Pcsm', 'Pcem', 'Phi_asm', 'Phi_aem', 'Phi_csm', 'Phi_cem', 'Wcp', 'Wa_inj', 'Wc_inj', 'Abp_a', 'Abp_c'] self.solver_variable_names_extension() # Several points are considered in each GDL and must be inserted into # the solver_variable_names. self.all_variable_names = self.solver_variable_names + ['t', 'Ucell', 'S_sorp_acl', 'S_sorp_ccl'] + \\ ['J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc', 'Phi_a_des', 'Phi_c_des'] self.variables = {key: [] for key in self.all_variable_names} # Initialize the control_variables dictionary. self.control_variables = {'t_control_Phi': self.parameters['t_step'][0], 'Phi_a_des': self.operating_inputs['Phi_a_des'], 'Phi_c_des': self.operating_inputs['Phi_c_des']} # Create the dynamic evolution. # Create time intervals if time_interval is not None: # Initial time interval may be given to the Simulator. self.time_interval = time_interval else: # If not, it is automatically generated. self.time_interval = self._create_time_interval() # Create the initial variable values if initial_variable_values is not None: # Initial variable values may be given to the Simulator. self.initial_variable_values = initial_variable_values else: # If not, they are generated considering an equilibrium at the operating inputs without current. self.initial_variable_values = self._create_initial_variable_values() # Resolution of the system of differential equations. event_negative.terminal = True # Integration is stopped if one of the crucial variables becomes negative. self.sol = solve_ivp(dydt, self.time_interval, self.initial_variable_values, method='BDF', max_step=self.parameters['max_step'], events=event_negative, args=(self.operating_inputs, self.parameters, self.solver_variable_names, self.control_variables)) # Recover the variable values calculated by the solver into the dictionary. self._recovery() # Calculate the cell voltage after computing the internal states of the cell. self.variables[\"Ucell\"].extend(calculate_cell_voltage(self.variables, self.operating_inputs, self.parameters)) def solver_variable_names_extension(self): \"\"\"Several points are considered in each GDL and must be inserted into the solver_variable_names. \"\"\" new_points_location = ['C_v_agdl', 'C_v_cgdl', 's_agdl', 's_cgdl', 'C_H2_agdl', 'C_O2_cgdl'] for variable in new_points_location: index = self.solver_variable_names.index(variable) # Delete the previous points self.solver_variable_names.pop(index) # Increase the number of points self.solver_variable_names[index:index] = [f'{variable}_{i}' for i in range(1, self.parameters['n_gdl'] + 1)] def _create_time_interval(self): \"\"\"Calculate the time intervals for numerical resolution, according to the current chosen, if it is not provided. Returns ------- list Time interval for numerical resolution. It is used when initial_variable_values == None. \"\"\" # Extraction of the parameters t_step, delta_pola, i_max_pola = self.parameters['t_step'], self.parameters['delta_pola'], self.parameters['i_max_pola'] type_current = self.parameters['type_current'] # Recovery of the good time interval if type_current == \"step\": t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = t_step t0_interval = t0_step tf_interval = tf_step elif type_current == \"polarization\": delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola t0_interval = 0 tf_interval = delta_t_ini_pola + int(i_max_pola / delta_i_pola + 1) * (delta_t_load_pola + delta_t_break_pola) else: # EIS time_interval is calculated in the main.py file. raise ValueError(\"Please enter a recognized type_current option for calculating the time interval.\") # To be reviewed self.control_variables['t_control_Phi'] = t0_interval return [t0_interval, tf_interval] def _create_initial_variable_values(self): \"\"\"Create the initial values of the solver variables if it is not provided. It is generated considering an equilibrium at the operating inputs without current. Returns ------- list Initial values of the solver variables. It is used when initial_variable_values == None. \"\"\" # Extraction of the operating inputs and parameters current_density, Tfc = self.operating_inputs['current_density'], self.operating_inputs['Tfc'] Pa_des, Pc_des = self.operating_inputs['Pa_des'], self.operating_inputs['Pc_des'] Phi_a_des, Phi_c_des = self.operating_inputs['Phi_a_des'], self.operating_inputs['Phi_c_des'] Hmem, kappa_co, i0_c_ref, = self.parameters['Hmem'], self.parameters['kappa_co'], self.parameters['i0_c_ref'] kappa_c = self.parameters['kappa_c'] a_slim, b_slim, a_switch = self.parameters['a_slim'], self.parameters['b_slim'], self.parameters['a_switch'] n_gdl = self.parameters['n_gdl'] # Mean value of the operating inputs Phi_des_moy = (Phi_a_des + Phi_c_des) / 2 P_des_moy = (Pa_des + Pc_des) / 2 # Initial fuel cell states # Intermediate values Psat_ini = 101325 * 10 ** (-2.1794 + 0.02953 * (Tfc - 273.15) - 9.1837e-5 * (Tfc - 273.15) ** 2 + 1.4454e-7 * (Tfc - 273.15) ** 3) slim = a_slim * (Pc_des / 1e5) + b_slim s_switch = a_switch * slim # Initial fuel cell states C_v_ini = Phi_des_moy * Psat_ini / (R * Tfc) # mol.m-3. It is the initial vapor concentration. C_H2_ini = (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial H2 concentration # in the fuel cell. C_O2_ini = yO2_ext * (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial O2 # concentration in the fuel cell. C_N2_ini = (1 - yO2_ext) * (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial N2 # concentration in the fuel cell. s_ini = 0 # It is the initial liquid water saturation in the fuel cell. lambda_mem_ini = lambda_eq(C_v_ini, s_ini, Tfc, Kshape) # It is the initial water # content in the fuel cell. i_fc_ini = current_density(self.time_interval[0], self.parameters) i_n_ini = 2 * F * R * Tfc / Hmem * C_H2_ini * k_H2(lambda_mem_ini, Tfc, kappa_co) + \\ 4 * F * R * Tfc / Hmem * C_O2_ini * k_O2(lambda_mem_ini, Tfc, kappa_co) f_drop_ini = 0.5 * (1.0 - np.tanh((4 * s_ini - 2 * slim - 2 * s_switch) / (slim - s_switch))) eta_c_ini = 1 / f_drop_ini * R * Tfc / (alpha_c * F) * \\ np.log((i_fc_ini + i_n_ini) / i0_c_ref * (C_O2ref / C_O2_ini) ** kappa_c) # It is the initial # cathode overpotential in the fuel cell. # Initial auxiliary system state Pasm_ini, Paem_ini = Pa_des, P_des_moy # Pa. It is the supply/exhaust manifold pressure at the anode side. Pcsm_ini, Pcem_ini = Pc_des, P_des_moy # Pa. It is the supply/exhaust manifold pressure at the cathode side. Phi_asm_ini, Phi_aem_ini = Phi_a_des, Phi_des_moy # It is the supply/exhaust manifold relative humidity # at the anode side. Phi_csm_ini, Phi_cem_ini = Phi_c_des, Phi_des_moy # It is the supply/exhaust manifold relative humidity # at the cathode side. Wcp_ini = 0 # kg.s-1. It is the flow rate of the air compressor. Wa_inj_ini = 0 # kg.s-1. It is the flow rate of the air compressor at the anode side. Wc_inj_ini = 0 # kg.s-1. It is the flow rate of the air compressor at the cathode side. Abp_a_ini = 0 # It is the throttle area of the back pressure valve at the anode. Abp_c_ini = 0 # It is the throttle area of the back pressure valve at the cathode. # Main variable initialization C_v_agc, C_v_agdl, C_v_acl, C_v_ccl, C_v_cgdl, C_v_cgc = [C_v_ini] * 6 s_agdl, s_acl, s_ccl, s_cgdl = [s_ini] * 4 s_boundary = 0 # Dirichlet boundary condition lambda_acl, lambda_mem, lambda_ccl = [lambda_mem_ini] * 3 C_H2_agc, C_H2_agdl, C_H2_acl = C_H2_ini, C_H2_ini, C_H2_ini C_O2_ccl, C_O2_cgdl, C_O2_cgc = C_O2_ini, C_O2_ini, C_O2_ini C_N2, eta_c = C_N2_ini, eta_c_ini Pasm, Paem, Pcsm, Pcem = Pasm_ini, Paem_ini, Pcsm_ini, Pcem_ini Phi_asm, Phi_aem, Phi_csm, Phi_cem = Phi_asm_ini, Phi_aem_ini, Phi_csm_ini, Phi_cem_ini Wcp, Wa_inj, Wc_inj, Abp_a, Abp_c = Wcp_ini, Wa_inj_ini, Wc_inj_ini, Abp_a_ini, Abp_c_ini # Gathering of the variables initial value into one list initial_variable_values = [C_v_agc] + [C_v_agdl] * n_gdl + [C_v_acl, C_v_ccl] + [C_v_cgdl] * n_gdl + \\ [C_v_cgc] + \\ [s_boundary] + [s_agdl] * (n_gdl - 1) + [s_acl, s_ccl] + [s_cgdl] * (n_gdl - 1) + \\ [s_boundary] + [lambda_acl, lambda_mem, lambda_ccl] + \\ [C_H2_agc] + [C_H2_agdl] * n_gdl + [C_H2_acl, C_O2_ccl] + [C_O2_cgdl] * n_gdl + \\ [C_O2_cgc, C_N2] + [eta_c] + \\ [Pasm, Paem, Pcsm, Pcem, Phi_asm, Phi_aem, Phi_csm, Phi_cem] + \\ [Wcp, Wa_inj, Wc_inj, Abp_a, Abp_c] return initial_variable_values def _recovery(self): \"\"\"Recover the values which have been calculated by the solver and add them into the variables' dictionary. However, the numerical resolution method does not, by design, recover all the internal states of the stack, even though they are calculated during this process. They therefore have to be recovered manually. \"\"\" # Recovery of the time span self.variables['t'].extend(list(self.sol.t)) # Recovery of the main variables dynamic evolution for index, key in enumerate(self.solver_variable_names): self.variables[key].extend(list(self.sol.y[index])) # Recovery of more variables # The control variables should be reinitialized. To be reviewed. if self.parameters['type_current'] == \"step\": self.control_variables['t_control_Phi'] = self.parameters['t_step'][0] else: self.control_variables['t_control_Phi'] = 0 self.control_variables['Phi_a_des'] = self.operating_inputs['Phi_a_des'] self.control_variables['Phi_c_des'] = self.operating_inputs['Phi_c_des'] for j in range(len(self.sol.t)): # For each time... # ... recovery of i_fc. i_fc = self.operating_inputs[\"current_density\"](self.variables['t'][j], self.parameters) # ... recovery of S_sorp_acl, S_sorp_ccl, Jmem_acl, Jmem_ccl, Pagc, Pcgc. last_solver_variables = {key: self.variables[key][j] for key in self.solver_variable_names} flows_recovery = calculate_flows(self.variables['t'][j], last_solver_variables, self.control_variables, i_fc, self.operating_inputs, self.parameters) for key in ['S_sorp_acl', 'S_sorp_ccl', 'J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc']: self.variables[key].append(flows_recovery[key]) # ... recovery of Phi_a_des and Phi_c_des. if self.parameters[\"type_control\"] == \"Phi_des\": sv = {'lambda_mem': self.variables['lambda_mem'][j], 's_ccl': self.variables['s_ccl'][j]} control_operating_conditions(self.variables['t'][j], sv, self.operating_inputs, self.parameters, self.control_variables) for key in ['Phi_a_des', 'Phi_c_des']: self.variables[key].append(self.control_variables[key]) def Display(self, ax1=None, ax2=None, ax3=None): \"\"\"Display the plots of the program. Parameters ---------- ax1 : matplotlib.axes.Axes, optional Axes for the first set of plots. The default is None. ax2 : matplotlib.axes.Axes, optional Axes for the second set of plots. The default is None. \"\"\" # Extraction of the operating inputs and parameters Tfc = self.operating_inputs['Tfc'] n_gdl, type_fuel_cell = self.parameters['n_gdl'], self.parameters['type_fuel_cell'] type_current, type_display = self.parameters['type_current'], self.parameters['type_display'] # Parameters' preparation n = len(self.variables['t']) subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 \\ else type_fuel_cell # Display if type_current == \"step\": if type_display == \"multiple\": figs, axes = zip(*[plt.subplots(figsize=(8, 8)) for _ in range(12)]) plot_ifc(self.variables, self.operating_inputs, self.parameters, n, axes[0]) plot_J(self.variables, self.parameters, axes[1]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, axes[2]) plot_lambda(self.variables, self.operating_inputs, self.parameters, axes[3]) plot_s(self.variables, self.operating_inputs, self.parameters, axes[4]) plot_C_O2(self.variables, n_gdl, axes[5]) plot_C_H2(self.variables, n_gdl, axes[6]) plot_C_N2(self.variables, axes[7]) plot_Ucell(self.variables, axes[8]) plot_P(self.variables, axes[9]) plot_Phi_a(self.variables, self.operating_inputs, axes[10]) plot_Phi_c(self.variables, self.operating_inputs, axes[11]) # Considering the number of plots, the saving instructions are made here and not in the main.py file. saving_instructions(\"results\", subfolder_name, \"step_current_ifc_1.pdf\", figs[0]) saving_instructions(\"results\", subfolder_name, \"step_current_J_1.pdf\", figs[1]) saving_instructions(\"results\", subfolder_name, \"step_current_Cv_1.pdf\", figs[2]) saving_instructions(\"results\", subfolder_name, \"step_current_lambda_1.pdf\", figs[3]) saving_instructions(\"results\", subfolder_name, \"step_current_s_1.pdf\", figs[4]) saving_instructions(\"results\", subfolder_name, \"step_current_C_O2_1.pdf\", figs[5]) saving_instructions(\"results\", subfolder_name, \"step_current_C_H2_1.pdf\", figs[6]) saving_instructions(\"results\", subfolder_name, \"step_current_C_N2_1.pdf\", figs[7]) saving_instructions(\"results\", subfolder_name, \"step_current_Ucell_1.pdf\", figs[8]) saving_instructions(\"results\", subfolder_name, \"step_current_P_1.pdf\", figs[9]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_a_1.pdf\", figs[10]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_c_1.pdf\", figs[11]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_ifc(self.variables, self.operating_inputs, self.parameters, n, ax1[0, 0]) plot_Ucell(self.variables, ax1[0, 1]) plot_J(self.variables, self.parameters, ax1[0, 2]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, ax1[1, 0]) plot_s(self.variables, self.operating_inputs, self.parameters, ax1[1, 1]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax1[1, 2]) plot_C_H2(self.variables, n_gdl, ax1[2, 0]) plot_C_O2(self.variables, n_gdl, ax1[2, 1]) plot_P(self.variables, ax1[2, 2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"polarization\": if type_display == \"multiple\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1[0]) plot_power_density_curve(self.variables, self.operating_inputs, self.parameters, n, ax1[1]) plot_cell_efficiency(self.variables, self.operating_inputs, self.parameters, n, ax1[2]) plot_Phi_des(self.variables, self.operating_inputs, self.parameters, ax2[0]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax2[1]) plot_s(self.variables, self.operating_inputs, self.parameters, ax2[2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"EIS\": if type_display == \"multiple\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax2) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax3) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1[0]) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax1[1]) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax1[2]) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode Display(ax1=None, ax2=None, ax3=None) Display the plots of the program. Parameters: ax1 ( Axes , default: None ) \u2013 Axes for the first set of plots. The default is None. ax2 ( Axes , default: None ) \u2013 Axes for the second set of plots. The default is None. Source code in model/AlphaPEM.py def Display(self, ax1=None, ax2=None, ax3=None): \"\"\"Display the plots of the program. Parameters ---------- ax1 : matplotlib.axes.Axes, optional Axes for the first set of plots. The default is None. ax2 : matplotlib.axes.Axes, optional Axes for the second set of plots. The default is None. \"\"\" # Extraction of the operating inputs and parameters Tfc = self.operating_inputs['Tfc'] n_gdl, type_fuel_cell = self.parameters['n_gdl'], self.parameters['type_fuel_cell'] type_current, type_display = self.parameters['type_current'], self.parameters['type_display'] # Parameters' preparation n = len(self.variables['t']) subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 \\ else type_fuel_cell # Display if type_current == \"step\": if type_display == \"multiple\": figs, axes = zip(*[plt.subplots(figsize=(8, 8)) for _ in range(12)]) plot_ifc(self.variables, self.operating_inputs, self.parameters, n, axes[0]) plot_J(self.variables, self.parameters, axes[1]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, axes[2]) plot_lambda(self.variables, self.operating_inputs, self.parameters, axes[3]) plot_s(self.variables, self.operating_inputs, self.parameters, axes[4]) plot_C_O2(self.variables, n_gdl, axes[5]) plot_C_H2(self.variables, n_gdl, axes[6]) plot_C_N2(self.variables, axes[7]) plot_Ucell(self.variables, axes[8]) plot_P(self.variables, axes[9]) plot_Phi_a(self.variables, self.operating_inputs, axes[10]) plot_Phi_c(self.variables, self.operating_inputs, axes[11]) # Considering the number of plots, the saving instructions are made here and not in the main.py file. saving_instructions(\"results\", subfolder_name, \"step_current_ifc_1.pdf\", figs[0]) saving_instructions(\"results\", subfolder_name, \"step_current_J_1.pdf\", figs[1]) saving_instructions(\"results\", subfolder_name, \"step_current_Cv_1.pdf\", figs[2]) saving_instructions(\"results\", subfolder_name, \"step_current_lambda_1.pdf\", figs[3]) saving_instructions(\"results\", subfolder_name, \"step_current_s_1.pdf\", figs[4]) saving_instructions(\"results\", subfolder_name, \"step_current_C_O2_1.pdf\", figs[5]) saving_instructions(\"results\", subfolder_name, \"step_current_C_H2_1.pdf\", figs[6]) saving_instructions(\"results\", subfolder_name, \"step_current_C_N2_1.pdf\", figs[7]) saving_instructions(\"results\", subfolder_name, \"step_current_Ucell_1.pdf\", figs[8]) saving_instructions(\"results\", subfolder_name, \"step_current_P_1.pdf\", figs[9]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_a_1.pdf\", figs[10]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_c_1.pdf\", figs[11]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_ifc(self.variables, self.operating_inputs, self.parameters, n, ax1[0, 0]) plot_Ucell(self.variables, ax1[0, 1]) plot_J(self.variables, self.parameters, ax1[0, 2]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, ax1[1, 0]) plot_s(self.variables, self.operating_inputs, self.parameters, ax1[1, 1]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax1[1, 2]) plot_C_H2(self.variables, n_gdl, ax1[2, 0]) plot_C_O2(self.variables, n_gdl, ax1[2, 1]) plot_P(self.variables, ax1[2, 2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"polarization\": if type_display == \"multiple\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1[0]) plot_power_density_curve(self.variables, self.operating_inputs, self.parameters, n, ax1[1]) plot_cell_efficiency(self.variables, self.operating_inputs, self.parameters, n, ax1[2]) plot_Phi_des(self.variables, self.operating_inputs, self.parameters, ax2[0]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax2[1]) plot_s(self.variables, self.operating_inputs, self.parameters, ax2[2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"EIS\": if type_display == \"multiple\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax2) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax3) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1[0]) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax1[1]) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax1[2]) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode __init__(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values=None, time_interval=None) Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). initial_variable_values ( list , default: None ) \u2013 Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval ( list , default: None ) \u2013 Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. Source code in model/AlphaPEM.py def __init__(self, current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values=None, time_interval=None): \"\"\"Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). initial_variable_values : list, optional Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval : list, optional Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. \"\"\" # Initialize the operating inputs and parameters dictionaries. self.operating_inputs = {'current_density': current_density, 'Tfc': Tfc, 'Pa_des': Pa_des, 'Pc_des': Pc_des, 'Sa': Sa, 'Sc': Sc, 'Phi_a_des': Phi_a_des, 'Phi_c_des': Phi_c_des} self.current_parameters = {'t_step': t_step, 'i_step': i_step, 'delta_pola': delta_pola, 'i_max_pola': i_max_pola, 'i_EIS': i_EIS, 'ratio_EIS': ratio_EIS, 't_EIS': t_EIS, 'f_EIS': f_EIS} self.accessible_physical_parameters = {'Aact': Aact, 'Hgdl': Hgdl, 'Hmem': Hmem, 'Hcl': Hcl, 'Hgc': Hgc, 'Wgc': Wgc, 'Lgc': Lgc} self.undetermined_physical_parameters = {'epsilon_gdl': epsilon_gdl, 'tau': tau, 'epsilon_mc': epsilon_mc, 'epsilon_c': epsilon_c, 'e': e, 'kappa_co': kappa_co, 'Re': Re, 'i0_c_ref': i0_c_ref, 'kappa_c': kappa_c, 'a_slim': a_slim, 'b_slim': b_slim, 'a_switch': a_switch, 'C_scl': C_scl} self.computing_parameters = {'max_step': max_step, 'n_gdl': n_gdl, 't_purge': t_purge, 'type_fuel_cell': type_fuel_cell, 'type_current': type_current, 'type_auxiliary': type_auxiliary, 'type_control': type_control, 'type_purge': type_purge, 'type_display': type_display, 'type_plot': type_plot} self.parameters = {**self.current_parameters, **self.accessible_physical_parameters, **self.undetermined_physical_parameters, **self.computing_parameters} if self.operating_inputs['Pa_des'] < Pext or self.operating_inputs['Pc_des'] < Pext: raise ValueError('The desired pressure is too low. It cannot be lower than the pressure outside the stack.') # Initialize the variables' dictionary. self.solver_variable_names = ['C_v_agc', 'C_v_agdl', 'C_v_acl', 'C_v_ccl', 'C_v_cgdl', 'C_v_cgc', 's_agdl', 's_acl', 's_ccl', 's_cgdl', 'lambda_acl', 'lambda_mem', 'lambda_ccl', 'C_H2_agc', 'C_H2_agdl', 'C_H2_acl', 'C_O2_ccl', 'C_O2_cgdl', 'C_O2_cgc', 'C_N2', 'eta_c', 'Pasm', 'Paem', 'Pcsm', 'Pcem', 'Phi_asm', 'Phi_aem', 'Phi_csm', 'Phi_cem', 'Wcp', 'Wa_inj', 'Wc_inj', 'Abp_a', 'Abp_c'] self.solver_variable_names_extension() # Several points are considered in each GDL and must be inserted into # the solver_variable_names. self.all_variable_names = self.solver_variable_names + ['t', 'Ucell', 'S_sorp_acl', 'S_sorp_ccl'] + \\ ['J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc', 'Phi_a_des', 'Phi_c_des'] self.variables = {key: [] for key in self.all_variable_names} # Initialize the control_variables dictionary. self.control_variables = {'t_control_Phi': self.parameters['t_step'][0], 'Phi_a_des': self.operating_inputs['Phi_a_des'], 'Phi_c_des': self.operating_inputs['Phi_c_des']} # Create the dynamic evolution. # Create time intervals if time_interval is not None: # Initial time interval may be given to the Simulator. self.time_interval = time_interval else: # If not, it is automatically generated. self.time_interval = self._create_time_interval() # Create the initial variable values if initial_variable_values is not None: # Initial variable values may be given to the Simulator. self.initial_variable_values = initial_variable_values else: # If not, they are generated considering an equilibrium at the operating inputs without current. self.initial_variable_values = self._create_initial_variable_values() # Resolution of the system of differential equations. event_negative.terminal = True # Integration is stopped if one of the crucial variables becomes negative. self.sol = solve_ivp(dydt, self.time_interval, self.initial_variable_values, method='BDF', max_step=self.parameters['max_step'], events=event_negative, args=(self.operating_inputs, self.parameters, self.solver_variable_names, self.control_variables)) # Recover the variable values calculated by the solver into the dictionary. self._recovery() # Calculate the cell voltage after computing the internal states of the cell. self.variables[\"Ucell\"].extend(calculate_cell_voltage(self.variables, self.operating_inputs, self.parameters)) solver_variable_names_extension() Several points are considered in each GDL and must be inserted into the solver_variable_names. Source code in model/AlphaPEM.py def solver_variable_names_extension(self): \"\"\"Several points are considered in each GDL and must be inserted into the solver_variable_names. \"\"\" new_points_location = ['C_v_agdl', 'C_v_cgdl', 's_agdl', 's_cgdl', 'C_H2_agdl', 'C_O2_cgdl'] for variable in new_points_location: index = self.solver_variable_names.index(variable) # Delete the previous points self.solver_variable_names.pop(index) # Increase the number of points self.solver_variable_names[index:index] = [f'{variable}_{i}' for i in range(1, self.parameters['n_gdl'] + 1)]","title":"AlphaPEM"},{"location":"functions/model/AlphaPEM/#alphapem","text":"Objectives: Create an open-source software package to simulate the PEM fuel cell for control system applications. Authors: Rapha\u00ebl GASS, Zhongliang LI, Rachid OUTBIB, Samir JEMEI and Daniel HISSEL. This file describes the AlphaPEM class, which is a PEM fuel cell system simulator. The model is one-dimensional, dynamic, biphasic, and isothermal. It has been published in the following articles: - Gass et al 2024 J. Electrochem. Soc. https://doi.org/10.1149/1945-7111/ad305a - Gass et al 2024 SSRN http://dx.doi.org/10.2139/ssrn.4812343","title":"AlphaPEM"},{"location":"functions/model/AlphaPEM/#model.AlphaPEM.AlphaPEM","text":"Source code in model/AlphaPEM.py class AlphaPEM: def __init__(self, current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values=None, time_interval=None): \"\"\"Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). initial_variable_values : list, optional Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval : list, optional Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. \"\"\" # Initialize the operating inputs and parameters dictionaries. self.operating_inputs = {'current_density': current_density, 'Tfc': Tfc, 'Pa_des': Pa_des, 'Pc_des': Pc_des, 'Sa': Sa, 'Sc': Sc, 'Phi_a_des': Phi_a_des, 'Phi_c_des': Phi_c_des} self.current_parameters = {'t_step': t_step, 'i_step': i_step, 'delta_pola': delta_pola, 'i_max_pola': i_max_pola, 'i_EIS': i_EIS, 'ratio_EIS': ratio_EIS, 't_EIS': t_EIS, 'f_EIS': f_EIS} self.accessible_physical_parameters = {'Aact': Aact, 'Hgdl': Hgdl, 'Hmem': Hmem, 'Hcl': Hcl, 'Hgc': Hgc, 'Wgc': Wgc, 'Lgc': Lgc} self.undetermined_physical_parameters = {'epsilon_gdl': epsilon_gdl, 'tau': tau, 'epsilon_mc': epsilon_mc, 'epsilon_c': epsilon_c, 'e': e, 'kappa_co': kappa_co, 'Re': Re, 'i0_c_ref': i0_c_ref, 'kappa_c': kappa_c, 'a_slim': a_slim, 'b_slim': b_slim, 'a_switch': a_switch, 'C_scl': C_scl} self.computing_parameters = {'max_step': max_step, 'n_gdl': n_gdl, 't_purge': t_purge, 'type_fuel_cell': type_fuel_cell, 'type_current': type_current, 'type_auxiliary': type_auxiliary, 'type_control': type_control, 'type_purge': type_purge, 'type_display': type_display, 'type_plot': type_plot} self.parameters = {**self.current_parameters, **self.accessible_physical_parameters, **self.undetermined_physical_parameters, **self.computing_parameters} if self.operating_inputs['Pa_des'] < Pext or self.operating_inputs['Pc_des'] < Pext: raise ValueError('The desired pressure is too low. It cannot be lower than the pressure outside the stack.') # Initialize the variables' dictionary. self.solver_variable_names = ['C_v_agc', 'C_v_agdl', 'C_v_acl', 'C_v_ccl', 'C_v_cgdl', 'C_v_cgc', 's_agdl', 's_acl', 's_ccl', 's_cgdl', 'lambda_acl', 'lambda_mem', 'lambda_ccl', 'C_H2_agc', 'C_H2_agdl', 'C_H2_acl', 'C_O2_ccl', 'C_O2_cgdl', 'C_O2_cgc', 'C_N2', 'eta_c', 'Pasm', 'Paem', 'Pcsm', 'Pcem', 'Phi_asm', 'Phi_aem', 'Phi_csm', 'Phi_cem', 'Wcp', 'Wa_inj', 'Wc_inj', 'Abp_a', 'Abp_c'] self.solver_variable_names_extension() # Several points are considered in each GDL and must be inserted into # the solver_variable_names. self.all_variable_names = self.solver_variable_names + ['t', 'Ucell', 'S_sorp_acl', 'S_sorp_ccl'] + \\ ['J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc', 'Phi_a_des', 'Phi_c_des'] self.variables = {key: [] for key in self.all_variable_names} # Initialize the control_variables dictionary. self.control_variables = {'t_control_Phi': self.parameters['t_step'][0], 'Phi_a_des': self.operating_inputs['Phi_a_des'], 'Phi_c_des': self.operating_inputs['Phi_c_des']} # Create the dynamic evolution. # Create time intervals if time_interval is not None: # Initial time interval may be given to the Simulator. self.time_interval = time_interval else: # If not, it is automatically generated. self.time_interval = self._create_time_interval() # Create the initial variable values if initial_variable_values is not None: # Initial variable values may be given to the Simulator. self.initial_variable_values = initial_variable_values else: # If not, they are generated considering an equilibrium at the operating inputs without current. self.initial_variable_values = self._create_initial_variable_values() # Resolution of the system of differential equations. event_negative.terminal = True # Integration is stopped if one of the crucial variables becomes negative. self.sol = solve_ivp(dydt, self.time_interval, self.initial_variable_values, method='BDF', max_step=self.parameters['max_step'], events=event_negative, args=(self.operating_inputs, self.parameters, self.solver_variable_names, self.control_variables)) # Recover the variable values calculated by the solver into the dictionary. self._recovery() # Calculate the cell voltage after computing the internal states of the cell. self.variables[\"Ucell\"].extend(calculate_cell_voltage(self.variables, self.operating_inputs, self.parameters)) def solver_variable_names_extension(self): \"\"\"Several points are considered in each GDL and must be inserted into the solver_variable_names. \"\"\" new_points_location = ['C_v_agdl', 'C_v_cgdl', 's_agdl', 's_cgdl', 'C_H2_agdl', 'C_O2_cgdl'] for variable in new_points_location: index = self.solver_variable_names.index(variable) # Delete the previous points self.solver_variable_names.pop(index) # Increase the number of points self.solver_variable_names[index:index] = [f'{variable}_{i}' for i in range(1, self.parameters['n_gdl'] + 1)] def _create_time_interval(self): \"\"\"Calculate the time intervals for numerical resolution, according to the current chosen, if it is not provided. Returns ------- list Time interval for numerical resolution. It is used when initial_variable_values == None. \"\"\" # Extraction of the parameters t_step, delta_pola, i_max_pola = self.parameters['t_step'], self.parameters['delta_pola'], self.parameters['i_max_pola'] type_current = self.parameters['type_current'] # Recovery of the good time interval if type_current == \"step\": t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = t_step t0_interval = t0_step tf_interval = tf_step elif type_current == \"polarization\": delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola t0_interval = 0 tf_interval = delta_t_ini_pola + int(i_max_pola / delta_i_pola + 1) * (delta_t_load_pola + delta_t_break_pola) else: # EIS time_interval is calculated in the main.py file. raise ValueError(\"Please enter a recognized type_current option for calculating the time interval.\") # To be reviewed self.control_variables['t_control_Phi'] = t0_interval return [t0_interval, tf_interval] def _create_initial_variable_values(self): \"\"\"Create the initial values of the solver variables if it is not provided. It is generated considering an equilibrium at the operating inputs without current. Returns ------- list Initial values of the solver variables. It is used when initial_variable_values == None. \"\"\" # Extraction of the operating inputs and parameters current_density, Tfc = self.operating_inputs['current_density'], self.operating_inputs['Tfc'] Pa_des, Pc_des = self.operating_inputs['Pa_des'], self.operating_inputs['Pc_des'] Phi_a_des, Phi_c_des = self.operating_inputs['Phi_a_des'], self.operating_inputs['Phi_c_des'] Hmem, kappa_co, i0_c_ref, = self.parameters['Hmem'], self.parameters['kappa_co'], self.parameters['i0_c_ref'] kappa_c = self.parameters['kappa_c'] a_slim, b_slim, a_switch = self.parameters['a_slim'], self.parameters['b_slim'], self.parameters['a_switch'] n_gdl = self.parameters['n_gdl'] # Mean value of the operating inputs Phi_des_moy = (Phi_a_des + Phi_c_des) / 2 P_des_moy = (Pa_des + Pc_des) / 2 # Initial fuel cell states # Intermediate values Psat_ini = 101325 * 10 ** (-2.1794 + 0.02953 * (Tfc - 273.15) - 9.1837e-5 * (Tfc - 273.15) ** 2 + 1.4454e-7 * (Tfc - 273.15) ** 3) slim = a_slim * (Pc_des / 1e5) + b_slim s_switch = a_switch * slim # Initial fuel cell states C_v_ini = Phi_des_moy * Psat_ini / (R * Tfc) # mol.m-3. It is the initial vapor concentration. C_H2_ini = (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial H2 concentration # in the fuel cell. C_O2_ini = yO2_ext * (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial O2 # concentration in the fuel cell. C_N2_ini = (1 - yO2_ext) * (P_des_moy - Phi_des_moy * Psat_ini) / (R * Tfc) # mol.m-3. It is the initial N2 # concentration in the fuel cell. s_ini = 0 # It is the initial liquid water saturation in the fuel cell. lambda_mem_ini = lambda_eq(C_v_ini, s_ini, Tfc, Kshape) # It is the initial water # content in the fuel cell. i_fc_ini = current_density(self.time_interval[0], self.parameters) i_n_ini = 2 * F * R * Tfc / Hmem * C_H2_ini * k_H2(lambda_mem_ini, Tfc, kappa_co) + \\ 4 * F * R * Tfc / Hmem * C_O2_ini * k_O2(lambda_mem_ini, Tfc, kappa_co) f_drop_ini = 0.5 * (1.0 - np.tanh((4 * s_ini - 2 * slim - 2 * s_switch) / (slim - s_switch))) eta_c_ini = 1 / f_drop_ini * R * Tfc / (alpha_c * F) * \\ np.log((i_fc_ini + i_n_ini) / i0_c_ref * (C_O2ref / C_O2_ini) ** kappa_c) # It is the initial # cathode overpotential in the fuel cell. # Initial auxiliary system state Pasm_ini, Paem_ini = Pa_des, P_des_moy # Pa. It is the supply/exhaust manifold pressure at the anode side. Pcsm_ini, Pcem_ini = Pc_des, P_des_moy # Pa. It is the supply/exhaust manifold pressure at the cathode side. Phi_asm_ini, Phi_aem_ini = Phi_a_des, Phi_des_moy # It is the supply/exhaust manifold relative humidity # at the anode side. Phi_csm_ini, Phi_cem_ini = Phi_c_des, Phi_des_moy # It is the supply/exhaust manifold relative humidity # at the cathode side. Wcp_ini = 0 # kg.s-1. It is the flow rate of the air compressor. Wa_inj_ini = 0 # kg.s-1. It is the flow rate of the air compressor at the anode side. Wc_inj_ini = 0 # kg.s-1. It is the flow rate of the air compressor at the cathode side. Abp_a_ini = 0 # It is the throttle area of the back pressure valve at the anode. Abp_c_ini = 0 # It is the throttle area of the back pressure valve at the cathode. # Main variable initialization C_v_agc, C_v_agdl, C_v_acl, C_v_ccl, C_v_cgdl, C_v_cgc = [C_v_ini] * 6 s_agdl, s_acl, s_ccl, s_cgdl = [s_ini] * 4 s_boundary = 0 # Dirichlet boundary condition lambda_acl, lambda_mem, lambda_ccl = [lambda_mem_ini] * 3 C_H2_agc, C_H2_agdl, C_H2_acl = C_H2_ini, C_H2_ini, C_H2_ini C_O2_ccl, C_O2_cgdl, C_O2_cgc = C_O2_ini, C_O2_ini, C_O2_ini C_N2, eta_c = C_N2_ini, eta_c_ini Pasm, Paem, Pcsm, Pcem = Pasm_ini, Paem_ini, Pcsm_ini, Pcem_ini Phi_asm, Phi_aem, Phi_csm, Phi_cem = Phi_asm_ini, Phi_aem_ini, Phi_csm_ini, Phi_cem_ini Wcp, Wa_inj, Wc_inj, Abp_a, Abp_c = Wcp_ini, Wa_inj_ini, Wc_inj_ini, Abp_a_ini, Abp_c_ini # Gathering of the variables initial value into one list initial_variable_values = [C_v_agc] + [C_v_agdl] * n_gdl + [C_v_acl, C_v_ccl] + [C_v_cgdl] * n_gdl + \\ [C_v_cgc] + \\ [s_boundary] + [s_agdl] * (n_gdl - 1) + [s_acl, s_ccl] + [s_cgdl] * (n_gdl - 1) + \\ [s_boundary] + [lambda_acl, lambda_mem, lambda_ccl] + \\ [C_H2_agc] + [C_H2_agdl] * n_gdl + [C_H2_acl, C_O2_ccl] + [C_O2_cgdl] * n_gdl + \\ [C_O2_cgc, C_N2] + [eta_c] + \\ [Pasm, Paem, Pcsm, Pcem, Phi_asm, Phi_aem, Phi_csm, Phi_cem] + \\ [Wcp, Wa_inj, Wc_inj, Abp_a, Abp_c] return initial_variable_values def _recovery(self): \"\"\"Recover the values which have been calculated by the solver and add them into the variables' dictionary. However, the numerical resolution method does not, by design, recover all the internal states of the stack, even though they are calculated during this process. They therefore have to be recovered manually. \"\"\" # Recovery of the time span self.variables['t'].extend(list(self.sol.t)) # Recovery of the main variables dynamic evolution for index, key in enumerate(self.solver_variable_names): self.variables[key].extend(list(self.sol.y[index])) # Recovery of more variables # The control variables should be reinitialized. To be reviewed. if self.parameters['type_current'] == \"step\": self.control_variables['t_control_Phi'] = self.parameters['t_step'][0] else: self.control_variables['t_control_Phi'] = 0 self.control_variables['Phi_a_des'] = self.operating_inputs['Phi_a_des'] self.control_variables['Phi_c_des'] = self.operating_inputs['Phi_c_des'] for j in range(len(self.sol.t)): # For each time... # ... recovery of i_fc. i_fc = self.operating_inputs[\"current_density\"](self.variables['t'][j], self.parameters) # ... recovery of S_sorp_acl, S_sorp_ccl, Jmem_acl, Jmem_ccl, Pagc, Pcgc. last_solver_variables = {key: self.variables[key][j] for key in self.solver_variable_names} flows_recovery = calculate_flows(self.variables['t'][j], last_solver_variables, self.control_variables, i_fc, self.operating_inputs, self.parameters) for key in ['S_sorp_acl', 'S_sorp_ccl', 'J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc']: self.variables[key].append(flows_recovery[key]) # ... recovery of Phi_a_des and Phi_c_des. if self.parameters[\"type_control\"] == \"Phi_des\": sv = {'lambda_mem': self.variables['lambda_mem'][j], 's_ccl': self.variables['s_ccl'][j]} control_operating_conditions(self.variables['t'][j], sv, self.operating_inputs, self.parameters, self.control_variables) for key in ['Phi_a_des', 'Phi_c_des']: self.variables[key].append(self.control_variables[key]) def Display(self, ax1=None, ax2=None, ax3=None): \"\"\"Display the plots of the program. Parameters ---------- ax1 : matplotlib.axes.Axes, optional Axes for the first set of plots. The default is None. ax2 : matplotlib.axes.Axes, optional Axes for the second set of plots. The default is None. \"\"\" # Extraction of the operating inputs and parameters Tfc = self.operating_inputs['Tfc'] n_gdl, type_fuel_cell = self.parameters['n_gdl'], self.parameters['type_fuel_cell'] type_current, type_display = self.parameters['type_current'], self.parameters['type_display'] # Parameters' preparation n = len(self.variables['t']) subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 \\ else type_fuel_cell # Display if type_current == \"step\": if type_display == \"multiple\": figs, axes = zip(*[plt.subplots(figsize=(8, 8)) for _ in range(12)]) plot_ifc(self.variables, self.operating_inputs, self.parameters, n, axes[0]) plot_J(self.variables, self.parameters, axes[1]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, axes[2]) plot_lambda(self.variables, self.operating_inputs, self.parameters, axes[3]) plot_s(self.variables, self.operating_inputs, self.parameters, axes[4]) plot_C_O2(self.variables, n_gdl, axes[5]) plot_C_H2(self.variables, n_gdl, axes[6]) plot_C_N2(self.variables, axes[7]) plot_Ucell(self.variables, axes[8]) plot_P(self.variables, axes[9]) plot_Phi_a(self.variables, self.operating_inputs, axes[10]) plot_Phi_c(self.variables, self.operating_inputs, axes[11]) # Considering the number of plots, the saving instructions are made here and not in the main.py file. saving_instructions(\"results\", subfolder_name, \"step_current_ifc_1.pdf\", figs[0]) saving_instructions(\"results\", subfolder_name, \"step_current_J_1.pdf\", figs[1]) saving_instructions(\"results\", subfolder_name, \"step_current_Cv_1.pdf\", figs[2]) saving_instructions(\"results\", subfolder_name, \"step_current_lambda_1.pdf\", figs[3]) saving_instructions(\"results\", subfolder_name, \"step_current_s_1.pdf\", figs[4]) saving_instructions(\"results\", subfolder_name, \"step_current_C_O2_1.pdf\", figs[5]) saving_instructions(\"results\", subfolder_name, \"step_current_C_H2_1.pdf\", figs[6]) saving_instructions(\"results\", subfolder_name, \"step_current_C_N2_1.pdf\", figs[7]) saving_instructions(\"results\", subfolder_name, \"step_current_Ucell_1.pdf\", figs[8]) saving_instructions(\"results\", subfolder_name, \"step_current_P_1.pdf\", figs[9]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_a_1.pdf\", figs[10]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_c_1.pdf\", figs[11]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_ifc(self.variables, self.operating_inputs, self.parameters, n, ax1[0, 0]) plot_Ucell(self.variables, ax1[0, 1]) plot_J(self.variables, self.parameters, ax1[0, 2]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, ax1[1, 0]) plot_s(self.variables, self.operating_inputs, self.parameters, ax1[1, 1]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax1[1, 2]) plot_C_H2(self.variables, n_gdl, ax1[2, 0]) plot_C_O2(self.variables, n_gdl, ax1[2, 1]) plot_P(self.variables, ax1[2, 2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"polarization\": if type_display == \"multiple\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1[0]) plot_power_density_curve(self.variables, self.operating_inputs, self.parameters, n, ax1[1]) plot_cell_efficiency(self.variables, self.operating_inputs, self.parameters, n, ax1[2]) plot_Phi_des(self.variables, self.operating_inputs, self.parameters, ax2[0]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax2[1]) plot_s(self.variables, self.operating_inputs, self.parameters, ax2[2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"EIS\": if type_display == \"multiple\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax2) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax3) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1[0]) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax1[1]) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax1[2]) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode","title":"AlphaPEM"},{"location":"functions/model/AlphaPEM/#model.AlphaPEM.AlphaPEM.Display","text":"Display the plots of the program. Parameters: ax1 ( Axes , default: None ) \u2013 Axes for the first set of plots. The default is None. ax2 ( Axes , default: None ) \u2013 Axes for the second set of plots. The default is None. Source code in model/AlphaPEM.py def Display(self, ax1=None, ax2=None, ax3=None): \"\"\"Display the plots of the program. Parameters ---------- ax1 : matplotlib.axes.Axes, optional Axes for the first set of plots. The default is None. ax2 : matplotlib.axes.Axes, optional Axes for the second set of plots. The default is None. \"\"\" # Extraction of the operating inputs and parameters Tfc = self.operating_inputs['Tfc'] n_gdl, type_fuel_cell = self.parameters['n_gdl'], self.parameters['type_fuel_cell'] type_current, type_display = self.parameters['type_current'], self.parameters['type_display'] # Parameters' preparation n = len(self.variables['t']) subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 \\ else type_fuel_cell # Display if type_current == \"step\": if type_display == \"multiple\": figs, axes = zip(*[plt.subplots(figsize=(8, 8)) for _ in range(12)]) plot_ifc(self.variables, self.operating_inputs, self.parameters, n, axes[0]) plot_J(self.variables, self.parameters, axes[1]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, axes[2]) plot_lambda(self.variables, self.operating_inputs, self.parameters, axes[3]) plot_s(self.variables, self.operating_inputs, self.parameters, axes[4]) plot_C_O2(self.variables, n_gdl, axes[5]) plot_C_H2(self.variables, n_gdl, axes[6]) plot_C_N2(self.variables, axes[7]) plot_Ucell(self.variables, axes[8]) plot_P(self.variables, axes[9]) plot_Phi_a(self.variables, self.operating_inputs, axes[10]) plot_Phi_c(self.variables, self.operating_inputs, axes[11]) # Considering the number of plots, the saving instructions are made here and not in the main.py file. saving_instructions(\"results\", subfolder_name, \"step_current_ifc_1.pdf\", figs[0]) saving_instructions(\"results\", subfolder_name, \"step_current_J_1.pdf\", figs[1]) saving_instructions(\"results\", subfolder_name, \"step_current_Cv_1.pdf\", figs[2]) saving_instructions(\"results\", subfolder_name, \"step_current_lambda_1.pdf\", figs[3]) saving_instructions(\"results\", subfolder_name, \"step_current_s_1.pdf\", figs[4]) saving_instructions(\"results\", subfolder_name, \"step_current_C_O2_1.pdf\", figs[5]) saving_instructions(\"results\", subfolder_name, \"step_current_C_H2_1.pdf\", figs[6]) saving_instructions(\"results\", subfolder_name, \"step_current_C_N2_1.pdf\", figs[7]) saving_instructions(\"results\", subfolder_name, \"step_current_Ucell_1.pdf\", figs[8]) saving_instructions(\"results\", subfolder_name, \"step_current_P_1.pdf\", figs[9]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_a_1.pdf\", figs[10]) saving_instructions(\"results\", subfolder_name, \"step_current_Phi_c_1.pdf\", figs[11]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_ifc(self.variables, self.operating_inputs, self.parameters, n, ax1[0, 0]) plot_Ucell(self.variables, ax1[0, 1]) plot_J(self.variables, self.parameters, ax1[0, 2]) plot_C_v(self.variables, n_gdl, C_v_sat(Tfc), n, ax1[1, 0]) plot_s(self.variables, self.operating_inputs, self.parameters, ax1[1, 1]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax1[1, 2]) plot_C_H2(self.variables, n_gdl, ax1[2, 0]) plot_C_O2(self.variables, n_gdl, ax1[2, 1]) plot_P(self.variables, ax1[2, 2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"polarization\": if type_display == \"multiple\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1[0]) plot_power_density_curve(self.variables, self.operating_inputs, self.parameters, n, ax1[1]) plot_cell_efficiency(self.variables, self.operating_inputs, self.parameters, n, ax1[2]) plot_Phi_des(self.variables, self.operating_inputs, self.parameters, ax2[0]) plot_lambda(self.variables, self.operating_inputs, self.parameters, ax2[1]) plot_s(self.variables, self.operating_inputs, self.parameters, ax2[2]) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": plot_polarisation_curve(self.variables, self.operating_inputs, self.parameters, ax1) plt.pause(0.001) # A break is necessary to plot the new points in dynamic mode elif type_current == \"EIS\": if type_display == \"multiple\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax2) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax3) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode elif type_display == \"synthetic\": Fourier_results = make_Fourier_transformation(self.variables, self.operating_inputs, self.parameters) plot_EIS_curve_Nyquist(self.parameters, Fourier_results, ax1[0]) plot_EIS_curve_Bode_amplitude(self.parameters, Fourier_results, ax1[1]) plot_EIS_curve_Bode_angle(self.parameters, Fourier_results, ax1[2]) # # Tests to verify the accuracy of EIS simulation. # plot_EIS_curve_tests(self.variables, self.operating_inputs, self.parameters, Fourier_results) plt.pause(0.1) # A break is necessary to plot the new points in dynamic mode","title":"Display"},{"location":"functions/model/AlphaPEM/#model.AlphaPEM.AlphaPEM.__init__","text":"Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). initial_variable_values ( list , default: None ) \u2013 Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval ( list , default: None ) \u2013 Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. Source code in model/AlphaPEM.py def __init__(self, current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values=None, time_interval=None): \"\"\"Initialise all parameters defining a fuel cell stack operation: nominal operating conditions, applied electrical load, dimensions, and undetermined variables. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). initial_variable_values : list, optional Initial values of the solver variables. The default is None, which implies that initial values are generated considering an equilibrium at the operating inputs without current. time_interval : list, optional Time intervals for numerical resolution. The default is None, which implies that it is automatically generated according to the data given in the current density parameters. \"\"\" # Initialize the operating inputs and parameters dictionaries. self.operating_inputs = {'current_density': current_density, 'Tfc': Tfc, 'Pa_des': Pa_des, 'Pc_des': Pc_des, 'Sa': Sa, 'Sc': Sc, 'Phi_a_des': Phi_a_des, 'Phi_c_des': Phi_c_des} self.current_parameters = {'t_step': t_step, 'i_step': i_step, 'delta_pola': delta_pola, 'i_max_pola': i_max_pola, 'i_EIS': i_EIS, 'ratio_EIS': ratio_EIS, 't_EIS': t_EIS, 'f_EIS': f_EIS} self.accessible_physical_parameters = {'Aact': Aact, 'Hgdl': Hgdl, 'Hmem': Hmem, 'Hcl': Hcl, 'Hgc': Hgc, 'Wgc': Wgc, 'Lgc': Lgc} self.undetermined_physical_parameters = {'epsilon_gdl': epsilon_gdl, 'tau': tau, 'epsilon_mc': epsilon_mc, 'epsilon_c': epsilon_c, 'e': e, 'kappa_co': kappa_co, 'Re': Re, 'i0_c_ref': i0_c_ref, 'kappa_c': kappa_c, 'a_slim': a_slim, 'b_slim': b_slim, 'a_switch': a_switch, 'C_scl': C_scl} self.computing_parameters = {'max_step': max_step, 'n_gdl': n_gdl, 't_purge': t_purge, 'type_fuel_cell': type_fuel_cell, 'type_current': type_current, 'type_auxiliary': type_auxiliary, 'type_control': type_control, 'type_purge': type_purge, 'type_display': type_display, 'type_plot': type_plot} self.parameters = {**self.current_parameters, **self.accessible_physical_parameters, **self.undetermined_physical_parameters, **self.computing_parameters} if self.operating_inputs['Pa_des'] < Pext or self.operating_inputs['Pc_des'] < Pext: raise ValueError('The desired pressure is too low. It cannot be lower than the pressure outside the stack.') # Initialize the variables' dictionary. self.solver_variable_names = ['C_v_agc', 'C_v_agdl', 'C_v_acl', 'C_v_ccl', 'C_v_cgdl', 'C_v_cgc', 's_agdl', 's_acl', 's_ccl', 's_cgdl', 'lambda_acl', 'lambda_mem', 'lambda_ccl', 'C_H2_agc', 'C_H2_agdl', 'C_H2_acl', 'C_O2_ccl', 'C_O2_cgdl', 'C_O2_cgc', 'C_N2', 'eta_c', 'Pasm', 'Paem', 'Pcsm', 'Pcem', 'Phi_asm', 'Phi_aem', 'Phi_csm', 'Phi_cem', 'Wcp', 'Wa_inj', 'Wc_inj', 'Abp_a', 'Abp_c'] self.solver_variable_names_extension() # Several points are considered in each GDL and must be inserted into # the solver_variable_names. self.all_variable_names = self.solver_variable_names + ['t', 'Ucell', 'S_sorp_acl', 'S_sorp_ccl'] + \\ ['J_lambda_mem_acl', 'J_lambda_mem_ccl', 'Pagc', 'Pcgc', 'Phi_a_des', 'Phi_c_des'] self.variables = {key: [] for key in self.all_variable_names} # Initialize the control_variables dictionary. self.control_variables = {'t_control_Phi': self.parameters['t_step'][0], 'Phi_a_des': self.operating_inputs['Phi_a_des'], 'Phi_c_des': self.operating_inputs['Phi_c_des']} # Create the dynamic evolution. # Create time intervals if time_interval is not None: # Initial time interval may be given to the Simulator. self.time_interval = time_interval else: # If not, it is automatically generated. self.time_interval = self._create_time_interval() # Create the initial variable values if initial_variable_values is not None: # Initial variable values may be given to the Simulator. self.initial_variable_values = initial_variable_values else: # If not, they are generated considering an equilibrium at the operating inputs without current. self.initial_variable_values = self._create_initial_variable_values() # Resolution of the system of differential equations. event_negative.terminal = True # Integration is stopped if one of the crucial variables becomes negative. self.sol = solve_ivp(dydt, self.time_interval, self.initial_variable_values, method='BDF', max_step=self.parameters['max_step'], events=event_negative, args=(self.operating_inputs, self.parameters, self.solver_variable_names, self.control_variables)) # Recover the variable values calculated by the solver into the dictionary. self._recovery() # Calculate the cell voltage after computing the internal states of the cell. self.variables[\"Ucell\"].extend(calculate_cell_voltage(self.variables, self.operating_inputs, self.parameters))","title":"__init__"},{"location":"functions/model/AlphaPEM/#model.AlphaPEM.AlphaPEM.solver_variable_names_extension","text":"Several points are considered in each GDL and must be inserted into the solver_variable_names. Source code in model/AlphaPEM.py def solver_variable_names_extension(self): \"\"\"Several points are considered in each GDL and must be inserted into the solver_variable_names. \"\"\" new_points_location = ['C_v_agdl', 'C_v_cgdl', 's_agdl', 's_cgdl', 'C_H2_agdl', 'C_O2_cgdl'] for variable in new_points_location: index = self.solver_variable_names.index(variable) # Delete the previous points self.solver_variable_names.pop(index) # Increase the number of points self.solver_variable_names[index:index] = [f'{variable}_{i}' for i in range(1, self.parameters['n_gdl'] + 1)]","title":"solver_variable_names_extension"},{"location":"functions/model/auxiliaries/","text":"Auxiliaries This file represents all the flows passing through the auxiliaries. It is a component of the fuel cell model. auxiliaries(t, solver_variables, control_variables, i_fc, operating_inputs, parameters) This function calculates the flows passing through the auxiliaries. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. i_fc ( float ) \u2013 Fuel cell current density at time t (A.m-2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Jv_a_in ( float ) \u2013 Vapor flow at the anode gas channel inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Vapor flow at the anode gas channel outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Vapor flow at the cathode gas channel inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Vapor flow at the cathode gas channel outlet (mol.m-2.s-1). J_H2_in ( float ) \u2013 H2 flow at the anode gas channel inlet (mol.m-2.s-1). J_H2_out ( float ) \u2013 H2 flow at the anode gas channel outlet (mol.m-2.s-1). J_O2_in ( float ) \u2013 O2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_O2_out ( float ) \u2013 O2 flow at the cathode gas channel outlet (mol.m-2.s-1). J_N2_in ( float ) \u2013 N2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_N2_out ( float ) \u2013 N2 flow at the cathode gas channel outlet (mol.m-2.s-1). Wasm_in ( float ) \u2013 Anode side supply manifold inlet flow (kg.s-1). Wasm_out ( float ) \u2013 Anode side supply manifold outlet flow (kg.s-1). Waem_in ( float ) \u2013 Anode side external manifold inlet flow (kg.s-1). Waem_out ( float ) \u2013 Anode side external manifold outlet flow (kg.s-1). Wcsm_in ( float ) \u2013 Cathode side supply manifold inlet flow (kg.s-1). Wcsm_out ( float ) \u2013 Cathode side supply manifold outlet flow (kg.s-1). Wcem_in ( float ) \u2013 Cathode side external manifold inlet flow (kg.s-1). Wcem_out ( float ) \u2013 Cathode side external manifold outlet flow (kg.s-1). Ware ( float ) \u2013 Anode side recirculation flow (kg.s-1). Wv_asm_in ( float ) \u2013 Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out ( float ) \u2013 Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in ( float ) \u2013 Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out ( float ) \u2013 Vapor flow at the cathode external manifold outlet (mol.s-1). Source code in model/auxiliaries.py def auxiliaries(t, solver_variables, control_variables, i_fc, operating_inputs, parameters): \"\"\"This function calculates the flows passing through the auxiliaries. Parameters ---------- t : float Time (s). solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. i_fc : float Fuel cell current density at time t (A.m-2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Jv_a_in : float Vapor flow at the anode gas channel inlet (mol.m-2.s-1). Jv_a_out : float Vapor flow at the anode gas channel outlet (mol.m-2.s-1). Jv_c_in : float Vapor flow at the cathode gas channel inlet (mol.m-2.s-1). Jv_c_out : float Vapor flow at the cathode gas channel outlet (mol.m-2.s-1). J_H2_in : float H2 flow at the anode gas channel inlet (mol.m-2.s-1). J_H2_out : float H2 flow at the anode gas channel outlet (mol.m-2.s-1). J_O2_in : float O2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_O2_out : float O2 flow at the cathode gas channel outlet (mol.m-2.s-1). J_N2_in : float N2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_N2_out : float N2 flow at the cathode gas channel outlet (mol.m-2.s-1). Wasm_in : float Anode side supply manifold inlet flow (kg.s-1). Wasm_out : float Anode side supply manifold outlet flow (kg.s-1). Waem_in : float Anode side external manifold inlet flow (kg.s-1). Waem_out : float Anode side external manifold outlet flow (kg.s-1). Wcsm_in : float Cathode side supply manifold inlet flow (kg.s-1). Wcsm_out : float Cathode side supply manifold outlet flow (kg.s-1). Wcem_in : float Cathode side external manifold inlet flow (kg.s-1). Wcem_out : float Cathode side external manifold outlet flow (kg.s-1). Ware : float Anode side recirculation flow (kg.s-1). Wv_asm_in : float Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out : float Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in : float Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out : float Vapor flow at the cathode external manifold outlet (mol.s-1). \"\"\" # __________________________________________________Preliminaries___________________________________________________ # Extraction of the variables Pasm, Paem, Pcsm = solver_variables['Pasm'], solver_variables['Paem'], solver_variables['Pcsm'] Pcem, Phi_asm, Phi_aem = solver_variables['Pcem'], solver_variables['Phi_asm'], solver_variables['Phi_aem'] Phi_csm, Phi_cem = solver_variables['Phi_csm'], solver_variables['Phi_cem'] Wcp, Wa_inj, Wc_inj = solver_variables['Wcp'], solver_variables['Wa_inj'], solver_variables['Wc_inj'] # Extraction of the operating inputs and the parameters Tfc, Pa_des, Pc_des = operating_inputs['Tfc'], operating_inputs['Pa_des'], operating_inputs['Pc_des'] Sa, Sc = operating_inputs['Sa'], operating_inputs['Sc'] Phi_a_des, Phi_c_des = control_variables['Phi_a_des'], control_variables['Phi_c_des'] Aact, Hgc, Wgc = parameters['Aact'], parameters['Hgc'], parameters['Wgc'] type_auxiliary = parameters['type_auxiliary'] # Intermediate values Mext, Pagc, Pcgc, Phi_agc, Phi_cgc, y_cgc, Magc, Mcgc, Pr_aem, Pr_cem, \\ Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c, i_n = \\ auxiliaries_int_values(t, solver_variables, operating_inputs, parameters) # _________________________________________Inlet and outlet global flows____________________________________________ \"\"\"Global flows here refer to flows that integrate all the chemical species circulating together. Slight differences are to be noted in the expression of these flows depending on the type of auxiliary selected. \"\"\" # At the anode side if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": # Anode inlet Wasm_in = Ksm_in * (Pa_des - Pasm) # kg.s-1 Wasm_out = Ksm_out * (Pasm - Pagc) # kg.s-1 Ja_in = Wasm_out / (Hgc * Wgc * Masm) # mol.m-2.s-1 # Anode outlet Waem_in = Kem_in * (Pagc - Paem) # kg.s-1 Ware = n_cell * Maem * (Paem / (Paem - Phi_aem * Psat(Tfc))) * (Sa - 1) * (i_fc + i_n) / ( 2 * F) * Aact # kg.s-1 Waem_out = k_purge * C_D * A_T * Paem / np.sqrt(R * Tfc) * Pr_aem ** (1 / gamma_H2) * \\ np.sqrt(Magc * 2 * gamma_H2 / (gamma_H2 - 1) * (1 - Pr_aem ** ((gamma_H2 - 1) / gamma_H2))) # kg.s-1 Ja_out = Waem_in / (Hgc * Wgc * Magc) # mol.m-2.s-1 elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Anode inlet Wrd = n_cell * M_H2 * Sa * (i_fc + i_n) / (2 * F) * Aact # kg.s-1 Wasm_in = Wrd + Wa_inj # kg.s-1 Wasm_out = Ksm_out * (Pasm - Pagc) # kg.s-1 Ja_in = Wasm_out / (Hgc * Wgc * Masm) # mol.m-2.s-1 # Anode outlet Waem_in = Kem_in * (Pagc - Paem) # kg.s-1 Ware = 0 # kg.s-1 Waem_out = C_D * Abp_a * Paem / np.sqrt(R * Tfc) * Pr_aem ** (1 / gamma_H2) * \\ np.sqrt(Magc * 2 * gamma_H2 / (gamma_H2 - 1) * (1 - Pr_aem ** ((gamma_H2 - 1) / gamma_H2))) # kg.s-1 Ja_out = Waem_in / (Hgc * Wgc * Magc) # mol.m-2.s-1 else: # elif type_auxiliary == \"no_auxiliary\" (only 1 cell): # Anode inlet Wasm_in, Wasm_out = 0, 0 # kg.s-1 Ja_in = (1 + Phi_a_des * Psat(Tfc) / (Pagc - Phi_a_des * Psat(Tfc))) * \\ Sa * (i_fc + i_n) / (2 * F) * Aact / (Hgc * Wgc) # mol.m-2.s-1 # Anode outlet Waem_in, Ware, Waem_out = 0, 0, 0 # kg.s-1 Ja_out = Kem_in * (Pagc - Pa_des) / (Hgc * Wgc * Magc) # mol.m-2.s-1 # At the cathode side if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Cathode inlet Wcsm_in = Wcp + Wc_inj # kg.s-1 Wcsm_out = Ksm_out * (Pcsm - Pcgc) # kg.s-1 Jc_in = Wcsm_out / (Hgc * Wgc * Mcsm) # mol.m-2.s-1 # Cathode outlet Wcem_in = Kem_in * (Pcgc - Pcem) # kg.s-1 Wcem_out = C_D * Abp_c * Pcem / np.sqrt(R * Tfc) * Pr_cem ** (1 / gamma) * \\ np.sqrt(Mcgc * 2 * gamma / (gamma - 1) * (1 - Pr_cem ** ((gamma - 1) / gamma))) # kg.s-1 Jc_out = Wcem_in / (Hgc * Wgc * Mcgc) # mol.m-2.s-1 else: # elif type_auxiliary == \"no_auxiliary\" (only 1 cell): # Cathode inlet Wcsm_in, Wcsm_out = 0, 0 # kg.s-1 Jc_in = (1 + Phi_c_des * Psat(Tfc) / (Pcgc - Phi_c_des * Psat(Tfc))) * \\ 1 / yO2_ext * Sc * (i_fc + i_n) / (4 * F) * Aact / (Hgc * Wgc) # mol.m-2.s-1 # Cathode outlet Wcem_in, Wcem_out = 0, 0 # kg.s-1 Jc_out = Kem_in * (Pcgc - Pc_des) / (Hgc * Wgc * Mcgc) # mol.m-2.s-1 # ________________________________________Inlet and outlet specific flows___________________________________________ \"\"\"Specific flows here refer to flows that integrate only a single chemical species within the ensemble of species circulating together. For example, only the water vapor flow within the ensemble of hydrogen and water vapor. \"\"\" # Vapor flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": Jv_a_in = Phi_asm * Psat(Tfc) / Pasm * Ja_in Jv_c_in = Phi_csm * Psat(Tfc) / Pcsm * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": Jv_a_in = Phi_a_des * Psat(Tfc) / Pagc * Ja_in Jv_c_in = Phi_c_des * Psat(Tfc) / Pcgc * Jc_in Jv_a_out = Phi_agc * Psat(Tfc) / Pagc * Ja_out Jv_c_out = Phi_cgc * Psat(Tfc) / Pcgc * Jc_out # H2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_H2_in = (1 - Phi_asm * Psat(Tfc) / Pasm) * Ja_in else: # elif type_auxiliary == \"no_auxiliary\": J_H2_in = (1 - Phi_a_des * Psat(Tfc) / Pagc) * Ja_in J_H2_out = (1 - Phi_agc * Psat(Tfc) / Pagc) * Ja_out # O2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_O2_in = yO2_ext * (1 - Phi_csm * Psat(Tfc) / Pcsm) * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": J_O2_in = yO2_ext * (1 - Phi_c_des * Psat(Tfc) / Pcgc) * Jc_in J_O2_out = y_cgc * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * Jc_out # N2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_N2_in = (1 - yO2_ext) * (1 - Phi_csm * Psat(Tfc) / Pcsm) * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": J_N2_in = (1 - yO2_ext) * (1 - Phi_c_des * Psat(Tfc) / Pcgc) * Jc_in J_N2_out = (1 - y_cgc) * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * Jc_out # Vapor flows at the manifold (mol.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": Wv_asm_in = Phi_aem * Psat(Tfc) / Paem * (Ware / Maem) Wv_aem_out = Phi_aem * Psat(Tfc) / Paem * (Waem_out / Maem) Wv_csm_in = Phi_ext * Psat(Text) / Pext * (Wcp / Mext) + Wc_inj / M_H2O Wv_cem_out = Phi_cem * Psat(Tfc) / Pcem * (Wcem_out / Mcem) elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": Wv_asm_in = Wa_inj / M_H2O Wv_aem_out = Phi_aem * Psat(Tfc) / Paem * (Waem_out / Maem) Wv_csm_in = Phi_ext * Psat(Text) / Pext * (Wcp / Mext) + Wc_inj / M_H2O Wv_cem_out = Phi_cem * Psat(Tfc) / Pcem * (Wcem_out / Mcem) else: # elif type_auxiliary == \"no_auxiliary\": Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out = [0] * 4 return Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, \\ J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, \\ Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, \\ Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out","title":"Auxiliaries"},{"location":"functions/model/auxiliaries/#auxiliaries","text":"This file represents all the flows passing through the auxiliaries. It is a component of the fuel cell model.","title":"Auxiliaries"},{"location":"functions/model/auxiliaries/#model.auxiliaries.auxiliaries","text":"This function calculates the flows passing through the auxiliaries. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. i_fc ( float ) \u2013 Fuel cell current density at time t (A.m-2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Jv_a_in ( float ) \u2013 Vapor flow at the anode gas channel inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Vapor flow at the anode gas channel outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Vapor flow at the cathode gas channel inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Vapor flow at the cathode gas channel outlet (mol.m-2.s-1). J_H2_in ( float ) \u2013 H2 flow at the anode gas channel inlet (mol.m-2.s-1). J_H2_out ( float ) \u2013 H2 flow at the anode gas channel outlet (mol.m-2.s-1). J_O2_in ( float ) \u2013 O2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_O2_out ( float ) \u2013 O2 flow at the cathode gas channel outlet (mol.m-2.s-1). J_N2_in ( float ) \u2013 N2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_N2_out ( float ) \u2013 N2 flow at the cathode gas channel outlet (mol.m-2.s-1). Wasm_in ( float ) \u2013 Anode side supply manifold inlet flow (kg.s-1). Wasm_out ( float ) \u2013 Anode side supply manifold outlet flow (kg.s-1). Waem_in ( float ) \u2013 Anode side external manifold inlet flow (kg.s-1). Waem_out ( float ) \u2013 Anode side external manifold outlet flow (kg.s-1). Wcsm_in ( float ) \u2013 Cathode side supply manifold inlet flow (kg.s-1). Wcsm_out ( float ) \u2013 Cathode side supply manifold outlet flow (kg.s-1). Wcem_in ( float ) \u2013 Cathode side external manifold inlet flow (kg.s-1). Wcem_out ( float ) \u2013 Cathode side external manifold outlet flow (kg.s-1). Ware ( float ) \u2013 Anode side recirculation flow (kg.s-1). Wv_asm_in ( float ) \u2013 Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out ( float ) \u2013 Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in ( float ) \u2013 Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out ( float ) \u2013 Vapor flow at the cathode external manifold outlet (mol.s-1). Source code in model/auxiliaries.py def auxiliaries(t, solver_variables, control_variables, i_fc, operating_inputs, parameters): \"\"\"This function calculates the flows passing through the auxiliaries. Parameters ---------- t : float Time (s). solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. i_fc : float Fuel cell current density at time t (A.m-2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Jv_a_in : float Vapor flow at the anode gas channel inlet (mol.m-2.s-1). Jv_a_out : float Vapor flow at the anode gas channel outlet (mol.m-2.s-1). Jv_c_in : float Vapor flow at the cathode gas channel inlet (mol.m-2.s-1). Jv_c_out : float Vapor flow at the cathode gas channel outlet (mol.m-2.s-1). J_H2_in : float H2 flow at the anode gas channel inlet (mol.m-2.s-1). J_H2_out : float H2 flow at the anode gas channel outlet (mol.m-2.s-1). J_O2_in : float O2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_O2_out : float O2 flow at the cathode gas channel outlet (mol.m-2.s-1). J_N2_in : float N2 flow at the cathode gas channel inlet (mol.m-2.s-1). J_N2_out : float N2 flow at the cathode gas channel outlet (mol.m-2.s-1). Wasm_in : float Anode side supply manifold inlet flow (kg.s-1). Wasm_out : float Anode side supply manifold outlet flow (kg.s-1). Waem_in : float Anode side external manifold inlet flow (kg.s-1). Waem_out : float Anode side external manifold outlet flow (kg.s-1). Wcsm_in : float Cathode side supply manifold inlet flow (kg.s-1). Wcsm_out : float Cathode side supply manifold outlet flow (kg.s-1). Wcem_in : float Cathode side external manifold inlet flow (kg.s-1). Wcem_out : float Cathode side external manifold outlet flow (kg.s-1). Ware : float Anode side recirculation flow (kg.s-1). Wv_asm_in : float Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out : float Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in : float Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out : float Vapor flow at the cathode external manifold outlet (mol.s-1). \"\"\" # __________________________________________________Preliminaries___________________________________________________ # Extraction of the variables Pasm, Paem, Pcsm = solver_variables['Pasm'], solver_variables['Paem'], solver_variables['Pcsm'] Pcem, Phi_asm, Phi_aem = solver_variables['Pcem'], solver_variables['Phi_asm'], solver_variables['Phi_aem'] Phi_csm, Phi_cem = solver_variables['Phi_csm'], solver_variables['Phi_cem'] Wcp, Wa_inj, Wc_inj = solver_variables['Wcp'], solver_variables['Wa_inj'], solver_variables['Wc_inj'] # Extraction of the operating inputs and the parameters Tfc, Pa_des, Pc_des = operating_inputs['Tfc'], operating_inputs['Pa_des'], operating_inputs['Pc_des'] Sa, Sc = operating_inputs['Sa'], operating_inputs['Sc'] Phi_a_des, Phi_c_des = control_variables['Phi_a_des'], control_variables['Phi_c_des'] Aact, Hgc, Wgc = parameters['Aact'], parameters['Hgc'], parameters['Wgc'] type_auxiliary = parameters['type_auxiliary'] # Intermediate values Mext, Pagc, Pcgc, Phi_agc, Phi_cgc, y_cgc, Magc, Mcgc, Pr_aem, Pr_cem, \\ Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c, i_n = \\ auxiliaries_int_values(t, solver_variables, operating_inputs, parameters) # _________________________________________Inlet and outlet global flows____________________________________________ \"\"\"Global flows here refer to flows that integrate all the chemical species circulating together. Slight differences are to be noted in the expression of these flows depending on the type of auxiliary selected. \"\"\" # At the anode side if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": # Anode inlet Wasm_in = Ksm_in * (Pa_des - Pasm) # kg.s-1 Wasm_out = Ksm_out * (Pasm - Pagc) # kg.s-1 Ja_in = Wasm_out / (Hgc * Wgc * Masm) # mol.m-2.s-1 # Anode outlet Waem_in = Kem_in * (Pagc - Paem) # kg.s-1 Ware = n_cell * Maem * (Paem / (Paem - Phi_aem * Psat(Tfc))) * (Sa - 1) * (i_fc + i_n) / ( 2 * F) * Aact # kg.s-1 Waem_out = k_purge * C_D * A_T * Paem / np.sqrt(R * Tfc) * Pr_aem ** (1 / gamma_H2) * \\ np.sqrt(Magc * 2 * gamma_H2 / (gamma_H2 - 1) * (1 - Pr_aem ** ((gamma_H2 - 1) / gamma_H2))) # kg.s-1 Ja_out = Waem_in / (Hgc * Wgc * Magc) # mol.m-2.s-1 elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Anode inlet Wrd = n_cell * M_H2 * Sa * (i_fc + i_n) / (2 * F) * Aact # kg.s-1 Wasm_in = Wrd + Wa_inj # kg.s-1 Wasm_out = Ksm_out * (Pasm - Pagc) # kg.s-1 Ja_in = Wasm_out / (Hgc * Wgc * Masm) # mol.m-2.s-1 # Anode outlet Waem_in = Kem_in * (Pagc - Paem) # kg.s-1 Ware = 0 # kg.s-1 Waem_out = C_D * Abp_a * Paem / np.sqrt(R * Tfc) * Pr_aem ** (1 / gamma_H2) * \\ np.sqrt(Magc * 2 * gamma_H2 / (gamma_H2 - 1) * (1 - Pr_aem ** ((gamma_H2 - 1) / gamma_H2))) # kg.s-1 Ja_out = Waem_in / (Hgc * Wgc * Magc) # mol.m-2.s-1 else: # elif type_auxiliary == \"no_auxiliary\" (only 1 cell): # Anode inlet Wasm_in, Wasm_out = 0, 0 # kg.s-1 Ja_in = (1 + Phi_a_des * Psat(Tfc) / (Pagc - Phi_a_des * Psat(Tfc))) * \\ Sa * (i_fc + i_n) / (2 * F) * Aact / (Hgc * Wgc) # mol.m-2.s-1 # Anode outlet Waem_in, Ware, Waem_out = 0, 0, 0 # kg.s-1 Ja_out = Kem_in * (Pagc - Pa_des) / (Hgc * Wgc * Magc) # mol.m-2.s-1 # At the cathode side if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Cathode inlet Wcsm_in = Wcp + Wc_inj # kg.s-1 Wcsm_out = Ksm_out * (Pcsm - Pcgc) # kg.s-1 Jc_in = Wcsm_out / (Hgc * Wgc * Mcsm) # mol.m-2.s-1 # Cathode outlet Wcem_in = Kem_in * (Pcgc - Pcem) # kg.s-1 Wcem_out = C_D * Abp_c * Pcem / np.sqrt(R * Tfc) * Pr_cem ** (1 / gamma) * \\ np.sqrt(Mcgc * 2 * gamma / (gamma - 1) * (1 - Pr_cem ** ((gamma - 1) / gamma))) # kg.s-1 Jc_out = Wcem_in / (Hgc * Wgc * Mcgc) # mol.m-2.s-1 else: # elif type_auxiliary == \"no_auxiliary\" (only 1 cell): # Cathode inlet Wcsm_in, Wcsm_out = 0, 0 # kg.s-1 Jc_in = (1 + Phi_c_des * Psat(Tfc) / (Pcgc - Phi_c_des * Psat(Tfc))) * \\ 1 / yO2_ext * Sc * (i_fc + i_n) / (4 * F) * Aact / (Hgc * Wgc) # mol.m-2.s-1 # Cathode outlet Wcem_in, Wcem_out = 0, 0 # kg.s-1 Jc_out = Kem_in * (Pcgc - Pc_des) / (Hgc * Wgc * Mcgc) # mol.m-2.s-1 # ________________________________________Inlet and outlet specific flows___________________________________________ \"\"\"Specific flows here refer to flows that integrate only a single chemical species within the ensemble of species circulating together. For example, only the water vapor flow within the ensemble of hydrogen and water vapor. \"\"\" # Vapor flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": Jv_a_in = Phi_asm * Psat(Tfc) / Pasm * Ja_in Jv_c_in = Phi_csm * Psat(Tfc) / Pcsm * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": Jv_a_in = Phi_a_des * Psat(Tfc) / Pagc * Ja_in Jv_c_in = Phi_c_des * Psat(Tfc) / Pcgc * Jc_in Jv_a_out = Phi_agc * Psat(Tfc) / Pagc * Ja_out Jv_c_out = Phi_cgc * Psat(Tfc) / Pcgc * Jc_out # H2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_H2_in = (1 - Phi_asm * Psat(Tfc) / Pasm) * Ja_in else: # elif type_auxiliary == \"no_auxiliary\": J_H2_in = (1 - Phi_a_des * Psat(Tfc) / Pagc) * Ja_in J_H2_out = (1 - Phi_agc * Psat(Tfc) / Pagc) * Ja_out # O2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_O2_in = yO2_ext * (1 - Phi_csm * Psat(Tfc) / Pcsm) * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": J_O2_in = yO2_ext * (1 - Phi_c_des * Psat(Tfc) / Pcgc) * Jc_in J_O2_out = y_cgc * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * Jc_out # N2 flows at the GC (mol.m-2.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": J_N2_in = (1 - yO2_ext) * (1 - Phi_csm * Psat(Tfc) / Pcsm) * Jc_in else: # elif type_auxiliary == \"no_auxiliary\": J_N2_in = (1 - yO2_ext) * (1 - Phi_c_des * Psat(Tfc) / Pcgc) * Jc_in J_N2_out = (1 - y_cgc) * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * Jc_out # Vapor flows at the manifold (mol.s-1) if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": Wv_asm_in = Phi_aem * Psat(Tfc) / Paem * (Ware / Maem) Wv_aem_out = Phi_aem * Psat(Tfc) / Paem * (Waem_out / Maem) Wv_csm_in = Phi_ext * Psat(Text) / Pext * (Wcp / Mext) + Wc_inj / M_H2O Wv_cem_out = Phi_cem * Psat(Tfc) / Pcem * (Wcem_out / Mcem) elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": Wv_asm_in = Wa_inj / M_H2O Wv_aem_out = Phi_aem * Psat(Tfc) / Paem * (Waem_out / Maem) Wv_csm_in = Phi_ext * Psat(Text) / Pext * (Wcp / Mext) + Wc_inj / M_H2O Wv_cem_out = Phi_cem * Psat(Tfc) / Pcem * (Wcem_out / Mcem) else: # elif type_auxiliary == \"no_auxiliary\": Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out = [0] * 4 return Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, \\ J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, \\ Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, \\ Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out","title":"auxiliaries"},{"location":"functions/model/cell_voltage/","text":"Cell voltage This file represents the equations for calculating the cell voltage. It is a component of the fuel cell model. calculate_cell_voltage(variables, operating_inputs, parameters) This function calculates the cell voltage at each time step. Parameters: variables ( dict ) \u2013 The dictionary containing the variables calculated by the solver. operating_inputs ( dict ) \u2013 The dictionary containing the operating inputs. parameters ( dict ) \u2013 The dictionary containing the parameters. Returns: Ucell_t ( list ) \u2013 The cell voltage at each time step. Source code in model/cell_voltage.py def calculate_cell_voltage(variables, operating_inputs, parameters): \"\"\"This function calculates the cell voltage at each time step. Parameters ---------- variables : dict The dictionary containing the variables calculated by the solver. operating_inputs : dict The dictionary containing the operating inputs. parameters : dict The dictionary containing the parameters. Returns ------- Ucell_t : list The cell voltage at each time step. \"\"\" # Extraction of the variables t, lambda_mem_t, lambda_ccl_t = variables['t'], variables['lambda_mem'], variables['lambda_ccl'] C_H2_acl_t, C_O2_ccl_t, eta_c_t = variables['C_H2_acl'], variables['C_O2_ccl'], variables['eta_c'] # Extraction of the operating inputs and the parameters Tfc = operating_inputs['Tfc'] Hmem, Hcl, epsilon_mc, tau = parameters['Hmem'], parameters['Hcl'], parameters['epsilon_mc'], parameters['tau'] Re, kappa_co = parameters['Re'], parameters['kappa_co'] # Initialisation n = len(t) Ucell_t = [0] * n # Loop for having Ucell_t at each time step for i in range(n): # Recovery of the already calculated variable values at each time step lambda_mem, lambda_ccl = lambda_mem_t[i], lambda_ccl_t[i] C_H2_acl, C_O2_ccl = C_H2_acl_t[i], C_O2_ccl_t[i] eta_c = eta_c_t[i] # Current density value at this time step i_fc = operating_inputs['current_density'](t[i], parameters) # The equilibrium potential Ueq = E0 - 8.5e-4 * (Tfc - 298.15) + R * Tfc / (2 * F) * (np.log(R * Tfc * C_H2_acl / Pref) + 0.5 * np.log(R * Tfc * C_O2_ccl / Pref)) # The crossover current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # The proton resistance # The proton resistance at the membrane : Rmem if lambda_mem >= 1: Rmem = Hmem / ((0.5139 * lambda_mem - 0.326) * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) else: Rmem = Hmem / (0.1879 * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) # The proton resistance at the cathode catalyst layer : Rccl if lambda_ccl >= 1: Rccl = Hcl / ((epsilon_mc ** tau) * (0.5139 * lambda_ccl - 0.326) * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) else: Rccl = Hcl / ((epsilon_mc ** tau) * 0.1879 * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) # The total proton resistance Rp = Rmem + Rccl # its value is around [4-7]e-6 ohm.m\u00b2. # The cell voltage Ucell_t[i] = Ueq - eta_c - (i_fc + i_n) * (Rp + Re) return Ucell_t calculate_eta_c_intermediate_values(solver_variables, operating_inputs, parameters) This function calculates the intermediate values needed for the calculation of the cathode overpotential dynamic evolution. Parameters: solver_variables ( dict ) \u2013 The dictionary containing the variables calculated by the solver. operating_inputs ( dict ) \u2013 The dictionary containing the operating inputs. parameters ( dict ) \u2013 The dictionary containing the parameters. Returns: dict \u2013 The dictionary containing the crossover current density i_n at time t, and the liquid water induced voltage drop function f_drop at time t. Source code in model/cell_voltage.py def calculate_eta_c_intermediate_values(solver_variables, operating_inputs, parameters): \"\"\"This function calculates the intermediate values needed for the calculation of the cathode overpotential dynamic evolution. Parameters ---------- solver_variables : dict The dictionary containing the variables calculated by the solver. operating_inputs : dict The dictionary containing the operating inputs. parameters : dict The dictionary containing the parameters. Returns ------- dict The dictionary containing the crossover current density i_n at time t, and the liquid water induced voltage drop function f_drop at time t. \"\"\" # Extraction of the variables s_ccl, lambda_mem = solver_variables['s_ccl'], solver_variables['lambda_mem'] C_H2_acl, C_O2_ccl = solver_variables['C_H2_acl'], solver_variables['C_O2_ccl'] # Extraction of the operating inputs and the parameters Tfc, Pc_des = operating_inputs['Tfc'], operating_inputs['Pc_des'] Hmem = parameters['Hmem'] i0_c_ref, kappa_co, kappa_c = parameters['i0_c_ref'], parameters['kappa_co'], parameters['kappa_c'] a_slim, b_slim, a_switch = parameters['a_slim'], parameters['b_slim'], parameters['a_switch'] # The crossover current density i_n i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # The liquid water induced voltage drop function f_drop slim = a_slim * (Pc_des / 1e5) + b_slim s_switch = a_switch * slim f_drop = 0.5 * (1.0 - np.tanh((4 * s_ccl - 2 * slim - 2 * s_switch) / (slim - s_switch))) return {'i_n': i_n, 'f_drop': f_drop}","title":"Cell voltage"},{"location":"functions/model/cell_voltage/#cell-voltage","text":"This file represents the equations for calculating the cell voltage. It is a component of the fuel cell model.","title":"Cell voltage"},{"location":"functions/model/cell_voltage/#model.cell_voltage.calculate_cell_voltage","text":"This function calculates the cell voltage at each time step. Parameters: variables ( dict ) \u2013 The dictionary containing the variables calculated by the solver. operating_inputs ( dict ) \u2013 The dictionary containing the operating inputs. parameters ( dict ) \u2013 The dictionary containing the parameters. Returns: Ucell_t ( list ) \u2013 The cell voltage at each time step. Source code in model/cell_voltage.py def calculate_cell_voltage(variables, operating_inputs, parameters): \"\"\"This function calculates the cell voltage at each time step. Parameters ---------- variables : dict The dictionary containing the variables calculated by the solver. operating_inputs : dict The dictionary containing the operating inputs. parameters : dict The dictionary containing the parameters. Returns ------- Ucell_t : list The cell voltage at each time step. \"\"\" # Extraction of the variables t, lambda_mem_t, lambda_ccl_t = variables['t'], variables['lambda_mem'], variables['lambda_ccl'] C_H2_acl_t, C_O2_ccl_t, eta_c_t = variables['C_H2_acl'], variables['C_O2_ccl'], variables['eta_c'] # Extraction of the operating inputs and the parameters Tfc = operating_inputs['Tfc'] Hmem, Hcl, epsilon_mc, tau = parameters['Hmem'], parameters['Hcl'], parameters['epsilon_mc'], parameters['tau'] Re, kappa_co = parameters['Re'], parameters['kappa_co'] # Initialisation n = len(t) Ucell_t = [0] * n # Loop for having Ucell_t at each time step for i in range(n): # Recovery of the already calculated variable values at each time step lambda_mem, lambda_ccl = lambda_mem_t[i], lambda_ccl_t[i] C_H2_acl, C_O2_ccl = C_H2_acl_t[i], C_O2_ccl_t[i] eta_c = eta_c_t[i] # Current density value at this time step i_fc = operating_inputs['current_density'](t[i], parameters) # The equilibrium potential Ueq = E0 - 8.5e-4 * (Tfc - 298.15) + R * Tfc / (2 * F) * (np.log(R * Tfc * C_H2_acl / Pref) + 0.5 * np.log(R * Tfc * C_O2_ccl / Pref)) # The crossover current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # The proton resistance # The proton resistance at the membrane : Rmem if lambda_mem >= 1: Rmem = Hmem / ((0.5139 * lambda_mem - 0.326) * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) else: Rmem = Hmem / (0.1879 * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) # The proton resistance at the cathode catalyst layer : Rccl if lambda_ccl >= 1: Rccl = Hcl / ((epsilon_mc ** tau) * (0.5139 * lambda_ccl - 0.326) * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) else: Rccl = Hcl / ((epsilon_mc ** tau) * 0.1879 * np.exp(1268 * (1 / 303.15 - 1 / Tfc))) # The total proton resistance Rp = Rmem + Rccl # its value is around [4-7]e-6 ohm.m\u00b2. # The cell voltage Ucell_t[i] = Ueq - eta_c - (i_fc + i_n) * (Rp + Re) return Ucell_t","title":"calculate_cell_voltage"},{"location":"functions/model/cell_voltage/#model.cell_voltage.calculate_eta_c_intermediate_values","text":"This function calculates the intermediate values needed for the calculation of the cathode overpotential dynamic evolution. Parameters: solver_variables ( dict ) \u2013 The dictionary containing the variables calculated by the solver. operating_inputs ( dict ) \u2013 The dictionary containing the operating inputs. parameters ( dict ) \u2013 The dictionary containing the parameters. Returns: dict \u2013 The dictionary containing the crossover current density i_n at time t, and the liquid water induced voltage drop function f_drop at time t. Source code in model/cell_voltage.py def calculate_eta_c_intermediate_values(solver_variables, operating_inputs, parameters): \"\"\"This function calculates the intermediate values needed for the calculation of the cathode overpotential dynamic evolution. Parameters ---------- solver_variables : dict The dictionary containing the variables calculated by the solver. operating_inputs : dict The dictionary containing the operating inputs. parameters : dict The dictionary containing the parameters. Returns ------- dict The dictionary containing the crossover current density i_n at time t, and the liquid water induced voltage drop function f_drop at time t. \"\"\" # Extraction of the variables s_ccl, lambda_mem = solver_variables['s_ccl'], solver_variables['lambda_mem'] C_H2_acl, C_O2_ccl = solver_variables['C_H2_acl'], solver_variables['C_O2_ccl'] # Extraction of the operating inputs and the parameters Tfc, Pc_des = operating_inputs['Tfc'], operating_inputs['Pc_des'] Hmem = parameters['Hmem'] i0_c_ref, kappa_co, kappa_c = parameters['i0_c_ref'], parameters['kappa_co'], parameters['kappa_c'] a_slim, b_slim, a_switch = parameters['a_slim'], parameters['b_slim'], parameters['a_switch'] # The crossover current density i_n i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # The liquid water induced voltage drop function f_drop slim = a_slim * (Pc_des / 1e5) + b_slim s_switch = a_switch * slim f_drop = 0.5 * (1.0 - np.tanh((4 * s_ccl - 2 * slim - 2 * s_switch) / (slim - s_switch))) return {'i_n': i_n, 'f_drop': f_drop}","title":"calculate_eta_c_intermediate_values"},{"location":"functions/model/control/","text":"Control This module contains the function that control the operating conditions of the MEA system. control_operating_conditions(t, solver_variables, operating_inputs, parameters, control_variables) This function controls the operating conditions of the MEA system, if required. This is an elementary rule-based control, serving as a demonstrator. It will need to be improved in the future. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Dictionary containing the solver variables. operating_inputs ( dict ) \u2013 Dictionary containing the operating inputs. parameters ( dict ) \u2013 Dictionary containing the parameters. control_variables ( dict ) \u2013 Dictionary containing the control variables. Source code in model/control.py def control_operating_conditions(t, solver_variables, operating_inputs, parameters, control_variables): \"\"\"This function controls the operating conditions of the MEA system, if required. This is an elementary rule-based control, serving as a demonstrator. It will need to be improved in the future. Parameters ---------- t : float Time (s). solver_variables : dict Dictionary containing the solver variables. operating_inputs : dict Dictionary containing the operating inputs. parameters : dict Dictionary containing the parameters. control_variables : dict Dictionary containing the control variables. \"\"\" if parameters[\"type_control\"] != \"Phi_des\": raise ValueError('You have to specify a type_control which is accepted.') elif parameters[\"type_control\"] == \"Phi_des\": # Initialisation delta_t_control_Phi = 20 # s. Every delta_t_control_Phi second the cell humidity is controlled. delta_Phi_des = 0.01 # Arbitrary value for the step change of Phi_des. slim = parameters['a_slim'] * (operating_inputs['Pc_des'] / 1e5) + parameters['b_slim'] s_ccl_max = 0.55 * slim # An arbitrary margin for s_ccl is established to ensure the CCL is not too flooded. # I may take s_switch instead of 0.55 ? lambda_mem_min = 8 # An arbitrary margin for lambda_mem is established to ensure the membrane is not too dry. # Control on Phi_des # Every delta_t_control_Phi second, Phi_a_des is monitored for controlling the cell humidity. if t > (control_variables['t_control_Phi'] + delta_t_control_Phi): # s. control_variables['t_control_Phi'] = control_variables['t_control_Phi'] + delta_t_control_Phi # Flooding is likely. if solver_variables['s_ccl'] > s_ccl_max and solver_variables['lambda_mem'] > lambda_mem_min: if control_variables['Phi_a_des'] - delta_Phi_des >= 0: control_variables['Phi_a_des'] = control_variables['Phi_a_des'] - delta_Phi_des if control_variables['Phi_c_des'] - delta_Phi_des >= 0: control_variables['Phi_c_des'] = control_variables['Phi_c_des'] - delta_Phi_des # Drying out is likely. elif solver_variables['lambda_mem'] < lambda_mem_min and solver_variables['s_ccl'] < s_ccl_max: if control_variables['Phi_a_des'] + delta_Phi_des <= 1: control_variables['Phi_a_des'] = control_variables['Phi_a_des'] + delta_Phi_des if control_variables['Phi_c_des'] + delta_Phi_des <= 1: control_variables['Phi_c_des'] = control_variables['Phi_c_des'] + delta_Phi_des # Both flooding and drying out are likely. Nothing can be done. elif solver_variables['s_ccl'] > s_ccl_max and solver_variables['lambda_mem'] < lambda_mem_min: pass # Both flooding and drying out are unlikely. It is the desired situation. else: # elif solver_variables['s_ccl'] < s_ccl_max and solver_variables['lambda_mem'] > lambda_mem_min: pass","title":"Control"},{"location":"functions/model/control/#control","text":"This module contains the function that control the operating conditions of the MEA system.","title":"Control"},{"location":"functions/model/control/#model.control.control_operating_conditions","text":"This function controls the operating conditions of the MEA system, if required. This is an elementary rule-based control, serving as a demonstrator. It will need to be improved in the future. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Dictionary containing the solver variables. operating_inputs ( dict ) \u2013 Dictionary containing the operating inputs. parameters ( dict ) \u2013 Dictionary containing the parameters. control_variables ( dict ) \u2013 Dictionary containing the control variables. Source code in model/control.py def control_operating_conditions(t, solver_variables, operating_inputs, parameters, control_variables): \"\"\"This function controls the operating conditions of the MEA system, if required. This is an elementary rule-based control, serving as a demonstrator. It will need to be improved in the future. Parameters ---------- t : float Time (s). solver_variables : dict Dictionary containing the solver variables. operating_inputs : dict Dictionary containing the operating inputs. parameters : dict Dictionary containing the parameters. control_variables : dict Dictionary containing the control variables. \"\"\" if parameters[\"type_control\"] != \"Phi_des\": raise ValueError('You have to specify a type_control which is accepted.') elif parameters[\"type_control\"] == \"Phi_des\": # Initialisation delta_t_control_Phi = 20 # s. Every delta_t_control_Phi second the cell humidity is controlled. delta_Phi_des = 0.01 # Arbitrary value for the step change of Phi_des. slim = parameters['a_slim'] * (operating_inputs['Pc_des'] / 1e5) + parameters['b_slim'] s_ccl_max = 0.55 * slim # An arbitrary margin for s_ccl is established to ensure the CCL is not too flooded. # I may take s_switch instead of 0.55 ? lambda_mem_min = 8 # An arbitrary margin for lambda_mem is established to ensure the membrane is not too dry. # Control on Phi_des # Every delta_t_control_Phi second, Phi_a_des is monitored for controlling the cell humidity. if t > (control_variables['t_control_Phi'] + delta_t_control_Phi): # s. control_variables['t_control_Phi'] = control_variables['t_control_Phi'] + delta_t_control_Phi # Flooding is likely. if solver_variables['s_ccl'] > s_ccl_max and solver_variables['lambda_mem'] > lambda_mem_min: if control_variables['Phi_a_des'] - delta_Phi_des >= 0: control_variables['Phi_a_des'] = control_variables['Phi_a_des'] - delta_Phi_des if control_variables['Phi_c_des'] - delta_Phi_des >= 0: control_variables['Phi_c_des'] = control_variables['Phi_c_des'] - delta_Phi_des # Drying out is likely. elif solver_variables['lambda_mem'] < lambda_mem_min and solver_variables['s_ccl'] < s_ccl_max: if control_variables['Phi_a_des'] + delta_Phi_des <= 1: control_variables['Phi_a_des'] = control_variables['Phi_a_des'] + delta_Phi_des if control_variables['Phi_c_des'] + delta_Phi_des <= 1: control_variables['Phi_c_des'] = control_variables['Phi_c_des'] + delta_Phi_des # Both flooding and drying out are likely. Nothing can be done. elif solver_variables['s_ccl'] > s_ccl_max and solver_variables['lambda_mem'] < lambda_mem_min: pass # Both flooding and drying out are unlikely. It is the desired situation. else: # elif solver_variables['s_ccl'] < s_ccl_max and solver_variables['lambda_mem'] > lambda_mem_min: pass","title":"control_operating_conditions"},{"location":"functions/model/dif_eq/","text":"Differential equations This file represents all the differential equations used for the fuel cell model. calculate_dyn_H2_O2_N2_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, J_H2_agc_agdl, J_H2_agdl_agdl, J_H2_agdl_acl, J_O2_ccl_cgdl, J_O2_cgdl_cgdl, J_O2_cgdl_cgc, S_H2_acl, S_O2_ccl, **kwargs) This function calculates the dynamic evolution of the hydrogen, oxygen and nitrogen in the gas channels, the gas diffusion layers and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). Hgc ( float ) \u2013 Thickness of the gas channel (m). Lgc ( float ) \u2013 Length of the gas channel (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. J_H2_in ( float ) \u2013 Hydrogen flow at the anode inlet (mol.m-2.s-1). J_H2_out ( float ) \u2013 Hydrogen flow at the anode outlet (mol.m-2.s-1). J_O2_in ( float ) \u2013 Oxygen flow at the cathode inlet (mol.m-2.s-1). J_O2_out ( float ) \u2013 Oxygen flow at the cathode outlet (mol.m-2.s-1). J_N2_in ( float ) \u2013 Nitrogen flow at the cathode inlet (mol.m-2.s-1). J_N2_out ( float ) \u2013 Nitrogen flow at the cathode outlet (mol.m-2.s-1). J_H2_agc_agdl ( float ) \u2013 Hydrogen flow between the anode gas channel and the anode GDL (mol.m-2.s-1). J_H2_agdl_agdl ( list ) \u2013 Hydrogen flow between two nodes of the anode GDL (mol.m-2.s-1). J_H2_agdl_acl ( float ) \u2013 Hydrogen flow between the anode GDL and the anode CL (mol.m-2.s-1). J_O2_ccl_cgdl ( float ) \u2013 Oxygen flow between the cathode CL and the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgdl ( list ) \u2013 Oxygen flow between two nodes of the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgc ( float ) \u2013 Oxygen flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). S_H2_acl ( float ) \u2013 Hydrogen consumed in the anode CL (mol.m-3.s-1). S_O2_ccl ( float ) \u2013 Oxygen consumed in the cathode CL (mol.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_H2_O2_N2_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, J_H2_agc_agdl, J_H2_agdl_agdl, J_H2_agdl_acl, J_O2_ccl_cgdl, J_O2_cgdl_cgdl, J_O2_cgdl_cgc, S_H2_acl, S_O2_ccl, **kwargs): \"\"\"This function calculates the dynamic evolution of the hydrogen, oxygen and nitrogen in the gas channels, the gas diffusion layers and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). Hgc : float Thickness of the gas channel (m). Lgc : float Length of the gas channel (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. J_H2_in : float Hydrogen flow at the anode inlet (mol.m-2.s-1). J_H2_out : float Hydrogen flow at the anode outlet (mol.m-2.s-1). J_O2_in : float Oxygen flow at the cathode inlet (mol.m-2.s-1). J_O2_out : float Oxygen flow at the cathode outlet (mol.m-2.s-1). J_N2_in : float Nitrogen flow at the cathode inlet (mol.m-2.s-1). J_N2_out : float Nitrogen flow at the cathode outlet (mol.m-2.s-1). J_H2_agc_agdl : float Hydrogen flow between the anode gas channel and the anode GDL (mol.m-2.s-1). J_H2_agdl_agdl : list Hydrogen flow between two nodes of the anode GDL (mol.m-2.s-1). J_H2_agdl_acl : float Hydrogen flow between the anode GDL and the anode CL (mol.m-2.s-1). J_O2_ccl_cgdl : float Oxygen flow between the cathode CL and the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgdl : list Oxygen flow between two nodes of the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgc : float Oxygen flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). S_H2_acl : float Hydrogen consumed in the anode CL (mol.m-3.s-1). S_O2_ccl : float Oxygen consumed in the cathode CL (mol.m-3.s-1). \"\"\" # At the anode side # Inside the AGC dif_eq['dC_H2_agc / dt'] = (J_H2_in - J_H2_out) / Lgc - J_H2_agc_agdl / Hgc # Inside the AGDL dif_eq['dC_H2_agdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_agdl_1'])) * \\ (J_H2_agc_agdl - J_H2_agdl_agdl[1]) / (Hgdl / n_gdl) for i in range(2, n_gdl): dif_eq[f'dC_H2_agdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{i}'])) * \\ (J_H2_agdl_agdl[i - 1] - J_H2_agdl_agdl[i]) / (Hgdl / n_gdl) dif_eq[f'dC_H2_agdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{n_gdl}'])) * \\ (J_H2_agdl_agdl[n_gdl - 1] - J_H2_agdl_acl) / (Hgdl / n_gdl) # Inside the ACL dif_eq['dC_H2_acl / dt'] = 1 / (epsilon_cl * (1 - sv['s_acl'])) * (J_H2_agdl_acl / Hcl + S_H2_acl) # At the cathode side # Inside the CCL dif_eq['dC_O2_ccl / dt'] = 1 / (epsilon_cl * (1 - sv['s_ccl'])) * (-J_O2_ccl_cgdl / Hcl + S_O2_ccl) # Inside the CGDL dif_eq['dC_O2_cgdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_cgdl_1'])) * \\ (J_O2_ccl_cgdl - J_O2_cgdl_cgdl[1]) / (Hgdl / n_gdl) for i in range(2, n_gdl): dif_eq[f'dC_O2_cgdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{i}'])) * \\ (J_O2_cgdl_cgdl[i - 1] - J_O2_cgdl_cgdl[i]) / (Hgdl / n_gdl) dif_eq[f'dC_O2_cgdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{n_gdl}'])) * \\ (J_O2_cgdl_cgdl[n_gdl - 1] - J_O2_cgdl_cgc) / (Hgdl / n_gdl) # Inside the CGC dif_eq['dC_O2_cgc / dt'] = (J_O2_in - J_O2_out) / Lgc + J_O2_cgdl_cgc / Hgc # Inside the whole cell dif_eq['dC_N2 / dt'] = (J_N2_in - J_N2_out) / Lgc calculate_dyn_air_compressor_and_humidifier_evolution(dif_eq, Wcp_des, Wa_inj_des, Wc_inj_des, type_auxiliary, Wcp, Wa_inj, Wc_inj, **kwargs) This function calculates the dynamic evolution of the air compressor and the humidifiers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Wcp_des ( float ) \u2013 Desired air compressor flow rate (kg.s-1). Wa_inj_des ( float ) \u2013 Desired anode humidifier flow rate (kg.s-1). Wc_inj_des ( float ) \u2013 Desired cathode humidifier flow rate (kg.s-1). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Wcp ( float ) \u2013 Air compressor flow rate (kg.s-1). Wa_inj ( float ) \u2013 Anode humidifier flow rate (kg.s-1). Wc_inj ( float ) \u2013 Cathode humidifier flow rate (kg.s-1). Source code in model/dif_eq.py def calculate_dyn_air_compressor_and_humidifier_evolution(dif_eq, Wcp_des, Wa_inj_des, Wc_inj_des, type_auxiliary, Wcp, Wa_inj, Wc_inj, **kwargs): \"\"\"This function calculates the dynamic evolution of the air compressor and the humidifiers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Wcp_des : float Desired air compressor flow rate (kg.s-1). Wa_inj_des : float Desired anode humidifier flow rate (kg.s-1). Wc_inj_des : float Desired cathode humidifier flow rate (kg.s-1). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Wcp : float Air compressor flow rate (kg.s-1). Wa_inj : float Anode humidifier flow rate (kg.s-1). Wc_inj : float Cathode humidifier flow rate (kg.s-1). \"\"\" # Air compressor evolution if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dWcp / dt'] = (Wcp_des - Wcp) / tau_cp # Estimation at the first order. elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dWcp / dt'] = (Wcp_des - Wcp) / tau_cp # Estimation at the first order. else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dWcp / dt'] = 0 # Anode and cathode humidifiers evolution if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dWa_inj / dt'] = 0 dif_eq['dWc_inj / dt'] = (Wc_inj_des - Wc_inj) / tau_hum # Estimation at the first order. elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dWa_inj / dt'] = (Wa_inj_des - Wa_inj) / tau_hum # Estimation at the first order. dif_eq['dWc_inj / dt'] = (Wc_inj_des - Wc_inj) / tau_hum # Estimation at the first order. else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dWa_inj / dt'], dif_eq['dWc_inj / dt'] = 0, 0 calculate_dyn_dissoved_water_evolution(dif_eq, Hmem, Hcl, epsilon_mc, S_sorp_acl, S_sorp_ccl, J_lambda_mem_acl, J_lambda_mem_ccl, Sp_acl, Sp_ccl, **kwargs) This function calculates the dynamic evolution of the dissolved water in the membrane and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Hmem ( float ) \u2013 Thickness of the membrane (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the catalyst layer. S_sorp_acl ( float ) \u2013 Water sorption in the anode catalyst layer (mol.m-3.s-1) S_sorp_ccl ( float ) \u2013 Water sorption in the cathode catalyst layer (mol.m-3.s-1) J_lambda_mem_acl ( float ) \u2013 Dissolved water flow between the membrane and the anode catalyst layer (mol.m-2.s-1) J_lambda_mem_ccl ( float ) \u2013 Dissolved water flow between the membrane and the cathode catalyst layer (mol.m-2.s-1) Sp_acl ( float ) \u2013 Water produced in the membrane at the ACL through the chemical reaction and crossover (mol.m-3.s-1) Sp_ccl ( float ) \u2013 Water produced in the membrane at the CCL through the chemical reaction and crossover (mol.m-3.s-1) Source code in model/dif_eq.py def calculate_dyn_dissoved_water_evolution(dif_eq, Hmem, Hcl, epsilon_mc, S_sorp_acl, S_sorp_ccl, J_lambda_mem_acl, J_lambda_mem_ccl, Sp_acl, Sp_ccl, **kwargs): \"\"\" This function calculates the dynamic evolution of the dissolved water in the membrane and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Hmem : float Thickness of the membrane (m). Hcl : float Thickness of the catalyst layer (m). epsilon_mc : float Volume fraction of ionomer in the catalyst layer. S_sorp_acl : float Water sorption in the anode catalyst layer (mol.m-3.s-1) S_sorp_ccl : float Water sorption in the cathode catalyst layer (mol.m-3.s-1) J_lambda_mem_acl : float Dissolved water flow between the membrane and the anode catalyst layer (mol.m-2.s-1) J_lambda_mem_ccl : float Dissolved water flow between the membrane and the cathode catalyst layer (mol.m-2.s-1) Sp_acl : float Water produced in the membrane at the ACL through the chemical reaction and crossover (mol.m-3.s-1) Sp_ccl : float Water produced in the membrane at the CCL through the chemical reaction and crossover (mol.m-3.s-1) \"\"\" dif_eq['dlambda_acl / dt'] = M_eq / (rho_mem * epsilon_mc) * (-J_lambda_mem_acl / Hcl + S_sorp_acl + Sp_acl) dif_eq['dlambda_mem / dt'] = M_eq / rho_mem * (J_lambda_mem_acl - J_lambda_mem_ccl) / Hmem dif_eq['dlambda_ccl / dt'] = M_eq / (rho_mem * epsilon_mc) * (J_lambda_mem_ccl / Hcl + S_sorp_ccl + Sp_ccl) calculate_dyn_liquid_water_evolution(dif_eq, rho_H2O, Hgdl, Hcl, epsilon_gdl, n_gdl, Jl_agdl_agdl, Jl_agdl_acl, Jl_ccl_cgdl, Jl_cgdl_cgdl, Sl_agdl, Sl_acl, Sl_ccl, Sl_cgdl, **kwargs) This function calculates the dynamic evolution of the liquid water in the gas diffusion and catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. rho_H2O ( float ) \u2013 Density of water (kg.m-3). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. Jl_agdl_agdl ( list ) \u2013 Liquid water flow between two nodes of the anode GDL (kg.m-2.s-1). Jl_agdl_acl ( float ) \u2013 Liquid water flow between the anode GDL and the anode CL (kg.m-2.s-1). Jl_ccl_cgdl ( float ) \u2013 Liquid water flow between the cathode CL and the cathode GDL (kg.m-2.s-1). Jl_cgdl_cgdl ( list ) \u2013 Liquid water flow between two nodes of the cathode GDL (kg.m-2.s-1). Sl_agdl ( list ) \u2013 Liquid water produced in the anode GDL (kg.m-3.s-1). Sl_acl ( float ) \u2013 Liquid water produced in the anode CL (kg.m-3.s-1). Sl_ccl ( float ) \u2013 Liquid water produced in the cathode CL (kg.m-3.s-1). Sl_cgdl ( list ) \u2013 Liquid water produced in the cathode GDL (kg.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_liquid_water_evolution(dif_eq, rho_H2O, Hgdl, Hcl, epsilon_gdl, n_gdl, Jl_agdl_agdl, Jl_agdl_acl, Jl_ccl_cgdl, Jl_cgdl_cgdl, Sl_agdl, Sl_acl, Sl_ccl, Sl_cgdl, **kwargs): \"\"\" This function calculates the dynamic evolution of the liquid water in the gas diffusion and catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. rho_H2O : float Density of water (kg.m-3). Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. Jl_agdl_agdl : list Liquid water flow between two nodes of the anode GDL (kg.m-2.s-1). Jl_agdl_acl : float Liquid water flow between the anode GDL and the anode CL (kg.m-2.s-1). Jl_ccl_cgdl : float Liquid water flow between the cathode CL and the cathode GDL (kg.m-2.s-1). Jl_cgdl_cgdl : list Liquid water flow between two nodes of the cathode GDL (kg.m-2.s-1). Sl_agdl : list Liquid water produced in the anode GDL (kg.m-3.s-1). Sl_acl : float Liquid water produced in the anode CL (kg.m-3.s-1). Sl_ccl : float Liquid water produced in the cathode CL (kg.m-3.s-1). Sl_cgdl : list Liquid water produced in the cathode GDL (kg.m-3.s-1). \"\"\" # At the anode side # Inside the AGDL dif_eq['ds_agdl_1 / dt'] = 0 # Dirichlet boundary condition. s_agdl_1 is initialized to 0 and remains constant. for i in range(2, n_gdl): dif_eq[f'ds_agdl_{i} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_agdl_agdl[i - 1] - Jl_agdl_agdl[i]) / (Hgdl / n_gdl) + M_H2O * Sl_agdl[i]) dif_eq[f'ds_agdl_{n_gdl} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_agdl_agdl[n_gdl - 1] - Jl_agdl_acl) / (Hgdl / n_gdl) + M_H2O * Sl_agdl[n_gdl]) # Inside the ACL dif_eq['ds_acl / dt'] = 1 / (rho_H2O * epsilon_cl) * (Jl_agdl_acl / Hcl + M_H2O * Sl_acl) # At the cathode side # Inside the CCL dif_eq['ds_ccl / dt'] = 1 / (rho_H2O * epsilon_cl) * (- Jl_ccl_cgdl / Hcl + M_H2O * Sl_ccl) # Inside the CGDL dif_eq['ds_cgdl_1 / dt'] = 1 / (rho_H2O * epsilon_gdl) * ((Jl_ccl_cgdl - Jl_cgdl_cgdl[1]) / (Hgdl / n_gdl) + M_H2O * Sl_cgdl[1]) for i in range(2, n_gdl): dif_eq[f'ds_cgdl_{i} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_cgdl_cgdl[i - 1] - Jl_cgdl_cgdl[i]) / (Hgdl / n_gdl) + M_H2O * Sl_cgdl[i]) dif_eq[f'ds_cgdl_{n_gdl} / dt'] = 0 # Dirichlet boundary condition. s_cgdl_n_gdl is initialized to 0 and remains calculate_dyn_manifold_pressure_and_humidity_evolution(dif_eq, Masm, Maem, Mcsm, Mcem, Tfc, Hgc, Wgc, type_auxiliary, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out, **kwargs) This function calculates the dynamic evolution of the pressure and humidity inside the manifolds. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Masm ( float ) \u2013 Molar mass of all the gaseous species inside the anode supply manifold (kg.mol-1). Maem ( float ) \u2013 Molar mass of all the gaseous species inside the anode exhaust manifold (kg.mol-1). Mcsm ( float ) \u2013 Molar mass of all the gaseous species inside the cathode supply manifold (kg.mol-1). Mcem ( float ) \u2013 Molar mass of all the gaseous species inside the cathode exhaust manifold (kg.mol-1). Tfc ( float ) \u2013 Fuel cell temperature (K). Hgc ( float ) \u2013 Thickness of the gas channel (m). Wgc ( float ) \u2013 Width of the gas channel (m). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Jv_a_in ( float ) \u2013 Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Water vapor flow at the cathode outlet (mol.m-2.s-1). Wasm_in ( float ) \u2013 Flow at the anode supply manifold inlet (kg.s-1). Wasm_out ( float ) \u2013 Flow at the anode supply manifold outlet (kg.s-1). Waem_in ( float ) \u2013 Flow at the anode exhaust manifold inlet (kg.s-1). Waem_out ( float ) \u2013 Flow at the anode exhaust manifold outlet (kg.s-1). Wcsm_in ( float ) \u2013 Flow at the cathode supply manifold inlet (kg.s-1). Wcsm_out ( float ) \u2013 Flow at the cathode supply manifold outlet (kg.s-1). Wcem_in ( float ) \u2013 Flow at the cathode exhaust manifold inlet (kg.s-1). Wcem_out ( float ) \u2013 Flow at the cathode exhaust manifold outlet (kg.s-1). Ware ( float ) \u2013 Anode side recirculation flow (kg.s-1). Wv_asm_in ( float ) \u2013 Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out ( float ) \u2013 Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in ( float ) \u2013 Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out ( float ) \u2013 Vapor flow at the cathode external manifold outlet (mol.s-1). Source code in model/dif_eq.py def calculate_dyn_manifold_pressure_and_humidity_evolution(dif_eq, Masm, Maem, Mcsm, Mcem, Tfc, Hgc, Wgc, type_auxiliary, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out, **kwargs): \"\"\"This function calculates the dynamic evolution of the pressure and humidity inside the manifolds. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Masm : float Molar mass of all the gaseous species inside the anode supply manifold (kg.mol-1). Maem : float Molar mass of all the gaseous species inside the anode exhaust manifold (kg.mol-1). Mcsm : float Molar mass of all the gaseous species inside the cathode supply manifold (kg.mol-1). Mcem : float Molar mass of all the gaseous species inside the cathode exhaust manifold (kg.mol-1). Tfc : float Fuel cell temperature (K). Hgc : float Thickness of the gas channel (m). Wgc : float Width of the gas channel (m). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Jv_a_in : float Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out : float Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in : float Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out : float Water vapor flow at the cathode outlet (mol.m-2.s-1). Wasm_in : float Flow at the anode supply manifold inlet (kg.s-1). Wasm_out : float Flow at the anode supply manifold outlet (kg.s-1). Waem_in : float Flow at the anode exhaust manifold inlet (kg.s-1). Waem_out : float Flow at the anode exhaust manifold outlet (kg.s-1). Wcsm_in : float Flow at the cathode supply manifold inlet (kg.s-1). Wcsm_out : float Flow at the cathode supply manifold outlet (kg.s-1). Wcem_in : float Flow at the cathode exhaust manifold inlet (kg.s-1). Wcem_out : float Flow at the cathode exhaust manifold outlet (kg.s-1). Ware : float Anode side recirculation flow (kg.s-1). Wv_asm_in : float Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out : float Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in : float Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out : float Vapor flow at the cathode external manifold outlet (mol.s-1). \"\"\" # Pressure evolution inside the manifolds if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dPasm / dt'] = (Wasm_in + Ware - n_cell * Wasm_out) / (Vsm * Masm) * R * Tfc dif_eq['dPaem / dt'] = (n_cell * Waem_in - Ware - Waem_out) / (Vem * Maem) * R * Tfc dif_eq['dPcsm / dt'] = (Wcsm_in - n_cell * Wcsm_out) / (Vsm * Mcsm) * R * Tfc dif_eq['dPcem / dt'] = (n_cell * Wcem_in - Wcem_out) / (Vem * Mcem) * R * Tfc elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dPasm / dt'] = (Wasm_in - n_cell * Wasm_out) / (Vsm * Masm) * R * Tfc dif_eq['dPaem / dt'] = (n_cell * Waem_in - Waem_out) / (Vem * Maem) * R * Tfc dif_eq['dPcsm / dt'] = (Wcsm_in - n_cell * Wcsm_out) / (Vsm * Mcsm) * R * Tfc dif_eq['dPcem / dt'] = (n_cell * Wcem_in - Wcem_out) / (Vem * Mcem) * R * Tfc else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dPasm / dt'], dif_eq['dPaem / dt'], dif_eq['dPcsm / dt'], dif_eq['dPcem / dt'] = 0, 0, 0, 0 # Humidity evolution inside the manifolds if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dPhi_asm / dt'] = (Wv_asm_in - Jv_a_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_aem / dt'] = (Jv_a_out * Hgc * Wgc * n_cell - Wv_asm_in - Wv_aem_out) / Vem * R * Tfc / Psat(Tfc) dif_eq['dPhi_csm / dt'] = (Wv_csm_in - Jv_c_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_cem / dt'] = (Jv_c_out * Hgc * Wgc * n_cell - Wv_cem_out) / Vem * R * Tfc / Psat(Tfc) elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dPhi_asm / dt'] = (Wv_asm_in - Jv_a_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_aem / dt'] = (Jv_a_out * Hgc * Wgc * n_cell - Wv_aem_out) / Vem * R * Tfc / Psat(Tfc) dif_eq['dPhi_csm / dt'] = (Wv_csm_in - Jv_c_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_cem / dt'] = (Jv_c_out * Hgc * Wgc * n_cell - Wv_cem_out) / Vem * R * Tfc / Psat(Tfc) else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dPhi_asm / dt'], dif_eq['dPhi_aem / dt'], dif_eq['dPhi_csm / dt'], dif_eq['dPhi_cem / dt'] = 0, 0, 0, 0 calculate_dyn_throttle_area_evolution(dif_eq, Pagc, Pcgc, type_auxiliary, Abp_a, Abp_c, Tfc, Pa_des, Pc_des, **kwargs) This function calculates the dynamic evolution of the throttle area inside the anode and cathode auxiliaries. This function has to be executed after 'calculate_dyn_vapor_evolution' and 'calculate_dyn_H2_O2_N2_evolution'. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Pagc ( float ) \u2013 Pressure inside the anode gas channel (Pa). Pcgc ( float ) \u2013 Pressure inside the cathode gas channel (Pa). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Abp_a ( float ) \u2013 Throttle area inside the anode auxiliaries (m2). Abp_c ( float ) \u2013 Throttle area inside the cathode auxiliaries (m2). Tfc ( float ) \u2013 Fuel cell temperature (K). Pa_des ( float ) \u2013 Desired pressure inside the anode gas channel (Pa). Pc_des ( float ) \u2013 Desired pressure inside the cathode gas channel (Pa). Source code in model/dif_eq.py def calculate_dyn_throttle_area_evolution(dif_eq, Pagc, Pcgc, type_auxiliary, Abp_a, Abp_c, Tfc, Pa_des, Pc_des, **kwargs): \"\"\"This function calculates the dynamic evolution of the throttle area inside the anode and cathode auxiliaries. This function has to be executed after 'calculate_dyn_vapor_evolution' and 'calculate_dyn_H2_O2_N2_evolution'. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Pagc : float Pressure inside the anode gas channel (Pa). Pcgc : float Pressure inside the cathode gas channel (Pa). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Abp_a : float Throttle area inside the anode auxiliaries (m2). Abp_c : float Throttle area inside the cathode auxiliaries (m2). Tfc : float Fuel cell temperature (K). Pa_des : float Desired pressure inside the anode gas channel (Pa). Pc_des : float Desired pressure inside the cathode gas channel (Pa). \"\"\" # Calculation of the pressure derivative inside the gas channels dPagcdt = (dif_eq['dC_v_agc / dt'] + dif_eq['dC_H2_agc / dt']) * R * Tfc dPcgcdt = (dif_eq['dC_v_cgc / dt'] + dif_eq['dC_O2_cgc / dt'] + dif_eq['dC_N2 / dt']) * R * Tfc # Throttle area evolution inside the anode auxiliaries if type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dAbp_a / dt'] = - Kp * (Pa_des - Pagc) + Kd * dPagcdt # PD controller if Abp_a > A_T and dif_eq['dAbp_a / dt'] > 0: # The throttle area cannot be higher than the maximum value dif_eq['dAbp_a / dt'] = 0 elif Abp_a < 0 and dif_eq['dAbp_a / dt'] < 0: # The throttle area cannot be lower than 0 dif_eq['dAbp_a / dt'] = 0 else: # elif type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ # type_auxiliary == \"no_auxiliary\": dif_eq['dAbp_a / dt'] = 0 # The throttle area is not considered # Throttle area evolution inside the cathode auxiliaries if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dAbp_c / dt'] = - Kp * (Pc_des - Pcgc) + Kd * dPcgcdt # PD controller if Abp_c > A_T and dif_eq['dAbp_c / dt'] > 0: # The throttle area cannot be higher than the maximum value dif_eq['dAbp_c / dt'] = 0 elif Abp_c < 0 and dif_eq['dAbp_c / dt'] < 0: # The throttle area cannot be lower than 0 dif_eq['dAbp_c / dt'] = 0 else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dAbp_a / dt'] = 0 # The throttle area is not considered calculate_dyn_vapor_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Jv_agc_agdl, Jv_agdl_agdl, Jv_agdl_acl, S_sorp_acl, S_sorp_ccl, Jv_ccl_cgdl, Jv_cgdl_cgdl, Jv_cgdl_cgc, Sv_agdl, Sv_acl, Sv_ccl, Sv_cgdl, **kwargs) This function calculates the dynamic evolution of the vapor in the gas channels, the gas diffusion layers and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). Hgc ( float ) \u2013 Thickness of the gas channel (m). Lgc ( float ) \u2013 Length of the gas channel (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. Jv_a_in ( float ) \u2013 Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Water vapor flow at the cathode outlet (mol.m-2.s-1). Jv_agc_agdl ( float ) \u2013 Water vapor flow between the anode gas channel and the anode GDL (mol.m-2.s-1). Jv_agdl_agdl ( list ) \u2013 Water vapor flow between two nodes of the anode GDL (mol.m-2.s-1). Jv_agdl_acl ( float ) \u2013 Water vapor flow between the anode GDL and the anode CL (mol.m-2.s-1). S_sorp_acl \u2013 Water vapor sorption in the anode CL (mol.m-3.s-1). S_sorp_ccl \u2013 Water vapor sorption in the cathode CL (mol.m-3.s-1). Jv_ccl_cgdl ( float ) \u2013 Water vapor flow between the cathode CL and the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgdl ( list ) \u2013 Water vapor flow between two nodes of the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgc ( float ) \u2013 Water vapor flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). Sv_agdl ( list ) \u2013 Water vapor produced in the anode GDL (mol.m-3.s-1). Sv_acl ( float ) \u2013 Water vapor produced in the anode CL (mol.m-3.s-1). Sv_ccl ( float ) \u2013 Water vapor produced in the cathode CL (mol.m-3.s-1). Sv_cgdl ( list ) \u2013 Water vapor produced in the cathode GDL (mol.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_vapor_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Jv_agc_agdl, Jv_agdl_agdl, Jv_agdl_acl, S_sorp_acl, S_sorp_ccl, Jv_ccl_cgdl, Jv_cgdl_cgdl, Jv_cgdl_cgc, Sv_agdl, Sv_acl, Sv_ccl, Sv_cgdl, **kwargs): \"\"\"This function calculates the dynamic evolution of the vapor in the gas channels, the gas diffusion layers and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). Hgc : float Thickness of the gas channel (m). Lgc : float Length of the gas channel (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. Jv_a_in : float Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out : float Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in : float Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out : float Water vapor flow at the cathode outlet (mol.m-2.s-1). Jv_agc_agdl : float Water vapor flow between the anode gas channel and the anode GDL (mol.m-2.s-1). Jv_agdl_agdl : list Water vapor flow between two nodes of the anode GDL (mol.m-2.s-1). Jv_agdl_acl : float Water vapor flow between the anode GDL and the anode CL (mol.m-2.s-1). S_sorp_acl: float Water vapor sorption in the anode CL (mol.m-3.s-1). S_sorp_ccl: float Water vapor sorption in the cathode CL (mol.m-3.s-1). Jv_ccl_cgdl : float Water vapor flow between the cathode CL and the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgdl : list Water vapor flow between two nodes of the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgc : float Water vapor flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). Sv_agdl : list Water vapor produced in the anode GDL (mol.m-3.s-1). Sv_acl : float Water vapor produced in the anode CL (mol.m-3.s-1). Sv_ccl : float Water vapor produced in the cathode CL (mol.m-3.s-1). Sv_cgdl : list Water vapor produced in the cathode GDL (mol.m-3.s-1). \"\"\" # At the anode side # Inside the AGC dif_eq['dC_v_agc / dt'] = (Jv_a_in - Jv_a_out) / Lgc - Jv_agc_agdl / Hgc # Inside the AGDL dif_eq['dC_v_agdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_agdl_1'])) * \\ ((Jv_agc_agdl - Jv_agdl_agdl[1]) / (Hgdl / n_gdl) + Sv_agdl[1]) for i in range(2, n_gdl): dif_eq[f'dC_v_agdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{i}'])) * \\ ((Jv_agdl_agdl[i - 1] - Jv_agdl_agdl[i]) / (Hgdl / n_gdl) + Sv_agdl[i]) dif_eq[f'dC_v_agdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{n_gdl}'])) * \\ ((Jv_agdl_agdl[n_gdl - 1] - Jv_agdl_acl) / (Hgdl / n_gdl) + Sv_agdl[n_gdl]) # Inside the ACL dif_eq['dC_v_acl / dt'] = 1 / (epsilon_cl * (1 - sv['s_acl'])) * (Jv_agdl_acl / Hcl - S_sorp_acl + Sv_acl) # At the cathode side # Inside the CCL dif_eq['dC_v_ccl / dt'] = 1 / (epsilon_cl * (1 - sv['s_ccl'])) * (- Jv_ccl_cgdl / Hcl - S_sorp_ccl + Sv_ccl) # Inside the CGDL dif_eq['dC_v_cgdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_cgdl_1'])) * \\ ((Jv_ccl_cgdl - Jv_cgdl_cgdl[1]) / (Hgdl / n_gdl) + Sv_cgdl[1]) for i in range(2, n_gdl): dif_eq[f'dC_v_cgdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{i}'])) * \\ ((Jv_cgdl_cgdl[i - 1] - Jv_cgdl_cgdl[i]) / (Hgdl / n_gdl) + Sv_cgdl[i]) dif_eq[f'dC_v_cgdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{n_gdl}'])) * \\ ((Jv_cgdl_cgdl[n_gdl - 1] - Jv_cgdl_cgc) / (Hgdl / n_gdl) + Sv_cgdl[n_gdl]) # Inside the CGC dif_eq['dC_v_cgc / dt'] = (Jv_c_in - Jv_c_out) / Lgc + Jv_cgdl_cgc / Hgc calculate_dyn_voltage_evolution(dif_eq, i_fc, C_O2_ccl, eta_c, Tfc, Hcl, i0_c_ref, kappa_c, C_scl, i_n, f_drop, **kwargs) This function calculates the dynamic evolution of the cell overpotential eta_c. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. i_fc ( float ) \u2013 Fuel cell current density (A.m-2). C_O2_ccl ( float ) \u2013 Oxygen concentration in the cathode catalyst layer (mol.m-3). eta_c ( float ) \u2013 Cell overpotential (V). Tfc ( float ) \u2013 Fuel cell temperature (K). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode (A.m-2). kappa_c ( float ) \u2013 Overpotential correction exponent. C_scl ( float ) \u2013 Volumetric space-charge layer capacitance (F.m-3). i_n ( float ) \u2013 Crossover current density (A.m-2). f_drop ( float ) \u2013 Liquid water induced voltage drop function. Source code in model/dif_eq.py def calculate_dyn_voltage_evolution(dif_eq, i_fc, C_O2_ccl, eta_c, Tfc, Hcl, i0_c_ref, kappa_c, C_scl, i_n, f_drop, **kwargs): \"\"\"This function calculates the dynamic evolution of the cell overpotential eta_c. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. i_fc : float Fuel cell current density (A.m-2). C_O2_ccl : float Oxygen concentration in the cathode catalyst layer (mol.m-3). eta_c : float Cell overpotential (V). Tfc : float Fuel cell temperature (K). Hcl : float Thickness of the catalyst layer (m). i0_c_ref : float Reference exchange current density at the cathode (A.m-2). kappa_c : float Overpotential correction exponent. C_scl : float Volumetric space-charge layer capacitance (F.m-3). i_n : float Crossover current density (A.m-2). f_drop : float Liquid water induced voltage drop function. \"\"\" dif_eq['deta_c / dt'] = 1 / (C_scl * Hcl) * ((i_fc + i_n) - i0_c_ref * (C_O2_ccl / C_O2ref) ** kappa_c * np.exp(f_drop * alpha_c * F / (R * Tfc) * eta_c)) dydt(t, y, operating_inputs, parameters, solver_variable_names, control_variables) This function gives the system of differential equations to solve. Parameters: t ( float ) \u2013 Time (s). y ( ndarray ) \u2013 Numpy list of the solver variables. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. solver_variable_names ( list ) \u2013 Names of the solver variables. control_variables ( dict ) \u2013 Variables controlled by the user. Returns: dydt ( list ) \u2013 List containing the derivative of the solver variables. Source code in model/dif_eq.py def dydt(t, y, operating_inputs, parameters, solver_variable_names, control_variables): \"\"\"This function gives the system of differential equations to solve. Parameters ---------- t : float Time (s). y : numpy.ndarray Numpy list of the solver variables. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. solver_variable_names : list Names of the solver variables. control_variables : dict Variables controlled by the user. Returns ------- dydt : list List containing the derivative of the solver variables. \"\"\" # Creation of the dif_eq dictionary. It is an intermediate calculation to simplify the writing of the code. dif_eq = {('d' + key + ' / dt'): 0 for key in solver_variable_names} # Creation of the solver_variables dict. It is an intermediate calculation to simplify the writing of the code. solver_variables = {} for index, key in enumerate(solver_variable_names): solver_variables[key] = y[index] # Modifications of the operating conditions in real time, if required. if parameters[\"type_control\"] != \"no_control\": control_operating_conditions(t, solver_variables, operating_inputs, parameters, control_variables) # Intermediate values i_fc = operating_inputs['current_density'](t, parameters) Mext, Pagc, Pcgc, i_n, Masm, Maem, Mcsm, Mcem, rho_H2O = dif_eq_int_values(solver_variables, control_variables, operating_inputs, parameters) Wcp_des, Wa_inj_des, Wc_inj_des = desired_flows(solver_variables, control_variables, i_n, i_fc, operating_inputs, parameters, Mext) eta_c_intermediate_values = calculate_eta_c_intermediate_values(solver_variables, operating_inputs, parameters) # Calculation of the flows flows_dico = calculate_flows(t, solver_variables, control_variables, i_fc, operating_inputs, parameters) # Calculation of the dynamic evolutions # Inside the cell calculate_dyn_dissoved_water_evolution(dif_eq, **parameters, **flows_dico) calculate_dyn_liquid_water_evolution(dif_eq, rho_H2O, **parameters, **flows_dico) calculate_dyn_vapor_evolution(dif_eq, solver_variables, **parameters, **flows_dico) calculate_dyn_H2_O2_N2_evolution(dif_eq, solver_variables, **parameters, **flows_dico) calculate_dyn_voltage_evolution(dif_eq, i_fc, **solver_variables, **operating_inputs, **parameters, **eta_c_intermediate_values) # Inside the auxiliary components calculate_dyn_manifold_pressure_and_humidity_evolution(dif_eq, Masm, Maem, Mcsm, Mcem, **solver_variables, **operating_inputs, **parameters, **flows_dico) calculate_dyn_air_compressor_and_humidifier_evolution(dif_eq, Wcp_des, Wa_inj_des, Wc_inj_des, **solver_variables, **parameters) calculate_dyn_throttle_area_evolution(dif_eq, Pagc, Pcgc, **solver_variables, **operating_inputs, **parameters) # dif_eq is converted to dydt because the solver requires an ordered list to work dydt = [] for key in solver_variable_names: dydt.append(dif_eq['d' + key + ' / dt']) return dydt","title":"Differentiel equations"},{"location":"functions/model/dif_eq/#differential-equations","text":"This file represents all the differential equations used for the fuel cell model.","title":"Differential equations"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_H2_O2_N2_evolution","text":"This function calculates the dynamic evolution of the hydrogen, oxygen and nitrogen in the gas channels, the gas diffusion layers and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). Hgc ( float ) \u2013 Thickness of the gas channel (m). Lgc ( float ) \u2013 Length of the gas channel (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. J_H2_in ( float ) \u2013 Hydrogen flow at the anode inlet (mol.m-2.s-1). J_H2_out ( float ) \u2013 Hydrogen flow at the anode outlet (mol.m-2.s-1). J_O2_in ( float ) \u2013 Oxygen flow at the cathode inlet (mol.m-2.s-1). J_O2_out ( float ) \u2013 Oxygen flow at the cathode outlet (mol.m-2.s-1). J_N2_in ( float ) \u2013 Nitrogen flow at the cathode inlet (mol.m-2.s-1). J_N2_out ( float ) \u2013 Nitrogen flow at the cathode outlet (mol.m-2.s-1). J_H2_agc_agdl ( float ) \u2013 Hydrogen flow between the anode gas channel and the anode GDL (mol.m-2.s-1). J_H2_agdl_agdl ( list ) \u2013 Hydrogen flow between two nodes of the anode GDL (mol.m-2.s-1). J_H2_agdl_acl ( float ) \u2013 Hydrogen flow between the anode GDL and the anode CL (mol.m-2.s-1). J_O2_ccl_cgdl ( float ) \u2013 Oxygen flow between the cathode CL and the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgdl ( list ) \u2013 Oxygen flow between two nodes of the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgc ( float ) \u2013 Oxygen flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). S_H2_acl ( float ) \u2013 Hydrogen consumed in the anode CL (mol.m-3.s-1). S_O2_ccl ( float ) \u2013 Oxygen consumed in the cathode CL (mol.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_H2_O2_N2_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, J_H2_agc_agdl, J_H2_agdl_agdl, J_H2_agdl_acl, J_O2_ccl_cgdl, J_O2_cgdl_cgdl, J_O2_cgdl_cgc, S_H2_acl, S_O2_ccl, **kwargs): \"\"\"This function calculates the dynamic evolution of the hydrogen, oxygen and nitrogen in the gas channels, the gas diffusion layers and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). Hgc : float Thickness of the gas channel (m). Lgc : float Length of the gas channel (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. J_H2_in : float Hydrogen flow at the anode inlet (mol.m-2.s-1). J_H2_out : float Hydrogen flow at the anode outlet (mol.m-2.s-1). J_O2_in : float Oxygen flow at the cathode inlet (mol.m-2.s-1). J_O2_out : float Oxygen flow at the cathode outlet (mol.m-2.s-1). J_N2_in : float Nitrogen flow at the cathode inlet (mol.m-2.s-1). J_N2_out : float Nitrogen flow at the cathode outlet (mol.m-2.s-1). J_H2_agc_agdl : float Hydrogen flow between the anode gas channel and the anode GDL (mol.m-2.s-1). J_H2_agdl_agdl : list Hydrogen flow between two nodes of the anode GDL (mol.m-2.s-1). J_H2_agdl_acl : float Hydrogen flow between the anode GDL and the anode CL (mol.m-2.s-1). J_O2_ccl_cgdl : float Oxygen flow between the cathode CL and the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgdl : list Oxygen flow between two nodes of the cathode GDL (mol.m-2.s-1). J_O2_cgdl_cgc : float Oxygen flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). S_H2_acl : float Hydrogen consumed in the anode CL (mol.m-3.s-1). S_O2_ccl : float Oxygen consumed in the cathode CL (mol.m-3.s-1). \"\"\" # At the anode side # Inside the AGC dif_eq['dC_H2_agc / dt'] = (J_H2_in - J_H2_out) / Lgc - J_H2_agc_agdl / Hgc # Inside the AGDL dif_eq['dC_H2_agdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_agdl_1'])) * \\ (J_H2_agc_agdl - J_H2_agdl_agdl[1]) / (Hgdl / n_gdl) for i in range(2, n_gdl): dif_eq[f'dC_H2_agdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{i}'])) * \\ (J_H2_agdl_agdl[i - 1] - J_H2_agdl_agdl[i]) / (Hgdl / n_gdl) dif_eq[f'dC_H2_agdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{n_gdl}'])) * \\ (J_H2_agdl_agdl[n_gdl - 1] - J_H2_agdl_acl) / (Hgdl / n_gdl) # Inside the ACL dif_eq['dC_H2_acl / dt'] = 1 / (epsilon_cl * (1 - sv['s_acl'])) * (J_H2_agdl_acl / Hcl + S_H2_acl) # At the cathode side # Inside the CCL dif_eq['dC_O2_ccl / dt'] = 1 / (epsilon_cl * (1 - sv['s_ccl'])) * (-J_O2_ccl_cgdl / Hcl + S_O2_ccl) # Inside the CGDL dif_eq['dC_O2_cgdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_cgdl_1'])) * \\ (J_O2_ccl_cgdl - J_O2_cgdl_cgdl[1]) / (Hgdl / n_gdl) for i in range(2, n_gdl): dif_eq[f'dC_O2_cgdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{i}'])) * \\ (J_O2_cgdl_cgdl[i - 1] - J_O2_cgdl_cgdl[i]) / (Hgdl / n_gdl) dif_eq[f'dC_O2_cgdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{n_gdl}'])) * \\ (J_O2_cgdl_cgdl[n_gdl - 1] - J_O2_cgdl_cgc) / (Hgdl / n_gdl) # Inside the CGC dif_eq['dC_O2_cgc / dt'] = (J_O2_in - J_O2_out) / Lgc + J_O2_cgdl_cgc / Hgc # Inside the whole cell dif_eq['dC_N2 / dt'] = (J_N2_in - J_N2_out) / Lgc","title":"calculate_dyn_H2_O2_N2_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_air_compressor_and_humidifier_evolution","text":"This function calculates the dynamic evolution of the air compressor and the humidifiers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Wcp_des ( float ) \u2013 Desired air compressor flow rate (kg.s-1). Wa_inj_des ( float ) \u2013 Desired anode humidifier flow rate (kg.s-1). Wc_inj_des ( float ) \u2013 Desired cathode humidifier flow rate (kg.s-1). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Wcp ( float ) \u2013 Air compressor flow rate (kg.s-1). Wa_inj ( float ) \u2013 Anode humidifier flow rate (kg.s-1). Wc_inj ( float ) \u2013 Cathode humidifier flow rate (kg.s-1). Source code in model/dif_eq.py def calculate_dyn_air_compressor_and_humidifier_evolution(dif_eq, Wcp_des, Wa_inj_des, Wc_inj_des, type_auxiliary, Wcp, Wa_inj, Wc_inj, **kwargs): \"\"\"This function calculates the dynamic evolution of the air compressor and the humidifiers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Wcp_des : float Desired air compressor flow rate (kg.s-1). Wa_inj_des : float Desired anode humidifier flow rate (kg.s-1). Wc_inj_des : float Desired cathode humidifier flow rate (kg.s-1). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Wcp : float Air compressor flow rate (kg.s-1). Wa_inj : float Anode humidifier flow rate (kg.s-1). Wc_inj : float Cathode humidifier flow rate (kg.s-1). \"\"\" # Air compressor evolution if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dWcp / dt'] = (Wcp_des - Wcp) / tau_cp # Estimation at the first order. elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dWcp / dt'] = (Wcp_des - Wcp) / tau_cp # Estimation at the first order. else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dWcp / dt'] = 0 # Anode and cathode humidifiers evolution if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dWa_inj / dt'] = 0 dif_eq['dWc_inj / dt'] = (Wc_inj_des - Wc_inj) / tau_hum # Estimation at the first order. elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dWa_inj / dt'] = (Wa_inj_des - Wa_inj) / tau_hum # Estimation at the first order. dif_eq['dWc_inj / dt'] = (Wc_inj_des - Wc_inj) / tau_hum # Estimation at the first order. else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dWa_inj / dt'], dif_eq['dWc_inj / dt'] = 0, 0","title":"calculate_dyn_air_compressor_and_humidifier_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_dissoved_water_evolution","text":"This function calculates the dynamic evolution of the dissolved water in the membrane and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Hmem ( float ) \u2013 Thickness of the membrane (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the catalyst layer. S_sorp_acl ( float ) \u2013 Water sorption in the anode catalyst layer (mol.m-3.s-1) S_sorp_ccl ( float ) \u2013 Water sorption in the cathode catalyst layer (mol.m-3.s-1) J_lambda_mem_acl ( float ) \u2013 Dissolved water flow between the membrane and the anode catalyst layer (mol.m-2.s-1) J_lambda_mem_ccl ( float ) \u2013 Dissolved water flow between the membrane and the cathode catalyst layer (mol.m-2.s-1) Sp_acl ( float ) \u2013 Water produced in the membrane at the ACL through the chemical reaction and crossover (mol.m-3.s-1) Sp_ccl ( float ) \u2013 Water produced in the membrane at the CCL through the chemical reaction and crossover (mol.m-3.s-1) Source code in model/dif_eq.py def calculate_dyn_dissoved_water_evolution(dif_eq, Hmem, Hcl, epsilon_mc, S_sorp_acl, S_sorp_ccl, J_lambda_mem_acl, J_lambda_mem_ccl, Sp_acl, Sp_ccl, **kwargs): \"\"\" This function calculates the dynamic evolution of the dissolved water in the membrane and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Hmem : float Thickness of the membrane (m). Hcl : float Thickness of the catalyst layer (m). epsilon_mc : float Volume fraction of ionomer in the catalyst layer. S_sorp_acl : float Water sorption in the anode catalyst layer (mol.m-3.s-1) S_sorp_ccl : float Water sorption in the cathode catalyst layer (mol.m-3.s-1) J_lambda_mem_acl : float Dissolved water flow between the membrane and the anode catalyst layer (mol.m-2.s-1) J_lambda_mem_ccl : float Dissolved water flow between the membrane and the cathode catalyst layer (mol.m-2.s-1) Sp_acl : float Water produced in the membrane at the ACL through the chemical reaction and crossover (mol.m-3.s-1) Sp_ccl : float Water produced in the membrane at the CCL through the chemical reaction and crossover (mol.m-3.s-1) \"\"\" dif_eq['dlambda_acl / dt'] = M_eq / (rho_mem * epsilon_mc) * (-J_lambda_mem_acl / Hcl + S_sorp_acl + Sp_acl) dif_eq['dlambda_mem / dt'] = M_eq / rho_mem * (J_lambda_mem_acl - J_lambda_mem_ccl) / Hmem dif_eq['dlambda_ccl / dt'] = M_eq / (rho_mem * epsilon_mc) * (J_lambda_mem_ccl / Hcl + S_sorp_ccl + Sp_ccl)","title":"calculate_dyn_dissoved_water_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_liquid_water_evolution","text":"This function calculates the dynamic evolution of the liquid water in the gas diffusion and catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. rho_H2O ( float ) \u2013 Density of water (kg.m-3). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. Jl_agdl_agdl ( list ) \u2013 Liquid water flow between two nodes of the anode GDL (kg.m-2.s-1). Jl_agdl_acl ( float ) \u2013 Liquid water flow between the anode GDL and the anode CL (kg.m-2.s-1). Jl_ccl_cgdl ( float ) \u2013 Liquid water flow between the cathode CL and the cathode GDL (kg.m-2.s-1). Jl_cgdl_cgdl ( list ) \u2013 Liquid water flow between two nodes of the cathode GDL (kg.m-2.s-1). Sl_agdl ( list ) \u2013 Liquid water produced in the anode GDL (kg.m-3.s-1). Sl_acl ( float ) \u2013 Liquid water produced in the anode CL (kg.m-3.s-1). Sl_ccl ( float ) \u2013 Liquid water produced in the cathode CL (kg.m-3.s-1). Sl_cgdl ( list ) \u2013 Liquid water produced in the cathode GDL (kg.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_liquid_water_evolution(dif_eq, rho_H2O, Hgdl, Hcl, epsilon_gdl, n_gdl, Jl_agdl_agdl, Jl_agdl_acl, Jl_ccl_cgdl, Jl_cgdl_cgdl, Sl_agdl, Sl_acl, Sl_ccl, Sl_cgdl, **kwargs): \"\"\" This function calculates the dynamic evolution of the liquid water in the gas diffusion and catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. rho_H2O : float Density of water (kg.m-3). Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. Jl_agdl_agdl : list Liquid water flow between two nodes of the anode GDL (kg.m-2.s-1). Jl_agdl_acl : float Liquid water flow between the anode GDL and the anode CL (kg.m-2.s-1). Jl_ccl_cgdl : float Liquid water flow between the cathode CL and the cathode GDL (kg.m-2.s-1). Jl_cgdl_cgdl : list Liquid water flow between two nodes of the cathode GDL (kg.m-2.s-1). Sl_agdl : list Liquid water produced in the anode GDL (kg.m-3.s-1). Sl_acl : float Liquid water produced in the anode CL (kg.m-3.s-1). Sl_ccl : float Liquid water produced in the cathode CL (kg.m-3.s-1). Sl_cgdl : list Liquid water produced in the cathode GDL (kg.m-3.s-1). \"\"\" # At the anode side # Inside the AGDL dif_eq['ds_agdl_1 / dt'] = 0 # Dirichlet boundary condition. s_agdl_1 is initialized to 0 and remains constant. for i in range(2, n_gdl): dif_eq[f'ds_agdl_{i} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_agdl_agdl[i - 1] - Jl_agdl_agdl[i]) / (Hgdl / n_gdl) + M_H2O * Sl_agdl[i]) dif_eq[f'ds_agdl_{n_gdl} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_agdl_agdl[n_gdl - 1] - Jl_agdl_acl) / (Hgdl / n_gdl) + M_H2O * Sl_agdl[n_gdl]) # Inside the ACL dif_eq['ds_acl / dt'] = 1 / (rho_H2O * epsilon_cl) * (Jl_agdl_acl / Hcl + M_H2O * Sl_acl) # At the cathode side # Inside the CCL dif_eq['ds_ccl / dt'] = 1 / (rho_H2O * epsilon_cl) * (- Jl_ccl_cgdl / Hcl + M_H2O * Sl_ccl) # Inside the CGDL dif_eq['ds_cgdl_1 / dt'] = 1 / (rho_H2O * epsilon_gdl) * ((Jl_ccl_cgdl - Jl_cgdl_cgdl[1]) / (Hgdl / n_gdl) + M_H2O * Sl_cgdl[1]) for i in range(2, n_gdl): dif_eq[f'ds_cgdl_{i} / dt'] = 1 / (rho_H2O * epsilon_gdl) * \\ ((Jl_cgdl_cgdl[i - 1] - Jl_cgdl_cgdl[i]) / (Hgdl / n_gdl) + M_H2O * Sl_cgdl[i]) dif_eq[f'ds_cgdl_{n_gdl} / dt'] = 0 # Dirichlet boundary condition. s_cgdl_n_gdl is initialized to 0 and remains","title":"calculate_dyn_liquid_water_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_manifold_pressure_and_humidity_evolution","text":"This function calculates the dynamic evolution of the pressure and humidity inside the manifolds. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Masm ( float ) \u2013 Molar mass of all the gaseous species inside the anode supply manifold (kg.mol-1). Maem ( float ) \u2013 Molar mass of all the gaseous species inside the anode exhaust manifold (kg.mol-1). Mcsm ( float ) \u2013 Molar mass of all the gaseous species inside the cathode supply manifold (kg.mol-1). Mcem ( float ) \u2013 Molar mass of all the gaseous species inside the cathode exhaust manifold (kg.mol-1). Tfc ( float ) \u2013 Fuel cell temperature (K). Hgc ( float ) \u2013 Thickness of the gas channel (m). Wgc ( float ) \u2013 Width of the gas channel (m). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Jv_a_in ( float ) \u2013 Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Water vapor flow at the cathode outlet (mol.m-2.s-1). Wasm_in ( float ) \u2013 Flow at the anode supply manifold inlet (kg.s-1). Wasm_out ( float ) \u2013 Flow at the anode supply manifold outlet (kg.s-1). Waem_in ( float ) \u2013 Flow at the anode exhaust manifold inlet (kg.s-1). Waem_out ( float ) \u2013 Flow at the anode exhaust manifold outlet (kg.s-1). Wcsm_in ( float ) \u2013 Flow at the cathode supply manifold inlet (kg.s-1). Wcsm_out ( float ) \u2013 Flow at the cathode supply manifold outlet (kg.s-1). Wcem_in ( float ) \u2013 Flow at the cathode exhaust manifold inlet (kg.s-1). Wcem_out ( float ) \u2013 Flow at the cathode exhaust manifold outlet (kg.s-1). Ware ( float ) \u2013 Anode side recirculation flow (kg.s-1). Wv_asm_in ( float ) \u2013 Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out ( float ) \u2013 Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in ( float ) \u2013 Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out ( float ) \u2013 Vapor flow at the cathode external manifold outlet (mol.s-1). Source code in model/dif_eq.py def calculate_dyn_manifold_pressure_and_humidity_evolution(dif_eq, Masm, Maem, Mcsm, Mcem, Tfc, Hgc, Wgc, type_auxiliary, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out, **kwargs): \"\"\"This function calculates the dynamic evolution of the pressure and humidity inside the manifolds. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Masm : float Molar mass of all the gaseous species inside the anode supply manifold (kg.mol-1). Maem : float Molar mass of all the gaseous species inside the anode exhaust manifold (kg.mol-1). Mcsm : float Molar mass of all the gaseous species inside the cathode supply manifold (kg.mol-1). Mcem : float Molar mass of all the gaseous species inside the cathode exhaust manifold (kg.mol-1). Tfc : float Fuel cell temperature (K). Hgc : float Thickness of the gas channel (m). Wgc : float Width of the gas channel (m). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Jv_a_in : float Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out : float Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in : float Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out : float Water vapor flow at the cathode outlet (mol.m-2.s-1). Wasm_in : float Flow at the anode supply manifold inlet (kg.s-1). Wasm_out : float Flow at the anode supply manifold outlet (kg.s-1). Waem_in : float Flow at the anode exhaust manifold inlet (kg.s-1). Waem_out : float Flow at the anode exhaust manifold outlet (kg.s-1). Wcsm_in : float Flow at the cathode supply manifold inlet (kg.s-1). Wcsm_out : float Flow at the cathode supply manifold outlet (kg.s-1). Wcem_in : float Flow at the cathode exhaust manifold inlet (kg.s-1). Wcem_out : float Flow at the cathode exhaust manifold outlet (kg.s-1). Ware : float Anode side recirculation flow (kg.s-1). Wv_asm_in : float Vapor flow at the anode supply manifold inlet (mol.s-1). Wv_aem_out : float Vapor flow at the anode external manifold outlet (mol.s-1). Wv_csm_in : float Vapor flow at the cathode supply manifold inlet (mol.s-1). Wv_cem_out : float Vapor flow at the cathode external manifold outlet (mol.s-1). \"\"\" # Pressure evolution inside the manifolds if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dPasm / dt'] = (Wasm_in + Ware - n_cell * Wasm_out) / (Vsm * Masm) * R * Tfc dif_eq['dPaem / dt'] = (n_cell * Waem_in - Ware - Waem_out) / (Vem * Maem) * R * Tfc dif_eq['dPcsm / dt'] = (Wcsm_in - n_cell * Wcsm_out) / (Vsm * Mcsm) * R * Tfc dif_eq['dPcem / dt'] = (n_cell * Wcem_in - Wcem_out) / (Vem * Mcem) * R * Tfc elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dPasm / dt'] = (Wasm_in - n_cell * Wasm_out) / (Vsm * Masm) * R * Tfc dif_eq['dPaem / dt'] = (n_cell * Waem_in - Waem_out) / (Vem * Maem) * R * Tfc dif_eq['dPcsm / dt'] = (Wcsm_in - n_cell * Wcsm_out) / (Vsm * Mcsm) * R * Tfc dif_eq['dPcem / dt'] = (n_cell * Wcem_in - Wcem_out) / (Vem * Mcem) * R * Tfc else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dPasm / dt'], dif_eq['dPaem / dt'], dif_eq['dPcsm / dt'], dif_eq['dPcem / dt'] = 0, 0, 0, 0 # Humidity evolution inside the manifolds if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\": dif_eq['dPhi_asm / dt'] = (Wv_asm_in - Jv_a_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_aem / dt'] = (Jv_a_out * Hgc * Wgc * n_cell - Wv_asm_in - Wv_aem_out) / Vem * R * Tfc / Psat(Tfc) dif_eq['dPhi_csm / dt'] = (Wv_csm_in - Jv_c_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_cem / dt'] = (Jv_c_out * Hgc * Wgc * n_cell - Wv_cem_out) / Vem * R * Tfc / Psat(Tfc) elif type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dPhi_asm / dt'] = (Wv_asm_in - Jv_a_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_aem / dt'] = (Jv_a_out * Hgc * Wgc * n_cell - Wv_aem_out) / Vem * R * Tfc / Psat(Tfc) dif_eq['dPhi_csm / dt'] = (Wv_csm_in - Jv_c_in * Hgc * Wgc * n_cell) / Vsm * R * Tfc / Psat(Tfc) dif_eq['dPhi_cem / dt'] = (Jv_c_out * Hgc * Wgc * n_cell - Wv_cem_out) / Vem * R * Tfc / Psat(Tfc) else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dPhi_asm / dt'], dif_eq['dPhi_aem / dt'], dif_eq['dPhi_csm / dt'], dif_eq['dPhi_cem / dt'] = 0, 0, 0, 0","title":"calculate_dyn_manifold_pressure_and_humidity_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_throttle_area_evolution","text":"This function calculates the dynamic evolution of the throttle area inside the anode and cathode auxiliaries. This function has to be executed after 'calculate_dyn_vapor_evolution' and 'calculate_dyn_H2_O2_N2_evolution'. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. Pagc ( float ) \u2013 Pressure inside the anode gas channel (Pa). Pcgc ( float ) \u2013 Pressure inside the cathode gas channel (Pa). type_auxiliary ( str ) \u2013 Type of auxiliary components used in the fuel cell model. Abp_a ( float ) \u2013 Throttle area inside the anode auxiliaries (m2). Abp_c ( float ) \u2013 Throttle area inside the cathode auxiliaries (m2). Tfc ( float ) \u2013 Fuel cell temperature (K). Pa_des ( float ) \u2013 Desired pressure inside the anode gas channel (Pa). Pc_des ( float ) \u2013 Desired pressure inside the cathode gas channel (Pa). Source code in model/dif_eq.py def calculate_dyn_throttle_area_evolution(dif_eq, Pagc, Pcgc, type_auxiliary, Abp_a, Abp_c, Tfc, Pa_des, Pc_des, **kwargs): \"\"\"This function calculates the dynamic evolution of the throttle area inside the anode and cathode auxiliaries. This function has to be executed after 'calculate_dyn_vapor_evolution' and 'calculate_dyn_H2_O2_N2_evolution'. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. Pagc : float Pressure inside the anode gas channel (Pa). Pcgc : float Pressure inside the cathode gas channel (Pa). type_auxiliary : str Type of auxiliary components used in the fuel cell model. Abp_a : float Throttle area inside the anode auxiliaries (m2). Abp_c : float Throttle area inside the cathode auxiliaries (m2). Tfc : float Fuel cell temperature (K). Pa_des : float Desired pressure inside the anode gas channel (Pa). Pc_des : float Desired pressure inside the cathode gas channel (Pa). \"\"\" # Calculation of the pressure derivative inside the gas channels dPagcdt = (dif_eq['dC_v_agc / dt'] + dif_eq['dC_H2_agc / dt']) * R * Tfc dPcgcdt = (dif_eq['dC_v_cgc / dt'] + dif_eq['dC_O2_cgc / dt'] + dif_eq['dC_N2 / dt']) * R * Tfc # Throttle area evolution inside the anode auxiliaries if type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dAbp_a / dt'] = - Kp * (Pa_des - Pagc) + Kd * dPagcdt # PD controller if Abp_a > A_T and dif_eq['dAbp_a / dt'] > 0: # The throttle area cannot be higher than the maximum value dif_eq['dAbp_a / dt'] = 0 elif Abp_a < 0 and dif_eq['dAbp_a / dt'] < 0: # The throttle area cannot be lower than 0 dif_eq['dAbp_a / dt'] = 0 else: # elif type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ # type_auxiliary == \"no_auxiliary\": dif_eq['dAbp_a / dt'] = 0 # The throttle area is not considered # Throttle area evolution inside the cathode auxiliaries if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": dif_eq['dAbp_c / dt'] = - Kp * (Pc_des - Pcgc) + Kd * dPcgcdt # PD controller if Abp_c > A_T and dif_eq['dAbp_c / dt'] > 0: # The throttle area cannot be higher than the maximum value dif_eq['dAbp_c / dt'] = 0 elif Abp_c < 0 and dif_eq['dAbp_c / dt'] < 0: # The throttle area cannot be lower than 0 dif_eq['dAbp_c / dt'] = 0 else: # elif type_auxiliary == \"no_auxiliary\": dif_eq['dAbp_a / dt'] = 0 # The throttle area is not considered","title":"calculate_dyn_throttle_area_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_vapor_evolution","text":"This function calculates the dynamic evolution of the vapor in the gas channels, the gas diffusion layers and the catalyst layers. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer (m). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). Hgc ( float ) \u2013 Thickness of the gas channel (m). Lgc ( float ) \u2013 Length of the gas channel (m). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. Jv_a_in ( float ) \u2013 Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out ( float ) \u2013 Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in ( float ) \u2013 Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out ( float ) \u2013 Water vapor flow at the cathode outlet (mol.m-2.s-1). Jv_agc_agdl ( float ) \u2013 Water vapor flow between the anode gas channel and the anode GDL (mol.m-2.s-1). Jv_agdl_agdl ( list ) \u2013 Water vapor flow between two nodes of the anode GDL (mol.m-2.s-1). Jv_agdl_acl ( float ) \u2013 Water vapor flow between the anode GDL and the anode CL (mol.m-2.s-1). S_sorp_acl \u2013 Water vapor sorption in the anode CL (mol.m-3.s-1). S_sorp_ccl \u2013 Water vapor sorption in the cathode CL (mol.m-3.s-1). Jv_ccl_cgdl ( float ) \u2013 Water vapor flow between the cathode CL and the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgdl ( list ) \u2013 Water vapor flow between two nodes of the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgc ( float ) \u2013 Water vapor flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). Sv_agdl ( list ) \u2013 Water vapor produced in the anode GDL (mol.m-3.s-1). Sv_acl ( float ) \u2013 Water vapor produced in the anode CL (mol.m-3.s-1). Sv_ccl ( float ) \u2013 Water vapor produced in the cathode CL (mol.m-3.s-1). Sv_cgdl ( list ) \u2013 Water vapor produced in the cathode GDL (mol.m-3.s-1). Source code in model/dif_eq.py def calculate_dyn_vapor_evolution(dif_eq, sv, Hgdl, Hcl, Hgc, Lgc, epsilon_gdl, n_gdl, Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, Jv_agc_agdl, Jv_agdl_agdl, Jv_agdl_acl, S_sorp_acl, S_sorp_ccl, Jv_ccl_cgdl, Jv_cgdl_cgdl, Jv_cgdl_cgc, Sv_agdl, Sv_acl, Sv_ccl, Sv_cgdl, **kwargs): \"\"\"This function calculates the dynamic evolution of the vapor in the gas channels, the gas diffusion layers and the catalyst layers. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. Hgdl : float Thickness of the gas diffusion layer (m). Hcl : float Thickness of the catalyst layer (m). Hgc : float Thickness of the gas channel (m). Lgc : float Length of the gas channel (m). epsilon_gdl : float Anode/cathode GDL porosity. n_gdl : int Number of model nodes placed inside each GDL. Jv_a_in : float Water vapor flow at the anode inlet (mol.m-2.s-1). Jv_a_out : float Water vapor flow at the anode outlet (mol.m-2.s-1). Jv_c_in : float Water vapor flow at the cathode inlet (mol.m-2.s-1). Jv_c_out : float Water vapor flow at the cathode outlet (mol.m-2.s-1). Jv_agc_agdl : float Water vapor flow between the anode gas channel and the anode GDL (mol.m-2.s-1). Jv_agdl_agdl : list Water vapor flow between two nodes of the anode GDL (mol.m-2.s-1). Jv_agdl_acl : float Water vapor flow between the anode GDL and the anode CL (mol.m-2.s-1). S_sorp_acl: float Water vapor sorption in the anode CL (mol.m-3.s-1). S_sorp_ccl: float Water vapor sorption in the cathode CL (mol.m-3.s-1). Jv_ccl_cgdl : float Water vapor flow between the cathode CL and the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgdl : list Water vapor flow between two nodes of the cathode GDL (mol.m-2.s-1). Jv_cgdl_cgc : float Water vapor flow between the cathode GDL and the cathode gas channel (mol.m-2.s-1). Sv_agdl : list Water vapor produced in the anode GDL (mol.m-3.s-1). Sv_acl : float Water vapor produced in the anode CL (mol.m-3.s-1). Sv_ccl : float Water vapor produced in the cathode CL (mol.m-3.s-1). Sv_cgdl : list Water vapor produced in the cathode GDL (mol.m-3.s-1). \"\"\" # At the anode side # Inside the AGC dif_eq['dC_v_agc / dt'] = (Jv_a_in - Jv_a_out) / Lgc - Jv_agc_agdl / Hgc # Inside the AGDL dif_eq['dC_v_agdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_agdl_1'])) * \\ ((Jv_agc_agdl - Jv_agdl_agdl[1]) / (Hgdl / n_gdl) + Sv_agdl[1]) for i in range(2, n_gdl): dif_eq[f'dC_v_agdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{i}'])) * \\ ((Jv_agdl_agdl[i - 1] - Jv_agdl_agdl[i]) / (Hgdl / n_gdl) + Sv_agdl[i]) dif_eq[f'dC_v_agdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_agdl_{n_gdl}'])) * \\ ((Jv_agdl_agdl[n_gdl - 1] - Jv_agdl_acl) / (Hgdl / n_gdl) + Sv_agdl[n_gdl]) # Inside the ACL dif_eq['dC_v_acl / dt'] = 1 / (epsilon_cl * (1 - sv['s_acl'])) * (Jv_agdl_acl / Hcl - S_sorp_acl + Sv_acl) # At the cathode side # Inside the CCL dif_eq['dC_v_ccl / dt'] = 1 / (epsilon_cl * (1 - sv['s_ccl'])) * (- Jv_ccl_cgdl / Hcl - S_sorp_ccl + Sv_ccl) # Inside the CGDL dif_eq['dC_v_cgdl_1 / dt'] = 1 / (epsilon_gdl * (1 - sv['s_cgdl_1'])) * \\ ((Jv_ccl_cgdl - Jv_cgdl_cgdl[1]) / (Hgdl / n_gdl) + Sv_cgdl[1]) for i in range(2, n_gdl): dif_eq[f'dC_v_cgdl_{i} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{i}'])) * \\ ((Jv_cgdl_cgdl[i - 1] - Jv_cgdl_cgdl[i]) / (Hgdl / n_gdl) + Sv_cgdl[i]) dif_eq[f'dC_v_cgdl_{n_gdl} / dt'] = 1 / (epsilon_gdl * (1 - sv[f's_cgdl_{n_gdl}'])) * \\ ((Jv_cgdl_cgdl[n_gdl - 1] - Jv_cgdl_cgc) / (Hgdl / n_gdl) + Sv_cgdl[n_gdl]) # Inside the CGC dif_eq['dC_v_cgc / dt'] = (Jv_c_in - Jv_c_out) / Lgc + Jv_cgdl_cgc / Hgc","title":"calculate_dyn_vapor_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.calculate_dyn_voltage_evolution","text":"This function calculates the dynamic evolution of the cell overpotential eta_c. Parameters: dif_eq ( dict ) \u2013 Dictionary used for saving the differential equations. i_fc ( float ) \u2013 Fuel cell current density (A.m-2). C_O2_ccl ( float ) \u2013 Oxygen concentration in the cathode catalyst layer (mol.m-3). eta_c ( float ) \u2013 Cell overpotential (V). Tfc ( float ) \u2013 Fuel cell temperature (K). Hcl ( float ) \u2013 Thickness of the catalyst layer (m). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode (A.m-2). kappa_c ( float ) \u2013 Overpotential correction exponent. C_scl ( float ) \u2013 Volumetric space-charge layer capacitance (F.m-3). i_n ( float ) \u2013 Crossover current density (A.m-2). f_drop ( float ) \u2013 Liquid water induced voltage drop function. Source code in model/dif_eq.py def calculate_dyn_voltage_evolution(dif_eq, i_fc, C_O2_ccl, eta_c, Tfc, Hcl, i0_c_ref, kappa_c, C_scl, i_n, f_drop, **kwargs): \"\"\"This function calculates the dynamic evolution of the cell overpotential eta_c. Parameters ---------- dif_eq : dict Dictionary used for saving the differential equations. i_fc : float Fuel cell current density (A.m-2). C_O2_ccl : float Oxygen concentration in the cathode catalyst layer (mol.m-3). eta_c : float Cell overpotential (V). Tfc : float Fuel cell temperature (K). Hcl : float Thickness of the catalyst layer (m). i0_c_ref : float Reference exchange current density at the cathode (A.m-2). kappa_c : float Overpotential correction exponent. C_scl : float Volumetric space-charge layer capacitance (F.m-3). i_n : float Crossover current density (A.m-2). f_drop : float Liquid water induced voltage drop function. \"\"\" dif_eq['deta_c / dt'] = 1 / (C_scl * Hcl) * ((i_fc + i_n) - i0_c_ref * (C_O2_ccl / C_O2ref) ** kappa_c * np.exp(f_drop * alpha_c * F / (R * Tfc) * eta_c))","title":"calculate_dyn_voltage_evolution"},{"location":"functions/model/dif_eq/#model.dif_eq.dydt","text":"This function gives the system of differential equations to solve. Parameters: t ( float ) \u2013 Time (s). y ( ndarray ) \u2013 Numpy list of the solver variables. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. solver_variable_names ( list ) \u2013 Names of the solver variables. control_variables ( dict ) \u2013 Variables controlled by the user. Returns: dydt ( list ) \u2013 List containing the derivative of the solver variables. Source code in model/dif_eq.py def dydt(t, y, operating_inputs, parameters, solver_variable_names, control_variables): \"\"\"This function gives the system of differential equations to solve. Parameters ---------- t : float Time (s). y : numpy.ndarray Numpy list of the solver variables. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. solver_variable_names : list Names of the solver variables. control_variables : dict Variables controlled by the user. Returns ------- dydt : list List containing the derivative of the solver variables. \"\"\" # Creation of the dif_eq dictionary. It is an intermediate calculation to simplify the writing of the code. dif_eq = {('d' + key + ' / dt'): 0 for key in solver_variable_names} # Creation of the solver_variables dict. It is an intermediate calculation to simplify the writing of the code. solver_variables = {} for index, key in enumerate(solver_variable_names): solver_variables[key] = y[index] # Modifications of the operating conditions in real time, if required. if parameters[\"type_control\"] != \"no_control\": control_operating_conditions(t, solver_variables, operating_inputs, parameters, control_variables) # Intermediate values i_fc = operating_inputs['current_density'](t, parameters) Mext, Pagc, Pcgc, i_n, Masm, Maem, Mcsm, Mcem, rho_H2O = dif_eq_int_values(solver_variables, control_variables, operating_inputs, parameters) Wcp_des, Wa_inj_des, Wc_inj_des = desired_flows(solver_variables, control_variables, i_n, i_fc, operating_inputs, parameters, Mext) eta_c_intermediate_values = calculate_eta_c_intermediate_values(solver_variables, operating_inputs, parameters) # Calculation of the flows flows_dico = calculate_flows(t, solver_variables, control_variables, i_fc, operating_inputs, parameters) # Calculation of the dynamic evolutions # Inside the cell calculate_dyn_dissoved_water_evolution(dif_eq, **parameters, **flows_dico) calculate_dyn_liquid_water_evolution(dif_eq, rho_H2O, **parameters, **flows_dico) calculate_dyn_vapor_evolution(dif_eq, solver_variables, **parameters, **flows_dico) calculate_dyn_H2_O2_N2_evolution(dif_eq, solver_variables, **parameters, **flows_dico) calculate_dyn_voltage_evolution(dif_eq, i_fc, **solver_variables, **operating_inputs, **parameters, **eta_c_intermediate_values) # Inside the auxiliary components calculate_dyn_manifold_pressure_and_humidity_evolution(dif_eq, Masm, Maem, Mcsm, Mcem, **solver_variables, **operating_inputs, **parameters, **flows_dico) calculate_dyn_air_compressor_and_humidifier_evolution(dif_eq, Wcp_des, Wa_inj_des, Wc_inj_des, **solver_variables, **parameters) calculate_dyn_throttle_area_evolution(dif_eq, Pagc, Pcgc, **solver_variables, **operating_inputs, **parameters) # dif_eq is converted to dydt because the solver requires an ordered list to work dydt = [] for key in solver_variable_names: dydt.append(dif_eq['d' + key + ' / dt']) return dydt","title":"dydt"},{"location":"functions/model/flows/","text":"Flows This file represents all the flows inside the fuel cell system. It is a component of the fuel cell model. calculate_flows(t, sv, control_variables, i_fc, operating_inputs, parameters) This function calculates the flows inside the fuel cell system. Parameters: t ( float ) \u2013 Time (s). sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. control_variables ( dict ) \u2013 Variables controlled by the user. i_fc ( float ) \u2013 Fuel cell current density at time t (A.m-2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: dict \u2013 Flows inside the fuel cell system. Source code in model/flows.py def calculate_flows(t, sv, control_variables, i_fc, operating_inputs, parameters): \"\"\"This function calculates the flows inside the fuel cell system. Parameters ---------- t : float Time (s). sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. control_variables : dict Variables controlled by the user. i_fc : float Fuel cell current density at time t (A.m-2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- dict Flows inside the fuel cell system. \"\"\" # ___________________________________________________Preliminaries__________________________________________________ # Extraction of the variables C_v_agc, C_v_acl, C_v_ccl, C_v_cgc = sv['C_v_agc'], sv['C_v_acl'], sv['C_v_ccl'], sv['C_v_cgc'] s_acl, s_ccl = sv['s_acl'], sv['s_ccl'] lambda_acl, lambda_mem, lambda_ccl = sv['lambda_acl'], sv['lambda_mem'], sv['lambda_ccl'] C_H2_agc, C_H2_acl, C_O2_ccl, C_O2_cgc = sv['C_H2_agc'], sv['C_H2_acl'], sv['C_O2_ccl'], sv['C_O2_cgc'] C_N2 = sv['C_N2'] # Extraction of the operating inputs and parameters Tfc, Pc_des = operating_inputs['Tfc'], operating_inputs['Pc_des'] Hgdl, Hmem, Hcl = parameters['Hgdl'], parameters['Hmem'], parameters['Hcl'] Hgc, Wgc = parameters['Hgc'], parameters['Wgc'] epsilon_gdl, epsilon_c = parameters['epsilon_gdl'], parameters['epsilon_c'] e, kappa_co, n_gdl = parameters['e'], parameters['kappa_co'], parameters['n_gdl'] a_slim, b_slim = parameters['a_slim'], parameters['b_slim'] # Intermediate values (Pagc, Pcgc, s_agdl_agdl, s_agdl_acl, s_ccl_cgdl, s_cgdl_cgdl, epsilon_mean, theta_c_mean, lambda_acl_mem, lambda_mem_ccl, Pagc_agdl, Pagdl_agdl, Pagdl_acl, Pccl_cgdl, Pcgdl_cgdl, Pcgdl_cgc, nu_l) \\ = flows_int_values(sv, operating_inputs, parameters) # Inlet and outlet flows Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, \\ Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, \\ Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out \\ = auxiliaries(t, sv, control_variables, i_fc, operating_inputs, parameters) # ________________________________________Dissolved water flows (mol.m-2.s-1)_______________________________________ # Anode side J_lambda_mem_acl = 2.5 / 22 * i_fc / F * lambda_acl_mem - 2 * rho_mem / M_eq * \\ D(lambda_acl_mem) * (lambda_mem - lambda_acl) / (Hmem + Hcl) # Cathode side J_lambda_mem_ccl = 2.5 / 22 * i_fc / F * lambda_mem_ccl - 2 * rho_mem / M_eq * \\ D(lambda_mem_ccl) * (lambda_ccl - lambda_mem) / (Hmem + Hcl) # _________________________________________Liquid water flows (kg.m-2.s-1)__________________________________________ # Anode side Jl_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jl_agdl_agdl[i] = - sigma(Tfc) * K0(epsilon_gdl, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_gdl)) * \\ (epsilon_gdl / K0(epsilon_gdl, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_agdl_agdl[i] ** e + 1e-7) * (1.417 - 4.24 * s_agdl_agdl[i] + 3.789 * s_agdl_agdl[i] ** 2) * \\ (sv[f's_agdl_{i + 1}'] - sv[f's_agdl_{i}']) / (Hgdl / n_gdl) Jl_agdl_acl = - 2 * sigma(Tfc) * K0(epsilon_mean, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_mean)) * \\ (epsilon_mean / K0(epsilon_mean, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_agdl_acl ** e + 1e-7) * (1.417 - 4.24 * s_agdl_acl + 3.789 * s_agdl_acl ** 2) * \\ (s_acl - sv[f's_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side Jl_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jl_cgdl_cgdl[i] = - sigma(Tfc) * K0(epsilon_gdl, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_gdl)) * \\ (epsilon_gdl / K0(epsilon_gdl, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_cgdl_cgdl[i] ** e + 1e-7) * (1.417 - 4.24 * s_cgdl_cgdl[i] + 3.789 * s_cgdl_cgdl[i] ** 2) * \\ (sv[f's_cgdl_{i + 1}'] - sv[f's_cgdl_{i}']) / (Hgdl / n_gdl) Jl_ccl_cgdl = - 2 * sigma(Tfc) * K0(epsilon_mean, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_mean)) * \\ (epsilon_mean / K0(epsilon_mean, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_ccl_cgdl ** e + 1e-7) * (1.417 - 4.24 * s_ccl_cgdl + 3.789 * s_ccl_cgdl ** 2) * \\ (sv['s_cgdl_1'] - s_ccl) / (Hgdl / n_gdl + Hcl) # _____________________________________________Vapor flows (mol.m-2.s-1)____________________________________________ # Convective vapor flows # Anode side Jv_agc_agdl = h_a(Pagc_agdl, Tfc, Wgc, Hgc) * (C_v_agc - sv['C_v_agdl_1']) # Cathode side Jv_cgdl_cgc = h_c(Pcgdl_cgc, Tfc, Wgc, Hgc) * (sv[f'C_v_cgdl_{n_gdl}'] - C_v_cgc) # Conductive vapor flows # Anode side Jv_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jv_agdl_agdl[i] = - Da_eff(s_agdl_agdl[i], epsilon_gdl, Pagdl_agdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_v_agdl_{i + 1}'] - sv[f'C_v_agdl_{i}']) / (Hgdl / n_gdl) Jv_agdl_acl = - 2 * Da_eff(s_agdl_acl, epsilon_mean, Pagdl_acl, Tfc, epsilon_c, epsilon_gdl) * \\ (C_v_acl - sv[f'C_v_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side Jv_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jv_cgdl_cgdl[i] = - Dc_eff(s_cgdl_cgdl[i], epsilon_gdl, Pcgdl_cgdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_v_cgdl_{i + 1}'] - sv[f'C_v_cgdl_{i}']) / (Hgdl / n_gdl) Jv_ccl_cgdl = - 2 * Dc_eff(s_ccl_cgdl, epsilon_mean, Pccl_cgdl, Tfc, epsilon_c, epsilon_gdl) * \\ (sv['C_v_cgdl_1'] - C_v_ccl) / (Hgdl / n_gdl + Hcl) # __________________________________________H2 and O2 flows (mol.m-2.s-1)___________________________________________ # Hydrogen and oxygen consumption # Anode side S_H2_acl = - i_fc / (2 * F * Hcl) - \\ R * Tfc / (Hmem * Hcl) * (k_H2(lambda_mem, Tfc, kappa_co) * C_H2_acl + 2 * k_O2(lambda_mem, Tfc, kappa_co) * C_O2_ccl) # Cathode side S_O2_ccl = - i_fc / (4 * F * Hcl) - \\ R * Tfc / (Hmem * Hcl) * (k_O2(lambda_mem, Tfc, kappa_co) * C_O2_ccl + 1 / 2 * k_H2(lambda_mem, Tfc, kappa_co) * C_H2_acl) # Conductive-convective H2 and O2 flows # Anode side J_H2_agc_agdl = h_a(Pagc_agdl, Tfc, Wgc, Hgc) * (C_H2_agc - sv['C_H2_agdl_1']) # Cathode side J_O2_cgdl_cgc = h_c(Pcgdl_cgc, Tfc, Wgc, Hgc) * (sv[f'C_O2_cgdl_{n_gdl}'] - C_O2_cgc) # Conductive H2 and O2 flows # Anode side J_H2_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): J_H2_agdl_agdl[i] = - Da_eff(s_agdl_agdl[i], epsilon_gdl, Pagdl_agdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_H2_agdl_{i + 1}'] - sv[f'C_H2_agdl_{i}']) / (Hgdl / n_gdl) J_H2_agdl_acl = - 2 * Da_eff(s_agdl_acl, epsilon_mean, Pagdl_acl, Tfc, epsilon_c, epsilon_gdl) * \\ (C_H2_acl - sv[f'C_H2_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side J_O2_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): J_O2_cgdl_cgdl[i] = - Dc_eff(s_cgdl_cgdl[i], epsilon_gdl, Pcgdl_cgdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_O2_cgdl_{i + 1}'] - sv[f'C_O2_cgdl_{i}']) / (Hgdl / n_gdl) J_O2_ccl_cgdl = - 2 * Dc_eff(s_ccl_cgdl, epsilon_mean, Pccl_cgdl, Tfc, epsilon_c, epsilon_gdl) * \\ (sv['C_O2_cgdl_1'] - C_O2_ccl) / (Hgdl / n_gdl + Hcl) # __________________________________________Water generated (mol.m-3.s-1)___________________________________________ # Water produced in the membrane at the CL through the chemical reaction and crossover # Anode side Sp_acl = 2 * k_O2(lambda_mem, Tfc, kappa_co) * R * Tfc / (Hmem * Hcl) * C_O2_ccl # Cathode side Sp_ccl = i_fc / (2 * F * Hcl) + k_H2(lambda_mem, Tfc, kappa_co) * R * Tfc / (Hmem * Hcl) * C_H2_acl # Water sorption in the CL: # Anode side S_sorp_acl = gamma_sorp(C_v_acl, s_acl, lambda_acl, Tfc, Hcl, Kshape) * rho_mem / M_eq * \\ (lambda_eq(C_v_acl, s_acl, Tfc, Kshape) - lambda_acl) # Cathode side S_sorp_ccl = gamma_sorp(C_v_ccl, s_ccl, lambda_ccl, Tfc, Hcl, Kshape) * rho_mem / M_eq * \\ (lambda_eq(C_v_ccl, s_ccl, Tfc, Kshape) - lambda_ccl) # Liquid water generated through vapor condensation or degenerated through evaporation # Anode side Sl_agdl = [None] + [Svl(sv[f's_agdl_{i}'], sv[f'C_v_agdl_{i}'], sv[f'C_v_agdl_{i}'] + sv[f'C_H2_agdl_{i}'], epsilon_gdl, Tfc, gamma_cond, gamma_evap) for i in range(1, n_gdl + 1)] Sl_acl = Svl(s_acl, C_v_acl, C_v_acl + C_H2_acl, epsilon_cl, Tfc, gamma_cond, gamma_evap) # Cathode side Sl_cgdl = [None] + [Svl(sv[f's_cgdl_{i}'], sv[f'C_v_cgdl_{i}'], sv[f'C_v_cgdl_{i}'] + sv[f'C_O2_cgdl_{i}'] + C_N2, epsilon_gdl, Tfc, gamma_cond, gamma_evap) for i in range(1, n_gdl + 1)] Sl_ccl = Svl(s_ccl, C_v_ccl, C_v_ccl + C_O2_ccl + C_N2, epsilon_cl, Tfc, gamma_cond, gamma_evap) # Vapor generated through liquid water evaporation or degenerated through condensation # Anode side Sv_agdl = [None] + [-x for x in Sl_agdl[1:]] Sv_acl = - Sl_acl # Cathode side Sv_cgdl = [None] + [-x for x in Sl_cgdl[1:]] Sv_ccl = - Sl_ccl return {'Jv_a_in': Jv_a_in, 'Jv_a_out': Jv_a_out, 'Jv_c_in': Jv_c_in, 'Jv_c_out': Jv_c_out, 'J_H2_in': J_H2_in, 'J_H2_out': J_H2_out, 'J_O2_in': J_O2_in, 'J_O2_out': J_O2_out, 'J_N2_in': J_N2_in, 'J_N2_out': J_N2_out, 'Jv_agc_agdl': Jv_agc_agdl, 'Jv_agdl_agdl': Jv_agdl_agdl, 'Jv_agdl_acl': Jv_agdl_acl, 'S_sorp_acl': S_sorp_acl, 'S_sorp_ccl': S_sorp_ccl, 'Jv_ccl_cgdl': Jv_ccl_cgdl, 'Jv_cgdl_cgdl': Jv_cgdl_cgdl, 'Jv_cgdl_cgc': Jv_cgdl_cgc, 'Jl_agdl_agdl': Jl_agdl_agdl, 'Jl_agdl_acl': Jl_agdl_acl, 'J_lambda_mem_acl': J_lambda_mem_acl, 'J_lambda_mem_ccl': J_lambda_mem_ccl, 'Jl_ccl_cgdl': Jl_ccl_cgdl, 'Jl_cgdl_cgdl': Jl_cgdl_cgdl, 'Sp_acl': Sp_acl, 'Sp_ccl': Sp_ccl, 'J_H2_agc_agdl': J_H2_agc_agdl, 'J_H2_agdl_agdl': J_H2_agdl_agdl, 'J_H2_agdl_acl': J_H2_agdl_acl, 'J_O2_ccl_cgdl': J_O2_ccl_cgdl, 'J_O2_cgdl_cgdl': J_O2_cgdl_cgdl, 'J_O2_cgdl_cgc': J_O2_cgdl_cgc, 'S_H2_acl': S_H2_acl, 'S_O2_ccl': S_O2_ccl, 'Sv_agdl': Sv_agdl, 'Sv_acl': Sv_acl, 'Sv_ccl': Sv_ccl, 'Sv_cgdl': Sv_cgdl, 'Sl_agdl': Sl_agdl, 'Sl_acl': Sl_acl, 'Sl_ccl': Sl_ccl, 'Sl_cgdl': Sl_cgdl, 'Pagc': Pagc, 'Pcgc': Pcgc, 'Wasm_in': Wasm_in, 'Wasm_out': Wasm_out, 'Waem_in': Waem_in, 'Waem_out': Waem_out, 'Wcsm_in': Wcsm_in, 'Wcsm_out': Wcsm_out, 'Wcem_in': Wcem_in, 'Wcem_out': Wcem_out, 'Ware': Ware, 'Wv_asm_in': Wv_asm_in, 'Wv_aem_out': Wv_aem_out, 'Wv_csm_in': Wv_csm_in, 'Wv_cem_out': Wv_cem_out}","title":"Flows"},{"location":"functions/model/flows/#flows","text":"This file represents all the flows inside the fuel cell system. It is a component of the fuel cell model.","title":"Flows"},{"location":"functions/model/flows/#model.flows.calculate_flows","text":"This function calculates the flows inside the fuel cell system. Parameters: t ( float ) \u2013 Time (s). sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. control_variables ( dict ) \u2013 Variables controlled by the user. i_fc ( float ) \u2013 Fuel cell current density at time t (A.m-2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: dict \u2013 Flows inside the fuel cell system. Source code in model/flows.py def calculate_flows(t, sv, control_variables, i_fc, operating_inputs, parameters): \"\"\"This function calculates the flows inside the fuel cell system. Parameters ---------- t : float Time (s). sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. control_variables : dict Variables controlled by the user. i_fc : float Fuel cell current density at time t (A.m-2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- dict Flows inside the fuel cell system. \"\"\" # ___________________________________________________Preliminaries__________________________________________________ # Extraction of the variables C_v_agc, C_v_acl, C_v_ccl, C_v_cgc = sv['C_v_agc'], sv['C_v_acl'], sv['C_v_ccl'], sv['C_v_cgc'] s_acl, s_ccl = sv['s_acl'], sv['s_ccl'] lambda_acl, lambda_mem, lambda_ccl = sv['lambda_acl'], sv['lambda_mem'], sv['lambda_ccl'] C_H2_agc, C_H2_acl, C_O2_ccl, C_O2_cgc = sv['C_H2_agc'], sv['C_H2_acl'], sv['C_O2_ccl'], sv['C_O2_cgc'] C_N2 = sv['C_N2'] # Extraction of the operating inputs and parameters Tfc, Pc_des = operating_inputs['Tfc'], operating_inputs['Pc_des'] Hgdl, Hmem, Hcl = parameters['Hgdl'], parameters['Hmem'], parameters['Hcl'] Hgc, Wgc = parameters['Hgc'], parameters['Wgc'] epsilon_gdl, epsilon_c = parameters['epsilon_gdl'], parameters['epsilon_c'] e, kappa_co, n_gdl = parameters['e'], parameters['kappa_co'], parameters['n_gdl'] a_slim, b_slim = parameters['a_slim'], parameters['b_slim'] # Intermediate values (Pagc, Pcgc, s_agdl_agdl, s_agdl_acl, s_ccl_cgdl, s_cgdl_cgdl, epsilon_mean, theta_c_mean, lambda_acl_mem, lambda_mem_ccl, Pagc_agdl, Pagdl_agdl, Pagdl_acl, Pccl_cgdl, Pcgdl_cgdl, Pcgdl_cgc, nu_l) \\ = flows_int_values(sv, operating_inputs, parameters) # Inlet and outlet flows Jv_a_in, Jv_a_out, Jv_c_in, Jv_c_out, J_H2_in, J_H2_out, J_O2_in, J_O2_out, J_N2_in, J_N2_out, \\ Wasm_in, Wasm_out, Waem_in, Waem_out, Wcsm_in, Wcsm_out, Wcem_in, Wcem_out, Ware, \\ Wv_asm_in, Wv_aem_out, Wv_csm_in, Wv_cem_out \\ = auxiliaries(t, sv, control_variables, i_fc, operating_inputs, parameters) # ________________________________________Dissolved water flows (mol.m-2.s-1)_______________________________________ # Anode side J_lambda_mem_acl = 2.5 / 22 * i_fc / F * lambda_acl_mem - 2 * rho_mem / M_eq * \\ D(lambda_acl_mem) * (lambda_mem - lambda_acl) / (Hmem + Hcl) # Cathode side J_lambda_mem_ccl = 2.5 / 22 * i_fc / F * lambda_mem_ccl - 2 * rho_mem / M_eq * \\ D(lambda_mem_ccl) * (lambda_ccl - lambda_mem) / (Hmem + Hcl) # _________________________________________Liquid water flows (kg.m-2.s-1)__________________________________________ # Anode side Jl_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jl_agdl_agdl[i] = - sigma(Tfc) * K0(epsilon_gdl, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_gdl)) * \\ (epsilon_gdl / K0(epsilon_gdl, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_agdl_agdl[i] ** e + 1e-7) * (1.417 - 4.24 * s_agdl_agdl[i] + 3.789 * s_agdl_agdl[i] ** 2) * \\ (sv[f's_agdl_{i + 1}'] - sv[f's_agdl_{i}']) / (Hgdl / n_gdl) Jl_agdl_acl = - 2 * sigma(Tfc) * K0(epsilon_mean, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_mean)) * \\ (epsilon_mean / K0(epsilon_mean, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_agdl_acl ** e + 1e-7) * (1.417 - 4.24 * s_agdl_acl + 3.789 * s_agdl_acl ** 2) * \\ (s_acl - sv[f's_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side Jl_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jl_cgdl_cgdl[i] = - sigma(Tfc) * K0(epsilon_gdl, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_gdl)) * \\ (epsilon_gdl / K0(epsilon_gdl, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_cgdl_cgdl[i] ** e + 1e-7) * (1.417 - 4.24 * s_cgdl_cgdl[i] + 3.789 * s_cgdl_cgdl[i] ** 2) * \\ (sv[f's_cgdl_{i + 1}'] - sv[f's_cgdl_{i}']) / (Hgdl / n_gdl) Jl_ccl_cgdl = - 2 * sigma(Tfc) * K0(epsilon_mean, epsilon_c, epsilon_gdl) / nu_l * abs(np.cos(theta_c_mean)) * \\ (epsilon_mean / K0(epsilon_mean, epsilon_c, epsilon_gdl)) ** 0.5 * \\ (s_ccl_cgdl ** e + 1e-7) * (1.417 - 4.24 * s_ccl_cgdl + 3.789 * s_ccl_cgdl ** 2) * \\ (sv['s_cgdl_1'] - s_ccl) / (Hgdl / n_gdl + Hcl) # _____________________________________________Vapor flows (mol.m-2.s-1)____________________________________________ # Convective vapor flows # Anode side Jv_agc_agdl = h_a(Pagc_agdl, Tfc, Wgc, Hgc) * (C_v_agc - sv['C_v_agdl_1']) # Cathode side Jv_cgdl_cgc = h_c(Pcgdl_cgc, Tfc, Wgc, Hgc) * (sv[f'C_v_cgdl_{n_gdl}'] - C_v_cgc) # Conductive vapor flows # Anode side Jv_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jv_agdl_agdl[i] = - Da_eff(s_agdl_agdl[i], epsilon_gdl, Pagdl_agdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_v_agdl_{i + 1}'] - sv[f'C_v_agdl_{i}']) / (Hgdl / n_gdl) Jv_agdl_acl = - 2 * Da_eff(s_agdl_acl, epsilon_mean, Pagdl_acl, Tfc, epsilon_c, epsilon_gdl) * \\ (C_v_acl - sv[f'C_v_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side Jv_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): Jv_cgdl_cgdl[i] = - Dc_eff(s_cgdl_cgdl[i], epsilon_gdl, Pcgdl_cgdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_v_cgdl_{i + 1}'] - sv[f'C_v_cgdl_{i}']) / (Hgdl / n_gdl) Jv_ccl_cgdl = - 2 * Dc_eff(s_ccl_cgdl, epsilon_mean, Pccl_cgdl, Tfc, epsilon_c, epsilon_gdl) * \\ (sv['C_v_cgdl_1'] - C_v_ccl) / (Hgdl / n_gdl + Hcl) # __________________________________________H2 and O2 flows (mol.m-2.s-1)___________________________________________ # Hydrogen and oxygen consumption # Anode side S_H2_acl = - i_fc / (2 * F * Hcl) - \\ R * Tfc / (Hmem * Hcl) * (k_H2(lambda_mem, Tfc, kappa_co) * C_H2_acl + 2 * k_O2(lambda_mem, Tfc, kappa_co) * C_O2_ccl) # Cathode side S_O2_ccl = - i_fc / (4 * F * Hcl) - \\ R * Tfc / (Hmem * Hcl) * (k_O2(lambda_mem, Tfc, kappa_co) * C_O2_ccl + 1 / 2 * k_H2(lambda_mem, Tfc, kappa_co) * C_H2_acl) # Conductive-convective H2 and O2 flows # Anode side J_H2_agc_agdl = h_a(Pagc_agdl, Tfc, Wgc, Hgc) * (C_H2_agc - sv['C_H2_agdl_1']) # Cathode side J_O2_cgdl_cgc = h_c(Pcgdl_cgc, Tfc, Wgc, Hgc) * (sv[f'C_O2_cgdl_{n_gdl}'] - C_O2_cgc) # Conductive H2 and O2 flows # Anode side J_H2_agdl_agdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): J_H2_agdl_agdl[i] = - Da_eff(s_agdl_agdl[i], epsilon_gdl, Pagdl_agdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_H2_agdl_{i + 1}'] - sv[f'C_H2_agdl_{i}']) / (Hgdl / n_gdl) J_H2_agdl_acl = - 2 * Da_eff(s_agdl_acl, epsilon_mean, Pagdl_acl, Tfc, epsilon_c, epsilon_gdl) * \\ (C_H2_acl - sv[f'C_H2_agdl_{n_gdl}']) / (Hgdl / n_gdl + Hcl) # Cathode side J_O2_cgdl_cgdl = [None] + [0] * (n_gdl - 1) for i in range(1, n_gdl): J_O2_cgdl_cgdl[i] = - Dc_eff(s_cgdl_cgdl[i], epsilon_gdl, Pcgdl_cgdl[i], Tfc, epsilon_c, epsilon_gdl) * \\ (sv[f'C_O2_cgdl_{i + 1}'] - sv[f'C_O2_cgdl_{i}']) / (Hgdl / n_gdl) J_O2_ccl_cgdl = - 2 * Dc_eff(s_ccl_cgdl, epsilon_mean, Pccl_cgdl, Tfc, epsilon_c, epsilon_gdl) * \\ (sv['C_O2_cgdl_1'] - C_O2_ccl) / (Hgdl / n_gdl + Hcl) # __________________________________________Water generated (mol.m-3.s-1)___________________________________________ # Water produced in the membrane at the CL through the chemical reaction and crossover # Anode side Sp_acl = 2 * k_O2(lambda_mem, Tfc, kappa_co) * R * Tfc / (Hmem * Hcl) * C_O2_ccl # Cathode side Sp_ccl = i_fc / (2 * F * Hcl) + k_H2(lambda_mem, Tfc, kappa_co) * R * Tfc / (Hmem * Hcl) * C_H2_acl # Water sorption in the CL: # Anode side S_sorp_acl = gamma_sorp(C_v_acl, s_acl, lambda_acl, Tfc, Hcl, Kshape) * rho_mem / M_eq * \\ (lambda_eq(C_v_acl, s_acl, Tfc, Kshape) - lambda_acl) # Cathode side S_sorp_ccl = gamma_sorp(C_v_ccl, s_ccl, lambda_ccl, Tfc, Hcl, Kshape) * rho_mem / M_eq * \\ (lambda_eq(C_v_ccl, s_ccl, Tfc, Kshape) - lambda_ccl) # Liquid water generated through vapor condensation or degenerated through evaporation # Anode side Sl_agdl = [None] + [Svl(sv[f's_agdl_{i}'], sv[f'C_v_agdl_{i}'], sv[f'C_v_agdl_{i}'] + sv[f'C_H2_agdl_{i}'], epsilon_gdl, Tfc, gamma_cond, gamma_evap) for i in range(1, n_gdl + 1)] Sl_acl = Svl(s_acl, C_v_acl, C_v_acl + C_H2_acl, epsilon_cl, Tfc, gamma_cond, gamma_evap) # Cathode side Sl_cgdl = [None] + [Svl(sv[f's_cgdl_{i}'], sv[f'C_v_cgdl_{i}'], sv[f'C_v_cgdl_{i}'] + sv[f'C_O2_cgdl_{i}'] + C_N2, epsilon_gdl, Tfc, gamma_cond, gamma_evap) for i in range(1, n_gdl + 1)] Sl_ccl = Svl(s_ccl, C_v_ccl, C_v_ccl + C_O2_ccl + C_N2, epsilon_cl, Tfc, gamma_cond, gamma_evap) # Vapor generated through liquid water evaporation or degenerated through condensation # Anode side Sv_agdl = [None] + [-x for x in Sl_agdl[1:]] Sv_acl = - Sl_acl # Cathode side Sv_cgdl = [None] + [-x for x in Sl_cgdl[1:]] Sv_ccl = - Sl_ccl return {'Jv_a_in': Jv_a_in, 'Jv_a_out': Jv_a_out, 'Jv_c_in': Jv_c_in, 'Jv_c_out': Jv_c_out, 'J_H2_in': J_H2_in, 'J_H2_out': J_H2_out, 'J_O2_in': J_O2_in, 'J_O2_out': J_O2_out, 'J_N2_in': J_N2_in, 'J_N2_out': J_N2_out, 'Jv_agc_agdl': Jv_agc_agdl, 'Jv_agdl_agdl': Jv_agdl_agdl, 'Jv_agdl_acl': Jv_agdl_acl, 'S_sorp_acl': S_sorp_acl, 'S_sorp_ccl': S_sorp_ccl, 'Jv_ccl_cgdl': Jv_ccl_cgdl, 'Jv_cgdl_cgdl': Jv_cgdl_cgdl, 'Jv_cgdl_cgc': Jv_cgdl_cgc, 'Jl_agdl_agdl': Jl_agdl_agdl, 'Jl_agdl_acl': Jl_agdl_acl, 'J_lambda_mem_acl': J_lambda_mem_acl, 'J_lambda_mem_ccl': J_lambda_mem_ccl, 'Jl_ccl_cgdl': Jl_ccl_cgdl, 'Jl_cgdl_cgdl': Jl_cgdl_cgdl, 'Sp_acl': Sp_acl, 'Sp_ccl': Sp_ccl, 'J_H2_agc_agdl': J_H2_agc_agdl, 'J_H2_agdl_agdl': J_H2_agdl_agdl, 'J_H2_agdl_acl': J_H2_agdl_acl, 'J_O2_ccl_cgdl': J_O2_ccl_cgdl, 'J_O2_cgdl_cgdl': J_O2_cgdl_cgdl, 'J_O2_cgdl_cgc': J_O2_cgdl_cgc, 'S_H2_acl': S_H2_acl, 'S_O2_ccl': S_O2_ccl, 'Sv_agdl': Sv_agdl, 'Sv_acl': Sv_acl, 'Sv_ccl': Sv_ccl, 'Sv_cgdl': Sv_cgdl, 'Sl_agdl': Sl_agdl, 'Sl_acl': Sl_acl, 'Sl_ccl': Sl_ccl, 'Sl_cgdl': Sl_cgdl, 'Pagc': Pagc, 'Pcgc': Pcgc, 'Wasm_in': Wasm_in, 'Wasm_out': Wasm_out, 'Waem_in': Waem_in, 'Waem_out': Waem_out, 'Wcsm_in': Wcsm_in, 'Wcsm_out': Wcsm_out, 'Wcem_in': Wcem_in, 'Wcem_out': Wcem_out, 'Ware': Ware, 'Wv_asm_in': Wv_asm_in, 'Wv_aem_out': Wv_aem_out, 'Wv_csm_in': Wv_csm_in, 'Wv_cem_out': Wv_cem_out}","title":"calculate_flows"},{"location":"functions/modules/GUI_modules/","text":"GUI modules This module contains some of the required functions for the GUI.py file. 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, choices_buttons) This function is called when the user selects a specific option from a dropdown menu for the type of fuel cell. Depending on the selected option, it either hides or displays specific input fields (labels or entry widgets) on the GUI. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choices_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def 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, choices_buttons): \"\"\"This function is called when the user selects a specific option from a dropdown menu for the type of fuel cell. Depending on the selected option, it either hides or displays specific input fields (labels or entry widgets) on the GUI. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. choices_buttons : dict A dictionary containing the button information. \"\"\" if choices_buttons['type_fuel_cell']['value'].get() != 'Enter your specifications': # Recovers the new settings recover_for_display_operating_inputs_and_physical_parameters(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choices_buttons) # Display the labels for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Label(operating_conditions_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Label(accessible_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Label(undetermined_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Label(current_density_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Label(computing_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) else: # choices_buttons['type_fuel_cell']['value'].get() == 'Enter your specifications': # Saves and displays the user entries for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Entry(operating_conditions_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Entry(accessible_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Entry(undetermined_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Entry(current_density_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Entry(computing_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) 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) This function displays labels on the GUI, representing operating conditions and physical parameters, without their actual values. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. Source code in modules/GUI_modules.py def 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): \"\"\"This function displays labels on the GUI, representing operating conditions and physical parameters, without their actual values. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # Display the titles ttk.Label(operating_conditions_frame, text='Operating conditions', font=('cmr10', 12, 'bold')). \\ grid(row=1, column=0, columnspan=6, ipady=15) ttk.Label(accessible_parameters_frame, text='Accessible physical parameters', font=('cmr10', 12, 'bold')). \\ grid(row=0, column=0, columnspan=6, ipady=15) # Display the labels for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Label(operating_conditions_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Label(accessible_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Label(undetermined_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Label(current_density_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # computing parameters for k, v in choice_computing_parameters.items(): ttk.Label(computing_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") 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) This function displays entry widgets on the GUI. There, the user can enter values for operating conditions and physical parameters. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. Source code in modules/GUI_modules.py def 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): \"\"\"This function displays entry widgets on the GUI. There, the user can enter values for operating conditions and physical parameters. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # Display the value for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Entry(operating_conditions_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Entry(accessible_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Entry(undetermined_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Entry(current_density_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Entry(computing_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) display_radiobuttons(model_possibilities_frame, choices_buttons) This function displays radiobuttons on the GUI, allowing the user to make choices for control, results display, plot style, etc. Parameters: model_possibilities_frame ( Frame ) \u2013 The frame where the graphical elements for the model possibilities and the choice of current density are placed. choices_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def display_radiobuttons(model_possibilities_frame, choices_buttons): \"\"\"This function displays radiobuttons on the GUI, allowing the user to make choices for control, results display, plot style, etc. Parameters ---------- model_possibilities_frame : ttk.Frame The frame where the graphical elements for the model possibilities and the choice of current density are placed. choices_buttons : dict A dictionary containing the button information. \"\"\" ttk.Label(model_possibilities_frame, text='Model possibilities', font=('cmr10', 12, 'bold')) \\ .grid(row=0, column=0, columnspan=6, ipady=15) # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Auxiliaries: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=0, columnspan=1, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No auxiliaries', value=0, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Forced-convective cathode\\nwith anodic recirculation', value=1, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Forced-convective cathode\\nwith flow-through anode', value=2, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Control: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_control']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No control', value=0, variable=choices_buttons['type_control']['value']). \\ grid(row=choices_buttons['type_control']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Humidity', value=1, variable=choices_buttons['type_control']['value']). \\ grid(row=choices_buttons['type_control']['label_row'], column=3, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Purge: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_purge']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No purge', value=0, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Periodic', value=1, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Constant', value=2, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Display: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_display']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No display', value=0, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Synthetic', value=1, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Multiple', value=2, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Plot: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_plot']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Fixed', value=0, variable=choices_buttons['type_plot']['value']). \\ grid(row=choices_buttons['type_plot']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Dynamic', value=1, variable=choices_buttons['type_plot']['value']). \\ grid(row=choices_buttons['type_plot']['label_row'], column=3, sticky=\"w\") launch_AlphaPEM_for_EIS_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) Launch the AlphaPEM simulator for an EIS current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_EIS_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for an EIS current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None t0_EIS, t_new_start, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # These are used for EIS max_step # actualization. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is a list of all the frequency tested. n = len(t_new_start) # It is the plot update number. time_interval = [0, t0_EIS] # It is the initial time interval. # A preliminary simulation run is necessary to equilibrate the internal variables of the cell at i_EIS # prior to initiating the EIS. Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization t0_EIS_temp = t0_EIS # It is the initial time for 1 EIS point. tf_EIS_temp = t_new_start[0] + delta_t_break_EIS[0] + delta_t_measurement_EIS[0] # It is the final time for # 1 EIS point. n_inf = np.where(t_new_start <= t0_EIS_temp)[0][-1] # It is the number of frequency changes which has been # made. max_step = 1 / (f[n_inf] * nb_points_EIS) # max_step is actualized according to the current frequency # for increased calculation time_interval = [t0_EIS_temp, tf_EIS_temp] # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_EIS_temp = Simulator.variables['t'][-1] # It is the initial time for 1 EIS point. tf_EIS_temp = t_new_start[i + 1] + delta_t_break_EIS[i + 1] + delta_t_measurement_EIS[i + 1] # It # is the final time for 1 EIS point. n_inf = np.where(t_new_start <= t0_EIS_temp)[0][-1] # It is the number of frequency changes which # has been made. max_step = 1 / (f[n_inf] * nb_points_EIS) # max_step is actualized according to the current # frequency for increased calculation time_interval = [t0_EIS_temp, tf_EIS_temp] # It is the time interval for 1 EIS point. # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3) launch_AlphaPEM_for_polarization_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) Launch the AlphaPEM simulator for a polarization current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_polarization_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for a polarization current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Dynamic display requires a dedicated use of the AlphaPEM class. if type_plot == \"dynamic\": # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola delta_t = delta_t_load_pola + delta_t_break_pola # s. It is the time of one load. tf = delta_t_ini_pola + int(i_max_pola_1 / delta_i_pola + 1) * delta_t # s. It is the polarization current # duration. n = int(tf / delta_t) # It is the plot update number. time_interval = [0, delta_t_ini_pola + delta_t] # It is the initial time interval. # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_interval = Simulator.variables['t'][-1] tf_interval = delta_t_ini_pola + (i + 2) * delta_t time_interval = [t0_interval, tf_interval] # Reset of the time interval # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) else: # elif type_plot == \"fixed\": # Simulation Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3) launch_AlphaPEM_for_step_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) Launch the AlphaPEM simulator for a step current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_step_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for a step current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Dynamic display requires a dedicated use of the AlphaPEM class. if type_plot == \"dynamic\": # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = t_step n = int(tf_step / delta_t_dyn_step) # It is the plot update number. time_interval = [0, delta_t_dyn_step] # It is the initial time interval. # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_interval = Simulator.variables['t'][-1] tf_interval = (i + 2) * delta_t_dyn_step time_interval = [t0_interval, tf_interval] # Reset of the time interval # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) else: # elif type_plot == \"fixed\": # Simulation Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3) recover_for_display_operating_inputs_and_physical_parameters(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons) This function retrieves parameter values for predefined stacks (e.g., \"EH-31 1.5 bar (2021)\", \"Biao Xie 1.0 bar (2015)\", etc.) and converts them to appropriate units for display on the GUI. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def recover_for_display_operating_inputs_and_physical_parameters(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons): \"\"\"This function retrieves parameter values for predefined stacks (e.g., \"EH-31 1.5 bar (2021)\", \"Biao Xie 1.0 bar (2015)\", etc.) and converts them to appropriate units for display on the GUI. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" if choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 1.5 bar (2021)\": type_fuel_cell = \"EH-31_1.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.0 bar (2021)\": type_fuel_cell = \"EH-31_2.0\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.25 bar (2021)\": type_fuel_cell = \"EH-31_2.25\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.5 bar (2021)\": type_fuel_cell = \"EH-31_2.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Linhao Fan (2010)\": type_fuel_cell = \"LF\" Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola = stored_operating_inputs(type_fuel_cell) Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, \\ a_slim, b_slim, a_switch, C_scl = \\ stored_physical_parameters(type_fuel_cell) # operating conditions recovery choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].set(np.round(Tfc - 273.15)) # \u00b0C choice_operating_conditions['Anode pressure - Pa (bar)']['value'].set(np.round(Pa_des / 1e5, 2)) # bar choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].set(np.round(Pc_des / 1e5, 2)) # bar choice_operating_conditions['Anode stoichiometry - Sa']['value'].set(np.round(Sa, 1)) choice_operating_conditions['Cathode stoichiometry - Sc']['value'].set(np.round(Sc, 1)) choice_operating_conditions['Anode humidity - \u03a6a']['value'].set(np.round(Phi_a_des, 1)) choice_operating_conditions['Cathode humidity - \u03a6c']['value'].set(np.round(Phi_c_des, 1)) # accessible physical parameters recovery choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].set(np.round(Aact * 1e4)) # cm\u00b2 choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].set(np.round(Hgdl * 1e6)) # \u00b5m choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].set(np.round(Hcl * 1e6)) # \u00b5m choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].set(np.round(Hmem * 1e6)) # \u00b5m choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].set(np.round(Hgc * 1e6)) # \u00b5m choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].set(np.round(Wgc * 1e6)) # \u00b5m choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].set(np.round(Lgc, 2)) # \u00b5m # undetermined physical parameters recovery choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].set(np.round(epsilon_gdl, 3)) choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].set(np.round(epsilon_mc, 3)) choice_undetermined_parameters['Tortuosity - \u03c4']['value'].set(np.round(tau, 3)) choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].set(np.round(epsilon_c, 3)) choice_undetermined_parameters['Capillary exponent - e']['value'].set(e) choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].set(np.round(Re * 1e6, 2)) # \u00b5\u03a9.m\u00b2 choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].set(np.round(i0_c_ref, 2)) # A.m-2 choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].set(np.round(kappa_co, 2)) # mol.m-1.s-1.Pa-1 choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].set(np.round(kappa_c, 2)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].set(np.round(a_slim, 7)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].set(np.round(b_slim, 7)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].set(np.round(a_switch, 7)) choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].set(np.round(C_scl * 1e-6, 2)) # F.cm-3 # i_max_pola recovery choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].set(np.round(i_max_pola / 1e4, 2)) # A/cm\u00b2 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) This function retrieves and converts the parameter values from the GUI into standard units for further calculations. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def 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): \"\"\"This function retrieves and converts the parameter values from the GUI into standard units for further calculations. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # operating conditions Tfc = choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].get() + 273.15 # K Pa_des = choice_operating_conditions['Anode pressure - Pa (bar)']['value'].get() * 1e5 # Pa Pc_des = choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() * 1e5 # Pa Sa = choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() Sc = choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() Phi_a_des = choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() Phi_c_des = choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() # accessible physical parameters Aact = choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].get() * 1e-4 # m\u00b2 Hgdl = choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() * 1e-6 # m Hcl = choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() * 1e-6 # m Hmem = choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() * 1e-6 # m Hgc = choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() * 1e-6 # m Wgc = choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() * 1e-6 # m Lgc = choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() # m # undetermined physical parameters epsilon_gdl = choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() epsilon_mc = choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() tau = choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() epsilon_c = choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() e = choice_undetermined_parameters['Capillary exponent - e']['value'].get() Re = choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() * 1e-6 # ohm.m\u00b2 i0_c_ref = choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() # A.m-2 kappa_co = choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() # mol.m-1.s-1.Pa-1 kappa_c = choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() a_slim = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() b_slim = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() a_switch = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() C_scl = choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() * 1e6 # F.m-3 # current density parameters t_step = (choice_current_density_parameters['Initial time - t0_step (s)']['value'].get(), choice_current_density_parameters['Final time - tf_step (s)']['value'].get(), choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get(), choice_computing_parameters['Time for dynamic\\ndisplay - \u0394t_dyn_step (s)']['value'].get()) # (s, s, s, s) i_step = (choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() * 1e4, choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get() * 1e4) # (A.m-2, A.m-2) i_max_pola = choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() * 1e4 # A.m-2 delta_pola = (choice_current_density_parameters['Loading time\\n- \u0394t_load_pola (s)']['value'].get(), choice_current_density_parameters['Breaking time\\n- \u0394t_break_pola (s)']['value'].get(), choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() * 1e4, choice_current_density_parameters['Initial breaking time\\n- \u0394t_ini_pola (s)']['value'].get()) # (s, s, A.m-2, s) i_EIS = choice_current_density_parameters['Static current\\n- i_EIS (A/cm\u00b2)']['value'].get() * 1e4 # (A.m-2) ratio_EIS = choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() / 100 f_EIS = (choice_current_density_parameters['Power of the\\ninitial frequency\\n- f_power_min_EIS']['value'].get(), choice_current_density_parameters['Power of the\\nfinal frequency\\n- f_power_max_EIS']['value'].get(), choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get(), choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get()) t_EIS = EIS_parameters(f_EIS) # Time parameters for the EIS_current density function. t_purge = choice_computing_parameters['Purge time - t_purge (s)']['value'].get() # s delta_t_purge = choice_computing_parameters['Time between two purges\\n- \u0394t_purge (s)']['value'].get() # s max_step = choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() # s n_gdl = choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get() if choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 1.5 bar (2021)\": type_fuel_cell = \"EH-31_1.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.0 bar (2021)\": type_fuel_cell = \"EH-31_2.0\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.25 bar (2021)\": type_fuel_cell = \"EH-31_2.25\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.5 bar (2021)\": type_fuel_cell = \"EH-31_2.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Linhao Fan (2010)\": type_fuel_cell = \"LF\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Enter your specifications\": type_fuel_cell = \"manual_setup\" if choice_buttons['type_auxiliary']['value'].get() == 0: type_auxiliary = \"no_auxiliary\" elif choice_buttons['type_auxiliary']['value'].get() == 1: type_auxiliary = \"forced-convective_cathode_with_anodic_recirculation\" else: type_auxiliary = \"forced-convective_cathode_with_flow-through_anode\" if choice_buttons['type_control']['value'].get() == 0: type_control = \"no_control\" else: type_control = \"Phi_des\" if choice_buttons['type_purge']['value'].get() == 0: type_purge = \"no_purge\" elif choice_buttons['type_purge']['value'].get() == 1: type_purge = \"periodic_purge\" else: type_purge = \"constant_purge\" if choice_buttons['type_display']['value'].get() == 0: type_display = \"no_display\" elif choice_buttons['type_display']['value'].get() == 1: type_display = \"synthetic\" else: type_display = \"multiple\" if choice_buttons['type_plot']['value'].get() == 0: type_plot = \"fixed\" else: type_plot = \"dynamic\" return (Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, Aact, Hgdl, Hcl, Hmem, Hgc, Wgc, Lgc, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, t_purge, delta_t_purge, max_step, n_gdl, type_fuel_cell, type_auxiliary, type_control, type_purge, type_display, type_plot) set_equal_width(frame1, frame2, frame3, frame4, frame5, frame6) Adjusts the width of the frames to be equal based on their maximum width. Parameters: frame1 ( Frame ) \u2013 The first frame to be resized. frame2 ( Frame ) \u2013 The second frame to be resized. frame3 ( Frame ) \u2013 The third frame to be resized. frame4 ( Frame ) \u2013 The fourth frame to be resized. frame5 ( Frame ) \u2013 The fifth frame to be resized. frame6 ( Frame ) \u2013 The sixth frame to be resized. Source code in modules/GUI_modules.py def set_equal_width(frame1, frame2, frame3, frame4, frame5, frame6): \"\"\" Adjusts the width of the frames to be equal based on their maximum width. Parameters ---------- frame1 : ttk.Frame The first frame to be resized. frame2 : ttk.Frame The second frame to be resized. frame3 : ttk.Frame The third frame to be resized. frame4 : ttk.Frame The fourth frame to be resized. frame5 : ttk.Frame The fifth frame to be resized. frame6 : ttk.Frame The sixth frame to be resized. \"\"\" # Initialisation of the list of widths widths = [] for frame in [frame1, frame2, frame3, frame4, frame5, frame6]: # Update the frame sizes frame.update_idletasks() # Get the current width of all frames widths.append(frame.winfo_width()) # Set all frames to the maximum width for frame in [frame1, frame2, frame3, frame4, frame5, frame6]: for i in range(6): frame.grid_columnconfigure(i, minsize=max(widths) / 5.5) # Set minimum width of all column to max_width / 5 value_control(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons, current_button) This function checks the integrity of the values entered by the user and returns an empty tuple if they are not valid. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in modules/GUI_modules.py def value_control(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons, current_button): \"\"\"This function checks the integrity of the values entered by the user and returns an empty tuple if they are not valid. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # The values entered by the user are checked for compliance if choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].get() < 0: messagebox.showerror(title='Temperatures', message='Negative temperatures do not exist in the Kelvin scale.') choices.clear() return if choice_operating_conditions['Anode pressure - Pa (bar)']['value'].get() < 0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() < 0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() > 5.0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() > 5.0: messagebox.showerror(title='Desired pressures', message='Desired pressure should be positive and bellow 5.0 ' 'bars.') choices.clear() return if choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() < 1 or \\ choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() > 5 or \\ choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() < 1 or \\ choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() > 5: messagebox.showerror(title='Stoichiometric ratios', message='The stoichiometric ratios Sa and Sc should be ' 'between 1 and 5.') choices.clear() return if choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() < 0 or \\ choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() > 1 or \\ choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() < 0 or \\ choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() > 1: messagebox.showerror(title='Desired humidity', message='The desired humidities should be between 0 and 1.') choices.clear() return if choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].get() < 0: messagebox.showerror(title='Active area', message='Negative active area is impossible.') choices.clear() return if choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() > 1000 or \\ choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() > 1000 or \\ choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() > 1000: messagebox.showerror(title='MEA thickness', message='All MEA components generally have a thickness between ' '1\u00b5m and 1mm.') choices.clear() return if choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() < 10 or \\ choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() > 10000 or \\ choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() < 10 or \\ choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() > 10000 or \\ choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() < 0 or \\ choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() > 100: messagebox.showerror(title='GC distances', message='GC generally have a thickness and a width between 10\u00b5m and ' '10mm. Also, GC length is generally between 0 and 100m') choices.clear() return if choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() < 0 or \\ choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() > 1 or \\ choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() < 0 or \\ choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() > 1: messagebox.showerror(title='Porosities', message='All porosities should be between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() < 1 or choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() > 4: messagebox.showerror(title='Pore structure coefficient', message='The pore structure coefficient should be ' 'between 1 and 4.') choices.clear() return if choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() < 0 or \\ choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() > 1: messagebox.showerror(title='Compression ratio', message='The compression ratio should be between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Capillary exponent - e']['value'].get() < 3 or choice_undetermined_parameters['Capillary exponent - e']['value'].get() > 5: messagebox.showerror(title='Capillary exponent', message='The capillary exponent should be between 3 and 5 and ' 'being an integer.') choices.clear() return if choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() < 0.5 or \\ choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() > 5: messagebox.showerror(title='Electron conduction resistance', message='The electron conduction resistance is ' 'generally between 0.5 and 5 \u00b5\u03a9.m\u00b2.') choices.clear() return if choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() < 0.001 or \\ choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() > 500: messagebox.showerror(title='Referenced exchange current density', message='The referenced exchange current ' 'density is generally between 0.001 ' 'and 500 A.m-2.') choices.clear() return if choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() < 0.01 or \\ choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() > 100: messagebox.showerror(title='Crossover correction coefficient', message='The crossover correction coefficient is' ' generally between 0.01 and 100 ' 'mol.m-1.s-1.Pa-1.') choices.clear() return if choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() < 0 or \\ choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() > 100: messagebox.showerror(title='Overpotential correction exponent', message='The overpotential correction exponent ' 'is generally between 0 and 100.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() > 1: messagebox.showerror(title='Slop of slim function', message='The slop of slim function is generally between 0 ' 'and 1.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() > 1: messagebox.showerror(title='Intercept of slim function', message='The intercept of slim function is generally ' 'between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() > 1: messagebox.showerror(title='Slop of switch function', message='The slop of switch function is generally between' ' 0 and 1.') choices.clear() return if choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() < 5 or \\ choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() > 100: messagebox.showerror(title='Double layer capacitance', message='I have not settled yet a range for C_scl.') choices.clear() return if choice_current_density_parameters['Initial time - t0_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Final time - tf_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get() < 0 or \\ choice_computing_parameters['Time for dynamic\\ndisplay - \u0394t_dyn_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Breaking time\\n- \u0394t_break_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Initial breaking time\\n- \u0394t_ini_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Initial time - t0_step (s)']['value'].get() > \\ choice_current_density_parameters['Final time - tf_step (s)']['value'].get() or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get() > \\ (choice_current_density_parameters['Final time - tf_step (s)']['value'].get() - choice_current_density_parameters['Initial time - t0_step (s)']['value'].get()): messagebox.showerror(title='Times', message='The times should be positive, t0_step < tf_step and ' 'delta_t_load_step < (tf_step - t0_step).') choices.clear() return if choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Static current\\n- i_EIS (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() > \\ choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() or \\ choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() > \\ choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get(): messagebox.showerror(title='Current densities', message='The current densities should be positive, ' 'delta_i_pola < i_max_pola and ' 'i_ini_step < i_final_step.') choices.clear() return if choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() < 0 or \\ choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() > 20: messagebox.showerror(title='Ratio EIS', message='Ratio EIS is a percentage of i_EIS and should be between 0 ' 'and 20 for plotting correct EIS.') choices.clear() return if choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get() < 0 or \\ choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get() < 0 or \\ type(choice_current_density_parameters['Power of the\\ninitial frequency\\n- f_power_min_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Power of the\\nfinal frequency\\n- f_power_max_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get()) != int: messagebox.showerror(title='f EIS', message='f_EIS parameters should be integer and number of points should ' 'be positive.') choices.clear() return if choice_computing_parameters['Purge time - t_purge (s)']['value'].get() < 0 or \\ choice_computing_parameters['Time between two purges\\n- \u0394t_purge (s)']['value'].get() < 0: messagebox.showerror(title='Purge times', message='Negative times does not characterise purges.') choices.clear() return if choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() < 0 or \\ choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() > 0.1: messagebox.showerror(title='Max step', message='The max step value for the solver should be positive and lower ' 'than 0.1 for normal use.') choices.clear() return if choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get() < 2 or \\ type(choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get()) != int: messagebox.showerror(title='n gdl', message='The n_gdl value should be an integer bigger than 2. ' 'A good compromise is 10.') choices.clear() return if current_button == 0 and choice_buttons['type_display']['value'].get() == 2 \\ and choice_buttons['type_plot']['value'].get() == 1 : messagebox.showerror(title='n gdl', message='dynamic plot is not thought to be used with step current and ' 'multiple display. There would be too much plots to handle.') choices.clear() return if current_button == 2 and choice_buttons['type_plot']['value'].get() == 0: messagebox.showerror(title='n gdl', message='EIS has to be plot with a dynamic type_plot setting, ' 'because max_step has to be adjusted at each frequency.') choices.clear() return","title":"GUI modules"},{"location":"functions/modules/GUI_modules/#gui-modules","text":"This module contains some of the required functions for the GUI.py file.","title":"GUI modules"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.changeValue","text":"This function is called when the user selects a specific option from a dropdown menu for the type of fuel cell. Depending on the selected option, it either hides or displays specific input fields (labels or entry widgets) on the GUI. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choices_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def 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, choices_buttons): \"\"\"This function is called when the user selects a specific option from a dropdown menu for the type of fuel cell. Depending on the selected option, it either hides or displays specific input fields (labels or entry widgets) on the GUI. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. choices_buttons : dict A dictionary containing the button information. \"\"\" if choices_buttons['type_fuel_cell']['value'].get() != 'Enter your specifications': # Recovers the new settings recover_for_display_operating_inputs_and_physical_parameters(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choices_buttons) # Display the labels for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Label(operating_conditions_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Label(accessible_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Label(undetermined_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Label(current_density_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Label(computing_parameters_frame, width=7, anchor='w', textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) else: # choices_buttons['type_fuel_cell']['value'].get() == 'Enter your specifications': # Saves and displays the user entries for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Entry(operating_conditions_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Entry(accessible_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Entry(undetermined_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Entry(current_density_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Entry(computing_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5)","title":"changeValue"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.display_parameter_labels","text":"This function displays labels on the GUI, representing operating conditions and physical parameters, without their actual values. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. Source code in modules/GUI_modules.py def 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): \"\"\"This function displays labels on the GUI, representing operating conditions and physical parameters, without their actual values. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # Display the titles ttk.Label(operating_conditions_frame, text='Operating conditions', font=('cmr10', 12, 'bold')). \\ grid(row=1, column=0, columnspan=6, ipady=15) ttk.Label(accessible_parameters_frame, text='Accessible physical parameters', font=('cmr10', 12, 'bold')). \\ grid(row=0, column=0, columnspan=6, ipady=15) # Display the labels for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Label(operating_conditions_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Label(accessible_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Label(undetermined_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Label(current_density_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\") # computing parameters for k, v in choice_computing_parameters.items(): ttk.Label(computing_parameters_frame, text=k, font=('cmr10', 10)). \\ grid(row=v['label_row'], column=v['label_column'] - 1, sticky=\"w\")","title":"display_parameter_labels"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.display_parameters_value","text":"This function displays entry widgets on the GUI. There, the user can enter values for operating conditions and physical parameters. Parameters: operating_conditions_frame ( Frame ) \u2013 The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame ( Frame ) \u2013 The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. Source code in modules/GUI_modules.py def 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): \"\"\"This function displays entry widgets on the GUI. There, the user can enter values for operating conditions and physical parameters. Parameters ---------- operating_conditions_frame : ttk.Frame The frame where the graphical elements for the operating condition and the choice of fuel cell are placed. accessible_parameters_frame : ttk.Frame The frame where the graphical elements for the accessible physical parameters are placed. undetermined_parameters_frame : ttk.Frame The frame where the graphical elements for the undetermined physical parameters are placed. current_density_parameters_frame : ttk.Frame The frame where the graphical elements for the current density parameters are placed. computing_parameters_frame : ttk.Frame The frame where the graphical elements for the computing parameters are placed. choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # Display the value for ... # operating conditions for k, v in choice_operating_conditions.items(): ttk.Entry(operating_conditions_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # accessible physical parameters for k, v in choice_accessible_parameters.items(): ttk.Entry(accessible_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # undetermined physical parameters for k, v in choice_undetermined_parameters.items(): ttk.Entry(undetermined_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # current density parameters for k, v in choice_current_density_parameters.items(): ttk.Entry(current_density_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5) # computing parameters for k, v in choice_computing_parameters.items(): ttk.Entry(computing_parameters_frame, width=7, textvariable=v['value']). \\ grid(row=v['label_row'], column=v['label_column'], padx=5)","title":"display_parameters_value"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.display_radiobuttons","text":"This function displays radiobuttons on the GUI, allowing the user to make choices for control, results display, plot style, etc. Parameters: model_possibilities_frame ( Frame ) \u2013 The frame where the graphical elements for the model possibilities and the choice of current density are placed. choices_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def display_radiobuttons(model_possibilities_frame, choices_buttons): \"\"\"This function displays radiobuttons on the GUI, allowing the user to make choices for control, results display, plot style, etc. Parameters ---------- model_possibilities_frame : ttk.Frame The frame where the graphical elements for the model possibilities and the choice of current density are placed. choices_buttons : dict A dictionary containing the button information. \"\"\" ttk.Label(model_possibilities_frame, text='Model possibilities', font=('cmr10', 12, 'bold')) \\ .grid(row=0, column=0, columnspan=6, ipady=15) # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Auxiliaries: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=0, columnspan=1, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No auxiliaries', value=0, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Forced-convective cathode\\nwith anodic recirculation', value=1, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Forced-convective cathode\\nwith flow-through anode', value=2, variable=choices_buttons['type_auxiliary']['value']). \\ grid(row=choices_buttons['type_auxiliary']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Control: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_control']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No control', value=0, variable=choices_buttons['type_control']['value']). \\ grid(row=choices_buttons['type_control']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Humidity', value=1, variable=choices_buttons['type_control']['value']). \\ grid(row=choices_buttons['type_control']['label_row'], column=3, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Purge: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_purge']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No purge', value=0, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Periodic', value=1, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Constant', value=2, variable=choices_buttons['type_purge']['value']). \\ grid(row=choices_buttons['type_purge']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Display: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_display']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='No display', value=0, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Synthetic', value=1, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=3, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Multiple', value=2, variable=choices_buttons['type_display']['value']). \\ grid(row=choices_buttons['type_display']['label_row'], column=4, sticky=\"w\") # Ask the user to choose an option and save it ttk.Label(model_possibilities_frame, text='Plot: ', font=('cmr10', 12)). \\ grid(row=choices_buttons['type_plot']['label_row'], column=0, columnspan=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Fixed', value=0, variable=choices_buttons['type_plot']['value']). \\ grid(row=choices_buttons['type_plot']['label_row'], column=2, sticky=\"w\") ttk.Radiobutton(model_possibilities_frame, text='Dynamic', value=1, variable=choices_buttons['type_plot']['value']). \\ grid(row=choices_buttons['type_plot']['label_row'], column=3, sticky=\"w\")","title":"display_radiobuttons"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.launch_AlphaPEM_for_EIS_current","text":"Launch the AlphaPEM simulator for an EIS current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_EIS_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for an EIS current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None t0_EIS, t_new_start, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # These are used for EIS max_step # actualization. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is a list of all the frequency tested. n = len(t_new_start) # It is the plot update number. time_interval = [0, t0_EIS] # It is the initial time interval. # A preliminary simulation run is necessary to equilibrate the internal variables of the cell at i_EIS # prior to initiating the EIS. Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization t0_EIS_temp = t0_EIS # It is the initial time for 1 EIS point. tf_EIS_temp = t_new_start[0] + delta_t_break_EIS[0] + delta_t_measurement_EIS[0] # It is the final time for # 1 EIS point. n_inf = np.where(t_new_start <= t0_EIS_temp)[0][-1] # It is the number of frequency changes which has been # made. max_step = 1 / (f[n_inf] * nb_points_EIS) # max_step is actualized according to the current frequency # for increased calculation time_interval = [t0_EIS_temp, tf_EIS_temp] # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_EIS_temp = Simulator.variables['t'][-1] # It is the initial time for 1 EIS point. tf_EIS_temp = t_new_start[i + 1] + delta_t_break_EIS[i + 1] + delta_t_measurement_EIS[i + 1] # It # is the final time for 1 EIS point. n_inf = np.where(t_new_start <= t0_EIS_temp)[0][-1] # It is the number of frequency changes which # has been made. max_step = 1 / (f[n_inf] * nb_points_EIS) # max_step is actualized according to the current # frequency for increased calculation time_interval = [t0_EIS_temp, tf_EIS_temp] # It is the time interval for 1 EIS point. # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3)","title":"launch_AlphaPEM_for_EIS_current"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.launch_AlphaPEM_for_polarization_current","text":"Launch the AlphaPEM simulator for a polarization current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_polarization_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for a polarization current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Dynamic display requires a dedicated use of the AlphaPEM class. if type_plot == \"dynamic\": # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola delta_t = delta_t_load_pola + delta_t_break_pola # s. It is the time of one load. tf = delta_t_ini_pola + int(i_max_pola_1 / delta_i_pola + 1) * delta_t # s. It is the polarization current # duration. n = int(tf / delta_t) # It is the plot update number. time_interval = [0, delta_t_ini_pola + delta_t] # It is the initial time interval. # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_interval = Simulator.variables['t'][-1] tf_interval = delta_t_ini_pola + (i + 2) * delta_t time_interval = [t0_interval, tf_interval] # Reset of the time interval # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) else: # elif type_plot == \"fixed\": # Simulation Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3)","title":"launch_AlphaPEM_for_polarization_current"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.launch_AlphaPEM_for_step_current","text":"Launch the AlphaPEM simulator for a step current density and display the results. Parameters: current_density ( function ) \u2013 Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin (operating input). Pa_des ( float ) \u2013 Desired anode pressure in Pascal (operating input). Pc_des ( float ) \u2013 Desired cathode pressure in Pascal (operating input). Sa ( float ) \u2013 Stoichiometric ratio of hydrogen (operating input). Sc ( float ) \u2013 Stoichiometric ratio of oxygen (operating input). Phi_a_des ( float ) \u2013 Desired anode relative humidity (operating input). Phi_c_des ( float ) \u2013 Desired cathode relative humidity (operating input). t_step ( tuple ) \u2013 Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step ( tuple ) \u2013 Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve (current parameter). delta_pola ( tuple ) \u2013 Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact ( float ) \u2013 Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem ( float ) \u2013 Thickness of the membrane in m (accessible physical parameter). Hcl ( float ) \u2013 Thickness of the catalyst layer in m (accessible physical parameter). Hgc ( float ) \u2013 Thickness of the gas channel in m (accessible physical parameter). Wgc ( float ) \u2013 Width of the gas channel in m (accessible physical parameter). Lgc ( float ) \u2013 Length of the gas channel in m (accessible physical parameter). epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity (undetermined physical parameter). tau ( float ) \u2013 Pore structure coefficient (undetermined physical parameter). epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c ( float ) \u2013 Compression ratio of the GDL (undetermined physical parameter). e ( float ) \u2013 Capillary exponent (undetermined physical parameter). Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c ( float ) \u2013 Overpotential correction exponent (undetermined physical parameter). a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl ( float ) \u2013 Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step ( float ) \u2013 Maximum time step for the solver (computing parameter). n_gdl ( int ) \u2013 Number of points considered in the GDL (computing parameter). t_purge ( tuple ) \u2013 Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration (computing parameter). type_current ( str ) \u2013 Type of current density function (computing parameter). type_auxiliary ( str ) \u2013 Type of auxiliary system (computing parameter). type_control ( str ) \u2013 Type of control system (computing parameter). type_purge ( str ) \u2013 Type of purge system (computing parameter). type_display ( str ) \u2013 Type of display (computing parameter). type_plot ( str ) \u2013 Type of plot (computing parameter). Source code in modules/GUI_modules.py def launch_AlphaPEM_for_step_current(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot): \"\"\"Launch the AlphaPEM simulator for a step current density and display the results. Parameters ---------- current_density : function Current density evolution over time (operating input). It is a function of time and parameters dictionary. Tfc : float Desired fuel cell temperature in Kelvin (operating input). Pa_des : float Desired anode pressure in Pascal (operating input). Pc_des : float Desired cathode pressure in Pascal (operating input). Sa : float Stoichiometric ratio of hydrogen (operating input). Sc : float Stoichiometric ratio of oxygen (operating input). Phi_a_des : float Desired anode relative humidity (operating input). Phi_c_des : float Desired cathode relative humidity (operating input). t_step : tuple Time parameters for the step_current density function (current parameters). It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load_step' and dynamic time for display 'delta_t_dyn_step'. i_step : tuple Current parameters for the step_current density function (current parameters). It is a tuple containing the initial and final current density value 'i_ini_step' and 'i_final_step'. i_max_pola : float Maximum current density for the polarization curve (current parameter). delta_pola : tuple Parameters for the polarization curve (current parameters). It is a tuple containing the loading time 'delta_t_load_pola', the breaking time 'delta_t_break_pola', the current density step 'delta_i_pola', and the initial breaking time 'delta_t_ini_pola'. i_EIS : float Current for which a ratio_EIS perturbation is added (current parameter). ratio_EIS : float Value of the perturbation on the current density for building the EIS curve (current parameter). t_EIS : tuple EIS parameters (current parameters). It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters (current parameters). It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Aact : float Active area of the cell in m\u00b2 (accessible physical parameter). Hgdl : float Thickness of the gas diffusion layer in m (accessible physical parameter). Hmem : float Thickness of the membrane in m (accessible physical parameter). Hcl : float Thickness of the catalyst layer in m (accessible physical parameter). Hgc : float Thickness of the gas channel in m (accessible physical parameter). Wgc : float Width of the gas channel in m (accessible physical parameter). Lgc : float Length of the gas channel in m (accessible physical parameter). epsilon_gdl : float Anode/cathode GDL porosity (undetermined physical parameter). tau : float Pore structure coefficient (undetermined physical parameter). epsilon_mc : float Volume fraction of ionomer in the CL (undetermined physical parameter). epsilon_c : float Compression ratio of the GDL (undetermined physical parameter). e : float Capillary exponent (undetermined physical parameter). Re : float Electron conduction resistance of the circuit in ohm.m\u00b2 (undetermined physical parameter). i0_c_ref : float Reference exchange current density at the cathode in A.m-2 (undetermined physical parameter). kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1 (undetermined physical parameter). kappa_c : float Overpotential correction exponent (undetermined physical parameter). a_slim : float One of the limit liquid saturation coefficients: the slop of slim function (undetermined physical parameter). b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function (undetermined physical parameter). a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function (undetermined physical parameter). C_scl : float Volumetric space-charge layer capacitance in F.m-3 (undetermined physical parameter). max_step : float Maximum time step for the solver (computing parameter). n_gdl : int Number of points considered in the GDL (computing parameter). t_purge : tuple Time parameters for purging the system (computing parameter). It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. type_fuel_cell : str Type of fuel cell configuration (computing parameter). type_current : str Type of current density function (computing parameter). type_auxiliary : str Type of auxiliary system (computing parameter). type_control : str Type of control system (computing parameter). type_purge : str Type of purge system (computing parameter). type_display : str Type of display (computing parameter). type_plot : str Type of plot (computing parameter). \"\"\" # Figures preparation fig1, ax1, fig2, ax2, fig3, ax3 = figures_preparation(type_current, type_display) # Dynamic display requires a dedicated use of the AlphaPEM class. if type_plot == \"dynamic\": # Initialization # ... of the plot update number (n) and the initial time interval (time_interval) initial_variable_values = None t0_step, tf_step, delta_t_load_step, delta_t_dyn_step = t_step n = int(tf_step / delta_t_dyn_step) # It is the plot update number. time_interval = [0, delta_t_dyn_step] # It is the initial time interval. # Dynamic simulation for i in range(n): Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot, initial_variable_values, time_interval) # time_interval actualization if i < (n - 1): # The final simulation does not require actualization. t0_interval = Simulator.variables['t'][-1] tf_interval = (i + 2) * delta_t_dyn_step time_interval = [t0_interval, tf_interval] # Reset of the time interval # Recovery of the internal states from the end of the preceding simulation. initial_variable_values = [] for x in Simulator.solver_variable_names: initial_variable_values.append(Simulator.variables[x][-1]) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) else: # elif type_plot == \"fixed\": # Simulation Simulator = AlphaPEM(current_density, Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, Aact, Hgdl, Hmem, Hcl, Hgc, Wgc, Lgc, epsilon_gdl, tau, epsilon_mc, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, max_step, n_gdl, t_purge, type_fuel_cell, type_current, type_auxiliary, type_control, type_purge, type_display, type_plot) # Display if type_display != \"no_display\": Simulator.Display(ax1, ax2, ax3) # Plot saving plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3)","title":"launch_AlphaPEM_for_step_current"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.recover_for_display_operating_inputs_and_physical_parameters","text":"This function retrieves parameter values for predefined stacks (e.g., \"EH-31 1.5 bar (2021)\", \"Biao Xie 1.0 bar (2015)\", etc.) and converts them to appropriate units for display on the GUI. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def recover_for_display_operating_inputs_and_physical_parameters(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons): \"\"\"This function retrieves parameter values for predefined stacks (e.g., \"EH-31 1.5 bar (2021)\", \"Biao Xie 1.0 bar (2015)\", etc.) and converts them to appropriate units for display on the GUI. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" if choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 1.5 bar (2021)\": type_fuel_cell = \"EH-31_1.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.0 bar (2021)\": type_fuel_cell = \"EH-31_2.0\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.25 bar (2021)\": type_fuel_cell = \"EH-31_2.25\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.5 bar (2021)\": type_fuel_cell = \"EH-31_2.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Linhao Fan (2010)\": type_fuel_cell = \"LF\" Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola = stored_operating_inputs(type_fuel_cell) Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, \\ a_slim, b_slim, a_switch, C_scl = \\ stored_physical_parameters(type_fuel_cell) # operating conditions recovery choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].set(np.round(Tfc - 273.15)) # \u00b0C choice_operating_conditions['Anode pressure - Pa (bar)']['value'].set(np.round(Pa_des / 1e5, 2)) # bar choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].set(np.round(Pc_des / 1e5, 2)) # bar choice_operating_conditions['Anode stoichiometry - Sa']['value'].set(np.round(Sa, 1)) choice_operating_conditions['Cathode stoichiometry - Sc']['value'].set(np.round(Sc, 1)) choice_operating_conditions['Anode humidity - \u03a6a']['value'].set(np.round(Phi_a_des, 1)) choice_operating_conditions['Cathode humidity - \u03a6c']['value'].set(np.round(Phi_c_des, 1)) # accessible physical parameters recovery choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].set(np.round(Aact * 1e4)) # cm\u00b2 choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].set(np.round(Hgdl * 1e6)) # \u00b5m choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].set(np.round(Hcl * 1e6)) # \u00b5m choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].set(np.round(Hmem * 1e6)) # \u00b5m choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].set(np.round(Hgc * 1e6)) # \u00b5m choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].set(np.round(Wgc * 1e6)) # \u00b5m choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].set(np.round(Lgc, 2)) # \u00b5m # undetermined physical parameters recovery choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].set(np.round(epsilon_gdl, 3)) choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].set(np.round(epsilon_mc, 3)) choice_undetermined_parameters['Tortuosity - \u03c4']['value'].set(np.round(tau, 3)) choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].set(np.round(epsilon_c, 3)) choice_undetermined_parameters['Capillary exponent - e']['value'].set(e) choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].set(np.round(Re * 1e6, 2)) # \u00b5\u03a9.m\u00b2 choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].set(np.round(i0_c_ref, 2)) # A.m-2 choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].set(np.round(kappa_co, 2)) # mol.m-1.s-1.Pa-1 choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].set(np.round(kappa_c, 2)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].set(np.round(a_slim, 7)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].set(np.round(b_slim, 7)) choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].set(np.round(a_switch, 7)) choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].set(np.round(C_scl * 1e-6, 2)) # F.cm-3 # i_max_pola recovery choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].set(np.round(i_max_pola / 1e4, 2)) # A/cm\u00b2","title":"recover_for_display_operating_inputs_and_physical_parameters"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.recover_for_use_operating_inputs_and_physical_parameters","text":"This function retrieves and converts the parameter values from the GUI into standard units for further calculations. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. Source code in modules/GUI_modules.py def 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): \"\"\"This function retrieves and converts the parameter values from the GUI into standard units for further calculations. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # operating conditions Tfc = choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].get() + 273.15 # K Pa_des = choice_operating_conditions['Anode pressure - Pa (bar)']['value'].get() * 1e5 # Pa Pc_des = choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() * 1e5 # Pa Sa = choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() Sc = choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() Phi_a_des = choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() Phi_c_des = choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() # accessible physical parameters Aact = choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].get() * 1e-4 # m\u00b2 Hgdl = choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() * 1e-6 # m Hcl = choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() * 1e-6 # m Hmem = choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() * 1e-6 # m Hgc = choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() * 1e-6 # m Wgc = choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() * 1e-6 # m Lgc = choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() # m # undetermined physical parameters epsilon_gdl = choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() epsilon_mc = choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() tau = choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() epsilon_c = choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() e = choice_undetermined_parameters['Capillary exponent - e']['value'].get() Re = choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() * 1e-6 # ohm.m\u00b2 i0_c_ref = choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() # A.m-2 kappa_co = choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() # mol.m-1.s-1.Pa-1 kappa_c = choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() a_slim = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() b_slim = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() a_switch = choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() C_scl = choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() * 1e6 # F.m-3 # current density parameters t_step = (choice_current_density_parameters['Initial time - t0_step (s)']['value'].get(), choice_current_density_parameters['Final time - tf_step (s)']['value'].get(), choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get(), choice_computing_parameters['Time for dynamic\\ndisplay - \u0394t_dyn_step (s)']['value'].get()) # (s, s, s, s) i_step = (choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() * 1e4, choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get() * 1e4) # (A.m-2, A.m-2) i_max_pola = choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() * 1e4 # A.m-2 delta_pola = (choice_current_density_parameters['Loading time\\n- \u0394t_load_pola (s)']['value'].get(), choice_current_density_parameters['Breaking time\\n- \u0394t_break_pola (s)']['value'].get(), choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() * 1e4, choice_current_density_parameters['Initial breaking time\\n- \u0394t_ini_pola (s)']['value'].get()) # (s, s, A.m-2, s) i_EIS = choice_current_density_parameters['Static current\\n- i_EIS (A/cm\u00b2)']['value'].get() * 1e4 # (A.m-2) ratio_EIS = choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() / 100 f_EIS = (choice_current_density_parameters['Power of the\\ninitial frequency\\n- f_power_min_EIS']['value'].get(), choice_current_density_parameters['Power of the\\nfinal frequency\\n- f_power_max_EIS']['value'].get(), choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get(), choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get()) t_EIS = EIS_parameters(f_EIS) # Time parameters for the EIS_current density function. t_purge = choice_computing_parameters['Purge time - t_purge (s)']['value'].get() # s delta_t_purge = choice_computing_parameters['Time between two purges\\n- \u0394t_purge (s)']['value'].get() # s max_step = choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() # s n_gdl = choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get() if choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 1.5 bar (2021)\": type_fuel_cell = \"EH-31_1.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.0 bar (2021)\": type_fuel_cell = \"EH-31_2.0\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.25 bar (2021)\": type_fuel_cell = \"EH-31_2.25\" elif choice_buttons['type_fuel_cell']['value'].get() == \"EH-31 2.5 bar (2021)\": type_fuel_cell = \"EH-31_2.5\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Linhao Fan (2010)\": type_fuel_cell = \"LF\" elif choice_buttons['type_fuel_cell']['value'].get() == \"Enter your specifications\": type_fuel_cell = \"manual_setup\" if choice_buttons['type_auxiliary']['value'].get() == 0: type_auxiliary = \"no_auxiliary\" elif choice_buttons['type_auxiliary']['value'].get() == 1: type_auxiliary = \"forced-convective_cathode_with_anodic_recirculation\" else: type_auxiliary = \"forced-convective_cathode_with_flow-through_anode\" if choice_buttons['type_control']['value'].get() == 0: type_control = \"no_control\" else: type_control = \"Phi_des\" if choice_buttons['type_purge']['value'].get() == 0: type_purge = \"no_purge\" elif choice_buttons['type_purge']['value'].get() == 1: type_purge = \"periodic_purge\" else: type_purge = \"constant_purge\" if choice_buttons['type_display']['value'].get() == 0: type_display = \"no_display\" elif choice_buttons['type_display']['value'].get() == 1: type_display = \"synthetic\" else: type_display = \"multiple\" if choice_buttons['type_plot']['value'].get() == 0: type_plot = \"fixed\" else: type_plot = \"dynamic\" return (Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, Aact, Hgdl, Hcl, Hmem, Hgc, Wgc, Lgc, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl, t_step, i_step, i_max_pola, delta_pola, i_EIS, ratio_EIS, f_EIS, t_EIS, t_purge, delta_t_purge, max_step, n_gdl, type_fuel_cell, type_auxiliary, type_control, type_purge, type_display, type_plot)","title":"recover_for_use_operating_inputs_and_physical_parameters"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.set_equal_width","text":"Adjusts the width of the frames to be equal based on their maximum width. Parameters: frame1 ( Frame ) \u2013 The first frame to be resized. frame2 ( Frame ) \u2013 The second frame to be resized. frame3 ( Frame ) \u2013 The third frame to be resized. frame4 ( Frame ) \u2013 The fourth frame to be resized. frame5 ( Frame ) \u2013 The fifth frame to be resized. frame6 ( Frame ) \u2013 The sixth frame to be resized. Source code in modules/GUI_modules.py def set_equal_width(frame1, frame2, frame3, frame4, frame5, frame6): \"\"\" Adjusts the width of the frames to be equal based on their maximum width. Parameters ---------- frame1 : ttk.Frame The first frame to be resized. frame2 : ttk.Frame The second frame to be resized. frame3 : ttk.Frame The third frame to be resized. frame4 : ttk.Frame The fourth frame to be resized. frame5 : ttk.Frame The fifth frame to be resized. frame6 : ttk.Frame The sixth frame to be resized. \"\"\" # Initialisation of the list of widths widths = [] for frame in [frame1, frame2, frame3, frame4, frame5, frame6]: # Update the frame sizes frame.update_idletasks() # Get the current width of all frames widths.append(frame.winfo_width()) # Set all frames to the maximum width for frame in [frame1, frame2, frame3, frame4, frame5, frame6]: for i in range(6): frame.grid_columnconfigure(i, minsize=max(widths) / 5.5) # Set minimum width of all column to max_width / 5","title":"set_equal_width"},{"location":"functions/modules/GUI_modules/#modules.GUI_modules.value_control","text":"This function checks the integrity of the values entered by the user and returns an empty tuple if they are not valid. Parameters: choice_operating_conditions ( dict ) \u2013 A dictionary containing the operating condition information. choice_accessible_parameters ( dict ) \u2013 A dictionary containing the accessible physical parameter information. choice_undetermined_parameters ( dict ) \u2013 A dictionary containing the undetermined physical parameter information. choice_current_density_parameters ( dict ) \u2013 A dictionary containing the current density parameter information. choice_computing_parameters ( dict ) \u2013 A dictionary containing the computing parameter information. choice_buttons ( dict ) \u2013 A dictionary containing the button information. current_button ( dict ) \u2013 A dictionary representing the clicked button. Source code in modules/GUI_modules.py def value_control(choice_operating_conditions, choice_accessible_parameters, choice_undetermined_parameters, choice_current_density_parameters, choice_computing_parameters, choice_buttons, current_button): \"\"\"This function checks the integrity of the values entered by the user and returns an empty tuple if they are not valid. Parameters ---------- choice_operating_conditions : dict A dictionary containing the operating condition information. choice_accessible_parameters : dict A dictionary containing the accessible physical parameter information. choice_undetermined_parameters : dict A dictionary containing the undetermined physical 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. \"\"\" # The values entered by the user are checked for compliance if choice_operating_conditions['Temperature - Tfc (\u00b0C)']['value'].get() < 0: messagebox.showerror(title='Temperatures', message='Negative temperatures do not exist in the Kelvin scale.') choices.clear() return if choice_operating_conditions['Anode pressure - Pa (bar)']['value'].get() < 0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() < 0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() > 5.0 or \\ choice_operating_conditions['Cathode pressure - Pc (bar)']['value'].get() > 5.0: messagebox.showerror(title='Desired pressures', message='Desired pressure should be positive and bellow 5.0 ' 'bars.') choices.clear() return if choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() < 1 or \\ choice_operating_conditions['Anode stoichiometry - Sa']['value'].get() > 5 or \\ choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() < 1 or \\ choice_operating_conditions['Cathode stoichiometry - Sc']['value'].get() > 5: messagebox.showerror(title='Stoichiometric ratios', message='The stoichiometric ratios Sa and Sc should be ' 'between 1 and 5.') choices.clear() return if choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() < 0 or \\ choice_operating_conditions['Anode humidity - \u03a6a']['value'].get() > 1 or \\ choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() < 0 or \\ choice_operating_conditions['Cathode humidity - \u03a6c']['value'].get() > 1: messagebox.showerror(title='Desired humidity', message='The desired humidities should be between 0 and 1.') choices.clear() return if choice_accessible_parameters['Active area - Aact (cm\u00b2)']['value'].get() < 0: messagebox.showerror(title='Active area', message='Negative active area is impossible.') choices.clear() return if choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['GDL thickness - Hgdl (\u00b5m)']['value'].get() > 1000 or \\ choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['CL thickness - Hcl (\u00b5m)']['value'].get() > 1000 or \\ choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() < 1 or \\ choice_accessible_parameters['Membrane thickness - Hmem (\u00b5m)']['value'].get() > 1000: messagebox.showerror(title='MEA thickness', message='All MEA components generally have a thickness between ' '1\u00b5m and 1mm.') choices.clear() return if choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() < 10 or \\ choice_accessible_parameters['GC thickness - Hgc (\u00b5m)']['value'].get() > 10000 or \\ choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() < 10 or \\ choice_accessible_parameters['GC width - Wgc (\u00b5m)']['value'].get() > 10000 or \\ choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() < 0 or \\ choice_accessible_parameters['GC cumulated length - Lgc (m)']['value'].get() > 100: messagebox.showerror(title='GC distances', message='GC generally have a thickness and a width between 10\u00b5m and ' '10mm. Also, GC length is generally between 0 and 100m') choices.clear() return if choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() < 0 or \\ choice_undetermined_parameters['GDL porosity - \u03b5_gdl']['value'].get() > 1 or \\ choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() < 0 or \\ choice_undetermined_parameters['Ionomer volume fraction\\n- \u03b5_mc']['value'].get() > 1: messagebox.showerror(title='Porosities', message='All porosities should be between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() < 1 or choice_undetermined_parameters['Tortuosity - \u03c4']['value'].get() > 4: messagebox.showerror(title='Pore structure coefficient', message='The pore structure coefficient should be ' 'between 1 and 4.') choices.clear() return if choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() < 0 or \\ choice_undetermined_parameters['Compression ratio - \u03b5_c']['value'].get() > 1: messagebox.showerror(title='Compression ratio', message='The compression ratio should be between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Capillary exponent - e']['value'].get() < 3 or choice_undetermined_parameters['Capillary exponent - e']['value'].get() > 5: messagebox.showerror(title='Capillary exponent', message='The capillary exponent should be between 3 and 5 and ' 'being an integer.') choices.clear() return if choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() < 0.5 or \\ choice_undetermined_parameters['Electron resistance\\n- Re (\u00b5\u03a9.m\u00b2)']['value'].get() > 5: messagebox.showerror(title='Electron conduction resistance', message='The electron conduction resistance is ' 'generally between 0.5 and 5 \u00b5\u03a9.m\u00b2.') choices.clear() return if choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() < 0.001 or \\ choice_undetermined_parameters['Reference exchange\\ncurrent density\\n- i0_c_ref (A/m\u00b2)']['value'].get() > 500: messagebox.showerror(title='Referenced exchange current density', message='The referenced exchange current ' 'density is generally between 0.001 ' 'and 500 A.m-2.') choices.clear() return if choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() < 0.01 or \\ choice_undetermined_parameters['Crossover correction\\ncoefficient\\n- \u03ba_co (mol/(m.s.Pa))']['value'].get() > 100: messagebox.showerror(title='Crossover correction coefficient', message='The crossover correction coefficient is' ' generally between 0.01 and 100 ' 'mol.m-1.s-1.Pa-1.') choices.clear() return if choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() < 0 or \\ choice_undetermined_parameters['Overpotential correction\\nexponent - \u03ba_c']['value'].get() > 100: messagebox.showerror(title='Overpotential correction exponent', message='The overpotential correction exponent ' 'is generally between 0 and 100.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_slim']['value'].get() > 1: messagebox.showerror(title='Slop of slim function', message='The slop of slim function is generally between 0 ' 'and 1.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - b_slim']['value'].get() > 1: messagebox.showerror(title='Intercept of slim function', message='The intercept of slim function is generally ' 'between 0 and 1.') choices.clear() return if choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() < 0 or \\ choice_undetermined_parameters['Limit liquid saturation\\ncoefficient - a_switch']['value'].get() > 1: messagebox.showerror(title='Slop of switch function', message='The slop of switch function is generally between' ' 0 and 1.') choices.clear() return if choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() < 5 or \\ choice_undetermined_parameters['Volumetric space-charge\\nlayer capacitance\\n- C_scl (F/cm\u00b3)']['value'].get() > 100: messagebox.showerror(title='Double layer capacitance', message='I have not settled yet a range for C_scl.') choices.clear() return if choice_current_density_parameters['Initial time - t0_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Final time - tf_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get() < 0 or \\ choice_computing_parameters['Time for dynamic\\ndisplay - \u0394t_dyn_step (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Breaking time\\n- \u0394t_break_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Initial breaking time\\n- \u0394t_ini_pola (s)']['value'].get() < 0 or \\ choice_current_density_parameters['Initial time - t0_step (s)']['value'].get() > \\ choice_current_density_parameters['Final time - tf_step (s)']['value'].get() or \\ choice_current_density_parameters['Loading time\\n- \u0394t_load_step (s)']['value'].get() > \\ (choice_current_density_parameters['Final time - tf_step (s)']['value'].get() - choice_current_density_parameters['Initial time - t0_step (s)']['value'].get()): messagebox.showerror(title='Times', message='The times should be positive, t0_step < tf_step and ' 'delta_t_load_step < (tf_step - t0_step).') choices.clear() return if choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Static current\\n- i_EIS (A/cm\u00b2)']['value'].get() < 0 or \\ choice_current_density_parameters['Current density step\\n- \u0394i_pola (A/cm\u00b2)']['value'].get() > \\ choice_current_density_parameters['Maximum current density\\n- i_max_pola (A/cm\u00b2)']['value'].get() or \\ choice_current_density_parameters['Initial current density\\n- i_ini_step (A/cm\u00b2)']['value'].get() > \\ choice_current_density_parameters['Final current density\\n- i_final_step (A/cm\u00b2)']['value'].get(): messagebox.showerror(title='Current densities', message='The current densities should be positive, ' 'delta_i_pola < i_max_pola and ' 'i_ini_step < i_final_step.') choices.clear() return if choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() < 0 or \\ choice_current_density_parameters['Current ratio\\n- ratio_EIS (%)']['value'].get() > 20: messagebox.showerror(title='Ratio EIS', message='Ratio EIS is a percentage of i_EIS and should be between 0 ' 'and 20 for plotting correct EIS.') choices.clear() return if choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get() < 0 or \\ choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get() < 0 or \\ type(choice_current_density_parameters['Power of the\\ninitial frequency\\n- f_power_min_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Power of the\\nfinal frequency\\n- f_power_max_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Number of frequencies\\ntested - nb_f_EIS']['value'].get()) != int or \\ type(choice_current_density_parameters['Number of points\\ncalculated - nb_points_EIS']['value'].get()) != int: messagebox.showerror(title='f EIS', message='f_EIS parameters should be integer and number of points should ' 'be positive.') choices.clear() return if choice_computing_parameters['Purge time - t_purge (s)']['value'].get() < 0 or \\ choice_computing_parameters['Time between two purges\\n- \u0394t_purge (s)']['value'].get() < 0: messagebox.showerror(title='Purge times', message='Negative times does not characterise purges.') choices.clear() return if choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() < 0 or \\ choice_computing_parameters['Maximum time step\\n- max_step (s)']['value'].get() > 0.1: messagebox.showerror(title='Max step', message='The max step value for the solver should be positive and lower ' 'than 0.1 for normal use.') choices.clear() return if choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get() < 2 or \\ type(choice_computing_parameters['Number of GDL nodes - n_gdl']['value'].get()) != int: messagebox.showerror(title='n gdl', message='The n_gdl value should be an integer bigger than 2. ' 'A good compromise is 10.') choices.clear() return if current_button == 0 and choice_buttons['type_display']['value'].get() == 2 \\ and choice_buttons['type_plot']['value'].get() == 1 : messagebox.showerror(title='n gdl', message='dynamic plot is not thought to be used with step current and ' 'multiple display. There would be too much plots to handle.') choices.clear() return if current_button == 2 and choice_buttons['type_plot']['value'].get() == 0: messagebox.showerror(title='n gdl', message='EIS has to be plot with a dynamic type_plot setting, ' 'because max_step has to be adjusted at each frequency.') choices.clear() return","title":"value_control"},{"location":"functions/modules/auxiliaries_modules/","text":"Auxiliaries modules This module is used to calculate intermediate values for the auxiliaries flows calculation. auxiliaries_int_values(t, solver_variables, operating_inputs, parameters) This functions calculates intermediate values for the auxiliaries flows calculation. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). Phi_agc ( float ) \u2013 Relative humidity in the anode gas channel. Phi_cgc ( float ) \u2013 Relative humidity in the cathode gas channel. y_cgc ( float ) \u2013 Oxygen ratio in dry air in the cathode gas channel. Magc ( float ) \u2013 Molar mass of all the gas species in the anode gas channel (kg/mol). Mcgc ( float ) \u2013 Molar mass of all the gas species in the cathode gas channel (kg/mol). Pr_aem ( float ) \u2013 Pressure ratio in the anode external manifold. Pr_cem ( float ) \u2013 Pressure ratio in the cathode external manifold. Maem ( float ) \u2013 Molar mass of all the gas species in the anode external manifold (kg/mol). Masm ( float ) \u2013 Molar mass of all the gas species in the anode supply manifold (kg/mol). Mcem ( float ) \u2013 Molar mass of all the gas species in the cathode external manifold (kg/mol). Mcsm ( float ) \u2013 Molar mass of all the gas species in the cathode supply manifold (kg/mol). k_purge ( float ) \u2013 Purge coefficient. It is equal to 1 if the purge is active and 0 otherwise. Abp_a ( float ) \u2013 Area of the back pressure valve in the anode external manifold (m\u00b2). Abp_c ( float ) \u2013 Area of the back pressure valve in the cathode external manifold (m\u00b2). i_n ( float ) \u2013 Internal current density (A/m\u00b2). Source code in modules/auxiliaries_modules.py def auxiliaries_int_values(t, solver_variables, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the auxiliaries flows calculation. Parameters ---------- t : float Time (s). solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Mext : float Molar mass of the ambient air outside the stack (kg/mol). Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). Phi_agc : float Relative humidity in the anode gas channel. Phi_cgc : float Relative humidity in the cathode gas channel. y_cgc : float Oxygen ratio in dry air in the cathode gas channel. Magc : float Molar mass of all the gas species in the anode gas channel (kg/mol). Mcgc : float Molar mass of all the gas species in the cathode gas channel (kg/mol). Pr_aem : float Pressure ratio in the anode external manifold. Pr_cem : float Pressure ratio in the cathode external manifold. Maem : float Molar mass of all the gas species in the anode external manifold (kg/mol). Masm : float Molar mass of all the gas species in the anode supply manifold (kg/mol). Mcem : float Molar mass of all the gas species in the cathode external manifold (kg/mol). Mcsm : float Molar mass of all the gas species in the cathode supply manifold (kg/mol). k_purge : float Purge coefficient. It is equal to 1 if the purge is active and 0 otherwise. Abp_a : float Area of the back pressure valve in the anode external manifold (m\u00b2). Abp_c : float Area of the back pressure valve in the cathode external manifold (m\u00b2). i_n : float Internal current density (A/m\u00b2). \"\"\" # Extraction of the variables C_v_agc, C_v_cgc = solver_variables['C_v_agc'], solver_variables['C_v_cgc'] lambda_mem = solver_variables['lambda_mem'] C_H2_agc, C_H2_acl = solver_variables['C_H2_agc'], solver_variables['C_H2_acl'] C_N2, C_O2_ccl, C_O2_cgc = solver_variables['C_N2'], solver_variables['C_O2_ccl'], solver_variables['C_O2_cgc'] Pasm, Paem, Pcsm = solver_variables['Pasm'], solver_variables['Paem'], solver_variables['Pcsm'] Pcem, Phi_asm, Phi_aem = solver_variables['Pcem'], solver_variables['Phi_asm'], solver_variables['Phi_aem'] Phi_csm, Phi_cem = solver_variables['Phi_csm'], solver_variables['Phi_cem'] Abp_a, Abp_c = solver_variables['Abp_a'], solver_variables['Abp_c'] # Extraction of the operating inputs and the parameters Tfc, Pa_des, Pc_des = operating_inputs['Tfc'], operating_inputs['Pa_des'], operating_inputs['Pc_des'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] t_purge, type_purge = parameters['t_purge'], parameters['type_purge'] # Molar mass of the ambient air Mext = Phi_ext * Psat(Text) / Pext * M_H2O + \\ yO2_ext * (1 - Phi_ext * Psat(Text) / Pext) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_ext * Psat(Text) / Pext) * M_N2 # Physical quantities inside the stack # Pressures Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Humidities Phi_agc = C_v_agc / C_v_sat(Tfc) Phi_cgc = C_v_cgc / C_v_sat(Tfc) # Oxygen ratio in dry air y_cgc = C_O2_cgc / (C_O2_cgc + C_N2) # Molar masses Magc = C_v_agc * R * Tfc / Pagc * M_H2O + \\ C_H2_agc * R * Tfc / Pagc * M_H2 Mcgc = Phi_cgc * Psat(Tfc) / Pcgc * M_H2O + \\ y_cgc * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * M_O2 + \\ (1 - y_cgc) * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * M_N2 # Internal current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # Physical quantities in the auxiliary system if parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_anodic_recirculation\" or \\ parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_flow-through_anode\": # Pressure ratios Pr_aem = (Pext / Paem) Pr_cem = (Pext / Pcem) # Oxygen ratio in dry air y_cem = (Pcem - Phi_cem * Psat(Tfc) - C_N2 * R * Tfc) / (Pcem - Phi_cem * Psat(Tfc)) # Molar masses Maem = Phi_aem * Psat(Tfc) / Paem * M_H2O + \\ (1 - Phi_aem * Psat(Tfc) / Paem) * M_H2 Masm = Phi_asm * Psat(Tfc) / Pasm * M_H2O + \\ (1 - Phi_asm * Psat(Tfc) / Pasm) * M_H2 Mcem = Phi_cem * Psat(Tfc) / Pcem * M_H2O + \\ y_cem * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_O2 + \\ (1 - y_cem) * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_N2 Mcsm = Phi_csm * Psat(Tfc) / Pcsm * M_H2O + \\ yO2_ext * (1 - Phi_csm * Psat(Tfc) / Pcsm) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_csm * Psat(Tfc) / Pcsm) * M_N2 # Purge if type_purge == \"no_purge\": k_purge = 0 elif type_purge == \"constant_purge\": k_purge = 1 elif type_purge == \"periodic_purge\": purge_time, delta_purge = t_purge if (t - int(t / (purge_time + delta_purge)) * (purge_time + delta_purge)) <= purge_time: k_purge = 1 else: k_purge = 0 else: raise ValueError(\"The type_purge variable should be correctly referenced.\") # Back pressure valve area if Abp_a > A_T: Abp_a = A_T elif Abp_a < 0: Abp_a = 0 if Abp_c > A_T: Abp_c = A_T elif Abp_c < 0: Abp_c = 0 else: # parameters[\"type_auxiliary\"] == \"no_auxiliary\" Pr_aem, Pr_cem, Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c = [0] * 9 return (Mext, Pagc, Pcgc, Phi_agc, Phi_cgc, y_cgc, Magc, Mcgc, Pr_aem, Pr_cem, Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c, i_n)","title":"Auxiliaries modules"},{"location":"functions/modules/auxiliaries_modules/#auxiliaries-modules","text":"This module is used to calculate intermediate values for the auxiliaries flows calculation.","title":"Auxiliaries modules"},{"location":"functions/modules/auxiliaries_modules/#modules.auxiliaries_modules.auxiliaries_int_values","text":"This functions calculates intermediate values for the auxiliaries flows calculation. Parameters: t ( float ) \u2013 Time (s). solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). Phi_agc ( float ) \u2013 Relative humidity in the anode gas channel. Phi_cgc ( float ) \u2013 Relative humidity in the cathode gas channel. y_cgc ( float ) \u2013 Oxygen ratio in dry air in the cathode gas channel. Magc ( float ) \u2013 Molar mass of all the gas species in the anode gas channel (kg/mol). Mcgc ( float ) \u2013 Molar mass of all the gas species in the cathode gas channel (kg/mol). Pr_aem ( float ) \u2013 Pressure ratio in the anode external manifold. Pr_cem ( float ) \u2013 Pressure ratio in the cathode external manifold. Maem ( float ) \u2013 Molar mass of all the gas species in the anode external manifold (kg/mol). Masm ( float ) \u2013 Molar mass of all the gas species in the anode supply manifold (kg/mol). Mcem ( float ) \u2013 Molar mass of all the gas species in the cathode external manifold (kg/mol). Mcsm ( float ) \u2013 Molar mass of all the gas species in the cathode supply manifold (kg/mol). k_purge ( float ) \u2013 Purge coefficient. It is equal to 1 if the purge is active and 0 otherwise. Abp_a ( float ) \u2013 Area of the back pressure valve in the anode external manifold (m\u00b2). Abp_c ( float ) \u2013 Area of the back pressure valve in the cathode external manifold (m\u00b2). i_n ( float ) \u2013 Internal current density (A/m\u00b2). Source code in modules/auxiliaries_modules.py def auxiliaries_int_values(t, solver_variables, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the auxiliaries flows calculation. Parameters ---------- t : float Time (s). solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Mext : float Molar mass of the ambient air outside the stack (kg/mol). Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). Phi_agc : float Relative humidity in the anode gas channel. Phi_cgc : float Relative humidity in the cathode gas channel. y_cgc : float Oxygen ratio in dry air in the cathode gas channel. Magc : float Molar mass of all the gas species in the anode gas channel (kg/mol). Mcgc : float Molar mass of all the gas species in the cathode gas channel (kg/mol). Pr_aem : float Pressure ratio in the anode external manifold. Pr_cem : float Pressure ratio in the cathode external manifold. Maem : float Molar mass of all the gas species in the anode external manifold (kg/mol). Masm : float Molar mass of all the gas species in the anode supply manifold (kg/mol). Mcem : float Molar mass of all the gas species in the cathode external manifold (kg/mol). Mcsm : float Molar mass of all the gas species in the cathode supply manifold (kg/mol). k_purge : float Purge coefficient. It is equal to 1 if the purge is active and 0 otherwise. Abp_a : float Area of the back pressure valve in the anode external manifold (m\u00b2). Abp_c : float Area of the back pressure valve in the cathode external manifold (m\u00b2). i_n : float Internal current density (A/m\u00b2). \"\"\" # Extraction of the variables C_v_agc, C_v_cgc = solver_variables['C_v_agc'], solver_variables['C_v_cgc'] lambda_mem = solver_variables['lambda_mem'] C_H2_agc, C_H2_acl = solver_variables['C_H2_agc'], solver_variables['C_H2_acl'] C_N2, C_O2_ccl, C_O2_cgc = solver_variables['C_N2'], solver_variables['C_O2_ccl'], solver_variables['C_O2_cgc'] Pasm, Paem, Pcsm = solver_variables['Pasm'], solver_variables['Paem'], solver_variables['Pcsm'] Pcem, Phi_asm, Phi_aem = solver_variables['Pcem'], solver_variables['Phi_asm'], solver_variables['Phi_aem'] Phi_csm, Phi_cem = solver_variables['Phi_csm'], solver_variables['Phi_cem'] Abp_a, Abp_c = solver_variables['Abp_a'], solver_variables['Abp_c'] # Extraction of the operating inputs and the parameters Tfc, Pa_des, Pc_des = operating_inputs['Tfc'], operating_inputs['Pa_des'], operating_inputs['Pc_des'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] t_purge, type_purge = parameters['t_purge'], parameters['type_purge'] # Molar mass of the ambient air Mext = Phi_ext * Psat(Text) / Pext * M_H2O + \\ yO2_ext * (1 - Phi_ext * Psat(Text) / Pext) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_ext * Psat(Text) / Pext) * M_N2 # Physical quantities inside the stack # Pressures Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Humidities Phi_agc = C_v_agc / C_v_sat(Tfc) Phi_cgc = C_v_cgc / C_v_sat(Tfc) # Oxygen ratio in dry air y_cgc = C_O2_cgc / (C_O2_cgc + C_N2) # Molar masses Magc = C_v_agc * R * Tfc / Pagc * M_H2O + \\ C_H2_agc * R * Tfc / Pagc * M_H2 Mcgc = Phi_cgc * Psat(Tfc) / Pcgc * M_H2O + \\ y_cgc * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * M_O2 + \\ (1 - y_cgc) * (1 - Phi_cgc * Psat(Tfc) / Pcgc) * M_N2 # Internal current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # Physical quantities in the auxiliary system if parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_anodic_recirculation\" or \\ parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_flow-through_anode\": # Pressure ratios Pr_aem = (Pext / Paem) Pr_cem = (Pext / Pcem) # Oxygen ratio in dry air y_cem = (Pcem - Phi_cem * Psat(Tfc) - C_N2 * R * Tfc) / (Pcem - Phi_cem * Psat(Tfc)) # Molar masses Maem = Phi_aem * Psat(Tfc) / Paem * M_H2O + \\ (1 - Phi_aem * Psat(Tfc) / Paem) * M_H2 Masm = Phi_asm * Psat(Tfc) / Pasm * M_H2O + \\ (1 - Phi_asm * Psat(Tfc) / Pasm) * M_H2 Mcem = Phi_cem * Psat(Tfc) / Pcem * M_H2O + \\ y_cem * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_O2 + \\ (1 - y_cem) * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_N2 Mcsm = Phi_csm * Psat(Tfc) / Pcsm * M_H2O + \\ yO2_ext * (1 - Phi_csm * Psat(Tfc) / Pcsm) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_csm * Psat(Tfc) / Pcsm) * M_N2 # Purge if type_purge == \"no_purge\": k_purge = 0 elif type_purge == \"constant_purge\": k_purge = 1 elif type_purge == \"periodic_purge\": purge_time, delta_purge = t_purge if (t - int(t / (purge_time + delta_purge)) * (purge_time + delta_purge)) <= purge_time: k_purge = 1 else: k_purge = 0 else: raise ValueError(\"The type_purge variable should be correctly referenced.\") # Back pressure valve area if Abp_a > A_T: Abp_a = A_T elif Abp_a < 0: Abp_a = 0 if Abp_c > A_T: Abp_c = A_T elif Abp_c < 0: Abp_c = 0 else: # parameters[\"type_auxiliary\"] == \"no_auxiliary\" Pr_aem, Pr_cem, Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c = [0] * 9 return (Mext, Pagc, Pcgc, Phi_agc, Phi_cgc, y_cgc, Magc, Mcgc, Pr_aem, Pr_cem, Maem, Masm, Mcem, Mcsm, k_purge, Abp_a, Abp_c, i_n)","title":"auxiliaries_int_values"},{"location":"functions/modules/calibration_modules/","text":"Calibration modules This module contains some of the functions required for the parameter calibration. calculate_simulation_error(Simulator1, U_exp1, i_exp1, Simulator2, U_exp2, i_exp2) This function is used to calculate the simulation maximal error between the experimental and the simulated polarization curves. Two simulations on different operating conditions and on the same stack, and so two set of experimental data, are considered as it is the minimum amount of data which is required for the calibration. Parameters: Simulator1 ( AlphaPEM object ) \u2013 PEM simulator which contains the simulation results for the first simulation. U_exp1 ( ndarray ) \u2013 Experimental values of the voltage for the first simulation. i_exp1 ( ndarray ) \u2013 Experimental values of the current density for the first simulation. Simulator2 ( AlphaPEM object ) \u2013 PEM simulator which contains the simulation results for the second simulation. U_exp2 ( ndarray ) \u2013 Experimental values of the voltage for the second simulation. i_exp2 ( ndarray ) \u2013 Experimental values of the current density for the second simulation. Returns: sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. Source code in modules/calibration_modules.py def calculate_simulation_error(Simulator1, U_exp1, i_exp1, Simulator2, U_exp2, i_exp2): \"\"\"This function is used to calculate the simulation maximal error between the experimental and the simulated polarization curves. Two simulations on different operating conditions and on the same stack, and so two set of experimental data, are considered as it is the minimum amount of data which is required for the calibration. Parameters ---------- Simulator1 : AlphaPEM object PEM simulator which contains the simulation results for the first simulation. U_exp1 : numpy.ndarray Experimental values of the voltage for the first simulation. i_exp1 : numpy.ndarray Experimental values of the current density for the first simulation. Simulator2 : AlphaPEM object PEM simulator which contains the simulation results for the second simulation. U_exp2 : numpy.ndarray Experimental values of the voltage for the second simulation. i_exp2 : numpy.ndarray Experimental values of the current density for the second simulation. Returns ------- sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. \"\"\" # Recovery of ifc_1 t1 = np.array(Simulator1.variables['t']) n1 = len(t1) ifc_t_1 = np.zeros(n1) for i in range(n1): # Creation of ifc_t and conversion in A/cm\u00b2 ifc_t_1[i] = Simulator1.operating_inputs['current_density'](t1[i], Simulator1.parameters) / 1e4 # Recovery of ifc_2 t2 = np.array(Simulator2.variables['t']) n2 = len(t2) ifc_t_2 = np.zeros(n2) for i in range(n2): # Creation of ifc_t and conversion in A/cm\u00b2 ifc_t_2[i] = Simulator2.operating_inputs['current_density'](t2[i], Simulator2.parameters) / 1e4 # Polarisation curve point recovery after stack stabilisation for Simulator1 delta_t_load, delta_t_break, delta_i, delta_t_ini = Simulator1.parameters['delta_pola'] nb_loads1 = int(Simulator1.parameters['i_pola'] / delta_i + 1) # Number of load which are made ifc_discretized1 = np.zeros(nb_loads1) Ucell_discretized1 = np.zeros(nb_loads1) for i in range(nb_loads1): t_load = delta_t_ini + (i + 1) * (delta_t_load + delta_t_break) - delta_t_break / 10 # time for the measurement idx1 = (np.abs(t1 - t_load)).argmin() # the corresponding index ifc_discretized1[i] = ifc_t_1[idx1] # the last value at the end of each load Ucell_discretized1[i] = Simulator1.variables['Ucell'][idx1] # the last value at the end of each load # Polarisation curve point recovery after stack stabilisation for Simulator2 delta_t_load, delta_t_break, delta_i, delta_t_ini = Simulator2.parameters['delta_pola'] nb_loads2 = int(Simulator2.parameters['i_pola'] / delta_i + 1) # Number of load which are made ifc_discretized2 = np.zeros(nb_loads2) Ucell_discretized2 = np.zeros(nb_loads2) for i in range(nb_loads2): t_load = delta_t_ini + (i + 1) * (delta_t_load + delta_t_break) - delta_t_break / 10 # time for the measurement idx2 = (np.abs(t2 - t_load)).argmin() # the corresponding index ifc_discretized2[i] = ifc_t_2[idx2] # the last value at the end of each load Ucell_discretized2[i] = Simulator2.variables['Ucell'][idx2] # the last value at the end of each load # Interpolation of experimental points to match model points for Simulator 1 i_fc_reduced1 = ifc_discretized1[(ifc_discretized1 >= i_exp1[0]) & (ifc_discretized1 <= i_exp1[-1])] Ucell_reduced1 = Ucell_discretized1[(ifc_discretized1 >= i_exp1[0]) & (ifc_discretized1 <= i_exp1[-1])] U_exp_interpolated1 = interp1d(i_exp1, U_exp1, kind='linear')(i_fc_reduced1) # Interpolation of experimental points to match model points for Simulator 2 i_fc_reduced2 = ifc_discretized2[(ifc_discretized2 >= i_exp2[0]) & (ifc_discretized2 <= i_exp2[-1])] Ucell_reduced2 = Ucell_discretized2[(ifc_discretized2 >= i_exp2[0]) & (ifc_discretized2 <= i_exp2[-1])] U_exp_interpolated2 = interp1d(i_exp2, U_exp2, kind='linear')(i_fc_reduced2) # Distance between the simulated and the experimental polarization curves. if np.isnan(Ucell_reduced1).any() or np.isnan(Ucell_reduced2).any(): sim_error = 1e5 # If the mass loss arrives before i_exp[-1], some value would be equal to NaN. else: sim_error = (np.max(np.abs(Ucell_reduced1 - U_exp_interpolated1) / U_exp_interpolated1 * 100) + np.max(np.abs(Ucell_reduced2 - U_exp_interpolated2) / U_exp_interpolated2 * 100)) / 2 # in %. return sim_error determined_parameters(type_fuel_cell) This function is used to determine the parameters of the fuel cell model for the calibration when a registered type_fuel_cell is considered. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_pola ( float ) \u2013 Maximum current density for the polarization curve. Aact ( float ) \u2013 Active area of the cell in m\u00b2. Hmem ( float ) \u2013 Thickness of the membrane in m. Hcl ( float ) \u2013 Thickness of the catalyst layer in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Wgc ( float ) \u2013 Width of the gas channel in m. Lgc ( float ) \u2013 Length of the gas channel in m. type_auxiliary ( str ) \u2013 Type of auxiliary system. type_control ( str ) \u2013 Type of control system. type_purge ( str ) \u2013 Type of purge system. type_display ( str ) \u2013 Type of display. type_plot ( str ) \u2013 Type of plot. type_current ( str ) \u2013 Type of current density function. current_density ( function ) \u2013 Current density evolution over time. It is a function of time and parameters dictionary. t_step ( tuple ) \u2013 Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load' and dynamic time for display 'delta_t_dyn'. i_step ( tuple ) \u2013 Current parameters for the step_current density function. It is a tuple containing the initial and final current density value 'i_ini' and 'i_final'. delta_pola ( tuple ) \u2013 Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load', the breaking time 'delta_t_break', the current density step 'delta_i', and the initial breaking time 'delta_t_ini'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added. ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve. t_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min': f_min = 10**f_power_min, the power of the final frequency 'f_power_max', the number of frequencies tested 'nb_f' and the number of points calculated per specific period 'nb_points'. t_purge ( tuple ) \u2013 Time parameters for purging the system. It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. max_step ( float ) \u2013 Maximum time step for the solver. n_gdl ( int ) \u2013 Number of points considered in the GDL. i_exp ( ndarray ) \u2013 Experimental values of the current density. U_exp ( ndarray ) \u2013 Experimental values of the voltage. Source code in modules/calibration_modules.py def determined_parameters(type_fuel_cell): \"\"\"This function is used to determine the parameters of the fuel cell model for the calibration when a registered type_fuel_cell is considered. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_pola : float Maximum current density for the polarization curve. Aact : float Active area of the cell in m\u00b2. Hmem : float Thickness of the membrane in m. Hcl : float Thickness of the catalyst layer in m. Hgc : float Thickness of the gas channel in m. Wgc : float Width of the gas channel in m. Lgc : float Length of the gas channel in m. type_auxiliary : str Type of auxiliary system. type_control : str Type of control system. type_purge : str Type of purge system. type_display : str Type of display. type_plot : str Type of plot. type_current : str Type of current density function. current_density : function Current density evolution over time. It is a function of time and parameters dictionary. t_step : tuple Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load' and dynamic time for display 'delta_t_dyn'. i_step : tuple Current parameters for the step_current density function. It is a tuple containing the initial and final current density value 'i_ini' and 'i_final'. delta_pola : tuple Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load', the breaking time 'delta_t_break', the current density step 'delta_i', and the initial breaking time 'delta_t_ini'. i_EIS : float Current for which a ratio_EIS perturbation is added. ratio_EIS : float Value of the perturbation on the current density for building the EIS curve. t_EIS : tuple EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min': f_min = 10**f_power_min, the power of the final frequency 'f_power_max', the number of frequencies tested 'nb_f' and the number of points calculated per specific period 'nb_points'. t_purge : tuple Time parameters for purging the system. It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. max_step : float Maximum time step for the solver. n_gdl : int Number of points considered in the GDL. i_exp : numpy.ndarray Experimental values of the current density. U_exp : numpy.ndarray Experimental values of the voltage. \"\"\" if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": # Given values by the author # Operating inputs Tfc = 74 + 273.15 # K. It is the temperature of the fuel cell. Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. if type_fuel_cell == \"EH-31_1.5\": Pa_des, Pc_des = 1.5e5, 1.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.3e4 elif type_fuel_cell == \"EH-31_2.0\": Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.5e4 elif type_fuel_cell == \"EH-31_2.25\": Pa_des, Pc_des = 2.25e5, 2.25e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.85e4 else: # type_fuel_cell == \"EH-31_2.5\": Pa_des, Pc_des = 2.5e5, 2.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 3.05e4 # Fuel cell physical parameters Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Extrapolated physical parameters Hmem = 2e-5 # m. It is the thickness of the membrane. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. Hgc = 5e-4 # m. It is the thickness of the gas channel. # Algorithm parameters for polarization curve generation type_auxiliary = \"forced-convective_cathode_with_flow-through_anode\" type_control = \"no_control\" type_purge = \"no_purge\" type_display = \"multiple\" type_plot = \"final\" type_current = \"polarization\" current_density = polarization_current t_step = np.nan, np.nan, np.nan, np.nan # It is the time parameters for the step_current density function. i_step = np.nan, np.nan # It is the current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 1 * 60 # It is the parameters for the polarization curve. i_EIS, ratio_EIS = np.nan, np.nan # (A/m\u00b2, ). i_EIS is the current for which a ratio_EIS perturbation is added. f_EIS, t_EIS = np.nan, np.nan # It is the EIS parameters. t_purge = 0.6, 15 # s It is the purge time and the distance between two purges. max_step = 0.05 # It is good enough for having graphs without instabilities. n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. elif type_fuel_cell == \"LF\": # Given values by the author # Operating inputs Tfc = 80 + 273.15 # K. It is the temperature of the fuel cell. Pa_des, Pc_des = 101325, 101325 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 2.0, 1.5 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.84, 0.59 # It is the desired relative humidity. i_pola = 1.45e4 # Fuel cell physical parameters Hmem = 5.08e-5 # m. It is the thickness of the membrane. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. Hgdl = 4.2e-4 # m. It is the thickness of the gas diffusion layer. Hgc = 1e-3 # m. It is the thickness of the gas channel. Wgc = 8e-4 # m. It is the width of the gas channel. # Extrapolated physical parameters Aact = 0.0025 # m\u00b2. It is the active area of the catalyst layer. Lgc = 1.6 # m. It is the length of the gas channel. # Algorithm parameters for polarization curve generation type_auxiliary = \"forced-convective_cathode_with_anodic_recirculation\" type_control = \"no_control\" type_purge = \"no_purge\" type_display = \"no_display\" type_plot = \"final\" type_current = \"polarization\" current_density = polarization_current t_step = np.nan # It is the time parameters for the step_current density function. i_step = np.nan, np.nan # It is the current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 60 * 60 # It is the parameters for the polarization curve. i_EIS, ratio_EIS = np.nan, np.nan # (A/m\u00b2, ). i_EIS is the current for which a ratio_EIS perturbation is added. f_EIS, t_EIS = np.nan, np.nan # It is the EIS parameters. t_purge = 0.6, 15 # s It is the purge time and the distance between two purges. max_step = 0.05 # It is good enough for having graphs without instabilities. n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. else: ValueError(\"A correct type_fuel_cell should be given.\") # Characteristic points of the experimental polarization curve i_exp, U_exp = pola_exp_values(type_fuel_cell) return (Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_pola, Aact, Hmem, Hcl, Hgdl, Hgc, Wgc, Lgc, type_auxiliary, type_control, type_purge, type_display, type_plot, type_current, current_density, t_step, i_step, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, t_purge, max_step, n_gdl, i_exp, U_exp) print_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error) This function is used to print the calibration results. Parameters: convergence ( dict ) \u2013 A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. epsilon_c ( float ) \u2013 Compression ratio of the GDL. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. Source code in modules/calibration_modules.py def print_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error): \"\"\"This function is used to print the calibration results. Parameters ---------- convergence : dict A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. epsilon_c : float Compression ratio of the GDL. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. \"\"\" print(\"The convergence is:\\n\", convergence) print(\"\\nThe optimized epsilon_gdl: \", epsilon_gdl) print(\"The optimized epsilon_mc: \", epsilon_mc) print(\"The optimized tau: \", tau) print(\"The optimized epsilon_c: \", epsilon_c) print(\"The optimized e: \", e) print(\"The optimized Re: \", Re) print(\"The optimized i0_c_ref: \", i0_c_ref) print(\"The optimized kappa_co: \", kappa_co) print(\"The optimized kappa_c: \", kappa_c) print(\"The optimized a_slim: \", a_slim) print(\"The optimized b_slim: \", b_slim) print(\"The optimized a_switch: \", a_switch) print(Fore.RED + \"\\nThe max simulation error is: \", sim_error, \"%\") print(Style.RESET_ALL) save_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error, type_fuel_cell) This function is used to save in a text file the calibration results. Parameters: convergence ( dict ) \u2013 A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. epsilon_c ( float ) \u2013 Compression ratio of the GDL. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Source code in modules/calibration_modules.py def save_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error, type_fuel_cell): \"\"\"This function is used to save in a text file the calibration results. Parameters ---------- convergence : dict A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. epsilon_c : float Compression ratio of the GDL. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. type_fuel_cell : str Type of fuel cell configuration. \"\"\" root_folder, filename = \"results\", \"parameter_calibration_1.txt\" subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 else type_fuel_cell counter = 1 # Create the folder if necessary folder_name = os.path.join(root_folder, subfolder_name) if not os.path.exists(folder_name): os.makedirs(folder_name) # Create the file without erasing the previous ones while os.path.isfile(os.path.join(folder_name, filename)): counter += 1 filename = \"parameter_calibration_\" + str(counter) + \".txt\" # Write information file_path = os.path.join(folder_name, filename) with open(file_path, \"w\") as file: file.write(\"The convergence is: \" + str(convergence) + \"\\nThe optimized epsilon_gdl: \" + str(epsilon_gdl) + \"\\nThe optimized epsilon_mc: \" + str(epsilon_mc) + \"\\nThe optimized tau: \" + str(tau) + \"\\nThe optimized epsilon_c: \" + str(epsilon_c) + \"\\nThe optimized e: \" + str(e) + \"\\nThe optimized Re: \" + str(Re) + \"\\nThe optimized i0_c_ref: \" + str(i0_c_ref) + \"\\nThe optimized kappa_co: \" + str(kappa_co) + \"\\nThe optimized kappa_c: \" + str(kappa_c) + \"\\nThe optimized a_slim: \" + str(a_slim) + \"\\nThe optimized b_slim: \" + str(b_slim) + \"\\nThe optimized a_switch: \" + str(a_switch) + \"\\nThe max simulation error is: \" + str(sim_error) + \"%\" + \"\\nHere the algorithm works with RG2&3 (global)\")","title":"Calibration modules"},{"location":"functions/modules/calibration_modules/#calibration-modules","text":"This module contains some of the functions required for the parameter calibration.","title":"Calibration modules"},{"location":"functions/modules/calibration_modules/#modules.calibration_modules.calculate_simulation_error","text":"This function is used to calculate the simulation maximal error between the experimental and the simulated polarization curves. Two simulations on different operating conditions and on the same stack, and so two set of experimental data, are considered as it is the minimum amount of data which is required for the calibration. Parameters: Simulator1 ( AlphaPEM object ) \u2013 PEM simulator which contains the simulation results for the first simulation. U_exp1 ( ndarray ) \u2013 Experimental values of the voltage for the first simulation. i_exp1 ( ndarray ) \u2013 Experimental values of the current density for the first simulation. Simulator2 ( AlphaPEM object ) \u2013 PEM simulator which contains the simulation results for the second simulation. U_exp2 ( ndarray ) \u2013 Experimental values of the voltage for the second simulation. i_exp2 ( ndarray ) \u2013 Experimental values of the current density for the second simulation. Returns: sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. Source code in modules/calibration_modules.py def calculate_simulation_error(Simulator1, U_exp1, i_exp1, Simulator2, U_exp2, i_exp2): \"\"\"This function is used to calculate the simulation maximal error between the experimental and the simulated polarization curves. Two simulations on different operating conditions and on the same stack, and so two set of experimental data, are considered as it is the minimum amount of data which is required for the calibration. Parameters ---------- Simulator1 : AlphaPEM object PEM simulator which contains the simulation results for the first simulation. U_exp1 : numpy.ndarray Experimental values of the voltage for the first simulation. i_exp1 : numpy.ndarray Experimental values of the current density for the first simulation. Simulator2 : AlphaPEM object PEM simulator which contains the simulation results for the second simulation. U_exp2 : numpy.ndarray Experimental values of the voltage for the second simulation. i_exp2 : numpy.ndarray Experimental values of the current density for the second simulation. Returns ------- sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. \"\"\" # Recovery of ifc_1 t1 = np.array(Simulator1.variables['t']) n1 = len(t1) ifc_t_1 = np.zeros(n1) for i in range(n1): # Creation of ifc_t and conversion in A/cm\u00b2 ifc_t_1[i] = Simulator1.operating_inputs['current_density'](t1[i], Simulator1.parameters) / 1e4 # Recovery of ifc_2 t2 = np.array(Simulator2.variables['t']) n2 = len(t2) ifc_t_2 = np.zeros(n2) for i in range(n2): # Creation of ifc_t and conversion in A/cm\u00b2 ifc_t_2[i] = Simulator2.operating_inputs['current_density'](t2[i], Simulator2.parameters) / 1e4 # Polarisation curve point recovery after stack stabilisation for Simulator1 delta_t_load, delta_t_break, delta_i, delta_t_ini = Simulator1.parameters['delta_pola'] nb_loads1 = int(Simulator1.parameters['i_pola'] / delta_i + 1) # Number of load which are made ifc_discretized1 = np.zeros(nb_loads1) Ucell_discretized1 = np.zeros(nb_loads1) for i in range(nb_loads1): t_load = delta_t_ini + (i + 1) * (delta_t_load + delta_t_break) - delta_t_break / 10 # time for the measurement idx1 = (np.abs(t1 - t_load)).argmin() # the corresponding index ifc_discretized1[i] = ifc_t_1[idx1] # the last value at the end of each load Ucell_discretized1[i] = Simulator1.variables['Ucell'][idx1] # the last value at the end of each load # Polarisation curve point recovery after stack stabilisation for Simulator2 delta_t_load, delta_t_break, delta_i, delta_t_ini = Simulator2.parameters['delta_pola'] nb_loads2 = int(Simulator2.parameters['i_pola'] / delta_i + 1) # Number of load which are made ifc_discretized2 = np.zeros(nb_loads2) Ucell_discretized2 = np.zeros(nb_loads2) for i in range(nb_loads2): t_load = delta_t_ini + (i + 1) * (delta_t_load + delta_t_break) - delta_t_break / 10 # time for the measurement idx2 = (np.abs(t2 - t_load)).argmin() # the corresponding index ifc_discretized2[i] = ifc_t_2[idx2] # the last value at the end of each load Ucell_discretized2[i] = Simulator2.variables['Ucell'][idx2] # the last value at the end of each load # Interpolation of experimental points to match model points for Simulator 1 i_fc_reduced1 = ifc_discretized1[(ifc_discretized1 >= i_exp1[0]) & (ifc_discretized1 <= i_exp1[-1])] Ucell_reduced1 = Ucell_discretized1[(ifc_discretized1 >= i_exp1[0]) & (ifc_discretized1 <= i_exp1[-1])] U_exp_interpolated1 = interp1d(i_exp1, U_exp1, kind='linear')(i_fc_reduced1) # Interpolation of experimental points to match model points for Simulator 2 i_fc_reduced2 = ifc_discretized2[(ifc_discretized2 >= i_exp2[0]) & (ifc_discretized2 <= i_exp2[-1])] Ucell_reduced2 = Ucell_discretized2[(ifc_discretized2 >= i_exp2[0]) & (ifc_discretized2 <= i_exp2[-1])] U_exp_interpolated2 = interp1d(i_exp2, U_exp2, kind='linear')(i_fc_reduced2) # Distance between the simulated and the experimental polarization curves. if np.isnan(Ucell_reduced1).any() or np.isnan(Ucell_reduced2).any(): sim_error = 1e5 # If the mass loss arrives before i_exp[-1], some value would be equal to NaN. else: sim_error = (np.max(np.abs(Ucell_reduced1 - U_exp_interpolated1) / U_exp_interpolated1 * 100) + np.max(np.abs(Ucell_reduced2 - U_exp_interpolated2) / U_exp_interpolated2 * 100)) / 2 # in %. return sim_error","title":"calculate_simulation_error"},{"location":"functions/modules/calibration_modules/#modules.calibration_modules.determined_parameters","text":"This function is used to determine the parameters of the fuel cell model for the calibration when a registered type_fuel_cell is considered. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_pola ( float ) \u2013 Maximum current density for the polarization curve. Aact ( float ) \u2013 Active area of the cell in m\u00b2. Hmem ( float ) \u2013 Thickness of the membrane in m. Hcl ( float ) \u2013 Thickness of the catalyst layer in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Wgc ( float ) \u2013 Width of the gas channel in m. Lgc ( float ) \u2013 Length of the gas channel in m. type_auxiliary ( str ) \u2013 Type of auxiliary system. type_control ( str ) \u2013 Type of control system. type_purge ( str ) \u2013 Type of purge system. type_display ( str ) \u2013 Type of display. type_plot ( str ) \u2013 Type of plot. type_current ( str ) \u2013 Type of current density function. current_density ( function ) \u2013 Current density evolution over time. It is a function of time and parameters dictionary. t_step ( tuple ) \u2013 Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load' and dynamic time for display 'delta_t_dyn'. i_step ( tuple ) \u2013 Current parameters for the step_current density function. It is a tuple containing the initial and final current density value 'i_ini' and 'i_final'. delta_pola ( tuple ) \u2013 Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load', the breaking time 'delta_t_break', the current density step 'delta_i', and the initial breaking time 'delta_t_ini'. i_EIS ( float ) \u2013 Current for which a ratio_EIS perturbation is added. ratio_EIS ( float ) \u2013 Value of the perturbation on the current density for building the EIS curve. t_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min': f_min = 10**f_power_min, the power of the final frequency 'f_power_max', the number of frequencies tested 'nb_f' and the number of points calculated per specific period 'nb_points'. t_purge ( tuple ) \u2013 Time parameters for purging the system. It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. max_step ( float ) \u2013 Maximum time step for the solver. n_gdl ( int ) \u2013 Number of points considered in the GDL. i_exp ( ndarray ) \u2013 Experimental values of the current density. U_exp ( ndarray ) \u2013 Experimental values of the voltage. Source code in modules/calibration_modules.py def determined_parameters(type_fuel_cell): \"\"\"This function is used to determine the parameters of the fuel cell model for the calibration when a registered type_fuel_cell is considered. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_pola : float Maximum current density for the polarization curve. Aact : float Active area of the cell in m\u00b2. Hmem : float Thickness of the membrane in m. Hcl : float Thickness of the catalyst layer in m. Hgc : float Thickness of the gas channel in m. Wgc : float Width of the gas channel in m. Lgc : float Length of the gas channel in m. type_auxiliary : str Type of auxiliary system. type_control : str Type of control system. type_purge : str Type of purge system. type_display : str Type of display. type_plot : str Type of plot. type_current : str Type of current density function. current_density : function Current density evolution over time. It is a function of time and parameters dictionary. t_step : tuple Time parameters for the step_current density function. It is a tuple containing the initial time 't0_step', final time 'tf_step', loading time 'delta_t_load' and dynamic time for display 'delta_t_dyn'. i_step : tuple Current parameters for the step_current density function. It is a tuple containing the initial and final current density value 'i_ini' and 'i_final'. delta_pola : tuple Parameters for the polarization curve. It is a tuple containing the loading time 'delta_t_load', the breaking time 'delta_t_break', the current density step 'delta_i', and the initial breaking time 'delta_t_ini'. i_EIS : float Current for which a ratio_EIS perturbation is added. ratio_EIS : float Value of the perturbation on the current density for building the EIS curve. t_EIS : tuple EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. f_EIS : tuple EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min': f_min = 10**f_power_min, the power of the final frequency 'f_power_max', the number of frequencies tested 'nb_f' and the number of points calculated per specific period 'nb_points'. t_purge : tuple Time parameters for purging the system. It is the purge time interval 'purge_time' and the time between two purges 'delta_purge'. max_step : float Maximum time step for the solver. n_gdl : int Number of points considered in the GDL. i_exp : numpy.ndarray Experimental values of the current density. U_exp : numpy.ndarray Experimental values of the voltage. \"\"\" if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": # Given values by the author # Operating inputs Tfc = 74 + 273.15 # K. It is the temperature of the fuel cell. Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. if type_fuel_cell == \"EH-31_1.5\": Pa_des, Pc_des = 1.5e5, 1.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.3e4 elif type_fuel_cell == \"EH-31_2.0\": Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.5e4 elif type_fuel_cell == \"EH-31_2.25\": Pa_des, Pc_des = 2.25e5, 2.25e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 2.85e4 else: # type_fuel_cell == \"EH-31_2.5\": Pa_des, Pc_des = 2.5e5, 2.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). i_pola = 3.05e4 # Fuel cell physical parameters Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Extrapolated physical parameters Hmem = 2e-5 # m. It is the thickness of the membrane. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. Hgc = 5e-4 # m. It is the thickness of the gas channel. # Algorithm parameters for polarization curve generation type_auxiliary = \"forced-convective_cathode_with_flow-through_anode\" type_control = \"no_control\" type_purge = \"no_purge\" type_display = \"multiple\" type_plot = \"final\" type_current = \"polarization\" current_density = polarization_current t_step = np.nan, np.nan, np.nan, np.nan # It is the time parameters for the step_current density function. i_step = np.nan, np.nan # It is the current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 1 * 60 # It is the parameters for the polarization curve. i_EIS, ratio_EIS = np.nan, np.nan # (A/m\u00b2, ). i_EIS is the current for which a ratio_EIS perturbation is added. f_EIS, t_EIS = np.nan, np.nan # It is the EIS parameters. t_purge = 0.6, 15 # s It is the purge time and the distance between two purges. max_step = 0.05 # It is good enough for having graphs without instabilities. n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. elif type_fuel_cell == \"LF\": # Given values by the author # Operating inputs Tfc = 80 + 273.15 # K. It is the temperature of the fuel cell. Pa_des, Pc_des = 101325, 101325 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 2.0, 1.5 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.84, 0.59 # It is the desired relative humidity. i_pola = 1.45e4 # Fuel cell physical parameters Hmem = 5.08e-5 # m. It is the thickness of the membrane. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. Hgdl = 4.2e-4 # m. It is the thickness of the gas diffusion layer. Hgc = 1e-3 # m. It is the thickness of the gas channel. Wgc = 8e-4 # m. It is the width of the gas channel. # Extrapolated physical parameters Aact = 0.0025 # m\u00b2. It is the active area of the catalyst layer. Lgc = 1.6 # m. It is the length of the gas channel. # Algorithm parameters for polarization curve generation type_auxiliary = \"forced-convective_cathode_with_anodic_recirculation\" type_control = \"no_control\" type_purge = \"no_purge\" type_display = \"no_display\" type_plot = \"final\" type_current = \"polarization\" current_density = polarization_current t_step = np.nan # It is the time parameters for the step_current density function. i_step = np.nan, np.nan # It is the current parameters for the step_current density function. delta_pola = 30, 30, 0.1e4, 60 * 60 # It is the parameters for the polarization curve. i_EIS, ratio_EIS = np.nan, np.nan # (A/m\u00b2, ). i_EIS is the current for which a ratio_EIS perturbation is added. f_EIS, t_EIS = np.nan, np.nan # It is the EIS parameters. t_purge = 0.6, 15 # s It is the purge time and the distance between two purges. max_step = 0.05 # It is good enough for having graphs without instabilities. n_gdl = int(Hgdl / Hcl / 2) # It is the number of model points placed inside each GDL. else: ValueError(\"A correct type_fuel_cell should be given.\") # Characteristic points of the experimental polarization curve i_exp, U_exp = pola_exp_values(type_fuel_cell) return (Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_pola, Aact, Hmem, Hcl, Hgdl, Hgc, Wgc, Lgc, type_auxiliary, type_control, type_purge, type_display, type_plot, type_current, current_density, t_step, i_step, delta_pola, i_EIS, ratio_EIS, t_EIS, f_EIS, t_purge, max_step, n_gdl, i_exp, U_exp)","title":"determined_parameters"},{"location":"functions/modules/calibration_modules/#modules.calibration_modules.print_calibration_results","text":"This function is used to print the calibration results. Parameters: convergence ( dict ) \u2013 A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. epsilon_c ( float ) \u2013 Compression ratio of the GDL. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. Source code in modules/calibration_modules.py def print_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error): \"\"\"This function is used to print the calibration results. Parameters ---------- convergence : dict A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. epsilon_c : float Compression ratio of the GDL. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. \"\"\" print(\"The convergence is:\\n\", convergence) print(\"\\nThe optimized epsilon_gdl: \", epsilon_gdl) print(\"The optimized epsilon_mc: \", epsilon_mc) print(\"The optimized tau: \", tau) print(\"The optimized epsilon_c: \", epsilon_c) print(\"The optimized e: \", e) print(\"The optimized Re: \", Re) print(\"The optimized i0_c_ref: \", i0_c_ref) print(\"The optimized kappa_co: \", kappa_co) print(\"The optimized kappa_c: \", kappa_c) print(\"The optimized a_slim: \", a_slim) print(\"The optimized b_slim: \", b_slim) print(\"The optimized a_switch: \", a_switch) print(Fore.RED + \"\\nThe max simulation error is: \", sim_error, \"%\") print(Style.RESET_ALL)","title":"print_calibration_results"},{"location":"functions/modules/calibration_modules/#modules.calibration_modules.save_calibration_results","text":"This function is used to save in a text file the calibration results. Parameters: convergence ( dict ) \u2013 A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. epsilon_c ( float ) \u2013 Compression ratio of the GDL. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error ( float ) \u2013 Maximum error between the experimental and the simulated polarization curves in percentage. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Source code in modules/calibration_modules.py def save_calibration_results(convergence, epsilon_gdl, epsilon_mc, tau, epsilon_c, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, sim_error, type_fuel_cell): \"\"\"This function is used to save in a text file the calibration results. Parameters ---------- convergence : dict A dictionary generated by the GeneticAlgorithm2 model's report method. It contains information about the convergence of the genetic algorithm used for optimizing the undetermined parameters in the calibration files. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. epsilon_c : float Compression ratio of the GDL. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. sim_error : float Maximum error between the experimental and the simulated polarization curves in percentage. type_fuel_cell : str Type of fuel cell configuration. \"\"\" root_folder, filename = \"results\", \"parameter_calibration_1.txt\" subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 else type_fuel_cell counter = 1 # Create the folder if necessary folder_name = os.path.join(root_folder, subfolder_name) if not os.path.exists(folder_name): os.makedirs(folder_name) # Create the file without erasing the previous ones while os.path.isfile(os.path.join(folder_name, filename)): counter += 1 filename = \"parameter_calibration_\" + str(counter) + \".txt\" # Write information file_path = os.path.join(folder_name, filename) with open(file_path, \"w\") as file: file.write(\"The convergence is: \" + str(convergence) + \"\\nThe optimized epsilon_gdl: \" + str(epsilon_gdl) + \"\\nThe optimized epsilon_mc: \" + str(epsilon_mc) + \"\\nThe optimized tau: \" + str(tau) + \"\\nThe optimized epsilon_c: \" + str(epsilon_c) + \"\\nThe optimized e: \" + str(e) + \"\\nThe optimized Re: \" + str(Re) + \"\\nThe optimized i0_c_ref: \" + str(i0_c_ref) + \"\\nThe optimized kappa_co: \" + str(kappa_co) + \"\\nThe optimized kappa_c: \" + str(kappa_c) + \"\\nThe optimized a_slim: \" + str(a_slim) + \"\\nThe optimized b_slim: \" + str(b_slim) + \"\\nThe optimized a_switch: \" + str(a_switch) + \"\\nThe max simulation error is: \" + str(sim_error) + \"%\" + \"\\nHere the algorithm works with RG2&3 (global)\")","title":"save_calibration_results"},{"location":"functions/modules/dif_eq_modules/","text":"Differential equations modules This module is used to determine intermediate values for the calculation of the differential equations and to implement integration events. desired_flows(solver_variables, control_variables, i_n, i_fc, operating_inputs, parameters, Mext) This function calculates the desired flow for the air compressor and the humidifiers. These desired flow are different from the real ones as the corresponding machines takes time to reach the desired values. Parameters: solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. i_n ( float ) \u2013 Internal current density (A/m\u00b2). i_fc ( float ) \u2013 Fuel cell current density (A/m\u00b2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Returns: Wcp_des ( float ) \u2013 Desired air compressor flow rate (kg/s). Wa_inj_des ( float ) \u2013 Desired humidifier flow rate at the anode side (kg/s). Wc_inj_des ( float ) \u2013 Desired humidifier flow rate at the cathode side (kg/s). Source code in modules/dif_eq_modules.py def desired_flows(solver_variables, control_variables, i_n, i_fc, operating_inputs, parameters, Mext): \"\"\" This function calculates the desired flow for the air compressor and the humidifiers. These desired flow are different from the real ones as the corresponding machines takes time to reach the desired values. Parameters ---------- solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. i_n : float Internal current density (A/m\u00b2). i_fc : float Fuel cell current density (A/m\u00b2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Mext : float Molar mass of the ambient air outside the stack (kg/mol). Returns ------- Wcp_des : float Desired air compressor flow rate (kg/s). Wa_inj_des : float Desired humidifier flow rate at the anode side (kg/s). Wc_inj_des : float Desired humidifier flow rate at the cathode side (kg/s). \"\"\" # Extraction of the variables Pasm, Pcsm, Wcp = solver_variables['Pasm'], solver_variables['Pcsm'], solver_variables['Wcp'] # Extraction of the operating inputs and the parameters Tfc, Sa, Sc = operating_inputs['Tfc'], operating_inputs['Sa'], operating_inputs['Sc'] Phi_a_des, Phi_c_des = control_variables['Phi_a_des'], control_variables['Phi_c_des'] Aact, type_auxiliary = parameters['Aact'], parameters['type_auxiliary'] if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Intermediate values Prd = Pasm Pcp = Pcsm # The desired air compressor flow rate Wcp_des (kg.s-1) Wcp_des = n_cell * Mext * Pext / (Pext - Phi_ext * Psat(Text)) * \\ 1 / yO2_ext * Sc * (i_fc + i_n) / (4 * F) * Aact # The desired humidifier flow rate at the anode side Wa_v_inj_des (kg.s-1) Wrd = n_cell * M_H2 * Sa * (i_fc + i_n) / (2 * F) * Aact Wa_inj_des = (M_H2O * Phi_a_des * Psat(Tfc) / (Prd + Phi_a_des * Psat(Tfc)) / (1 - Phi_a_des * Psat(Tfc) / (Prd + Phi_a_des * Psat(Tfc))) * (Wrd / M_H2)) # The desired humidifier flow rate at the cathode side Wc_inj_des (kg.s-1) Wv_hum_in = M_H2O * Phi_ext * Psat(Text) / Pext * (Wcp / Mext) # Vapor flow rate from the outside Wc_v_des = M_H2O * Phi_c_des * Psat(Tfc) / Pcp * (Wcp / Mext) # Desired vapor flow rate Wc_inj_des = Wc_v_des - Wv_hum_in # Desired humidifier flow rate else: # elif type_auxiliary == \"no_auxiliary\": Wcp_des, Wa_inj_des, Wc_inj_des = 0, 0, 0 return Wcp_des, Wa_inj_des, Wc_inj_des dif_eq_int_values(solver_variables, control_variables, operating_inputs, parameters) This functions calculates intermediate values for the calculation of the differential equations Parameters: solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). i_n ( float ) \u2013 Internal current density (A/m\u00b2). Masm ( float ) \u2013 Molar mass of all the gas species in the anode supply manifold (kg/mol). Maem ( float ) \u2013 Molar mass of all the gas species in the anode external manifold (kg/mol). Mcsm ( float ) \u2013 Molar mass of all the gas species in the cathode supply manifold (kg/mol). Mcem ( float ) \u2013 Molar mass of all the gas species in the cathode external manifold (kg/mol). rho_H2O(Tfc) : float \u2013 Density of water vapor at the fuel cell temperature (kg/m\u00b3). Source code in modules/dif_eq_modules.py def dif_eq_int_values(solver_variables, control_variables, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the calculation of the differential equations Parameters ---------- solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Mext : float Molar mass of the ambient air outside the stack (kg/mol). Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). i_n : float Internal current density (A/m\u00b2). Masm : float Molar mass of all the gas species in the anode supply manifold (kg/mol). Maem : float Molar mass of all the gas species in the anode external manifold (kg/mol). Mcsm : float Molar mass of all the gas species in the cathode supply manifold (kg/mol). Mcem : float Molar mass of all the gas species in the cathode external manifold (kg/mol). rho_H2O(Tfc) : float Density of water vapor at the fuel cell temperature (kg/m\u00b3). \"\"\" # Extraction of the variables C_v_agc, C_v_cgc = solver_variables['C_v_agc'], solver_variables['C_v_cgc'] C_H2_agc, C_H2_acl = solver_variables['C_H2_agc'], solver_variables['C_H2_acl'] C_O2_ccl, C_O2_cgc, C_N2 = solver_variables['C_O2_ccl'], solver_variables['C_O2_cgc'], solver_variables['C_N2'] lambda_mem, Pasm = solver_variables['lambda_mem'], solver_variables['Pasm'] Paem, Pcsm, Pcem = solver_variables['Paem'], solver_variables['Pcsm'], solver_variables['Pcem'] # Extraction of the operating inputs and the parameters Tfc, Phi_c_des = operating_inputs['Tfc'], control_variables['Phi_c_des'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] # Physical quantities outside the stack # Molar masses Mext = Phi_ext * Psat(Text) / Pext * M_H2O + \\ yO2_ext * (1 - Phi_ext * Psat(Text) / Pext) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_ext * Psat(Text) / Pext) * M_N2 # Physical quantities inside the stack # Pressures Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Humidities Phi_agc = C_v_agc / C_v_sat(Tfc) Phi_cgc = C_v_cgc / C_v_sat(Tfc) # Oxygen ratio in dry air y_c = C_O2_cgc / (C_O2_cgc + C_N2) # Internal current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # Physical quantities inside the auxiliary system if parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_anodic_recirculation\" or \\ parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_flow-through_anode\": # Pressure Pp = Pasm # Humidities Phi_aem = Phi_agc * Paem / Pagc Phi_asm = Phi_aem * Pp / Paem Phi_cem = Phi_cgc * Pcem / Pcgc # Molar masses Masm = Phi_asm * Psat(Tfc) / Pasm * M_H2O + \\ (1 - Phi_asm * Psat(Tfc) / Pasm) * M_H2 Maem = Phi_aem * Psat(Tfc) / Paem * M_H2O + \\ (1 - Phi_aem * Psat(Tfc) / Paem) * M_H2 Mcsm = Phi_c_des * Psat(Tfc) / Pcsm * M_H2O + \\ yO2_ext * (1 - Phi_c_des * Psat(Tfc) / Pcsm) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_c_des * Psat(Tfc) / Pcsm) * M_N2 Mcem = Phi_cem * Psat(Tfc) / Pcem * M_H2O + \\ y_c * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_O2 + \\ (1 - y_c) * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_N2 else: # parameters[\"type_auxiliary\"] == \"no_auxiliary\" Masm, Maem, Mcsm, Mcem = [0] * 4 return Mext, Pagc, Pcgc, i_n, Masm, Maem, Mcsm, Mcem, rho_H2O(Tfc) event_negative(t, y, operating_inputs, parameters, solver_variable_names, control_variables) This function creates an event that will be checked at each step of solve_ivp integration. The integration stops if one of the crucial variables (C_v, lambda, C_O2, C_H2) becomes negative (or smaller than 1e-5). Parameters: t ( float ) \u2013 Time (s). y ( ndarray ) \u2013 Numpy list of the solver variables. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. solver_variable_names ( list ) \u2013 Names of the solver variables. control_variables ( dict ) \u2013 Variables controlled by the user. Returns: The difference between the minimum value of the crucial variables and 1e-5. \u2013 Source code in modules/dif_eq_modules.py def event_negative(t, y, operating_inputs, parameters, solver_variable_names, control_variables): \"\"\"This function creates an event that will be checked at each step of solve_ivp integration. The integration stops if one of the crucial variables (C_v, lambda, C_O2, C_H2) becomes negative (or smaller than 1e-5). Parameters ---------- t : float Time (s). y : numpy.ndarray Numpy list of the solver variables. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. solver_variable_names : list Names of the solver variables. control_variables : dict Variables controlled by the user. Returns ------- The difference between the minimum value of the crucial variables and 1e-5. \"\"\" negative_solver_variables = {} # Dictionary to store the crucial variables for index, key in enumerate(solver_variable_names): if (key.startswith(\"C_v_\")) or (key.startswith(\"lambda_\")) or \\ (key.startswith(\"C_O2_\")) or (key.startswith(\"C_H2_\")): negative_solver_variables[key] = y[index] return min(negative_solver_variables.values()) - 1e-5 # 1e-5 is a control parameter to stop the program before","title":"Differential equations modules"},{"location":"functions/modules/dif_eq_modules/#differential-equations-modules","text":"This module is used to determine intermediate values for the calculation of the differential equations and to implement integration events.","title":"Differential equations modules"},{"location":"functions/modules/dif_eq_modules/#modules.dif_eq_modules.desired_flows","text":"This function calculates the desired flow for the air compressor and the humidifiers. These desired flow are different from the real ones as the corresponding machines takes time to reach the desired values. Parameters: solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. i_n ( float ) \u2013 Internal current density (A/m\u00b2). i_fc ( float ) \u2013 Fuel cell current density (A/m\u00b2). operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Returns: Wcp_des ( float ) \u2013 Desired air compressor flow rate (kg/s). Wa_inj_des ( float ) \u2013 Desired humidifier flow rate at the anode side (kg/s). Wc_inj_des ( float ) \u2013 Desired humidifier flow rate at the cathode side (kg/s). Source code in modules/dif_eq_modules.py def desired_flows(solver_variables, control_variables, i_n, i_fc, operating_inputs, parameters, Mext): \"\"\" This function calculates the desired flow for the air compressor and the humidifiers. These desired flow are different from the real ones as the corresponding machines takes time to reach the desired values. Parameters ---------- solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. i_n : float Internal current density (A/m\u00b2). i_fc : float Fuel cell current density (A/m\u00b2). operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Mext : float Molar mass of the ambient air outside the stack (kg/mol). Returns ------- Wcp_des : float Desired air compressor flow rate (kg/s). Wa_inj_des : float Desired humidifier flow rate at the anode side (kg/s). Wc_inj_des : float Desired humidifier flow rate at the cathode side (kg/s). \"\"\" # Extraction of the variables Pasm, Pcsm, Wcp = solver_variables['Pasm'], solver_variables['Pcsm'], solver_variables['Wcp'] # Extraction of the operating inputs and the parameters Tfc, Sa, Sc = operating_inputs['Tfc'], operating_inputs['Sa'], operating_inputs['Sc'] Phi_a_des, Phi_c_des = control_variables['Phi_a_des'], control_variables['Phi_c_des'] Aact, type_auxiliary = parameters['Aact'], parameters['type_auxiliary'] if type_auxiliary == \"forced-convective_cathode_with_anodic_recirculation\" or \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Intermediate values Prd = Pasm Pcp = Pcsm # The desired air compressor flow rate Wcp_des (kg.s-1) Wcp_des = n_cell * Mext * Pext / (Pext - Phi_ext * Psat(Text)) * \\ 1 / yO2_ext * Sc * (i_fc + i_n) / (4 * F) * Aact # The desired humidifier flow rate at the anode side Wa_v_inj_des (kg.s-1) Wrd = n_cell * M_H2 * Sa * (i_fc + i_n) / (2 * F) * Aact Wa_inj_des = (M_H2O * Phi_a_des * Psat(Tfc) / (Prd + Phi_a_des * Psat(Tfc)) / (1 - Phi_a_des * Psat(Tfc) / (Prd + Phi_a_des * Psat(Tfc))) * (Wrd / M_H2)) # The desired humidifier flow rate at the cathode side Wc_inj_des (kg.s-1) Wv_hum_in = M_H2O * Phi_ext * Psat(Text) / Pext * (Wcp / Mext) # Vapor flow rate from the outside Wc_v_des = M_H2O * Phi_c_des * Psat(Tfc) / Pcp * (Wcp / Mext) # Desired vapor flow rate Wc_inj_des = Wc_v_des - Wv_hum_in # Desired humidifier flow rate else: # elif type_auxiliary == \"no_auxiliary\": Wcp_des, Wa_inj_des, Wc_inj_des = 0, 0, 0 return Wcp_des, Wa_inj_des, Wc_inj_des","title":"desired_flows"},{"location":"functions/modules/dif_eq_modules/#modules.dif_eq_modules.dif_eq_int_values","text":"This functions calculates intermediate values for the calculation of the differential equations Parameters: solver_variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables ( dict ) \u2013 Variables controlled by the user. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Mext ( float ) \u2013 Molar mass of the ambient air outside the stack (kg/mol). Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). i_n ( float ) \u2013 Internal current density (A/m\u00b2). Masm ( float ) \u2013 Molar mass of all the gas species in the anode supply manifold (kg/mol). Maem ( float ) \u2013 Molar mass of all the gas species in the anode external manifold (kg/mol). Mcsm ( float ) \u2013 Molar mass of all the gas species in the cathode supply manifold (kg/mol). Mcem ( float ) \u2013 Molar mass of all the gas species in the cathode external manifold (kg/mol). rho_H2O(Tfc) : float \u2013 Density of water vapor at the fuel cell temperature (kg/m\u00b3). Source code in modules/dif_eq_modules.py def dif_eq_int_values(solver_variables, control_variables, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the calculation of the differential equations Parameters ---------- solver_variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. control_variables : dict Variables controlled by the user. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Mext : float Molar mass of the ambient air outside the stack (kg/mol). Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). i_n : float Internal current density (A/m\u00b2). Masm : float Molar mass of all the gas species in the anode supply manifold (kg/mol). Maem : float Molar mass of all the gas species in the anode external manifold (kg/mol). Mcsm : float Molar mass of all the gas species in the cathode supply manifold (kg/mol). Mcem : float Molar mass of all the gas species in the cathode external manifold (kg/mol). rho_H2O(Tfc) : float Density of water vapor at the fuel cell temperature (kg/m\u00b3). \"\"\" # Extraction of the variables C_v_agc, C_v_cgc = solver_variables['C_v_agc'], solver_variables['C_v_cgc'] C_H2_agc, C_H2_acl = solver_variables['C_H2_agc'], solver_variables['C_H2_acl'] C_O2_ccl, C_O2_cgc, C_N2 = solver_variables['C_O2_ccl'], solver_variables['C_O2_cgc'], solver_variables['C_N2'] lambda_mem, Pasm = solver_variables['lambda_mem'], solver_variables['Pasm'] Paem, Pcsm, Pcem = solver_variables['Paem'], solver_variables['Pcsm'], solver_variables['Pcem'] # Extraction of the operating inputs and the parameters Tfc, Phi_c_des = operating_inputs['Tfc'], control_variables['Phi_c_des'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] # Physical quantities outside the stack # Molar masses Mext = Phi_ext * Psat(Text) / Pext * M_H2O + \\ yO2_ext * (1 - Phi_ext * Psat(Text) / Pext) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_ext * Psat(Text) / Pext) * M_N2 # Physical quantities inside the stack # Pressures Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Humidities Phi_agc = C_v_agc / C_v_sat(Tfc) Phi_cgc = C_v_cgc / C_v_sat(Tfc) # Oxygen ratio in dry air y_c = C_O2_cgc / (C_O2_cgc + C_N2) # Internal current density i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl * k_H2(lambda_mem, Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl * k_O2(lambda_mem, Tfc, kappa_co) i_n = i_H2 + i_O2 # Physical quantities inside the auxiliary system if parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_anodic_recirculation\" or \\ parameters[\"type_auxiliary\"] == \"forced-convective_cathode_with_flow-through_anode\": # Pressure Pp = Pasm # Humidities Phi_aem = Phi_agc * Paem / Pagc Phi_asm = Phi_aem * Pp / Paem Phi_cem = Phi_cgc * Pcem / Pcgc # Molar masses Masm = Phi_asm * Psat(Tfc) / Pasm * M_H2O + \\ (1 - Phi_asm * Psat(Tfc) / Pasm) * M_H2 Maem = Phi_aem * Psat(Tfc) / Paem * M_H2O + \\ (1 - Phi_aem * Psat(Tfc) / Paem) * M_H2 Mcsm = Phi_c_des * Psat(Tfc) / Pcsm * M_H2O + \\ yO2_ext * (1 - Phi_c_des * Psat(Tfc) / Pcsm) * M_O2 + \\ (1 - yO2_ext) * (1 - Phi_c_des * Psat(Tfc) / Pcsm) * M_N2 Mcem = Phi_cem * Psat(Tfc) / Pcem * M_H2O + \\ y_c * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_O2 + \\ (1 - y_c) * (1 - Phi_cem * Psat(Tfc) / Pcem) * M_N2 else: # parameters[\"type_auxiliary\"] == \"no_auxiliary\" Masm, Maem, Mcsm, Mcem = [0] * 4 return Mext, Pagc, Pcgc, i_n, Masm, Maem, Mcsm, Mcem, rho_H2O(Tfc)","title":"dif_eq_int_values"},{"location":"functions/modules/dif_eq_modules/#modules.dif_eq_modules.event_negative","text":"This function creates an event that will be checked at each step of solve_ivp integration. The integration stops if one of the crucial variables (C_v, lambda, C_O2, C_H2) becomes negative (or smaller than 1e-5). Parameters: t ( float ) \u2013 Time (s). y ( ndarray ) \u2013 Numpy list of the solver variables. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. solver_variable_names ( list ) \u2013 Names of the solver variables. control_variables ( dict ) \u2013 Variables controlled by the user. Returns: The difference between the minimum value of the crucial variables and 1e-5. \u2013 Source code in modules/dif_eq_modules.py def event_negative(t, y, operating_inputs, parameters, solver_variable_names, control_variables): \"\"\"This function creates an event that will be checked at each step of solve_ivp integration. The integration stops if one of the crucial variables (C_v, lambda, C_O2, C_H2) becomes negative (or smaller than 1e-5). Parameters ---------- t : float Time (s). y : numpy.ndarray Numpy list of the solver variables. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. solver_variable_names : list Names of the solver variables. control_variables : dict Variables controlled by the user. Returns ------- The difference between the minimum value of the crucial variables and 1e-5. \"\"\" negative_solver_variables = {} # Dictionary to store the crucial variables for index, key in enumerate(solver_variable_names): if (key.startswith(\"C_v_\")) or (key.startswith(\"lambda_\")) or \\ (key.startswith(\"C_O2_\")) or (key.startswith(\"C_H2_\")): negative_solver_variables[key] = y[index] return min(negative_solver_variables.values()) - 1e-5 # 1e-5 is a control parameter to stop the program before","title":"event_negative"},{"location":"functions/modules/display_modules/","text":"Display modules This module is used to accurately plot the figures. calculate_simulation_error(Ucell, U_exp_t) This function calculates the simulation error between the simulated cell voltage and the experimental cell voltage. It is calculated as the maximum relative difference between the two voltages (in %). Parameters: Ucell ( ndarray ) \u2013 Simulated cell voltage. U_exp_t ( ndarray ) \u2013 Experimental cell voltage. Returns: float \u2013 Simulation error between the simulated cell voltage and the experimental cell voltage (in %). Source code in modules/display_modules.py def calculate_simulation_error(Ucell, U_exp_t): \"\"\"This function calculates the simulation error between the simulated cell voltage and the experimental cell voltage. It is calculated as the maximum relative difference between the two voltages (in %). Parameters ---------- Ucell : numpy.ndarray Simulated cell voltage. U_exp_t : numpy.ndarray Experimental cell voltage. Returns ------- float Simulation error between the simulated cell voltage and the experimental cell voltage (in %). \"\"\" return np.round(np.max(np.abs(Ucell - U_exp_t) / U_exp_t * 100), 2) # in %. make_Fourier_transformation(variables, operating_inputs, parameters) This function calculates the Fourier transformation of both cell voltage and current density. It will be used to display the Nyquist and Bode diagrams. To generate it at each frequency change, the cell voltage and the current density are recorded. The time for which these points are captured is determined using the following approach: at the beginning of each frequency change, a delta_t_break_EIS time is observed to ensure the dynamic stability of the stack's variables. Subsequently, a delta_t_measurement_EIS time is needed to record the cell voltage and the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: dict \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. Source code in modules/display_modules.py def make_Fourier_transformation(variables, operating_inputs, parameters): \"\"\" This function calculates the Fourier transformation of both cell voltage and current density. It will be used to display the Nyquist and Bode diagrams. To generate it at each frequency change, the cell voltage and the current density are recorded. The time for which these points are captured is determined using the following approach: at the beginning of each frequency change, a delta_t_break_EIS time is observed to ensure the dynamic stability of the stack's variables. Subsequently, a delta_t_measurement_EIS time is needed to record the cell voltage and the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), np.array(variables['Ucell']) # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] t_EIS, max_step = parameters['t_EIS'], parameters['max_step'] # Creation of ifc ifc_t = np.zeros(len(t)) for i in range(len(t)): ifc_t[i] = current_density(t[i], parameters) # Identify the areas where Ucell and ifc can be measured for the EIS: after equilibrium and at each frequency change t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS n_inf = np.where(t_new_start_EIS <= t[0])[0][-1] # The number of frequency changes which has been mad so far. Ucell_EIS_measured = Ucell_t[np.where((t > (t[0] + delta_t_break_EIS[n_inf])) & (t < (t[0] + delta_t_break_EIS[n_inf] + delta_t_measurement_EIS[n_inf])))] ifc_EIS_measured = ifc_t[np.where((t > (t[0] + delta_t_break_EIS[n_inf])) & (t < (t[0] + delta_t_break_EIS[n_inf] + delta_t_measurement_EIS[n_inf])))] # Determination of the Fourier transformation N = Ucell_EIS_measured.size # Number of points used for the Fourier transformation Ucell_Fourier = fft(Ucell_EIS_measured) # Ucell Fourier transformation ifc_Fourier = fft(ifc_EIS_measured) # ifc Fourier transformation A_period_t = np.concatenate( ([np.abs(Ucell_Fourier)[0] / N], np.abs(Ucell_Fourier[1:N // 2]) * 2 / N)) # Recovery of # all amplitude values calculated by fft A = max(A_period_t[1:]) # Amplitude at the frequency of the perturbation freq_t = fftfreq(N, max_step)[:N // 2] # Recovery of all frequency values used by fft f = freq_t[np.argmax(A_period_t == A)] # Recovery of the studied frequency return {'Ucell_Fourier': Ucell_Fourier, 'ifc_Fourier': ifc_Fourier, 'A_period_t': A_period_t, 'A': A, 'freq_t': freq_t, 'f': f, 'N': N} plot_Bode_amplitude_instructions(f_EIS, type_fuel_cell, ax) This function adds the instructions for amplitude Bode plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_Bode_amplitude_instructions(f_EIS, type_fuel_cell, ax): \"\"\"This function adds the instructions for amplitude Bode plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. ax.set_xscale('log') # set logarithmic scale for the x-axis # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(LogLocator(base=10.0, numticks=f_power_max_EIS - f_power_min_EIS + 1)) ax.xaxis.set_minor_locator(LogLocator(base=10.0, subs=np.arange(2, 10) * .1, numticks=(f_power_max_EIS - f_power_min_EIS + 1) * len(np.arange(2, 10)))) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(30)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(30 / 5)) ax.set_xlim([10**f_power_min_EIS, 10**f_power_max_EIS]) plot_Bode_phase_instructions(f_EIS, type_fuel_cell, ax) This function adds the instructions for phase Bode plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_Bode_phase_instructions(f_EIS, type_fuel_cell, ax): \"\"\"This function adds the instructions for phase Bode plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. ax.set_xscale('log') # set logarithmic scale for the x-axis if not ax.yaxis_inverted(): ax.invert_yaxis() # Invert the y-axis # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(LogLocator(base=10.0, numticks = f_power_max_EIS-f_power_min_EIS+1)) ax.xaxis.set_minor_locator(LogLocator(base=10.0, subs=np.arange(2, 10) * .1, numticks = (f_power_max_EIS-f_power_min_EIS+1)*len(np.arange(2, 10)))) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(5 / 5)) ax.set_xlim([10**f_power_min_EIS, 10**f_power_max_EIS]) plot_C_H2(variables, n_gdl, ax) This function plots the hydrogen concentration at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. ax ( Axes ) \u2013 Axes on which the hydrogen concentration will be plotted. Source code in modules/display_modules.py def plot_C_H2(variables, n_gdl, ax): \"\"\"This function plots the hydrogen concentration at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. ax : matplotlib.axes.Axes Axes on which the hydrogen concentration will be plotted. \"\"\" # Extraction of the variables t, C_H2_agc_t = variables['t'], variables['C_H2_agc'] C_H2_agdl_t, C_H2_acl_t = variables[f'C_H2_agdl_{n_gdl // 2}'], variables['C_H2_acl'] # Plot the hydrogen concentration at different spatial localisations: C_H2 ax.plot(t, C_H2_agc_t, color=colors(0)) ax.plot(t, C_H2_agdl_t, color=colors(1)) ax.plot(t, C_H2_acl_t, color=colors(2)) ax.legend([r'$\\mathregular{C_{H_{2},agc}}$', r'$\\mathregular{C_{H_{2},agdl}}$', r'$\\mathregular{C_{H_{2},acl}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Hydrogen}$ $\\mathbf{concentration}$ $\\mathbf{C_{H_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(55, 58) plot_C_N2(variables, ax) This function plots the nitrogen concentration as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the nitrogen concentration will be plotted. Source code in modules/display_modules.py def plot_C_N2(variables, ax): \"\"\"This function plots the nitrogen concentration as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the nitrogen concentration will be plotted. \"\"\" # Extraction of the variables t, C_N2_t = variables['t'], variables['C_N2'] # Plot C_N2 ax.plot(t, C_N2_t, color=colors(6)) ax.legend([r'$\\mathregular{C_{N_{2}}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Nitrogen}$ $\\mathbf{concentration}$ $\\mathbf{C_{N_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.set_ylim(47, 49) plot_C_O2(variables, n_gdl, ax) This function plots the oxygen concentration at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. ax ( Axes ) \u2013 Axes on which the oxygen concentration will be plotted. Source code in modules/display_modules.py def plot_C_O2(variables, n_gdl, ax): \"\"\"This function plots the oxygen concentration at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. ax : matplotlib.axes.Axes Axes on which the oxygen concentration will be plotted. \"\"\" # Extraction of the variables t, C_O2_ccl_t = variables['t'], variables['C_O2_ccl'] C_O2_cgdl_t, C_O2_cgc_t = variables[f'C_O2_cgdl_{n_gdl // 2}'], variables['C_O2_cgc'] # Plot the oxygen concentration at different spatial localisations: C_O2 ax.plot(t, C_O2_ccl_t, color=colors(4)) ax.plot(t, C_O2_cgdl_t, color=colors(5)) ax.plot(t, C_O2_cgc_t, color=colors(6)) ax.legend([r'$\\mathregular{C_{O_{2},ccl}}$', r'$\\mathregular{C_{O_{2},cgdl}}$', r'$\\mathregular{C_{O_{2},cgc}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Oxygen}$ $\\mathbf{concentration}$ $\\mathbf{C_{O_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(6, 11) plot_C_v(variables, n_gdl, C_v_sat, n, ax) This function plots the vapor concentrations at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. C_v_sat ( float ) \u2013 Saturation vapor concentration. n ( int ) \u2013 Number of points used to plot the vapor concentration. ax ( Axes ) \u2013 Axes on which the vapor concentration will be plotted. Source code in modules/display_modules.py def plot_C_v(variables, n_gdl, C_v_sat, n, ax): \"\"\"This function plots the vapor concentrations at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. C_v_sat : float Saturation vapor concentration. n : int Number of points used to plot the vapor concentration. ax : matplotlib.axes.Axes Axes on which the vapor concentration will be plotted. \"\"\" # Extraction of the variables t, C_v_agc_t, C_v_agdl_t = variables['t'], variables['C_v_agc'], variables[f'C_v_agdl_{n_gdl // 2}'] C_v_acl_t, C_v_ccl_t = variables['C_v_acl'], variables['C_v_ccl'] C_v_cgdl_t, C_v_cgc_t = variables[f'C_v_cgdl_{n_gdl // 2}'], variables['C_v_cgc'] # Plot the vapor concentrations at different spatial localisations Cv C_v_sat_t = np.ones(n) * C_v_sat ax.plot(t, C_v_agc_t, color=colors(0)) ax.plot(t, C_v_agdl_t, color=colors(1)) ax.plot(t, C_v_acl_t, color=colors(2)) ax.plot(t, C_v_ccl_t, color=colors(4)) ax.plot(t, C_v_cgdl_t, color=colors(5)) ax.plot(t, C_v_cgc_t, color=colors(6)) ax.plot(t, C_v_sat_t, color='k') ax.legend([r'$\\mathregular{C_{v,agc}}$', r'$\\mathregular{C_{v,agdl}}$', r'$\\mathregular{C_{v,acl}}$', r'$\\mathregular{C_{v,ccl}}$', r'$\\mathregular{C_{v,cgdl}}$', r'$\\mathregular{C_{v,cgc}}$', r'$\\mathregular{C_{v,sat}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r\"$\\mathbf{Vapor}$ $\\mathbf{concentration}$ $\\mathbf{C_{v}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$\", labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(11, 16) plot_EIS_Nyquist_instructions(type_fuel_cell, f_Fourier, x, y, ax) This function adds the instructions for EIS plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. f_Fourier ( ndarray ) \u2013 Frequency at which the EIS is simulated. x ( ndarray ) \u2013 x-axis values for plotting the annotation. y ( ndarray ) \u2013 y-axis values for plotting the annotation. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_EIS_Nyquist_instructions(type_fuel_cell, f_Fourier, x, y, ax): \"\"\"This function adds the instructions for EIS plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. f_Fourier : numpy.ndarray Frequency at which the EIS is simulated. x : numpy.ndarray x-axis values for plotting the annotation. y : numpy.ndarray y-axis values for plotting the annotation. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions ax.set_aspect('equal', adjustable='box') # Set orthonormal axis. # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": # Double charge transfer if (f_Fourier >= 70 and f_Fourier <= 80): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, -40), ha='center', fontsize=14, rotation=90, weight='bold') # Auxiliary system if (f_Fourier >= 0.14 and f_Fourier <= 0.16): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 7), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 1.2 and f_Fourier <= 1.4): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 10), ha='center', fontsize=14, rotation=90, weight='bold') # Diffusion if (f_Fourier >= 0.015 and f_Fourier <= 0.020): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(30, 0), ha='center', fontsize=14, rotation=0, weight='bold') if (f_Fourier >= 0.9 and f_Fourier <= 1.1): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 10), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 70 and f_Fourier <= 90): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, -40), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 10000 and f_Fourier <= 12000): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(35, 0), ha='center', fontsize=14, rotation=0, weight='bold') ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(20)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(20 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(10)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(10 / 5)) ax.set_xlim(30, 200) ax.set_ylim(-25, 55) plot_EIS_curve_Bode_amplitude(parameters, Fourier_results, ax) This function is used to plot the amplitude Bode diagram of the EIS curves. Parameters: parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the amplitude Bode diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Bode_amplitude(parameters, Fourier_results, ax): \"\"\"This function is used to plot the amplitude Bode diagram of the EIS curves. Parameters ---------- parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the amplitude Bode diagram will be plotted. \"\"\" # Extraction of the parameters i_EIS, ratio_EIS, f_EIS = parameters['i_EIS'], parameters['ratio_EIS'], parameters['f_EIS'] type_fuel_cell = parameters['type_fuel_cell'] # Extraction of the Fourier results A, f = Fourier_results['A'], Fourier_results['f'] # Calculation of the impedance of the perturbation Z0 = A / (ratio_EIS * (-i_EIS)) * 1e7 # in m\u03a9.cm\u00b2. The sign of i is inverted to comply with the standards of EIS, # which measure a device under load rather than a current source. # Plot the amplitude Bode diagram ax.plot(f, np.abs(Z0), 'o', color=colors(1), label='Amplitude Bode diagram') ax.set_xlabel(r'$\\mathbf{Frequency}$ $\\mathbf{(Hz,}$ $\\mathbf{logarithmic}$ $\\mathbf{scale)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Impedance}$ $\\mathbf{amplitude}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_Bode_amplitude_instructions(f_EIS, type_fuel_cell, ax) plot_EIS_curve_Bode_angle(parameters, Fourier_results, ax) This function is used to plot the angle Bode diagram. It only works with an entry signal made with a cosinus (not a sinus). Parameters: Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the angle Bode diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Bode_angle(parameters, Fourier_results, ax): \"\"\"This function is used to plot the angle Bode diagram. It only works with an entry signal made with a cosinus (not a sinus). Parameters ---------- Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the angle Bode diagram will be plotted. \"\"\" # Extraction of the parameters f_EIS, type_fuel_cell = parameters['f_EIS'], parameters['type_fuel_cell'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] A_period_t, A = Fourier_results['A_period_t'], Fourier_results['A'] f, N = Fourier_results['f'], Fourier_results['N'] # Calculation of the dephasing values at the frequency of the perturbation theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) + np.pi # Recovery of all dephasing values calculated by fft. # An angle of pi is added to comply with the standards of EIS, # which measure a device under load rather than a current source. theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation phi_U_i = ((theta_U - theta_i) * 180 / np.pi) % 360 # Dephasing between Ucell and ifc with a value between 0 and 360 if phi_U_i > 180: phi_U_i -= 360 # To have a value between -180 and 180 # Plot the angle Bode diagram ax.plot(f, phi_U_i, 'o', color=colors(2), label='Angle Bode diagram') ax.set_xlabel(r'$\\mathbf{Frequency}$ $\\mathbf{(Hz,}$ $\\mathbf{logarithmic}$ $\\mathbf{scale)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Phase}$ $\\mathbf{(^\\circ)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_Bode_phase_instructions(f_EIS, type_fuel_cell, ax) plot_EIS_curve_Nyquist(parameters, Fourier_results, ax) This function is used to plot the Nyquist diagram of the EIS curves. Parameters: parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the Nyquist diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Nyquist(parameters, Fourier_results, ax): \"\"\" This function is used to plot the Nyquist diagram of the EIS curves. Parameters ---------- parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the Nyquist diagram will be plotted. \"\"\" # Extraction of the parameters i_EIS, ratio_EIS, type_fuel_cell = parameters['i_EIS'], parameters['ratio_EIS'], parameters['type_fuel_cell'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] f_Fourier = Fourier_results['f'] A_period_t, A, N = Fourier_results['A_period_t'], Fourier_results['A'], Fourier_results['N'] # Calculation of the real and imaginary component of the impedance for each period Z0 = A / (ratio_EIS * (-i_EIS)) * 1e7 # Impedance of the perturbation in m\u03a9.cm\u00b2. The sign of i is inverted to # comply with the standards of EIS, which measure a device under load rather than a current source. theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation Z_real = Z0 * np.cos(theta_U - theta_i) # Real component of the impedance for each period Z_imag = Z0 * np.sin(theta_U - theta_i) # Imaginary component of the impedance for each period # Plot the Nyquist diagram ax.plot(Z_real, -Z_imag, 'o', color=colors(0), label='Nyquist diagram') ax.set_xlabel(r'$\\mathbf{Z_{real}}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{-Z_{imag}}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_EIS_Nyquist_instructions(type_fuel_cell, f_Fourier, Z_real, -Z_imag, ax) plot_EIS_curve_tests(variables, operating_inputs, parameters, Fourier_results) This function is used to test the accuracy of the EIS results. It compares the reconstructed Ucell_Fourier(t) from the Fourier transformation with the current density ifc(t), and displays Ucell(t) given by the model with the reconstructed Ucell_Fourier(t). Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. Source code in modules/display_modules.py def plot_EIS_curve_tests(variables, operating_inputs, parameters, Fourier_results): \"\"\"This function is used to test the accuracy of the EIS results. It compares the reconstructed Ucell_Fourier(t) from the Fourier transformation with the current density ifc(t), and displays Ucell(t) given by the model with the reconstructed Ucell_Fourier(t). Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), variables['Ucell'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] i_EIS, ratio_EIS = parameters['i_EIS'], parameters['ratio_EIS'] t_EIS, f_EIS = parameters['t_EIS'], parameters['f_EIS'] max_step = parameters['max_step'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] A_period_t, A = Fourier_results['A_period_t'], Fourier_results['A'] f, N = Fourier_results['f'], Fourier_results['N'] # Reconstructed Ucell with a cosinus form, and comparison of its form with the current density one. t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS n_inf = np.where(t_new_start_EIS <= t[0])[0][-1] # The number of frequency changes which has been made. f_current = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation print(\"Ucell:\", round(A_period_t[0], 4), ' + ', round(A, 6), \" * np.cos(2*np.pi*\", round(f, 4), \"*t + \", round(theta_U, 4), \"). \") print(\"Current:\", i_EIS, ' + ', ratio_EIS * i_EIS, \" * np.cos(2*np.pi*\", round(f_current[n_inf], 4), \"*t + \", round(theta_i, 4), \"). \\n\") # Display ifc(t) plt.figure(3) plt.subplot(2, 1, 1) # Creation of ifc_t n = len(t) ifc_t = np.zeros(n) for i in range(n): # Conversion in A/cm\u00b2 ifc_t[i] = current_density(t[i], parameters) / 1e4 # Plot of ifc_t plt.plot(t, ifc_t, color='blue', label='ifc') plt.xlabel('Time (s)') plt.ylabel('Current density (A/cm\u00b2)') plt.title('The current density\\nbehaviour over time') # Display Ucell(t) and compare it with the reconstructed Ucell_Fourier(t) from the Fourier transformation plt.subplot(2, 1, 2) Ucell_Fourier = A_period_t[0] + A * np.cos(2 * np.pi * f * t + theta_U) plt.plot(t, Ucell_t, color='blue', label='Ucell') plt.plot(t, Ucell_Fourier, color='black', label='Ucell_Fourier') plt.xlabel('Time (s)') plt.ylabel('Cell voltage (V)') plt.title('The cell voltage\\nbehaviour over time') plot_J(variables, parameters, ax) This function plots the sorption and dissolved water flows as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the flows will be plotted. Source code in modules/display_modules.py def plot_J(variables, parameters, ax): \"\"\"This function plots the sorption and dissolved water flows as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the flows will be plotted. \"\"\" # Extraction of the variables t, S_sorp_acl_t, S_sorp_ccl_t = variables['t'], variables['S_sorp_acl'], variables['S_sorp_ccl'], J_lambda_mem_acl_t, J_lambda_mem_ccl_t = variables['J_lambda_mem_acl'], variables['J_lambda_mem_ccl'] # Extraction of the operating inputs and the parameters Hcl = parameters['Hcl'] # Plot the sorption and dissolved water flows: J J_sorp_acl, J_sorp_ccl = [x * Hcl for x in S_sorp_acl_t], [x * Hcl for x in S_sorp_ccl_t] # Conversion in # mol.m\u207b\u00b2.s\u207b\u00b9 for comparison ax.plot(t, J_sorp_acl, color=colors(2)) ax.plot(t, J_lambda_mem_acl_t, color=colors(3)) ax.plot(t, J_sorp_ccl, color=colors(4)) ax.plot(t, J_lambda_mem_ccl_t, color=colors(7)) ax.legend([r'$\\mathregular{J_{sorp,acl}}$', r'$\\mathregular{J_{\\lambda,mem,acl}}$', r'$\\mathregular{J_{sorp,ccl}}$', r'$\\mathregular{J_{\\lambda,mem,ccl}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Flows}$ $\\mathbf{J}$ $\\mathbf{\\left( mol.m^{-2}.s^{-1} \\right)}$', labelpad=3) ax.ticklabel_format(style='scientific', axis='y', scilimits=(0, 0)) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.02)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.02 / 5)) plt.show() plot_P(variables, ax) This function plots the pressure at different spatial localisations as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the pressure will be plotted. Source code in modules/display_modules.py def plot_P(variables, ax): \"\"\"This function plots the pressure at different spatial localisations as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the pressure will be plotted. \"\"\" # Extraction of the variables t, Pagc_t, Pcgc_t = variables['t'], variables['Pagc'], variables['Pcgc'] Pasm_t, Paem_t, Pcsm_t, Pcem_t = variables['Pasm'], variables['Paem'], variables['Pcsm'], variables['Pcem'] # Conversion in atm Pagc_t, Pcgc_t, Pasm_t = [x / 1e5 for x in Pagc_t], [x / 1e5 for x in Pcgc_t], [x / 1e5 for x in Pasm_t] Paem_t, Pcsm_t, Pcem_t = [x / 1e5 for x in Paem_t], [x / 1e5 for x in Pcsm_t], [x / 1e5 for x in Pcem_t] # Plot the pressure at different spatial localisations: P ax.plot(t, Pagc_t, color=colors(0)) ax.plot(t, Pcgc_t, color=colors(6)) ax.plot(t, Pasm_t, color=colors(7)) ax.plot(t, Paem_t, color=colors(8)) ax.plot(t, Pcsm_t, color=colors(9)) ax.plot(t, Pcem_t, color=colors(3)) ax.legend([r'$\\mathregular{P_{agc}}$', r'$\\mathregular{P_{cgc}}$', r'$\\mathregular{P_{asm}}$', r'$\\mathregular{P_{aem}}$', r'$\\mathregular{P_{csm}}$', r'$\\mathregular{P_{cem}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Pressure}$ $\\mathbf{P}$ $\\mathbf{\\left( bar \\right)}$', labelpad=3) ax.ticklabel_format(style='scientific', axis='y', scilimits=(0, 0)) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5e-4)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5e-4 / 5)) ax.set_ylim(1.99980, 2.00015) plot_Phi_a(variables, operating_inputs, ax) This function plots the humidity at the anode side, at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_a(variables, operating_inputs, ax): \"\"\"This function plots the humidity at the anode side, at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t, C_v_agc_t = variables['t'], variables['C_v_agc'] Phi_asm_t, Phi_aem_t = variables['Phi_asm'], variables['Phi_aem'] # Extraction of the operating inputs Tfc, Phi_a_des = operating_inputs['Tfc'], operating_inputs['Phi_a_des'] # Calculate the humidity Phi Phi_agc_t = [0] * len(t) for i in range(len(t)): Phi_agc_t[i] = C_v_agc_t[i] * R * Tfc / Psat(Tfc) # Plot the humidity at different spatial localisations: Phi ax.plot(t, Phi_agc_t, color=colors(0), label=r'$\\mathregular{\\Phi_{agc}}$') ax.plot(t, Phi_asm_t, color=colors(1), label=r'$\\mathregular{\\Phi_{asm}}$') ax.plot(t, Phi_aem_t, color=colors(2), label=r'$\\mathregular{\\Phi_{aem}}$') ax.plot(t, [Phi_a_des]*len(t), color='black', label=r'$\\mathregular{\\Phi_{a,des}}$') ax.legend(loc='center right', bbox_to_anchor=(1, 0.67)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Humidity}$ $\\mathbf{at}$ $\\mathbf{the}$ $\\mathbf{anode}$ $\\mathbf{side}$ $\\mathbf{\\Phi}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) plot_Phi_c(variables, operating_inputs, ax) This function plots the humidity, at the cathode side, at different spatial localisations as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_c(variables, operating_inputs, ax): \"\"\"This function plots the humidity, at the cathode side, at different spatial localisations as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t, C_v_cgc_t = variables['t'], variables['C_v_cgc'] Phi_csm_t, Phi_cem_t = variables['Phi_csm'], variables['Phi_cem'] # Extraction of the operating inputs Tfc, Phi_c_des = operating_inputs['Tfc'], operating_inputs['Phi_c_des'] # Calculate the humidity Phi Phi_cgc_t = [0] * len(t) for i in range(len(t)): Phi_cgc_t[i] = C_v_cgc_t[i] * R * Tfc / Psat(Tfc) # Plot the humidity at different spatial localisations: Phi ax.plot(t, Phi_cgc_t, color=colors(0), label=r'$\\mathregular{\\Phi_{cgc}}$') ax.plot(t, Phi_csm_t, color=colors(1), label=r'$\\mathregular{\\Phi_{csm}}$') ax.plot(t, Phi_cem_t, color=colors(2), label=r'$\\mathregular{\\Phi_{cem}}$') ax.plot(t, [Phi_c_des]*len(t), color='black', label=r'$\\mathregular{\\Phi_{c,des}}$') ax.legend(loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Humidity}$ $\\mathbf{at}$ $\\mathbf{the}$ $\\mathbf{cathode}$ $\\mathbf{side}$ $\\mathbf{\\Phi}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) plot_Phi_des(variables, operating_inputs, parameters, ax) This function plots the controlled or uncontrolled desired humidity at the anode and cathode as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_des(variables, operating_inputs, parameters, ax): \"\"\"This function plots the controlled or uncontrolled desired humidity at the anode and cathode as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t = variables['t'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] if parameters['type_control'] == \"Phi_des\": Phi_a_des, Phi_c_des = variables['Phi_a_des'], variables['Phi_c_des'] ax.set_ylabel(r'$\\mathbf{Controlled}$ $\\mathbf{inlet}$ $\\mathbf{humidity}$ $\\mathbf{\\Phi_{des}}$', labelpad=3) else: Phi_a_des, Phi_c_des = [operating_inputs['Phi_a_des']] * len(t), [operating_inputs['Phi_c_des']] * len(t) ax.set_ylabel(r'$\\mathbf{Uncontrolled}$ $\\mathbf{inlet}$ $\\mathbf{humidity}$ $\\mathbf{\\Phi_{des}}$', labelpad=3) # Plot Phi_des n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of ifc_t ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, Phi_c_des, color=colors(6), label=r'$\\mathregular{\\Phi_{c,des}}$') ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) if parameters['type_auxiliary'] == \"forced-convective_cathode_with_flow-through_anode\" or \\ parameters['type_auxiliary'] == \"no_auxiliary\": ax.plot(t, Phi_a_des, color=colors(0), label=r'$\\mathregular{\\Phi_{a,des}}$') ax.legend([r'$\\mathregular{\\Phi_{a,des}}$', r'$\\mathregular{\\Phi_{c,des}}$'], loc='best') else: ax.legend([r'$\\mathregular{\\Phi_{c,des}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.2)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.2 / 5)) ax.set_xlim(0, 4.1) plot_Ucell(variables, ax) This function plots the cell voltage as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the cell voltage will be plotted. Source code in modules/display_modules.py def plot_Ucell(variables, ax): \"\"\"This function plots the cell voltage as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the cell voltage will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = variables['t'], variables['Ucell'] # Plot the cell voltage: Ucell ax.plot(t, Ucell_t, color=colors(0), label=r'$\\mathregular{U_{cell}}$') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Cell}$ $\\mathbf{voltage}$ $\\mathbf{U_{cell}}$ $\\mathbf{\\left( V \\right)}$', labelpad=3) ax.legend([r'$\\mathregular{U_{cell}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.05)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.05 / 5)) plot_cell_efficiency(variables, operating_inputs, parameters, n, ax) This function plots the fuel cell efficiency eta_fc as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the fuel cell efficiency. ax ( Axes ) \u2013 Axes on which the fuel cell efficiency will be plotted. Source code in modules/display_modules.py def plot_cell_efficiency(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the fuel cell efficiency eta_fc as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the fuel cell efficiency. ax : matplotlib.axes.Axes Axes on which the fuel cell efficiency will be plotted. \"\"\" # Extraction of the variables t, Ucell_t, lambda_mem_t = variables['t'], variables['Ucell'], variables['lambda_mem'] C_H2_acl_t, C_O2_ccl_t = variables['C_H2_acl'], variables['C_O2_ccl'] # Extraction of the operating inputs and the parameters current_density, Tfc = operating_inputs['current_density'], operating_inputs['Tfc'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control = parameters['type_control'] # Creation of the fuel cell efficiency: eta_fc ifc_t, Pfc_t, eta_fc_t = np.zeros(n), np.zeros(n), np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 Pfc_t[i] = Ucell_t[i] * ifc_t[i] Ueq = E0 - 8.5e-4 * (Tfc - 298.15) + R * Tfc / (2 * F) * (np.log(R * Tfc * C_H2_acl_t[i] / Pref) + 0.5 * np.log(R * Tfc * C_O2_ccl_t[i] / Pref)) i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl_t[i] * k_H2(lambda_mem_t[i], Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl_t[i] * k_O2(lambda_mem_t[i], Tfc, kappa_co) i_n = (i_H2 + i_O2) / 1e4 # Conversion in A/cm\u00b2 eta_fc_t[i] = Pfc_t[i] / (Ueq * (ifc_t[i] + i_n)) # Plot of the fuel cell efficiency: eta_fc plot_specific_line(ifc_t, eta_fc_t, type_fuel_cell, type_auxiliary, type_control, None, ax) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=0) ax.set_ylabel(r'$\\mathbf{Fuel}$ $\\mathbf{cell}$ $\\mathbf{efficiency}$ $\\mathbf{\\eta_{fc}}$', labelpad=0) ax.legend(loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) ax.set_xlim(0, 4.1) ax.set_ylim(0, 0.7) plot_general_instructions(ax) This function adds the common instructions for all the plots displayed by AlphaPEM to the ax object. Parameters: ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_general_instructions(ax): \"\"\"This function adds the common instructions for all the plots displayed by AlphaPEM to the ax object. Parameters ---------- ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" ax.tick_params(axis='both', which='major', size=10, width=1.5, direction='out') ax.tick_params(axis='both', which='minor', size=5, width=1.5, direction='out') plt.tight_layout() # Adjust layout to prevent overlap between labels and the figure plt.show() # Show the figure plot_ifc(variables, operating_inputs, parameters, n, ax) This function plots the current density as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the current density. ax ( Axes ) \u2013 Axes on which the current density will be plotted. Source code in modules/display_modules.py def plot_ifc(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the current density as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the current density. ax : matplotlib.axes.Axes Axes on which the current density will be plotted. \"\"\" # Extraction of the variables t = variables['t'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] # Plot the current density: ifc ifc_t = np.zeros(n) for i in range(n): # Creation of ifc_t ifc_t[i] = current_density(t[i], parameters) / 10000 # Conversion in A/cm\u00b2 ax.plot(t, ifc_t, color=colors(0), label=r'$\\mathregular{i_{fc}}$') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) ax.legend([r'$\\mathregular{i_{fc}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) plot_lambda(variables, operating_inputs, parameters, ax) This function plots the water content at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the water content will be plotted. Source code in modules/display_modules.py def plot_lambda(variables, operating_inputs, parameters, ax): \"\"\"This function plots the water content at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the water content will be plotted. \"\"\" # Extraction of the variables t, lambda_acl_t = variables['t'], variables['lambda_acl'] lambda_mem_t, lambda_ccl_t = variables['lambda_mem'], variables['lambda_ccl'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] type_current = parameters['type_current'] # Plot the water content at different spatial localisations: lambda if type_current == \"polarization\": n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of i_fc ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, lambda_acl_t, color=colors(2)) ax.plot(ifc_t, lambda_mem_t, color=colors(3)) ax.plot(ifc_t, lambda_ccl_t, color=colors(4)) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) else: ax.plot(t, lambda_acl_t, color=colors(2)) ax.plot(t, lambda_mem_t, color=colors(3)) ax.plot(t, lambda_ccl_t, color=colors(4)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Water}$ $\\mathbf{content}$ $\\mathbf{\\lambda}$', labelpad=3) ax.legend([r'$\\mathregular{\\lambda_{acl}}$', r'$\\mathregular{\\lambda_{mem}}$', r'$\\mathregular{\\lambda_{ccl}}$'], loc='best') # Plot instructions plot_general_instructions(ax) if type_current == \"polarization\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) else: ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(3)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(3 / 5)) plot_pola_instructions(type_fuel_cell, ax) This function adds the specific instructions for polarisation plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_pola_instructions(type_fuel_cell, ax): \"\"\"This function adds the specific instructions for polarisation plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) ax.set_xlim(0, 3.0) ax.set_ylim(0.4, 1.04) # For LF fuel cell elif type_fuel_cell == \"LF\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.4)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.4 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.2)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.2 / 5)) ax.set_xlim(-0.05, 1.6) ax.set_ylim(0, 1.0) # For other fuel cell else: pass plot_polarisation_curve(variables, operating_inputs, parameters, ax) This function plots the model polarisation curve, and compare it to the experimental one (if it exists). The polarisation curve is a classical representation of the cell performances, showing the cell voltage as a function of the current density. To generate it, the current density is increased step by step, and the cell voltage is recorded at each step. The time for which this point is captured is determined using the following approach: at the beginning of each load, a delta_t_load_pola time is needed to raise the current density to its next value. Subsequently, a delta_t_break_pola time is observed to ensure the dynamic stability of the stack's variables before initiating a new load. Ideally, each polarisation point should be recorded at the end of each delta_t_break_pola time. However, due to the design of the increments to minimize program instability (as observed in step_current function), the end of each delta_t_break_pola time corresponds to the beginning of a new load. To ensure a stationary operation and accurate polarisation point measurements, it is recommended to take the polarisation point just before by subtracting a delta_t value from it. This adjustment allows for stable and consistent measurements during the stationary period. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the polarisation curve will be plotted. Source code in modules/display_modules.py def plot_polarisation_curve(variables, operating_inputs, parameters, ax): \"\"\" This function plots the model polarisation curve, and compare it to the experimental one (if it exists). The polarisation curve is a classical representation of the cell performances, showing the cell voltage as a function of the current density. To generate it, the current density is increased step by step, and the cell voltage is recorded at each step. The time for which this point is captured is determined using the following approach: at the beginning of each load, a delta_t_load_pola time is needed to raise the current density to its next value. Subsequently, a delta_t_break_pola time is observed to ensure the dynamic stability of the stack's variables before initiating a new load. Ideally, each polarisation point should be recorded at the end of each delta_t_break_pola time. However, due to the design of the increments to minimize program instability (as observed in step_current function), the end of each delta_t_break_pola time corresponds to the beginning of a new load. To ensure a stationary operation and accurate polarisation point measurements, it is recommended to take the polarisation point just before by subtracting a delta_t value from it. This adjustment allows for stable and consistent measurements during the stationary period. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the polarisation curve will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), np.array(variables['Ucell']) # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] t_step, i_step, i_max_pola = parameters['t_step'], parameters['i_step'], parameters['i_max_pola'] delta_pola = parameters['delta_pola'] i_EIS, t_EIS, f_EIS = parameters['i_EIS'], parameters['t_EIS'], parameters['f_EIS'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control, type_plot = parameters['type_control'], parameters['type_plot'] if type_plot == \"fixed\": # Creation of ifc_t n = len(t) ifc_t = np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 # Recovery of ifc and Ucell from the model after each stack stabilisation delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola nb_loads = int(i_max_pola / delta_i_pola + 1) # Number of loads which are made ifc_discretized = np.zeros(nb_loads) Ucell_discretized = np.zeros(nb_loads) for i in range(nb_loads): t_load = delta_t_ini_pola + (i + 1) * (delta_t_load_pola + delta_t_break_pola) - delta_t_break_pola / 10 # # time for measurement idx = (np.abs(t - t_load)).argmin() # the corresponding index ifc_discretized[i] = ifc_t[idx] # the last value at the end of each load Ucell_discretized[i] = Ucell_t[idx] # the last value at the end of each load # Plot the experimental polarization curve and calculate the simulation error compared with experimental data if type_fuel_cell != \"manual_setup\" and \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Experimental points are accessible # Plot of the experimental polarization curve i_exp_t, U_exp_t = pola_exp_values(type_fuel_cell) plot_experimental_polarisation_curve(type_fuel_cell, i_exp_t, U_exp_t, ax) # Calculate the simulation error compared with experimental data # i_fc and Ucell are reduced to remain within experimental limits for comparison i_fc_reduced = ifc_discretized[(ifc_discretized >= i_exp_t[0]) & (ifc_discretized <= i_exp_t[-1])] Ucell_reduced = Ucell_discretized[(ifc_discretized >= i_exp_t[0]) & (ifc_discretized <= i_exp_t[-1])] # Experimental points are interpolated to correspond to the model points U_exp_interpolated = interp1d(i_exp_t, U_exp_t, kind='linear')(i_fc_reduced) sim_error = calculate_simulation_error(Ucell_reduced, U_exp_interpolated) else: sim_error = None # Plot the model polarisation curve plot_specific_line(ifc_discretized, Ucell_discretized, type_fuel_cell, type_auxiliary, type_control, sim_error, ax) plot_pola_instructions(type_fuel_cell, ax) else: # type_plot == \"dynamic\" # Plot of the polarisation curve produced by the model delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola idx = (np.abs(t - t[-1] + delta_t_break_pola / 10)).argmin() # index for polarisation measurement ifc = np.array(current_density(t[idx], parameters) / 1e4) # time for polarisation measurement Ucell = np.array(Ucell_t[idx]) # voltage measurement ax.plot(ifc, Ucell, 'og', markersize=2) # Add the common instructions for the plot ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Cell}$ $\\mathbf{voltage}$ $\\mathbf{U_{cell}}$ $\\mathbf{\\left( V \\right)}$', labelpad=3) plot_general_instructions(ax) if type_plot == \"fixed\": ax.legend(loc='best') plot_power_density_curve(variables, operating_inputs, parameters, n, ax) This function plots the power density curve Pfc, produced by a cell, as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the power density curve. ax ( Axes ) \u2013 Axes on which the power density curve will be plotted. Source code in modules/display_modules.py def plot_power_density_curve(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the power density curve Pfc, produced by a cell, as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the power density curve. ax : matplotlib.axes.Axes Axes on which the power density curve will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = variables['t'], variables['Ucell'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control = parameters['type_control'] # Creation of the power density function: Pfc ifc_t, Pfc_t = np.zeros(n), np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 Pfc_t[i] = Ucell_t[i] * ifc_t[i] # Plot of the power density function: Pfc plot_specific_line(ifc_t, Pfc_t, type_fuel_cell, type_auxiliary, type_control, None, ax) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=0) ax.set_ylabel(r'$\\mathbf{Fuel}$ $\\mathbf{cell}$ $\\mathbf{power}$ $\\mathbf{density}$ $\\mathbf{P_{fc}}$ $\\mathbf{\\left( W.cm^{-2} \\right)}$', labelpad=0) ax.legend(loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.3)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.3 / 5)) ax.set_xlim(0, 4.1) ax.set_ylim(0, 2.1) plot_s(variables, operating_inputs, parameters, ax) This function plots the liquid water saturation at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the liquid water saturation will be plotted. Source code in modules/display_modules.py def plot_s(variables, operating_inputs, parameters, ax): \"\"\"This function plots the liquid water saturation at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the liquid water saturation will be plotted. \"\"\" # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] n_gdl, type_current = parameters['n_gdl'], parameters['type_current'] # Extraction of the variables t, s_agdl_t, s_acl_t = variables['t'], variables[f's_agdl_{n_gdl // 2}'], variables['s_acl'] s_ccl_t, s_cgdl_t = variables['s_ccl'], variables[f's_cgdl_{n_gdl // 2}'] # Plot the liquid water saturation at different spatial localisations: s if type_current == \"polarization\": n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of i_fc ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, s_agdl_t, color=colors(1)) ax.plot(ifc_t, s_acl_t, color=colors(2)) ax.plot(ifc_t, s_ccl_t, color=colors(4)) ax.plot(ifc_t, s_cgdl_t, color=colors(5)) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) else: ax.plot(t, s_agdl_t, color=colors(1)) ax.plot(t, s_acl_t, color=colors(2)) ax.plot(t, s_ccl_t, color=colors(4)) ax.plot(t, s_cgdl_t, color=colors(5)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Liquid}$ $\\mathbf{water}$ $\\mathbf{saturation}$ $\\mathbf{s}$', labelpad=3) ax.legend([r'$\\mathregular{s_{agdl}}$', r'$\\mathregular{s_{acl}}$', r'$\\mathregular{s_{ccl}}$', r'$\\mathregular{s_{cgdl}}$'], loc='best') # Plot instructions plot_general_instructions(ax) if type_current == \"polarization\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) else: ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.04)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.04 / 5)) plot_specific_line(x, y, type_fuel_cell, type_auxiliary, type_control, sim_error, ax) This function adds the appropriate plot configuration according to the type_input to the ax object. Parameters: x ( ndarray ) \u2013 x-axis values. y ( ndarray ) \u2013 y-axis values. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. type_auxiliary ( str ) \u2013 Type of auxiliary system. type_control ( str ) \u2013 Type of control system. sim_error ( float ) \u2013 Simulation error between the simulated cell voltage and the experimental cell voltage (in %). ax ( Axes ) \u2013 Axes on which the line will be plotted. Source code in modules/display_modules.py def plot_specific_line(x, y, type_fuel_cell, type_auxiliary, type_control, sim_error, ax): \"\"\" This function adds the appropriate plot configuration according to the type_input to the ax object. Parameters ---------- x : numpy.ndarray x-axis values. y : numpy.ndarray y-axis values. type_fuel_cell : str Type of fuel cell configuration. type_auxiliary : str Type of auxiliary system. type_control : str Type of control system. sim_error : float Simulation error between the simulated cell voltage and the experimental cell voltage (in %). ax : matplotlib.axes.Axes Axes on which the line will be plotted. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": if type_fuel_cell == \"EH-31_1.5\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(0), label='Sim. - P = 1.5 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_1.5\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(0), label='Sim. - P = 1.5 bar') elif type_fuel_cell == \"EH-31_2.0\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, '--', color=colors(1), label='Sim. - P = 2.0 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.0\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": if type_control == \"Phi_des\": ax.plot(x, y, color=colors(5), label=r'Sim. - P = 2.0 bar - controlled $\\mathregular{\\Phi_{des}}$') else: ax.plot(x, y, color=colors(1), label=r'Sim. - P = 2.0 bar - uncontrolled $\\mathregular{\\Phi_{des}}$') elif type_fuel_cell == \"EH-31_2.25\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, '--', color=colors(2), label='Sim. - P = 2.25 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.25\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(2), label='Sim. - P = 2.25 bar') elif type_fuel_cell == \"EH-31_2.5\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(3), label='Sim - P = 2.5 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.5\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(3), label='Sim - P = 2.5 bar') # For LF fuel cell elif type_fuel_cell == \"LF\": ax.plot(x, y, color=colors(0), label='Simulation') # For other fuel cell else: ax.plot(x, y, color=colors(0), label='Simulation')","title":"Display modules"},{"location":"functions/modules/display_modules/#display-modules","text":"This module is used to accurately plot the figures.","title":"Display modules"},{"location":"functions/modules/display_modules/#modules.display_modules.calculate_simulation_error","text":"This function calculates the simulation error between the simulated cell voltage and the experimental cell voltage. It is calculated as the maximum relative difference between the two voltages (in %). Parameters: Ucell ( ndarray ) \u2013 Simulated cell voltage. U_exp_t ( ndarray ) \u2013 Experimental cell voltage. Returns: float \u2013 Simulation error between the simulated cell voltage and the experimental cell voltage (in %). Source code in modules/display_modules.py def calculate_simulation_error(Ucell, U_exp_t): \"\"\"This function calculates the simulation error between the simulated cell voltage and the experimental cell voltage. It is calculated as the maximum relative difference between the two voltages (in %). Parameters ---------- Ucell : numpy.ndarray Simulated cell voltage. U_exp_t : numpy.ndarray Experimental cell voltage. Returns ------- float Simulation error between the simulated cell voltage and the experimental cell voltage (in %). \"\"\" return np.round(np.max(np.abs(Ucell - U_exp_t) / U_exp_t * 100), 2) # in %.","title":"calculate_simulation_error"},{"location":"functions/modules/display_modules/#modules.display_modules.make_Fourier_transformation","text":"This function calculates the Fourier transformation of both cell voltage and current density. It will be used to display the Nyquist and Bode diagrams. To generate it at each frequency change, the cell voltage and the current density are recorded. The time for which these points are captured is determined using the following approach: at the beginning of each frequency change, a delta_t_break_EIS time is observed to ensure the dynamic stability of the stack's variables. Subsequently, a delta_t_measurement_EIS time is needed to record the cell voltage and the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: dict \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. Source code in modules/display_modules.py def make_Fourier_transformation(variables, operating_inputs, parameters): \"\"\" This function calculates the Fourier transformation of both cell voltage and current density. It will be used to display the Nyquist and Bode diagrams. To generate it at each frequency change, the cell voltage and the current density are recorded. The time for which these points are captured is determined using the following approach: at the beginning of each frequency change, a delta_t_break_EIS time is observed to ensure the dynamic stability of the stack's variables. Subsequently, a delta_t_measurement_EIS time is needed to record the cell voltage and the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), np.array(variables['Ucell']) # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] t_EIS, max_step = parameters['t_EIS'], parameters['max_step'] # Creation of ifc ifc_t = np.zeros(len(t)) for i in range(len(t)): ifc_t[i] = current_density(t[i], parameters) # Identify the areas where Ucell and ifc can be measured for the EIS: after equilibrium and at each frequency change t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS n_inf = np.where(t_new_start_EIS <= t[0])[0][-1] # The number of frequency changes which has been mad so far. Ucell_EIS_measured = Ucell_t[np.where((t > (t[0] + delta_t_break_EIS[n_inf])) & (t < (t[0] + delta_t_break_EIS[n_inf] + delta_t_measurement_EIS[n_inf])))] ifc_EIS_measured = ifc_t[np.where((t > (t[0] + delta_t_break_EIS[n_inf])) & (t < (t[0] + delta_t_break_EIS[n_inf] + delta_t_measurement_EIS[n_inf])))] # Determination of the Fourier transformation N = Ucell_EIS_measured.size # Number of points used for the Fourier transformation Ucell_Fourier = fft(Ucell_EIS_measured) # Ucell Fourier transformation ifc_Fourier = fft(ifc_EIS_measured) # ifc Fourier transformation A_period_t = np.concatenate( ([np.abs(Ucell_Fourier)[0] / N], np.abs(Ucell_Fourier[1:N // 2]) * 2 / N)) # Recovery of # all amplitude values calculated by fft A = max(A_period_t[1:]) # Amplitude at the frequency of the perturbation freq_t = fftfreq(N, max_step)[:N // 2] # Recovery of all frequency values used by fft f = freq_t[np.argmax(A_period_t == A)] # Recovery of the studied frequency return {'Ucell_Fourier': Ucell_Fourier, 'ifc_Fourier': ifc_Fourier, 'A_period_t': A_period_t, 'A': A, 'freq_t': freq_t, 'f': f, 'N': N}","title":"make_Fourier_transformation"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Bode_amplitude_instructions","text":"This function adds the instructions for amplitude Bode plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_Bode_amplitude_instructions(f_EIS, type_fuel_cell, ax): \"\"\"This function adds the instructions for amplitude Bode plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. ax.set_xscale('log') # set logarithmic scale for the x-axis # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(LogLocator(base=10.0, numticks=f_power_max_EIS - f_power_min_EIS + 1)) ax.xaxis.set_minor_locator(LogLocator(base=10.0, subs=np.arange(2, 10) * .1, numticks=(f_power_max_EIS - f_power_min_EIS + 1) * len(np.arange(2, 10)))) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(30)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(30 / 5)) ax.set_xlim([10**f_power_min_EIS, 10**f_power_max_EIS])","title":"plot_Bode_amplitude_instructions"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Bode_phase_instructions","text":"This function adds the instructions for phase Bode plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_Bode_phase_instructions(f_EIS, type_fuel_cell, ax): \"\"\"This function adds the instructions for phase Bode plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. ax.set_xscale('log') # set logarithmic scale for the x-axis if not ax.yaxis_inverted(): ax.invert_yaxis() # Invert the y-axis # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(LogLocator(base=10.0, numticks = f_power_max_EIS-f_power_min_EIS+1)) ax.xaxis.set_minor_locator(LogLocator(base=10.0, subs=np.arange(2, 10) * .1, numticks = (f_power_max_EIS-f_power_min_EIS+1)*len(np.arange(2, 10)))) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(5 / 5)) ax.set_xlim([10**f_power_min_EIS, 10**f_power_max_EIS])","title":"plot_Bode_phase_instructions"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_C_H2","text":"This function plots the hydrogen concentration at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. ax ( Axes ) \u2013 Axes on which the hydrogen concentration will be plotted. Source code in modules/display_modules.py def plot_C_H2(variables, n_gdl, ax): \"\"\"This function plots the hydrogen concentration at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. ax : matplotlib.axes.Axes Axes on which the hydrogen concentration will be plotted. \"\"\" # Extraction of the variables t, C_H2_agc_t = variables['t'], variables['C_H2_agc'] C_H2_agdl_t, C_H2_acl_t = variables[f'C_H2_agdl_{n_gdl // 2}'], variables['C_H2_acl'] # Plot the hydrogen concentration at different spatial localisations: C_H2 ax.plot(t, C_H2_agc_t, color=colors(0)) ax.plot(t, C_H2_agdl_t, color=colors(1)) ax.plot(t, C_H2_acl_t, color=colors(2)) ax.legend([r'$\\mathregular{C_{H_{2},agc}}$', r'$\\mathregular{C_{H_{2},agdl}}$', r'$\\mathregular{C_{H_{2},acl}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Hydrogen}$ $\\mathbf{concentration}$ $\\mathbf{C_{H_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(55, 58)","title":"plot_C_H2"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_C_N2","text":"This function plots the nitrogen concentration as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the nitrogen concentration will be plotted. Source code in modules/display_modules.py def plot_C_N2(variables, ax): \"\"\"This function plots the nitrogen concentration as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the nitrogen concentration will be plotted. \"\"\" # Extraction of the variables t, C_N2_t = variables['t'], variables['C_N2'] # Plot C_N2 ax.plot(t, C_N2_t, color=colors(6)) ax.legend([r'$\\mathregular{C_{N_{2}}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Nitrogen}$ $\\mathbf{concentration}$ $\\mathbf{C_{N_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.set_ylim(47, 49)","title":"plot_C_N2"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_C_O2","text":"This function plots the oxygen concentration at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. ax ( Axes ) \u2013 Axes on which the oxygen concentration will be plotted. Source code in modules/display_modules.py def plot_C_O2(variables, n_gdl, ax): \"\"\"This function plots the oxygen concentration at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. ax : matplotlib.axes.Axes Axes on which the oxygen concentration will be plotted. \"\"\" # Extraction of the variables t, C_O2_ccl_t = variables['t'], variables['C_O2_ccl'] C_O2_cgdl_t, C_O2_cgc_t = variables[f'C_O2_cgdl_{n_gdl // 2}'], variables['C_O2_cgc'] # Plot the oxygen concentration at different spatial localisations: C_O2 ax.plot(t, C_O2_ccl_t, color=colors(4)) ax.plot(t, C_O2_cgdl_t, color=colors(5)) ax.plot(t, C_O2_cgc_t, color=colors(6)) ax.legend([r'$\\mathregular{C_{O_{2},ccl}}$', r'$\\mathregular{C_{O_{2},cgdl}}$', r'$\\mathregular{C_{O_{2},cgc}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Oxygen}$ $\\mathbf{concentration}$ $\\mathbf{C_{O_{2}}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(6, 11)","title":"plot_C_O2"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_C_v","text":"This function plots the vapor concentrations at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl ( int ) \u2013 Number of model nodes placed inside each GDL. C_v_sat ( float ) \u2013 Saturation vapor concentration. n ( int ) \u2013 Number of points used to plot the vapor concentration. ax ( Axes ) \u2013 Axes on which the vapor concentration will be plotted. Source code in modules/display_modules.py def plot_C_v(variables, n_gdl, C_v_sat, n, ax): \"\"\"This function plots the vapor concentrations at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. n_gdl : int Number of model nodes placed inside each GDL. C_v_sat : float Saturation vapor concentration. n : int Number of points used to plot the vapor concentration. ax : matplotlib.axes.Axes Axes on which the vapor concentration will be plotted. \"\"\" # Extraction of the variables t, C_v_agc_t, C_v_agdl_t = variables['t'], variables['C_v_agc'], variables[f'C_v_agdl_{n_gdl // 2}'] C_v_acl_t, C_v_ccl_t = variables['C_v_acl'], variables['C_v_ccl'] C_v_cgdl_t, C_v_cgc_t = variables[f'C_v_cgdl_{n_gdl // 2}'], variables['C_v_cgc'] # Plot the vapor concentrations at different spatial localisations Cv C_v_sat_t = np.ones(n) * C_v_sat ax.plot(t, C_v_agc_t, color=colors(0)) ax.plot(t, C_v_agdl_t, color=colors(1)) ax.plot(t, C_v_acl_t, color=colors(2)) ax.plot(t, C_v_ccl_t, color=colors(4)) ax.plot(t, C_v_cgdl_t, color=colors(5)) ax.plot(t, C_v_cgc_t, color=colors(6)) ax.plot(t, C_v_sat_t, color='k') ax.legend([r'$\\mathregular{C_{v,agc}}$', r'$\\mathregular{C_{v,agdl}}$', r'$\\mathregular{C_{v,acl}}$', r'$\\mathregular{C_{v,ccl}}$', r'$\\mathregular{C_{v,cgdl}}$', r'$\\mathregular{C_{v,cgc}}$', r'$\\mathregular{C_{v,sat}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r\"$\\mathbf{Vapor}$ $\\mathbf{concentration}$ $\\mathbf{C_{v}}$ $\\mathbf{\\left( mol.m^{-3} \\right)}$\", labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1 / 5)) ax.set_ylim(11, 16)","title":"plot_C_v"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_EIS_Nyquist_instructions","text":"This function adds the instructions for EIS plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. f_Fourier ( ndarray ) \u2013 Frequency at which the EIS is simulated. x ( ndarray ) \u2013 x-axis values for plotting the annotation. y ( ndarray ) \u2013 y-axis values for plotting the annotation. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_EIS_Nyquist_instructions(type_fuel_cell, f_Fourier, x, y, ax): \"\"\"This function adds the instructions for EIS plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. f_Fourier : numpy.ndarray Frequency at which the EIS is simulated. x : numpy.ndarray x-axis values for plotting the annotation. y : numpy.ndarray y-axis values for plotting the annotation. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # Commun instructions ax.set_aspect('equal', adjustable='box') # Set orthonormal axis. # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": # Double charge transfer if (f_Fourier >= 70 and f_Fourier <= 80): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, -40), ha='center', fontsize=14, rotation=90, weight='bold') # Auxiliary system if (f_Fourier >= 0.14 and f_Fourier <= 0.16): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 7), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 1.2 and f_Fourier <= 1.4): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 10), ha='center', fontsize=14, rotation=90, weight='bold') # Diffusion if (f_Fourier >= 0.015 and f_Fourier <= 0.020): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(30, 0), ha='center', fontsize=14, rotation=0, weight='bold') if (f_Fourier >= 0.9 and f_Fourier <= 1.1): freq_str = f'{f_Fourier:.2g} Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, 10), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 70 and f_Fourier <= 90): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(0, -40), ha='center', fontsize=14, rotation=90, weight='bold') if (f_Fourier >= 10000 and f_Fourier <= 12000): freq_str = str(int(f_Fourier)) + ' Hz' # Frequency annotation. ax.annotate(freq_str, (x, y), textcoords=\"offset points\", xytext=(35, 0), ha='center', fontsize=14, rotation=0, weight='bold') ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(20)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(20 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(10)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(10 / 5)) ax.set_xlim(30, 200) ax.set_ylim(-25, 55)","title":"plot_EIS_Nyquist_instructions"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_EIS_curve_Bode_amplitude","text":"This function is used to plot the amplitude Bode diagram of the EIS curves. Parameters: parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the amplitude Bode diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Bode_amplitude(parameters, Fourier_results, ax): \"\"\"This function is used to plot the amplitude Bode diagram of the EIS curves. Parameters ---------- parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the amplitude Bode diagram will be plotted. \"\"\" # Extraction of the parameters i_EIS, ratio_EIS, f_EIS = parameters['i_EIS'], parameters['ratio_EIS'], parameters['f_EIS'] type_fuel_cell = parameters['type_fuel_cell'] # Extraction of the Fourier results A, f = Fourier_results['A'], Fourier_results['f'] # Calculation of the impedance of the perturbation Z0 = A / (ratio_EIS * (-i_EIS)) * 1e7 # in m\u03a9.cm\u00b2. The sign of i is inverted to comply with the standards of EIS, # which measure a device under load rather than a current source. # Plot the amplitude Bode diagram ax.plot(f, np.abs(Z0), 'o', color=colors(1), label='Amplitude Bode diagram') ax.set_xlabel(r'$\\mathbf{Frequency}$ $\\mathbf{(Hz,}$ $\\mathbf{logarithmic}$ $\\mathbf{scale)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Impedance}$ $\\mathbf{amplitude}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_Bode_amplitude_instructions(f_EIS, type_fuel_cell, ax)","title":"plot_EIS_curve_Bode_amplitude"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_EIS_curve_Bode_angle","text":"This function is used to plot the angle Bode diagram. It only works with an entry signal made with a cosinus (not a sinus). Parameters: Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the angle Bode diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Bode_angle(parameters, Fourier_results, ax): \"\"\"This function is used to plot the angle Bode diagram. It only works with an entry signal made with a cosinus (not a sinus). Parameters ---------- Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the angle Bode diagram will be plotted. \"\"\" # Extraction of the parameters f_EIS, type_fuel_cell = parameters['f_EIS'], parameters['type_fuel_cell'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] A_period_t, A = Fourier_results['A_period_t'], Fourier_results['A'] f, N = Fourier_results['f'], Fourier_results['N'] # Calculation of the dephasing values at the frequency of the perturbation theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) + np.pi # Recovery of all dephasing values calculated by fft. # An angle of pi is added to comply with the standards of EIS, # which measure a device under load rather than a current source. theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation phi_U_i = ((theta_U - theta_i) * 180 / np.pi) % 360 # Dephasing between Ucell and ifc with a value between 0 and 360 if phi_U_i > 180: phi_U_i -= 360 # To have a value between -180 and 180 # Plot the angle Bode diagram ax.plot(f, phi_U_i, 'o', color=colors(2), label='Angle Bode diagram') ax.set_xlabel(r'$\\mathbf{Frequency}$ $\\mathbf{(Hz,}$ $\\mathbf{logarithmic}$ $\\mathbf{scale)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Phase}$ $\\mathbf{(^\\circ)}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_Bode_phase_instructions(f_EIS, type_fuel_cell, ax)","title":"plot_EIS_curve_Bode_angle"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_EIS_curve_Nyquist","text":"This function is used to plot the Nyquist diagram of the EIS curves. Parameters: parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax ( Axes ) \u2013 Axes on which the Nyquist diagram will be plotted. Source code in modules/display_modules.py def plot_EIS_curve_Nyquist(parameters, Fourier_results, ax): \"\"\" This function is used to plot the Nyquist diagram of the EIS curves. Parameters ---------- parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. ax : matplotlib.axes.Axes Axes on which the Nyquist diagram will be plotted. \"\"\" # Extraction of the parameters i_EIS, ratio_EIS, type_fuel_cell = parameters['i_EIS'], parameters['ratio_EIS'], parameters['type_fuel_cell'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] f_Fourier = Fourier_results['f'] A_period_t, A, N = Fourier_results['A_period_t'], Fourier_results['A'], Fourier_results['N'] # Calculation of the real and imaginary component of the impedance for each period Z0 = A / (ratio_EIS * (-i_EIS)) * 1e7 # Impedance of the perturbation in m\u03a9.cm\u00b2. The sign of i is inverted to # comply with the standards of EIS, which measure a device under load rather than a current source. theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation Z_real = Z0 * np.cos(theta_U - theta_i) # Real component of the impedance for each period Z_imag = Z0 * np.sin(theta_U - theta_i) # Imaginary component of the impedance for each period # Plot the Nyquist diagram ax.plot(Z_real, -Z_imag, 'o', color=colors(0), label='Nyquist diagram') ax.set_xlabel(r'$\\mathbf{Z_{real}}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{-Z_{imag}}$ $\\mathbf{(m\\Omega.cm^{2})}$', labelpad=3) # Plot instructions plot_general_instructions(ax) plot_EIS_Nyquist_instructions(type_fuel_cell, f_Fourier, Z_real, -Z_imag, ax)","title":"plot_EIS_curve_Nyquist"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_EIS_curve_tests","text":"This function is used to test the accuracy of the EIS results. It compares the reconstructed Ucell_Fourier(t) from the Fourier transformation with the current density ifc(t), and displays Ucell(t) given by the model with the reconstructed Ucell_Fourier(t). Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Fourier_results ( dict ) \u2013 Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. Source code in modules/display_modules.py def plot_EIS_curve_tests(variables, operating_inputs, parameters, Fourier_results): \"\"\"This function is used to test the accuracy of the EIS results. It compares the reconstructed Ucell_Fourier(t) from the Fourier transformation with the current density ifc(t), and displays Ucell(t) given by the model with the reconstructed Ucell_Fourier(t). Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Fourier_results : dict Dictionary containing the Fourier transformation (FT) of the cell voltage and the current density, all amplitude values of the cell voltage calculated by the FT, the amplitude of the cell voltage at the frequency of the perturbation, all frequency values used vy the FT, the frequency of the perturbation, and the number of points used in the FT. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), variables['Ucell'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] i_EIS, ratio_EIS = parameters['i_EIS'], parameters['ratio_EIS'] t_EIS, f_EIS = parameters['t_EIS'], parameters['f_EIS'] max_step = parameters['max_step'] # Extraction of the Fourier results Ucell_Fourier, ifc_Fourier = Fourier_results['Ucell_Fourier'], Fourier_results['ifc_Fourier'] A_period_t, A = Fourier_results['A_period_t'], Fourier_results['A'] f, N = Fourier_results['f'], Fourier_results['N'] # Reconstructed Ucell with a cosinus form, and comparison of its form with the current density one. t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS = t_EIS f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS n_inf = np.where(t_new_start_EIS <= t[0])[0][-1] # The number of frequency changes which has been made. f_current = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) theta_U_t = np.angle(Ucell_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_i_t = np.angle(ifc_Fourier[0:N // 2]) # Recovery of all dephasing values calculated by fft theta_U = theta_U_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation theta_i = theta_i_t[np.argmax(A_period_t == A)] # Dephasing at the frequency of the perturbation print(\"Ucell:\", round(A_period_t[0], 4), ' + ', round(A, 6), \" * np.cos(2*np.pi*\", round(f, 4), \"*t + \", round(theta_U, 4), \"). \") print(\"Current:\", i_EIS, ' + ', ratio_EIS * i_EIS, \" * np.cos(2*np.pi*\", round(f_current[n_inf], 4), \"*t + \", round(theta_i, 4), \"). \\n\") # Display ifc(t) plt.figure(3) plt.subplot(2, 1, 1) # Creation of ifc_t n = len(t) ifc_t = np.zeros(n) for i in range(n): # Conversion in A/cm\u00b2 ifc_t[i] = current_density(t[i], parameters) / 1e4 # Plot of ifc_t plt.plot(t, ifc_t, color='blue', label='ifc') plt.xlabel('Time (s)') plt.ylabel('Current density (A/cm\u00b2)') plt.title('The current density\\nbehaviour over time') # Display Ucell(t) and compare it with the reconstructed Ucell_Fourier(t) from the Fourier transformation plt.subplot(2, 1, 2) Ucell_Fourier = A_period_t[0] + A * np.cos(2 * np.pi * f * t + theta_U) plt.plot(t, Ucell_t, color='blue', label='Ucell') plt.plot(t, Ucell_Fourier, color='black', label='Ucell_Fourier') plt.xlabel('Time (s)') plt.ylabel('Cell voltage (V)') plt.title('The cell voltage\\nbehaviour over time')","title":"plot_EIS_curve_tests"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_J","text":"This function plots the sorption and dissolved water flows as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the flows will be plotted. Source code in modules/display_modules.py def plot_J(variables, parameters, ax): \"\"\"This function plots the sorption and dissolved water flows as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the flows will be plotted. \"\"\" # Extraction of the variables t, S_sorp_acl_t, S_sorp_ccl_t = variables['t'], variables['S_sorp_acl'], variables['S_sorp_ccl'], J_lambda_mem_acl_t, J_lambda_mem_ccl_t = variables['J_lambda_mem_acl'], variables['J_lambda_mem_ccl'] # Extraction of the operating inputs and the parameters Hcl = parameters['Hcl'] # Plot the sorption and dissolved water flows: J J_sorp_acl, J_sorp_ccl = [x * Hcl for x in S_sorp_acl_t], [x * Hcl for x in S_sorp_ccl_t] # Conversion in # mol.m\u207b\u00b2.s\u207b\u00b9 for comparison ax.plot(t, J_sorp_acl, color=colors(2)) ax.plot(t, J_lambda_mem_acl_t, color=colors(3)) ax.plot(t, J_sorp_ccl, color=colors(4)) ax.plot(t, J_lambda_mem_ccl_t, color=colors(7)) ax.legend([r'$\\mathregular{J_{sorp,acl}}$', r'$\\mathregular{J_{\\lambda,mem,acl}}$', r'$\\mathregular{J_{sorp,ccl}}$', r'$\\mathregular{J_{\\lambda,mem,ccl}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Flows}$ $\\mathbf{J}$ $\\mathbf{\\left( mol.m^{-2}.s^{-1} \\right)}$', labelpad=3) ax.ticklabel_format(style='scientific', axis='y', scilimits=(0, 0)) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.02)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.02 / 5)) plt.show()","title":"plot_J"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_P","text":"This function plots the pressure at different spatial localisations as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the pressure will be plotted. Source code in modules/display_modules.py def plot_P(variables, ax): \"\"\"This function plots the pressure at different spatial localisations as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the pressure will be plotted. \"\"\" # Extraction of the variables t, Pagc_t, Pcgc_t = variables['t'], variables['Pagc'], variables['Pcgc'] Pasm_t, Paem_t, Pcsm_t, Pcem_t = variables['Pasm'], variables['Paem'], variables['Pcsm'], variables['Pcem'] # Conversion in atm Pagc_t, Pcgc_t, Pasm_t = [x / 1e5 for x in Pagc_t], [x / 1e5 for x in Pcgc_t], [x / 1e5 for x in Pasm_t] Paem_t, Pcsm_t, Pcem_t = [x / 1e5 for x in Paem_t], [x / 1e5 for x in Pcsm_t], [x / 1e5 for x in Pcem_t] # Plot the pressure at different spatial localisations: P ax.plot(t, Pagc_t, color=colors(0)) ax.plot(t, Pcgc_t, color=colors(6)) ax.plot(t, Pasm_t, color=colors(7)) ax.plot(t, Paem_t, color=colors(8)) ax.plot(t, Pcsm_t, color=colors(9)) ax.plot(t, Pcem_t, color=colors(3)) ax.legend([r'$\\mathregular{P_{agc}}$', r'$\\mathregular{P_{cgc}}$', r'$\\mathregular{P_{asm}}$', r'$\\mathregular{P_{aem}}$', r'$\\mathregular{P_{csm}}$', r'$\\mathregular{P_{cem}}$'], loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Pressure}$ $\\mathbf{P}$ $\\mathbf{\\left( bar \\right)}$', labelpad=3) ax.ticklabel_format(style='scientific', axis='y', scilimits=(0, 0)) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5e-4)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5e-4 / 5)) ax.set_ylim(1.99980, 2.00015)","title":"plot_P"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Phi_a","text":"This function plots the humidity at the anode side, at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_a(variables, operating_inputs, ax): \"\"\"This function plots the humidity at the anode side, at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t, C_v_agc_t = variables['t'], variables['C_v_agc'] Phi_asm_t, Phi_aem_t = variables['Phi_asm'], variables['Phi_aem'] # Extraction of the operating inputs Tfc, Phi_a_des = operating_inputs['Tfc'], operating_inputs['Phi_a_des'] # Calculate the humidity Phi Phi_agc_t = [0] * len(t) for i in range(len(t)): Phi_agc_t[i] = C_v_agc_t[i] * R * Tfc / Psat(Tfc) # Plot the humidity at different spatial localisations: Phi ax.plot(t, Phi_agc_t, color=colors(0), label=r'$\\mathregular{\\Phi_{agc}}$') ax.plot(t, Phi_asm_t, color=colors(1), label=r'$\\mathregular{\\Phi_{asm}}$') ax.plot(t, Phi_aem_t, color=colors(2), label=r'$\\mathregular{\\Phi_{aem}}$') ax.plot(t, [Phi_a_des]*len(t), color='black', label=r'$\\mathregular{\\Phi_{a,des}}$') ax.legend(loc='center right', bbox_to_anchor=(1, 0.67)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Humidity}$ $\\mathbf{at}$ $\\mathbf{the}$ $\\mathbf{anode}$ $\\mathbf{side}$ $\\mathbf{\\Phi}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5))","title":"plot_Phi_a"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Phi_c","text":"This function plots the humidity, at the cathode side, at different spatial localisations as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_c(variables, operating_inputs, ax): \"\"\"This function plots the humidity, at the cathode side, at different spatial localisations as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t, C_v_cgc_t = variables['t'], variables['C_v_cgc'] Phi_csm_t, Phi_cem_t = variables['Phi_csm'], variables['Phi_cem'] # Extraction of the operating inputs Tfc, Phi_c_des = operating_inputs['Tfc'], operating_inputs['Phi_c_des'] # Calculate the humidity Phi Phi_cgc_t = [0] * len(t) for i in range(len(t)): Phi_cgc_t[i] = C_v_cgc_t[i] * R * Tfc / Psat(Tfc) # Plot the humidity at different spatial localisations: Phi ax.plot(t, Phi_cgc_t, color=colors(0), label=r'$\\mathregular{\\Phi_{cgc}}$') ax.plot(t, Phi_csm_t, color=colors(1), label=r'$\\mathregular{\\Phi_{csm}}$') ax.plot(t, Phi_cem_t, color=colors(2), label=r'$\\mathregular{\\Phi_{cem}}$') ax.plot(t, [Phi_c_des]*len(t), color='black', label=r'$\\mathregular{\\Phi_{c,des}}$') ax.legend(loc='best') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Humidity}$ $\\mathbf{at}$ $\\mathbf{the}$ $\\mathbf{cathode}$ $\\mathbf{side}$ $\\mathbf{\\Phi}$', labelpad=3) # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5))","title":"plot_Phi_c"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Phi_des","text":"This function plots the controlled or uncontrolled desired humidity at the anode and cathode as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the humidity will be plotted. Source code in modules/display_modules.py def plot_Phi_des(variables, operating_inputs, parameters, ax): \"\"\"This function plots the controlled or uncontrolled desired humidity at the anode and cathode as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the humidity will be plotted. \"\"\" # Extraction of the variables t = variables['t'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] if parameters['type_control'] == \"Phi_des\": Phi_a_des, Phi_c_des = variables['Phi_a_des'], variables['Phi_c_des'] ax.set_ylabel(r'$\\mathbf{Controlled}$ $\\mathbf{inlet}$ $\\mathbf{humidity}$ $\\mathbf{\\Phi_{des}}$', labelpad=3) else: Phi_a_des, Phi_c_des = [operating_inputs['Phi_a_des']] * len(t), [operating_inputs['Phi_c_des']] * len(t) ax.set_ylabel(r'$\\mathbf{Uncontrolled}$ $\\mathbf{inlet}$ $\\mathbf{humidity}$ $\\mathbf{\\Phi_{des}}$', labelpad=3) # Plot Phi_des n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of ifc_t ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, Phi_c_des, color=colors(6), label=r'$\\mathregular{\\Phi_{c,des}}$') ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) if parameters['type_auxiliary'] == \"forced-convective_cathode_with_flow-through_anode\" or \\ parameters['type_auxiliary'] == \"no_auxiliary\": ax.plot(t, Phi_a_des, color=colors(0), label=r'$\\mathregular{\\Phi_{a,des}}$') ax.legend([r'$\\mathregular{\\Phi_{a,des}}$', r'$\\mathregular{\\Phi_{c,des}}$'], loc='best') else: ax.legend([r'$\\mathregular{\\Phi_{c,des}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.2)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.2 / 5)) ax.set_xlim(0, 4.1)","title":"plot_Phi_des"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_Ucell","text":"This function plots the cell voltage as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. ax ( Axes ) \u2013 Axes on which the cell voltage will be plotted. Source code in modules/display_modules.py def plot_Ucell(variables, ax): \"\"\"This function plots the cell voltage as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. ax : matplotlib.axes.Axes Axes on which the cell voltage will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = variables['t'], variables['Ucell'] # Plot the cell voltage: Ucell ax.plot(t, Ucell_t, color=colors(0), label=r'$\\mathregular{U_{cell}}$') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Cell}$ $\\mathbf{voltage}$ $\\mathbf{U_{cell}}$ $\\mathbf{\\left( V \\right)}$', labelpad=3) ax.legend([r'$\\mathregular{U_{cell}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.05)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.05 / 5))","title":"plot_Ucell"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_cell_efficiency","text":"This function plots the fuel cell efficiency eta_fc as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the fuel cell efficiency. ax ( Axes ) \u2013 Axes on which the fuel cell efficiency will be plotted. Source code in modules/display_modules.py def plot_cell_efficiency(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the fuel cell efficiency eta_fc as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the fuel cell efficiency. ax : matplotlib.axes.Axes Axes on which the fuel cell efficiency will be plotted. \"\"\" # Extraction of the variables t, Ucell_t, lambda_mem_t = variables['t'], variables['Ucell'], variables['lambda_mem'] C_H2_acl_t, C_O2_ccl_t = variables['C_H2_acl'], variables['C_O2_ccl'] # Extraction of the operating inputs and the parameters current_density, Tfc = operating_inputs['current_density'], operating_inputs['Tfc'] Hmem, kappa_co = parameters['Hmem'], parameters['kappa_co'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control = parameters['type_control'] # Creation of the fuel cell efficiency: eta_fc ifc_t, Pfc_t, eta_fc_t = np.zeros(n), np.zeros(n), np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 Pfc_t[i] = Ucell_t[i] * ifc_t[i] Ueq = E0 - 8.5e-4 * (Tfc - 298.15) + R * Tfc / (2 * F) * (np.log(R * Tfc * C_H2_acl_t[i] / Pref) + 0.5 * np.log(R * Tfc * C_O2_ccl_t[i] / Pref)) i_H2 = 2 * F * R * Tfc / Hmem * C_H2_acl_t[i] * k_H2(lambda_mem_t[i], Tfc, kappa_co) i_O2 = 4 * F * R * Tfc / Hmem * C_O2_ccl_t[i] * k_O2(lambda_mem_t[i], Tfc, kappa_co) i_n = (i_H2 + i_O2) / 1e4 # Conversion in A/cm\u00b2 eta_fc_t[i] = Pfc_t[i] / (Ueq * (ifc_t[i] + i_n)) # Plot of the fuel cell efficiency: eta_fc plot_specific_line(ifc_t, eta_fc_t, type_fuel_cell, type_auxiliary, type_control, None, ax) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=0) ax.set_ylabel(r'$\\mathbf{Fuel}$ $\\mathbf{cell}$ $\\mathbf{efficiency}$ $\\mathbf{\\eta_{fc}}$', labelpad=0) ax.legend(loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) ax.set_xlim(0, 4.1) ax.set_ylim(0, 0.7)","title":"plot_cell_efficiency"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_general_instructions","text":"This function adds the common instructions for all the plots displayed by AlphaPEM to the ax object. Parameters: ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_general_instructions(ax): \"\"\"This function adds the common instructions for all the plots displayed by AlphaPEM to the ax object. Parameters ---------- ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" ax.tick_params(axis='both', which='major', size=10, width=1.5, direction='out') ax.tick_params(axis='both', which='minor', size=5, width=1.5, direction='out') plt.tight_layout() # Adjust layout to prevent overlap between labels and the figure plt.show() # Show the figure","title":"plot_general_instructions"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_ifc","text":"This function plots the current density as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the current density. ax ( Axes ) \u2013 Axes on which the current density will be plotted. Source code in modules/display_modules.py def plot_ifc(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the current density as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the current density. ax : matplotlib.axes.Axes Axes on which the current density will be plotted. \"\"\" # Extraction of the variables t = variables['t'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] # Plot the current density: ifc ifc_t = np.zeros(n) for i in range(n): # Creation of ifc_t ifc_t[i] = current_density(t[i], parameters) / 10000 # Conversion in A/cm\u00b2 ax.plot(t, ifc_t, color=colors(0), label=r'$\\mathregular{i_{fc}}$') ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) ax.legend([r'$\\mathregular{i_{fc}}$'], loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5))","title":"plot_ifc"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_lambda","text":"This function plots the water content at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the water content will be plotted. Source code in modules/display_modules.py def plot_lambda(variables, operating_inputs, parameters, ax): \"\"\"This function plots the water content at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the water content will be plotted. \"\"\" # Extraction of the variables t, lambda_acl_t = variables['t'], variables['lambda_acl'] lambda_mem_t, lambda_ccl_t = variables['lambda_mem'], variables['lambda_ccl'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] type_current = parameters['type_current'] # Plot the water content at different spatial localisations: lambda if type_current == \"polarization\": n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of i_fc ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, lambda_acl_t, color=colors(2)) ax.plot(ifc_t, lambda_mem_t, color=colors(3)) ax.plot(ifc_t, lambda_ccl_t, color=colors(4)) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) else: ax.plot(t, lambda_acl_t, color=colors(2)) ax.plot(t, lambda_mem_t, color=colors(3)) ax.plot(t, lambda_ccl_t, color=colors(4)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Water}$ $\\mathbf{content}$ $\\mathbf{\\lambda}$', labelpad=3) ax.legend([r'$\\mathregular{\\lambda_{acl}}$', r'$\\mathregular{\\lambda_{mem}}$', r'$\\mathregular{\\lambda_{ccl}}$'], loc='best') # Plot instructions plot_general_instructions(ax) if type_current == \"polarization\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) else: ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(3)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(3 / 5))","title":"plot_lambda"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_pola_instructions","text":"This function adds the specific instructions for polarisation plots according to the type_input to the ax object. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. ax ( Axes ) \u2013 Axes on which the instructions will be added. Source code in modules/display_modules.py def plot_pola_instructions(type_fuel_cell, ax): \"\"\"This function adds the specific instructions for polarisation plots according to the type_input to the ax object. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. ax : matplotlib.axes.Axes Axes on which the instructions will be added. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or \\ type_fuel_cell == \"EH-31_2.25\" or type_fuel_cell == \"EH-31_2.5\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.1)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.1 / 5)) ax.set_xlim(0, 3.0) ax.set_ylim(0.4, 1.04) # For LF fuel cell elif type_fuel_cell == \"LF\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.4)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.4 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.2)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.2 / 5)) ax.set_xlim(-0.05, 1.6) ax.set_ylim(0, 1.0) # For other fuel cell else: pass","title":"plot_pola_instructions"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_polarisation_curve","text":"This function plots the model polarisation curve, and compare it to the experimental one (if it exists). The polarisation curve is a classical representation of the cell performances, showing the cell voltage as a function of the current density. To generate it, the current density is increased step by step, and the cell voltage is recorded at each step. The time for which this point is captured is determined using the following approach: at the beginning of each load, a delta_t_load_pola time is needed to raise the current density to its next value. Subsequently, a delta_t_break_pola time is observed to ensure the dynamic stability of the stack's variables before initiating a new load. Ideally, each polarisation point should be recorded at the end of each delta_t_break_pola time. However, due to the design of the increments to minimize program instability (as observed in step_current function), the end of each delta_t_break_pola time corresponds to the beginning of a new load. To ensure a stationary operation and accurate polarisation point measurements, it is recommended to take the polarisation point just before by subtracting a delta_t value from it. This adjustment allows for stable and consistent measurements during the stationary period. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the polarisation curve will be plotted. Source code in modules/display_modules.py def plot_polarisation_curve(variables, operating_inputs, parameters, ax): \"\"\" This function plots the model polarisation curve, and compare it to the experimental one (if it exists). The polarisation curve is a classical representation of the cell performances, showing the cell voltage as a function of the current density. To generate it, the current density is increased step by step, and the cell voltage is recorded at each step. The time for which this point is captured is determined using the following approach: at the beginning of each load, a delta_t_load_pola time is needed to raise the current density to its next value. Subsequently, a delta_t_break_pola time is observed to ensure the dynamic stability of the stack's variables before initiating a new load. Ideally, each polarisation point should be recorded at the end of each delta_t_break_pola time. However, due to the design of the increments to minimize program instability (as observed in step_current function), the end of each delta_t_break_pola time corresponds to the beginning of a new load. To ensure a stationary operation and accurate polarisation point measurements, it is recommended to take the polarisation point just before by subtracting a delta_t value from it. This adjustment allows for stable and consistent measurements during the stationary period. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the polarisation curve will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = np.array(variables['t']), np.array(variables['Ucell']) # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] t_step, i_step, i_max_pola = parameters['t_step'], parameters['i_step'], parameters['i_max_pola'] delta_pola = parameters['delta_pola'] i_EIS, t_EIS, f_EIS = parameters['i_EIS'], parameters['t_EIS'], parameters['f_EIS'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control, type_plot = parameters['type_control'], parameters['type_plot'] if type_plot == \"fixed\": # Creation of ifc_t n = len(t) ifc_t = np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 # Recovery of ifc and Ucell from the model after each stack stabilisation delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola nb_loads = int(i_max_pola / delta_i_pola + 1) # Number of loads which are made ifc_discretized = np.zeros(nb_loads) Ucell_discretized = np.zeros(nb_loads) for i in range(nb_loads): t_load = delta_t_ini_pola + (i + 1) * (delta_t_load_pola + delta_t_break_pola) - delta_t_break_pola / 10 # # time for measurement idx = (np.abs(t - t_load)).argmin() # the corresponding index ifc_discretized[i] = ifc_t[idx] # the last value at the end of each load Ucell_discretized[i] = Ucell_t[idx] # the last value at the end of each load # Plot the experimental polarization curve and calculate the simulation error compared with experimental data if type_fuel_cell != \"manual_setup\" and \\ type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": # Experimental points are accessible # Plot of the experimental polarization curve i_exp_t, U_exp_t = pola_exp_values(type_fuel_cell) plot_experimental_polarisation_curve(type_fuel_cell, i_exp_t, U_exp_t, ax) # Calculate the simulation error compared with experimental data # i_fc and Ucell are reduced to remain within experimental limits for comparison i_fc_reduced = ifc_discretized[(ifc_discretized >= i_exp_t[0]) & (ifc_discretized <= i_exp_t[-1])] Ucell_reduced = Ucell_discretized[(ifc_discretized >= i_exp_t[0]) & (ifc_discretized <= i_exp_t[-1])] # Experimental points are interpolated to correspond to the model points U_exp_interpolated = interp1d(i_exp_t, U_exp_t, kind='linear')(i_fc_reduced) sim_error = calculate_simulation_error(Ucell_reduced, U_exp_interpolated) else: sim_error = None # Plot the model polarisation curve plot_specific_line(ifc_discretized, Ucell_discretized, type_fuel_cell, type_auxiliary, type_control, sim_error, ax) plot_pola_instructions(type_fuel_cell, ax) else: # type_plot == \"dynamic\" # Plot of the polarisation curve produced by the model delta_t_load_pola, delta_t_break_pola, delta_i_pola, delta_t_ini_pola = delta_pola idx = (np.abs(t - t[-1] + delta_t_break_pola / 10)).argmin() # index for polarisation measurement ifc = np.array(current_density(t[idx], parameters) / 1e4) # time for polarisation measurement Ucell = np.array(Ucell_t[idx]) # voltage measurement ax.plot(ifc, Ucell, 'og', markersize=2) # Add the common instructions for the plot ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Cell}$ $\\mathbf{voltage}$ $\\mathbf{U_{cell}}$ $\\mathbf{\\left( V \\right)}$', labelpad=3) plot_general_instructions(ax) if type_plot == \"fixed\": ax.legend(loc='best')","title":"plot_polarisation_curve"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_power_density_curve","text":"This function plots the power density curve Pfc, produced by a cell, as a function of the current density. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. n ( int ) \u2013 Number of points used to plot the power density curve. ax ( Axes ) \u2013 Axes on which the power density curve will be plotted. Source code in modules/display_modules.py def plot_power_density_curve(variables, operating_inputs, parameters, n, ax): \"\"\"This function plots the power density curve Pfc, produced by a cell, as a function of the current density. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. n : int Number of points used to plot the power density curve. ax : matplotlib.axes.Axes Axes on which the power density curve will be plotted. \"\"\" # Extraction of the variables t, Ucell_t = variables['t'], variables['Ucell'] # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] type_fuel_cell, type_auxiliary = parameters['type_fuel_cell'], parameters['type_auxiliary'] type_control = parameters['type_control'] # Creation of the power density function: Pfc ifc_t, Pfc_t = np.zeros(n), np.zeros(n) for i in range(n): ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 Pfc_t[i] = Ucell_t[i] * ifc_t[i] # Plot of the power density function: Pfc plot_specific_line(ifc_t, Pfc_t, type_fuel_cell, type_auxiliary, type_control, None, ax) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=0) ax.set_ylabel(r'$\\mathbf{Fuel}$ $\\mathbf{cell}$ $\\mathbf{power}$ $\\mathbf{density}$ $\\mathbf{P_{fc}}$ $\\mathbf{\\left( W.cm^{-2} \\right)}$', labelpad=0) ax.legend(loc='best') # Plot instructions plot_general_instructions(ax) ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.3)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.3 / 5)) ax.set_xlim(0, 4.1) ax.set_ylim(0, 2.1)","title":"plot_power_density_curve"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_s","text":"This function plots the liquid water saturation at different spatial localisations, as a function of time. Parameters: variables ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. ax ( Axes ) \u2013 Axes on which the liquid water saturation will be plotted. Source code in modules/display_modules.py def plot_s(variables, operating_inputs, parameters, ax): \"\"\"This function plots the liquid water saturation at different spatial localisations, as a function of time. Parameters ---------- variables : dict Variables calculated by the solver. They correspond to the fuel cell internal states. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. ax : matplotlib.axes.Axes Axes on which the liquid water saturation will be plotted. \"\"\" # Extraction of the operating inputs and the parameters current_density = operating_inputs['current_density'] n_gdl, type_current = parameters['n_gdl'], parameters['type_current'] # Extraction of the variables t, s_agdl_t, s_acl_t = variables['t'], variables[f's_agdl_{n_gdl // 2}'], variables['s_acl'] s_ccl_t, s_cgdl_t = variables['s_ccl'], variables[f's_cgdl_{n_gdl // 2}'] # Plot the liquid water saturation at different spatial localisations: s if type_current == \"polarization\": n = len(t) ifc_t = np.zeros(n) for i in range(n): # Creation of i_fc ifc_t[i] = current_density(t[i], parameters) / 1e4 # Conversion in A/cm\u00b2 ax.plot(ifc_t, s_agdl_t, color=colors(1)) ax.plot(ifc_t, s_acl_t, color=colors(2)) ax.plot(ifc_t, s_ccl_t, color=colors(4)) ax.plot(ifc_t, s_cgdl_t, color=colors(5)) ax.set_xlabel(r'$\\mathbf{Current}$ $\\mathbf{density}$ $\\mathbf{i_{fc}}$ $\\mathbf{\\left( A.cm^{-2} \\right)}$', labelpad=3) else: ax.plot(t, s_agdl_t, color=colors(1)) ax.plot(t, s_acl_t, color=colors(2)) ax.plot(t, s_ccl_t, color=colors(4)) ax.plot(t, s_cgdl_t, color=colors(5)) ax.set_xlabel(r'$\\mathbf{Time}$ $\\mathbf{t}$ $\\mathbf{\\left( s \\right)}$', labelpad=3) ax.set_ylabel(r'$\\mathbf{Liquid}$ $\\mathbf{water}$ $\\mathbf{saturation}$ $\\mathbf{s}$', labelpad=3) ax.legend([r'$\\mathregular{s_{agdl}}$', r'$\\mathregular{s_{acl}}$', r'$\\mathregular{s_{ccl}}$', r'$\\mathregular{s_{cgdl}}$'], loc='best') # Plot instructions plot_general_instructions(ax) if type_current == \"polarization\": ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5 / 5)) else: ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(200)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(200 / 5)) ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.04)) ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.04 / 5))","title":"plot_s"},{"location":"functions/modules/display_modules/#modules.display_modules.plot_specific_line","text":"This function adds the appropriate plot configuration according to the type_input to the ax object. Parameters: x ( ndarray ) \u2013 x-axis values. y ( ndarray ) \u2013 y-axis values. type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. type_auxiliary ( str ) \u2013 Type of auxiliary system. type_control ( str ) \u2013 Type of control system. sim_error ( float ) \u2013 Simulation error between the simulated cell voltage and the experimental cell voltage (in %). ax ( Axes ) \u2013 Axes on which the line will be plotted. Source code in modules/display_modules.py def plot_specific_line(x, y, type_fuel_cell, type_auxiliary, type_control, sim_error, ax): \"\"\" This function adds the appropriate plot configuration according to the type_input to the ax object. Parameters ---------- x : numpy.ndarray x-axis values. y : numpy.ndarray y-axis values. type_fuel_cell : str Type of fuel cell configuration. type_auxiliary : str Type of auxiliary system. type_control : str Type of control system. sim_error : float Simulation error between the simulated cell voltage and the experimental cell voltage (in %). ax : matplotlib.axes.Axes Axes on which the line will be plotted. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": if type_fuel_cell == \"EH-31_1.5\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(0), label='Sim. - P = 1.5 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_1.5\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(0), label='Sim. - P = 1.5 bar') elif type_fuel_cell == \"EH-31_2.0\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, '--', color=colors(1), label='Sim. - P = 2.0 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.0\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": if type_control == \"Phi_des\": ax.plot(x, y, color=colors(5), label=r'Sim. - P = 2.0 bar - controlled $\\mathregular{\\Phi_{des}}$') else: ax.plot(x, y, color=colors(1), label=r'Sim. - P = 2.0 bar - uncontrolled $\\mathregular{\\Phi_{des}}$') elif type_fuel_cell == \"EH-31_2.25\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, '--', color=colors(2), label='Sim. - P = 2.25 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.25\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(2), label='Sim. - P = 2.25 bar') elif type_fuel_cell == \"EH-31_2.5\" and type_auxiliary == \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(3), label='Sim - P = 2.5 bar' + r' - $\u0394U_{max}$ =' f' {sim_error} %') elif type_fuel_cell == \"EH-31_2.5\" and type_auxiliary != \"forced-convective_cathode_with_flow-through_anode\": ax.plot(x, y, color=colors(3), label='Sim - P = 2.5 bar') # For LF fuel cell elif type_fuel_cell == \"LF\": ax.plot(x, y, color=colors(0), label='Simulation') # For other fuel cell else: ax.plot(x, y, color=colors(0), label='Simulation')","title":"plot_specific_line"},{"location":"functions/modules/flows_modules/","text":"Flows modules This module is used to calculate intermediate values for the flows calculation. flows_int_values(sv, operating_inputs, parameters) This functions calculates intermediate values for the flows calculation. Parameters: sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). s_agdl_agdl ( list ) \u2013 Mean value of the saturated liquid water variable in the anode GDL between two adjacent GDL nodes. s_agdl_acl ( float ) \u2013 Mean value of the saturated liquid water variable between the last GDL node and the anode CL. s_ccl_cgdl ( float ) \u2013 Mean value of the saturated liquid water variable between the cathode CL and the first GDL node. s_cgdl_cgdl ( list ) \u2013 Mean value of the saturated liquid water variable in the cathode GDL between two adjacent GDL nodes. epsilon_mean ( float ) \u2013 Mean value of the porosity in the GDL and the CL. theta_c_mean ( float ) \u2013 Mean value of the contact angle in the GDL and the CL. lambda_acl_mem ( float ) \u2013 Mean value of the dissolved water variable between the anode CL and the membrane. lambda_mem_ccl ( float ) \u2013 Mean value of the dissolved water variable between the membrane and the cathode CL. Pagc_agdl ( float ) \u2013 Mean value of the pressure between the anode gas channel and the first GDL node. Pagdl_agdl ( list ) \u2013 Mean value of the pressure in the anode GDL between two adjacent GDL nodes. Pagdl_acl ( float ) \u2013 Mean value of the pressure between the last GDL node and the anode CL. Pccl_cgdl ( float ) \u2013 Mean value of the pressure between the cathode CL and the first GDL node. Pcgdl_cgdl ( list ) \u2013 Mean value of the pressure in the cathode GDL between two adjacent GDL nodes. Pcgdl_cgc ( float ) \u2013 Mean value of the pressure between the last GDL node and the cathode gas channel. nu_l ( float ) \u2013 Liquid water kinematic viscosity (m\u00b2.s-1). Source code in modules/flows_modules.py def flows_int_values(sv, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the flows calculation. Parameters ---------- sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). s_agdl_agdl : list Mean value of the saturated liquid water variable in the anode GDL between two adjacent GDL nodes. s_agdl_acl : float Mean value of the saturated liquid water variable between the last GDL node and the anode CL. s_ccl_cgdl : float Mean value of the saturated liquid water variable between the cathode CL and the first GDL node. s_cgdl_cgdl : list Mean value of the saturated liquid water variable in the cathode GDL between two adjacent GDL nodes. epsilon_mean : float Mean value of the porosity in the GDL and the CL. theta_c_mean : float Mean value of the contact angle in the GDL and the CL. lambda_acl_mem : float Mean value of the dissolved water variable between the anode CL and the membrane. lambda_mem_ccl : float Mean value of the dissolved water variable between the membrane and the cathode CL. Pagc_agdl : float Mean value of the pressure between the anode gas channel and the first GDL node. Pagdl_agdl : list Mean value of the pressure in the anode GDL between two adjacent GDL nodes. Pagdl_acl : float Mean value of the pressure between the last GDL node and the anode CL. Pccl_cgdl : float Mean value of the pressure between the cathode CL and the first GDL node. Pcgdl_cgdl : list Mean value of the pressure in the cathode GDL between two adjacent GDL nodes. Pcgdl_cgc : float Mean value of the pressure between the last GDL node and the cathode gas channel. nu_l : float Liquid water kinematic viscosity (m\u00b2.s-1). \"\"\" # Extraction of the variables C_v_agc, C_v_acl, C_v_ccl, C_v_cgc = sv['C_v_agc'], sv['C_v_acl'], sv['C_v_ccl'], sv['C_v_cgc'] s_acl, s_ccl = sv['s_acl'], sv['s_ccl'] lambda_acl, lambda_mem, lambda_ccl = sv['lambda_acl'], sv['lambda_mem'], sv['lambda_ccl'] C_H2_agc, C_H2_acl, C_O2_ccl, C_O2_cgc = sv['C_H2_agc'], sv['C_H2_acl'], sv['C_O2_ccl'], sv['C_O2_cgc'] C_N2 = sv['C_N2'] # Extraction of the operating inputs and the parameters Tfc = operating_inputs['Tfc'] epsilon_gdl, n_gdl = parameters['epsilon_gdl'], parameters['n_gdl'] # Pressures in the stack Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pagdl = [(sv[f'C_v_agdl_{i}'] + sv[f'C_H2_agdl_{i}']) * R * Tfc for i in range(1, n_gdl + 1)] Pacl = (C_v_acl + C_H2_acl) * R * Tfc Pccl = (C_v_ccl + C_O2_ccl + C_N2) * R * Tfc Pcgdl = [(sv[f'C_v_cgdl_{i}'] + sv[f'C_O2_cgdl_{i}'] + C_N2) * R * Tfc for i in range(1, n_gdl + 1)] Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Mean values ... # ... of the saturated liquid water variable s_agdl_agdl = [None] + [sv[f's_agdl_{i}'] / 2 + sv[f's_agdl_{i + 1}'] / 2 for i in range(1, n_gdl)] s_agdl_acl = sv[f's_agdl_{n_gdl}'] / 2 + s_acl / 2 s_ccl_cgdl = s_ccl / 2 + sv['s_cgdl_1'] / 2 s_cgdl_cgdl = [None] + [sv[f's_cgdl_{i}'] / 2 + sv[f's_cgdl_{i + 1}'] / 2 for i in range(1, n_gdl)] # ... of the porosity and the contact angle epsilon_mean = epsilon_gdl / 2 + epsilon_cl / 2 theta_c_mean = theta_c_gdl / 2 + theta_c_cl / 2 # ... of the dissolved water variable lambda_acl_mem = lambda_acl / 2 + lambda_mem / 2 lambda_mem_ccl = lambda_mem / 2 + lambda_ccl / 2 # ... of the pressure Pagc_agdl = Pagc / 2 + Pagdl[0] / 2 Pagdl_agdl = [None] + [Pagdl[i] / 2 + Pagdl[i + 1] / 2 for i in range(0, n_gdl - 1)] Pagdl_acl = Pagdl[-1] / 2 + Pacl / 2 Pccl_cgdl = Pccl / 2 + Pcgdl[0] / 2 Pcgdl_cgdl = [None] + [Pcgdl[i] / 2 + Pcgdl[i + 1] / 2 for i in range(0, n_gdl - 1)] Pcgdl_cgc = Pcgdl[n_gdl - 1] / 2 + Pcgc / 2 return (Pagc, Pcgc, s_agdl_agdl, s_agdl_acl, s_ccl_cgdl, s_cgdl_cgdl, epsilon_mean, theta_c_mean, lambda_acl_mem, lambda_mem_ccl, Pagc_agdl, Pagdl_agdl, Pagdl_acl, Pccl_cgdl, Pcgdl_cgdl, Pcgdl_cgc, nu_l(Tfc))","title":"Flows modules"},{"location":"functions/modules/flows_modules/#flows-modules","text":"This module is used to calculate intermediate values for the flows calculation.","title":"Flows modules"},{"location":"functions/modules/flows_modules/#modules.flows_modules.flows_int_values","text":"This functions calculates intermediate values for the flows calculation. Parameters: sv ( dict ) \u2013 Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. operating_inputs ( dict ) \u2013 Operating inputs of the fuel cell. parameters ( dict ) \u2013 Parameters of the fuel cell model. Returns: Pagc ( float ) \u2013 Global pressure in the anode gas channel (Pa). Pcgc ( float ) \u2013 Global pressure in the cathode gas channel (Pa). s_agdl_agdl ( list ) \u2013 Mean value of the saturated liquid water variable in the anode GDL between two adjacent GDL nodes. s_agdl_acl ( float ) \u2013 Mean value of the saturated liquid water variable between the last GDL node and the anode CL. s_ccl_cgdl ( float ) \u2013 Mean value of the saturated liquid water variable between the cathode CL and the first GDL node. s_cgdl_cgdl ( list ) \u2013 Mean value of the saturated liquid water variable in the cathode GDL between two adjacent GDL nodes. epsilon_mean ( float ) \u2013 Mean value of the porosity in the GDL and the CL. theta_c_mean ( float ) \u2013 Mean value of the contact angle in the GDL and the CL. lambda_acl_mem ( float ) \u2013 Mean value of the dissolved water variable between the anode CL and the membrane. lambda_mem_ccl ( float ) \u2013 Mean value of the dissolved water variable between the membrane and the cathode CL. Pagc_agdl ( float ) \u2013 Mean value of the pressure between the anode gas channel and the first GDL node. Pagdl_agdl ( list ) \u2013 Mean value of the pressure in the anode GDL between two adjacent GDL nodes. Pagdl_acl ( float ) \u2013 Mean value of the pressure between the last GDL node and the anode CL. Pccl_cgdl ( float ) \u2013 Mean value of the pressure between the cathode CL and the first GDL node. Pcgdl_cgdl ( list ) \u2013 Mean value of the pressure in the cathode GDL between two adjacent GDL nodes. Pcgdl_cgc ( float ) \u2013 Mean value of the pressure between the last GDL node and the cathode gas channel. nu_l ( float ) \u2013 Liquid water kinematic viscosity (m\u00b2.s-1). Source code in modules/flows_modules.py def flows_int_values(sv, operating_inputs, parameters): \"\"\"This functions calculates intermediate values for the flows calculation. Parameters ---------- sv : dict Variables calculated by the solver. They correspond to the fuel cell internal states. sv is a contraction of solver_variables for enhanced readability. operating_inputs : dict Operating inputs of the fuel cell. parameters : dict Parameters of the fuel cell model. Returns ------- Pagc : float Global pressure in the anode gas channel (Pa). Pcgc : float Global pressure in the cathode gas channel (Pa). s_agdl_agdl : list Mean value of the saturated liquid water variable in the anode GDL between two adjacent GDL nodes. s_agdl_acl : float Mean value of the saturated liquid water variable between the last GDL node and the anode CL. s_ccl_cgdl : float Mean value of the saturated liquid water variable between the cathode CL and the first GDL node. s_cgdl_cgdl : list Mean value of the saturated liquid water variable in the cathode GDL between two adjacent GDL nodes. epsilon_mean : float Mean value of the porosity in the GDL and the CL. theta_c_mean : float Mean value of the contact angle in the GDL and the CL. lambda_acl_mem : float Mean value of the dissolved water variable between the anode CL and the membrane. lambda_mem_ccl : float Mean value of the dissolved water variable between the membrane and the cathode CL. Pagc_agdl : float Mean value of the pressure between the anode gas channel and the first GDL node. Pagdl_agdl : list Mean value of the pressure in the anode GDL between two adjacent GDL nodes. Pagdl_acl : float Mean value of the pressure between the last GDL node and the anode CL. Pccl_cgdl : float Mean value of the pressure between the cathode CL and the first GDL node. Pcgdl_cgdl : list Mean value of the pressure in the cathode GDL between two adjacent GDL nodes. Pcgdl_cgc : float Mean value of the pressure between the last GDL node and the cathode gas channel. nu_l : float Liquid water kinematic viscosity (m\u00b2.s-1). \"\"\" # Extraction of the variables C_v_agc, C_v_acl, C_v_ccl, C_v_cgc = sv['C_v_agc'], sv['C_v_acl'], sv['C_v_ccl'], sv['C_v_cgc'] s_acl, s_ccl = sv['s_acl'], sv['s_ccl'] lambda_acl, lambda_mem, lambda_ccl = sv['lambda_acl'], sv['lambda_mem'], sv['lambda_ccl'] C_H2_agc, C_H2_acl, C_O2_ccl, C_O2_cgc = sv['C_H2_agc'], sv['C_H2_acl'], sv['C_O2_ccl'], sv['C_O2_cgc'] C_N2 = sv['C_N2'] # Extraction of the operating inputs and the parameters Tfc = operating_inputs['Tfc'] epsilon_gdl, n_gdl = parameters['epsilon_gdl'], parameters['n_gdl'] # Pressures in the stack Pagc = (C_v_agc + C_H2_agc) * R * Tfc Pagdl = [(sv[f'C_v_agdl_{i}'] + sv[f'C_H2_agdl_{i}']) * R * Tfc for i in range(1, n_gdl + 1)] Pacl = (C_v_acl + C_H2_acl) * R * Tfc Pccl = (C_v_ccl + C_O2_ccl + C_N2) * R * Tfc Pcgdl = [(sv[f'C_v_cgdl_{i}'] + sv[f'C_O2_cgdl_{i}'] + C_N2) * R * Tfc for i in range(1, n_gdl + 1)] Pcgc = (C_v_cgc + C_O2_cgc + C_N2) * R * Tfc # Mean values ... # ... of the saturated liquid water variable s_agdl_agdl = [None] + [sv[f's_agdl_{i}'] / 2 + sv[f's_agdl_{i + 1}'] / 2 for i in range(1, n_gdl)] s_agdl_acl = sv[f's_agdl_{n_gdl}'] / 2 + s_acl / 2 s_ccl_cgdl = s_ccl / 2 + sv['s_cgdl_1'] / 2 s_cgdl_cgdl = [None] + [sv[f's_cgdl_{i}'] / 2 + sv[f's_cgdl_{i + 1}'] / 2 for i in range(1, n_gdl)] # ... of the porosity and the contact angle epsilon_mean = epsilon_gdl / 2 + epsilon_cl / 2 theta_c_mean = theta_c_gdl / 2 + theta_c_cl / 2 # ... of the dissolved water variable lambda_acl_mem = lambda_acl / 2 + lambda_mem / 2 lambda_mem_ccl = lambda_mem / 2 + lambda_ccl / 2 # ... of the pressure Pagc_agdl = Pagc / 2 + Pagdl[0] / 2 Pagdl_agdl = [None] + [Pagdl[i] / 2 + Pagdl[i + 1] / 2 for i in range(0, n_gdl - 1)] Pagdl_acl = Pagdl[-1] / 2 + Pacl / 2 Pccl_cgdl = Pccl / 2 + Pcgdl[0] / 2 Pcgdl_cgdl = [None] + [Pcgdl[i] / 2 + Pcgdl[i + 1] / 2 for i in range(0, n_gdl - 1)] Pcgdl_cgc = Pcgdl[n_gdl - 1] / 2 + Pcgc / 2 return (Pagc, Pcgc, s_agdl_agdl, s_agdl_acl, s_ccl_cgdl, s_cgdl_cgdl, epsilon_mean, theta_c_mean, lambda_acl_mem, lambda_mem_ccl, Pagc_agdl, Pagdl_agdl, Pagdl_acl, Pccl_cgdl, Pcgdl_cgdl, Pcgdl_cgc, nu_l(Tfc))","title":"flows_int_values"},{"location":"functions/modules/main_modules/","text":"Main modules This module contains some of the required functions for the main.py file. figures_preparation(type_current, type_display) This function create the required figures and axes according to the type_current and type_display. Parameters: type_current ( str ) \u2013 Type of current density function. type_display ( str ) \u2013 Type of display. Returns: fig1 ( Figure ) \u2013 Figure for the first plot. ax1 ( AxesSubplot ) \u2013 Axes for the first plot. fig2 ( Figure ) \u2013 Figure for the second plot. ax2 ( AxesSubplot ) \u2013 Axes for the second plot. Source code in modules/main_modules.py def figures_preparation(type_current, type_display): \"\"\" This function create the required figures and axes according to the type_current and type_display. Parameters ---------- type_current : str Type of current density function. type_display : str Type of display. Returns ------- fig1 : matplotlib.figure.Figure Figure for the first plot. ax1 : matplotlib.axes._subplots.AxesSubplot Axes for the first plot. fig2 : matplotlib.figure.Figure Figure for the second plot. ax2 : matplotlib.axes._subplots.AxesSubplot Axes for the second plot. \"\"\" mpl.rcParams['font.family'] = 'cmr10' # 'cmr10' for English characters and 'DejaVu Serif' for French ones mpl.rcParams['axes.formatter.use_mathtext'] = True # For the scientific notation mpl.rcParams['lines.linewidth'] = 2.0 mpl.rcParams['lines.markersize'] = 5.0 if type_display == \"no_display\": fig1, ax1 = None, None fig2, ax2 = None, None fig3, ax3 = None, None # For the step current if type_current == \"step\": if type_display == \"multiple\": # saving instruction is directly implemented within AlphaPEM.Display here. mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = None, None # Here, additional plots are unnecessary fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 13 # Font size for all text fig1, ax1 = plt.subplots(3, 3, figsize=(14, 14)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) # For the polarization curve elif type_current == \"polarization\": if type_display == \"multiple\": mpl.rcParams['font.size'] = 11 # Font size for all text fig1, ax1 = plt.subplots(1, 3, figsize=(14, 4.7)) fig2, ax2 = plt.subplots(1, 3, figsize=(14, 4.7)) fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = plt.subplots(figsize=(8, 8)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary # For the EIS curve elif type_current == \"EIS\": if type_display == \"multiple\": mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = plt.subplots(figsize=(8, 8)) fig2, ax2 = plt.subplots(figsize=(8, 8)) fig3, ax3 = plt.subplots(figsize=(8, 8)) elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 13 # Font size for all text fig1, ax1 = plt.subplots(1, 3, figsize=(14, 4.7)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) return fig1, ax1, fig2, ax2, fig3, ax3 plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3) This function saves the plots in the mentioned folder. The names of the files are automatically generated according to the type_current and the type_display. Parameters: type_fuel_cell ( str ) \u2013 Type of the fuel cell. type_current ( str ) \u2013 Type of current density function. type_display ( str ) \u2013 Type of display. fig1 ( Figure ) \u2013 Figure for the first plot. fig2 ( Figure ) \u2013 Figure for the second plot. Source code in modules/main_modules.py def plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3): \"\"\"This function saves the plots in the mentioned folder. The names of the files are automatically generated according to the type_current and the type_display. Parameters ---------- type_fuel_cell : str Type of the fuel cell. type_current : str Type of current density function. type_display : str Type of display. fig1 : matplotlib.figure.Figure Figure for the first plot. fig2 : matplotlib.figure.Figure Figure for the second plot. \"\"\" # Folder name subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 else type_fuel_cell # For the step current if type_current == \"step\": if type_display == \"multiple\": pass # saving instruction is directly implemented within AlphaPEM.Display for this situation. if type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"step_current_syn_1.pdf\", fig1) # For the polarization curve elif type_current == \"polarization\": if type_display == \"multiple\": saving_instructions(\"results\", subfolder_name, \"global_indicators_1.pdf\", fig1) saving_instructions(\"results\", subfolder_name, \"pola_curve_syn_1.pdf\", fig2) elif type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"pola_curve_1.pdf\", fig1) # For the EIS curve elif type_current == \"EIS\": if type_display == \"multiple\": saving_instructions(\"results\", subfolder_name, \"Nyquist_plot_1.pdf\", fig1) saving_instructions(\"results\", subfolder_name, \"Bode_amplitude_curve_1.pdf\", fig2) saving_instructions(\"results\", subfolder_name, \"Bode_angle_curve_1.pdf\", fig3) elif type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"Nyquist_plot_syn_1.pdf\", fig1) saving_instructions(root_folder, subfolder_name, filename, fig) This function gives the saving instructions for the figures. Parameters: root_folder ( str ) \u2013 The root folder for the saving. subfolder_name ( str ) \u2013 The subfolder name for the saving. filename ( str ) \u2013 The filename for the saving. fig ( Figure ) \u2013 The figure to be saved. Source code in modules/main_modules.py def saving_instructions(root_folder, subfolder_name, filename, fig): \"\"\"This function gives the saving instructions for the figures. Parameters ---------- root_folder : str The root folder for the saving. subfolder_name : str The subfolder name for the saving. filename : str The filename for the saving. fig : matplotlib.figure.Figure The figure to be saved. \"\"\" # Create the folder if necessary folder_name = os.path.join(root_folder, subfolder_name) if not os.path.exists(folder_name): os.makedirs(folder_name) # Create the filename without erasing the previous ones counter = 1 while os.path.isfile(os.path.join(folder_name, filename)): counter += 1 if filename[-6] == \"_\": # for the numbers between 1 and 9 filename = filename[:-5] + str(counter) + \".pdf\" elif filename[-7] == \"_\": # for the numbers between 10 and 99. filename = filename[:-6] + str(counter) + \".pdf\" else: # for the numbers between 100 and 999. The bigger numbers are not considered. filename = filename[:-7] + str(counter) + \".pdf\" # Save the figure file_path = os.path.join(folder_name, filename) fig.savefig(file_path, dpi=900, transparent=False, bbox_inches='tight')","title":"Main modules"},{"location":"functions/modules/main_modules/#main-modules","text":"This module contains some of the required functions for the main.py file.","title":"Main modules"},{"location":"functions/modules/main_modules/#modules.main_modules.figures_preparation","text":"This function create the required figures and axes according to the type_current and type_display. Parameters: type_current ( str ) \u2013 Type of current density function. type_display ( str ) \u2013 Type of display. Returns: fig1 ( Figure ) \u2013 Figure for the first plot. ax1 ( AxesSubplot ) \u2013 Axes for the first plot. fig2 ( Figure ) \u2013 Figure for the second plot. ax2 ( AxesSubplot ) \u2013 Axes for the second plot. Source code in modules/main_modules.py def figures_preparation(type_current, type_display): \"\"\" This function create the required figures and axes according to the type_current and type_display. Parameters ---------- type_current : str Type of current density function. type_display : str Type of display. Returns ------- fig1 : matplotlib.figure.Figure Figure for the first plot. ax1 : matplotlib.axes._subplots.AxesSubplot Axes for the first plot. fig2 : matplotlib.figure.Figure Figure for the second plot. ax2 : matplotlib.axes._subplots.AxesSubplot Axes for the second plot. \"\"\" mpl.rcParams['font.family'] = 'cmr10' # 'cmr10' for English characters and 'DejaVu Serif' for French ones mpl.rcParams['axes.formatter.use_mathtext'] = True # For the scientific notation mpl.rcParams['lines.linewidth'] = 2.0 mpl.rcParams['lines.markersize'] = 5.0 if type_display == \"no_display\": fig1, ax1 = None, None fig2, ax2 = None, None fig3, ax3 = None, None # For the step current if type_current == \"step\": if type_display == \"multiple\": # saving instruction is directly implemented within AlphaPEM.Display here. mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = None, None # Here, additional plots are unnecessary fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 13 # Font size for all text fig1, ax1 = plt.subplots(3, 3, figsize=(14, 14)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) # For the polarization curve elif type_current == \"polarization\": if type_display == \"multiple\": mpl.rcParams['font.size'] = 11 # Font size for all text fig1, ax1 = plt.subplots(1, 3, figsize=(14, 4.7)) fig2, ax2 = plt.subplots(1, 3, figsize=(14, 4.7)) fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = plt.subplots(figsize=(8, 8)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary # For the EIS curve elif type_current == \"EIS\": if type_display == \"multiple\": mpl.rcParams['font.size'] = 18 # Font size for all text fig1, ax1 = plt.subplots(figsize=(8, 8)) fig2, ax2 = plt.subplots(figsize=(8, 8)) fig3, ax3 = plt.subplots(figsize=(8, 8)) elif type_display == \"synthetic\": mpl.rcParams['font.size'] = 13 # Font size for all text fig1, ax1 = plt.subplots(1, 3, figsize=(14, 4.7)) fig2, ax2 = None, None # Here, additional plots are unnecessary fig3, ax3 = None, None # Here, additional plots are unnecessary plt.subplots_adjust(left=0.04, right=0.98, top=0.96, bottom=0.07, wspace=0.2, hspace=0.15) return fig1, ax1, fig2, ax2, fig3, ax3","title":"figures_preparation"},{"location":"functions/modules/main_modules/#modules.main_modules.plot_saving","text":"This function saves the plots in the mentioned folder. The names of the files are automatically generated according to the type_current and the type_display. Parameters: type_fuel_cell ( str ) \u2013 Type of the fuel cell. type_current ( str ) \u2013 Type of current density function. type_display ( str ) \u2013 Type of display. fig1 ( Figure ) \u2013 Figure for the first plot. fig2 ( Figure ) \u2013 Figure for the second plot. Source code in modules/main_modules.py def plot_saving(type_fuel_cell, type_current, type_display, fig1, fig2, fig3): \"\"\"This function saves the plots in the mentioned folder. The names of the files are automatically generated according to the type_current and the type_display. Parameters ---------- type_fuel_cell : str Type of the fuel cell. type_current : str Type of current density function. type_display : str Type of display. fig1 : matplotlib.figure.Figure Figure for the first plot. fig2 : matplotlib.figure.Figure Figure for the second plot. \"\"\" # Folder name subfolder_name = type_fuel_cell[:type_fuel_cell.rfind('_')] if type_fuel_cell.rfind('_') != -1 else type_fuel_cell # For the step current if type_current == \"step\": if type_display == \"multiple\": pass # saving instruction is directly implemented within AlphaPEM.Display for this situation. if type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"step_current_syn_1.pdf\", fig1) # For the polarization curve elif type_current == \"polarization\": if type_display == \"multiple\": saving_instructions(\"results\", subfolder_name, \"global_indicators_1.pdf\", fig1) saving_instructions(\"results\", subfolder_name, \"pola_curve_syn_1.pdf\", fig2) elif type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"pola_curve_1.pdf\", fig1) # For the EIS curve elif type_current == \"EIS\": if type_display == \"multiple\": saving_instructions(\"results\", subfolder_name, \"Nyquist_plot_1.pdf\", fig1) saving_instructions(\"results\", subfolder_name, \"Bode_amplitude_curve_1.pdf\", fig2) saving_instructions(\"results\", subfolder_name, \"Bode_angle_curve_1.pdf\", fig3) elif type_display == \"synthetic\": saving_instructions(\"results\", subfolder_name, \"Nyquist_plot_syn_1.pdf\", fig1)","title":"plot_saving"},{"location":"functions/modules/main_modules/#modules.main_modules.saving_instructions","text":"This function gives the saving instructions for the figures. Parameters: root_folder ( str ) \u2013 The root folder for the saving. subfolder_name ( str ) \u2013 The subfolder name for the saving. filename ( str ) \u2013 The filename for the saving. fig ( Figure ) \u2013 The figure to be saved. Source code in modules/main_modules.py def saving_instructions(root_folder, subfolder_name, filename, fig): \"\"\"This function gives the saving instructions for the figures. Parameters ---------- root_folder : str The root folder for the saving. subfolder_name : str The subfolder name for the saving. filename : str The filename for the saving. fig : matplotlib.figure.Figure The figure to be saved. \"\"\" # Create the folder if necessary folder_name = os.path.join(root_folder, subfolder_name) if not os.path.exists(folder_name): os.makedirs(folder_name) # Create the filename without erasing the previous ones counter = 1 while os.path.isfile(os.path.join(folder_name, filename)): counter += 1 if filename[-6] == \"_\": # for the numbers between 1 and 9 filename = filename[:-5] + str(counter) + \".pdf\" elif filename[-7] == \"_\": # for the numbers between 10 and 99. filename = filename[:-6] + str(counter) + \".pdf\" else: # for the numbers between 100 and 999. The bigger numbers are not considered. filename = filename[:-7] + str(counter) + \".pdf\" # Save the figure file_path = os.path.join(folder_name, filename) fig.savefig(file_path, dpi=900, transparent=False, bbox_inches='tight')","title":"saving_instructions"},{"location":"functions/modules/settings_modules/","text":"Settings modules This modul contains some of the required functions for the settings. EIS_parameters(f_EIS) This function gives the time parameters for the EIS_current density function. Parameters: f_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Returns: t_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. Source code in modules/settings_modules.py def EIS_parameters(f_EIS): \"\"\"This function gives the time parameters for the EIS_current density function. Parameters ---------- f_EIS : tuple EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Returns ------- t_EIS : tuple EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. \"\"\" # Initialisation # Frequencies f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is the tested frequencies nb_period_break_EIS, nb_period_measurement_EIS = 50, 50 # They are the number of temporal periods which are used # for break and for measurement. It is more accurate to use # periods than time as the frequency range is big. # Time parameters delta_t_break_EIS = np.array([]) # It is the estimated time for reaching equilibrium at each frequency. delta_t_measurement_EIS = np.array([]) # It is the estimated time for measuring the voltage response. # Time parameters calculation t0_EIS = 1 / f[0] # s. It is the simulation starting time. # [0, t0_EIS] is used to let the stack equilibrate to i_EIS. t_new_start_EIS = np.array([t0_EIS]) # It is a list of time parameters which gives the beginning of each frequency # change. for i in range(nb_f_EIS): # The goal is to measure nb_f_EIS periods of the signal in order to have precise enough values. T_i = 1 / (f[i]) # s. It is the period of the signal. if i < (nb_f_EIS - 1): delta_t_break_EIS = np.concatenate((delta_t_break_EIS, [nb_period_break_EIS * T_i])) delta_t_measurement_EIS = np.concatenate((delta_t_measurement_EIS, [nb_period_measurement_EIS * T_i])) next_start_EIS = t_new_start_EIS[i] + delta_t_break_EIS[i] + delta_t_measurement_EIS[i] t_new_start_EIS = np.concatenate((t_new_start_EIS, [next_start_EIS])) else: delta_t_break_EIS = np.concatenate((delta_t_break_EIS, [nb_period_break_EIS * T_i])) delta_t_measurement_EIS = np.concatenate((delta_t_measurement_EIS, [nb_period_measurement_EIS * T_i])) tf_EIS = t_new_start_EIS[-1] + delta_t_break_EIS[-1] + delta_t_measurement_EIS[-1] # s. It is the # simulation ending time t_EIS = t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS return t_EIS stored_operating_inputs(type_fuel_cell) This function gives the operating inputs which correspond to the given type_fuel_cell. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve. Source code in modules/settings_modules.py def stored_operating_inputs(type_fuel_cell): \"\"\"This function gives the operating inputs which correspond to the given type_fuel_cell. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_max_pola : float Maximum current density for the polarization curve. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 1.5e5, 1.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.0\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.25\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.25e5, 2.25e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.5\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.5e5, 2.5e5 # Pa. It is the desired pressures of the fuel gas. Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. # For LF fuel cell elif type_fuel_cell == \"LF\": Tfc = 80 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 101325, 101325 # Pa. It is the desired pressures of the fuel gas. Sa, Sc = 2.0, 1.5 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.84, 0.59 # It is the desired relative humidity. i_max_pola = 1.6e4 # A.m-2. It is the maximum current density for the polarization curve. # For other fuel cells else: raise ValueError('the type_fuel_cell given is not valid.') return Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola stored_physical_parameters(type_fuel_cell) This function gives the physical parameters which correspond to the given type_fuel_cell. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Hcl ( float ) \u2013 Thickness of the catalyst layer in m. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. Hmem ( float ) \u2013 Thickness of the membrane in m. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. Hgc ( float ) \u2013 Thickness of the gas channel in m. Wgc ( float ) \u2013 Width of the gas channel in m. Lgc ( float ) \u2013 Length of the gas channel in m. Aact ( float ) \u2013 Active area of the cell in m\u00b2. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl ( float ) \u2013 Volumetric double layer capacitance in F.m-3. Source code in modules/settings_modules.py def stored_physical_parameters(type_fuel_cell): \"\"\"This function gives the physical parameters which correspond to the given type_fuel_cell. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Hcl : float Thickness of the catalyst layer in m. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. Hmem : float Thickness of the membrane in m. Hgdl : float Thickness of the gas diffusion layer in m. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_c : float Compression ratio of the GDL. Hgc : float Thickness of the gas channel in m. Wgc : float Width of the gas channel in m. Lgc : float Length of the gas channel in m. Aact : float Active area of the cell in m\u00b2. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl : float Volumetric double layer capacitance in F.m-3. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": # Catalyst layer Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.399 # It is the volume fraction of ionomer in the CL. tau = 1.016 # It is the pore structure coefficient, without units. # Membrane Hmem = 2e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.701 # It is the anode/cathode GDL porosity. epsilon_c = 0.271 # It is the compression ratio of the GDL. # Gas channel Hgc = 5e-4 # m. It is the thickness of the gas channel. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Interaction parameters between water and PEMFC structure e = 5.0 # It is the capillary exponent # Voltage polarization Re = 5.70e-07 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 2.79 # A.m-2.It is the reference exchange current density at the cathode. kappa_co = 27.2 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.61 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0.05553, 0.10514, 0.63654 # It is the limit liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. # For LF fuel cell elif type_fuel_cell == \"LF\": # Catalyst layer Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.27 # It is the volume fraction of ionomer in the CL. tau = 1.2 # It is the pore structure coefficient, without units. # Membrane Hmem = 5.08e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 4.2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.6 # It is the anode/cathode GDL porosity. epsilon_c = 0.21 # It is the compression ratio of the GDL. # Gas channel. Hgc = 1e-3 # m. It is the thickness of the gas channel. Wgc = 8e-4 # m. It is the width of the gas channel. Wrib = 7e-4 # m. It is the rib of the gas channel. L1gc = 0.1 # m. It is the length of 1 channel. Ngc = 16 # . It is the number of channels in the gas channel. It is taken to have Aact = 25cm\u00b2. Lgc = (L1gc + Wrib) * Ngc # m. It is the length of the gas channel. Aact = (L1gc + 2 * Wrib) * (Wgc + Wrib) * Ngc + (L1gc + 2 * Wrib) * 7e-4 # m\u00b2. It is the CL active area. # Interaction parameters between water and PEMFC structure e = 3.0 # It is the capillary exponent # Voltage polarization Re = 1e-6 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 10 # A.m-2.It is the reference exchange current density at the cathode. kappa_co = 25 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.5 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0, 1, 1 # It is the limit liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. # For other fuel cells else: raise ValueError('the type_input given is not valid.') return Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, \\ Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl","title":"Settings modules"},{"location":"functions/modules/settings_modules/#settings-modules","text":"This modul contains some of the required functions for the settings.","title":"Settings modules"},{"location":"functions/modules/settings_modules/#modules.settings_modules.EIS_parameters","text":"This function gives the time parameters for the EIS_current density function. Parameters: f_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Returns: t_EIS ( tuple ) \u2013 EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. Source code in modules/settings_modules.py def EIS_parameters(f_EIS): \"\"\"This function gives the time parameters for the EIS_current density function. Parameters ---------- f_EIS : tuple EIS parameters. It is a tuple containing the power of the initial frequency 'f_power_min_EIS': f_min_EIS = 10**f_power_min_EIS, the power of the final frequency 'f_power_max_EIS', the number of frequencies tested 'nb_f_EIS' and the number of points calculated per specific period 'nb_points_EIS'. Returns ------- t_EIS : tuple EIS parameters. It is a tuple containing the initial EIS time after stack equilibrium 't0_EIS', a list of time parameters which gives the beginning of each frequency change 't_new_start_EIS', the final time 'tf_EIS', a list of time parameters which gives the estimated time for reaching equilibrium at each frequency 'delta_t_break_EIS', and a list of time parameters which gives the estimated time for measuring the voltage response at each frequency 'delta_t_measurement_EIS'. \"\"\" # Initialisation # Frequencies f_power_min_EIS, f_power_max_EIS, nb_f_EIS, nb_points_EIS = f_EIS # They are the frequency parameters for the EIS # simulation. f = np.logspace(f_power_min_EIS, f_power_max_EIS, num=nb_f_EIS) # It is the tested frequencies nb_period_break_EIS, nb_period_measurement_EIS = 50, 50 # They are the number of temporal periods which are used # for break and for measurement. It is more accurate to use # periods than time as the frequency range is big. # Time parameters delta_t_break_EIS = np.array([]) # It is the estimated time for reaching equilibrium at each frequency. delta_t_measurement_EIS = np.array([]) # It is the estimated time for measuring the voltage response. # Time parameters calculation t0_EIS = 1 / f[0] # s. It is the simulation starting time. # [0, t0_EIS] is used to let the stack equilibrate to i_EIS. t_new_start_EIS = np.array([t0_EIS]) # It is a list of time parameters which gives the beginning of each frequency # change. for i in range(nb_f_EIS): # The goal is to measure nb_f_EIS periods of the signal in order to have precise enough values. T_i = 1 / (f[i]) # s. It is the period of the signal. if i < (nb_f_EIS - 1): delta_t_break_EIS = np.concatenate((delta_t_break_EIS, [nb_period_break_EIS * T_i])) delta_t_measurement_EIS = np.concatenate((delta_t_measurement_EIS, [nb_period_measurement_EIS * T_i])) next_start_EIS = t_new_start_EIS[i] + delta_t_break_EIS[i] + delta_t_measurement_EIS[i] t_new_start_EIS = np.concatenate((t_new_start_EIS, [next_start_EIS])) else: delta_t_break_EIS = np.concatenate((delta_t_break_EIS, [nb_period_break_EIS * T_i])) delta_t_measurement_EIS = np.concatenate((delta_t_measurement_EIS, [nb_period_measurement_EIS * T_i])) tf_EIS = t_new_start_EIS[-1] + delta_t_break_EIS[-1] + delta_t_measurement_EIS[-1] # s. It is the # simulation ending time t_EIS = t0_EIS, t_new_start_EIS, tf_EIS, delta_t_break_EIS, delta_t_measurement_EIS return t_EIS","title":"EIS_parameters"},{"location":"functions/modules/settings_modules/#modules.settings_modules.stored_operating_inputs","text":"This function gives the operating inputs which correspond to the given type_fuel_cell. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Tfc ( float ) \u2013 Desired fuel cell temperature in Kelvin. Pa_des ( float ) \u2013 Desired anode pressure in Pascal. Pc_des ( float ) \u2013 Desired cathode pressure in Pascal. Sa ( float ) \u2013 Stoichiometric ratio of hydrogen. Sc ( float ) \u2013 Stoichiometric ratio of oxygen. Phi_a_des ( float ) \u2013 Desired anode relative humidity. Phi_c_des ( float ) \u2013 Desired cathode relative humidity. i_max_pola ( float ) \u2013 Maximum current density for the polarization curve. Source code in modules/settings_modules.py def stored_operating_inputs(type_fuel_cell): \"\"\"This function gives the operating inputs which correspond to the given type_fuel_cell. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Tfc : float Desired fuel cell temperature in Kelvin. Pa_des : float Desired anode pressure in Pascal. Pc_des : float Desired cathode pressure in Pascal. Sa : float Stoichiometric ratio of hydrogen. Sc : float Stoichiometric ratio of oxygen. Phi_a_des : float Desired anode relative humidity. Phi_c_des : float Desired cathode relative humidity. i_max_pola : float Maximum current density for the polarization curve. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 1.5e5, 1.5e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.0\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.0e5, 2.0e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.25\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.25e5, 2.25e5 # Pa. It is the desired pressure of the fuel gas (at the anode/cathode). Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. elif type_fuel_cell == \"EH-31_2.5\": Tfc = 74 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 2.5e5, 2.5e5 # Pa. It is the desired pressures of the fuel gas. Sa, Sc = 1.2, 2.0 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.4, 0.6 # It is the desired relative humidity. i_max_pola = 3.0e4 # A.m-2. It is the maximum current density for the polarization curve. # For LF fuel cell elif type_fuel_cell == \"LF\": Tfc = 80 + 273.15 # K. It is the desired fuel cell temperature. Pa_des, Pc_des = 101325, 101325 # Pa. It is the desired pressures of the fuel gas. Sa, Sc = 2.0, 1.5 # It is the stoichiometric ratio (of hydrogen and oxygen). Phi_a_des, Phi_c_des = 0.84, 0.59 # It is the desired relative humidity. i_max_pola = 1.6e4 # A.m-2. It is the maximum current density for the polarization curve. # For other fuel cells else: raise ValueError('the type_fuel_cell given is not valid.') return Tfc, Pa_des, Pc_des, Sa, Sc, Phi_a_des, Phi_c_des, i_max_pola","title":"stored_operating_inputs"},{"location":"functions/modules/settings_modules/#modules.settings_modules.stored_physical_parameters","text":"This function gives the physical parameters which correspond to the given type_fuel_cell. Parameters: type_fuel_cell ( str ) \u2013 Type of fuel cell configuration. Returns: Hcl ( float ) \u2013 Thickness of the catalyst layer in m. epsilon_mc ( float ) \u2013 Volume fraction of ionomer in the CL. tau ( float ) \u2013 Pore structure coefficient. Hmem ( float ) \u2013 Thickness of the membrane in m. Hgdl ( float ) \u2013 Thickness of the gas diffusion layer in m. epsilon_gdl ( float ) \u2013 Anode/cathode GDL porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. Hgc ( float ) \u2013 Thickness of the gas channel in m. Wgc ( float ) \u2013 Width of the gas channel in m. Lgc ( float ) \u2013 Length of the gas channel in m. Aact ( float ) \u2013 Active area of the cell in m\u00b2. e ( float ) \u2013 Capillary exponent. Re ( float ) \u2013 Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref ( float ) \u2013 Reference exchange current density at the cathode in A.m-2. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c ( float ) \u2013 Overpotential correction exponent. a_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of slim function. b_slim ( float ) \u2013 One of the limit liquid saturation coefficients: the intercept of slim function. a_switch ( float ) \u2013 One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl ( float ) \u2013 Volumetric double layer capacitance in F.m-3. Source code in modules/settings_modules.py def stored_physical_parameters(type_fuel_cell): \"\"\"This function gives the physical parameters which correspond to the given type_fuel_cell. Parameters ---------- type_fuel_cell : str Type of fuel cell configuration. Returns ------- Hcl : float Thickness of the catalyst layer in m. epsilon_mc : float Volume fraction of ionomer in the CL. tau : float Pore structure coefficient. Hmem : float Thickness of the membrane in m. Hgdl : float Thickness of the gas diffusion layer in m. epsilon_gdl : float Anode/cathode GDL porosity. epsilon_c : float Compression ratio of the GDL. Hgc : float Thickness of the gas channel in m. Wgc : float Width of the gas channel in m. Lgc : float Length of the gas channel in m. Aact : float Active area of the cell in m\u00b2. e : float Capillary exponent. Re : float Electron conduction resistance of the circuit in ohm.m\u00b2. i0_c_ref : float Reference exchange current density at the cathode in A.m-2. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. kappa_c : float Overpotential correction exponent. a_slim : float One of the limit liquid saturation coefficients: the slop of slim function. b_slim : float One of the limit liquid saturation coefficients: the intercept of slim function. a_switch : float One of the limit liquid saturation coefficients: the slop of s_switch function. C_dl : float Volumetric double layer capacitance in F.m-3. \"\"\" # For EH-31 fuel cell if type_fuel_cell == \"EH-31_1.5\" or type_fuel_cell == \"EH-31_2.0\" or type_fuel_cell == \"EH-31_2.25\" or \\ type_fuel_cell == \"EH-31_2.5\": # Catalyst layer Aact = 8.5e-3 # m\u00b2. It is the active area of the catalyst layer. Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.399 # It is the volume fraction of ionomer in the CL. tau = 1.016 # It is the pore structure coefficient, without units. # Membrane Hmem = 2e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.701 # It is the anode/cathode GDL porosity. epsilon_c = 0.271 # It is the compression ratio of the GDL. # Gas channel Hgc = 5e-4 # m. It is the thickness of the gas channel. Wgc = 4.5e-4 # m. It is the width of the gas channel. Lgc = 9.67 # m. It is the length of the gas channel. # Interaction parameters between water and PEMFC structure e = 5.0 # It is the capillary exponent # Voltage polarization Re = 5.70e-07 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 2.79 # A.m-2.It is the reference exchange current density at the cathode. kappa_co = 27.2 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.61 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0.05553, 0.10514, 0.63654 # It is the limit liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. # For LF fuel cell elif type_fuel_cell == \"LF\": # Catalyst layer Hcl = 1e-5 # m. It is the thickness of the anode or cathode catalyst layer. epsilon_mc = 0.27 # It is the volume fraction of ionomer in the CL. tau = 1.2 # It is the pore structure coefficient, without units. # Membrane Hmem = 5.08e-5 # m. It is the thickness of the membrane. # Gas diffusion layer Hgdl = 4.2e-4 # m. It is the thickness of the gas diffusion layer. epsilon_gdl = 0.6 # It is the anode/cathode GDL porosity. epsilon_c = 0.21 # It is the compression ratio of the GDL. # Gas channel. Hgc = 1e-3 # m. It is the thickness of the gas channel. Wgc = 8e-4 # m. It is the width of the gas channel. Wrib = 7e-4 # m. It is the rib of the gas channel. L1gc = 0.1 # m. It is the length of 1 channel. Ngc = 16 # . It is the number of channels in the gas channel. It is taken to have Aact = 25cm\u00b2. Lgc = (L1gc + Wrib) * Ngc # m. It is the length of the gas channel. Aact = (L1gc + 2 * Wrib) * (Wgc + Wrib) * Ngc + (L1gc + 2 * Wrib) * 7e-4 # m\u00b2. It is the CL active area. # Interaction parameters between water and PEMFC structure e = 3.0 # It is the capillary exponent # Voltage polarization Re = 1e-6 # ohm.m\u00b2. It is the electron conduction resistance of the circuit. i0_c_ref = 10 # A.m-2.It is the reference exchange current density at the cathode. kappa_co = 25 # mol.m-1.s-1.Pa-1. It is the crossover correction coefficient. kappa_c = 1.5 # It is the overpotential correction exponent. a_slim, b_slim, a_switch = 0, 1, 1 # It is the limit liquid saturation coefficients. C_scl = 2e7 # F.m-3. It is the volumetric space-charge layer capacitance. # For other fuel cells else: raise ValueError('the type_input given is not valid.') return Hcl, epsilon_mc, tau, Hmem, Hgdl, epsilon_gdl, epsilon_c, \\ Hgc, Wgc, Lgc, Aact, e, Re, i0_c_ref, kappa_co, kappa_c, a_slim, b_slim, a_switch, C_scl","title":"stored_physical_parameters"},{"location":"functions/modules/transitory_functions/","text":"Transitory functions This module contains transitory functions which all have a specific physical meaning for modeling the PEM fuel cell. C_v_sat(T) This function calculates the saturated vapor concentration for a perfect gas, in mol.m-3, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Saturated vapor concentration for a perfect gas in mol.m-3. Source code in modules/transitory_functions.py def C_v_sat(T): \"\"\"This function calculates the saturated vapor concentration for a perfect gas, in mol.m-3, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Saturated vapor concentration for a perfect gas in mol.m-3. \"\"\" return Psat(T) / (R * T) D(lambdaa) This function calculates the diffusion coefficient of water in the membrane, in m\u00b2.s-1. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. Returns: float \u2013 Diffusion coefficient of water in the membrane in m\u00b2.s-1. Source code in modules/transitory_functions.py def D(lambdaa): \"\"\"This function calculates the diffusion coefficient of water in the membrane, in m\u00b2.s-1. Parameters ---------- lambdaa : float Water content in the membrane. Returns ------- float Diffusion coefficient of water in the membrane in m\u00b2.s-1. \"\"\" return 4.1e-10 * (lambdaa / 25.0) ** 0.15 * (1.0 + np.tanh((lambdaa - 2.5) / 1.4)) Da(P, T) This function calculates the diffusion coefficient at the anode, in m\u00b2.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Returns: float \u2013 Diffusion coefficient at the anode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Da(P, T): \"\"\"This function calculates the diffusion coefficient at the anode, in m\u00b2.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Returns ------- float Diffusion coefficient at the anode in m\u00b2.s-1. \"\"\" return 1.644e-4 * (T / 333) ** 2.334 * (101325 / P) Da_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl) This function calculates the effective diffusion coefficient at the anode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: s ( float ) \u2013 Liquid water saturation variable. epsilon ( float ) \u2013 Porosity. P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Effective diffusion coefficient at the anode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Da_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl): \"\"\"This function calculates the effective diffusion coefficient at the anode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- s : float Liquid water saturation variable. epsilon : float Porosity. P : float Pressure in Pa. T : float Temperature in K. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Effective diffusion coefficient at the anode in m\u00b2.s-1. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta2 = -1.59 elif 0.67 <= epsilon_gdl < 0.8: beta2 = -0.90 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon * ((epsilon - 0.11) / (1 - 0.11)) ** 0.785 * np.exp(beta2 * epsilon_c) * (1 - s) ** 2 * Da(P, T) Dc(P, T) This function calculates the diffusion coefficient at the cathode, in m\u00b2.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Returns: float \u2013 Diffusion coefficient at the cathode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Dc(P, T): \"\"\"This function calculates the diffusion coefficient at the cathode, in m\u00b2.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Returns ------- float Diffusion coefficient at the cathode in m\u00b2.s-1. \"\"\" return 3.242e-5 * (T / 333) ** 2.334 * (101325 / P) Dc_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl) This function calculates the effective diffusion coefficient at the cathode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: s ( float ) \u2013 Liquid water saturation variable. epsilon ( float ) \u2013 Porosity. P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Effective diffusion coefficient at the cathode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Dc_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl): \"\"\"This function calculates the effective diffusion coefficient at the cathode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- s : float Liquid water saturation variable. epsilon : float Porosity. P : float Pressure in Pa. T : float Temperature in K. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Effective diffusion coefficient at the cathode in m\u00b2.s-1. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta2 = -1.59 elif 0.67 <= epsilon_gdl < 0.8: beta2 = -0.90 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon * ((epsilon - 0.11) / (1 - 0.11)) ** 0.785 * np.exp(beta2 * epsilon_c) * (1 - s) ** 2 * Dc(P, T) K0(epsilon, epsilon_c, epsilon_gdl) This function calculates the intrinsic permeability, in m\u00b2, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: epsilon ( float ) \u2013 Porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Intrinsic permeability in m\u00b2. Source code in modules/transitory_functions.py def K0(epsilon, epsilon_c, epsilon_gdl): \"\"\"This function calculates the intrinsic permeability, in m\u00b2, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- epsilon : float Porosity. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Intrinsic permeability in m\u00b2. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta1 = -3.60 elif 0.67 <= epsilon_gdl < 0.8: beta1 = -2.60 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon / (8 * np.log(epsilon) ** 2) * (epsilon - 0.11) ** (0.785 + 2) * \\ 4.6e-6 ** 2 / ((1 - 0.11) ** 0.785 * ((0.785 + 1) * epsilon - 0.11) ** 2) * np.exp(beta1 * epsilon_c) Psat(T) This function calculates the saturated partial pressure of vapor, in Pa, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Saturated partial pressure of vapor in Pa. Source code in modules/transitory_functions.py def Psat(T): \"\"\"This function calculates the saturated partial pressure of vapor, in Pa, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Saturated partial pressure of vapor in Pa. \"\"\" return 101325 * 10 ** (-2.1794 + 0.02953 * (T - 273.15) - 9.1837e-5 * (T - 273.15) ** 2 + 1.4454e-7 * (T - 273.15) ** 3) Svl(s, C_v, Ctot, epsilon, T, gamma_cond, gamma_evap) This function calculates the phase transfer rate of water condensation or evaporation, in mol.m-3.s-1. Parameters: s ( float ) \u2013 Liquid water saturation variable. C_v ( float ) \u2013 Water concentration variable in mol.m-3. Ctot ( float ) \u2013 Total gas concentration in mol.m-3. epsilon ( float ) \u2013 Porosity. T ( float ) \u2013 Temperature in K. gamma_cond ( float ) \u2013 Overall condensation rate constant for water in s-1. gamma_evap ( float ) \u2013 Overall evaporation rate constant for water in Pa-1.s-1. Returns: float \u2013 Phase transfer rate of water condensation or evaporation in mol.m-3.s-1. Source code in modules/transitory_functions.py def Svl(s, C_v, Ctot, epsilon, T, gamma_cond, gamma_evap): \"\"\"This function calculates the phase transfer rate of water condensation or evaporation, in mol.m-3.s-1. Parameters ---------- s : float Liquid water saturation variable. C_v : float Water concentration variable in mol.m-3. Ctot : float Total gas concentration in mol.m-3. epsilon : float Porosity. T : float Temperature in K. gamma_cond : float Overall condensation rate constant for water in s-1. gamma_evap : float Overall evaporation rate constant for water in Pa-1.s-1. Returns ------- float Phase transfer rate of water condensation or evaporation in mol.m-3.s-1. \"\"\" if C_v > C_v_sat(T): # condensation return gamma_cond * epsilon * (1 - s) * (C_v / Ctot) * (C_v - C_v_sat(T)) else: # evaporation return -gamma_evap * epsilon * s * rho_H2O(T) / M_H2O * R * T * (C_v_sat(T) - C_v) gamma_sorp(C_v, s, lambdaa, T, Hcl, Kshape) This function calculates the sorption rate of water in the membrane, in s-1. Parameters: C_v ( float ) \u2013 Water concentration variable in mol.m-3. s ( float ) \u2013 Liquid water saturation variable. lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. Hcl ( float ) \u2013 Thickness of the CL layer. Kshape ( float ) \u2013 Mathematical factor governing lambda_eq smoothing Returns: float \u2013 Sorption rate of water in the membrane in s-1. Source code in modules/transitory_functions.py def gamma_sorp(C_v, s, lambdaa, T, Hcl, Kshape): \"\"\"This function calculates the sorption rate of water in the membrane, in s-1. Parameters ---------- C_v : float Water concentration variable in mol.m-3. s : float Liquid water saturation variable. lambdaa : float Water content in the membrane. T : float Temperature in K. Hcl : float Thickness of the CL layer. Kshape : float Mathematical factor governing lambda_eq smoothing Returns ------- float Sorption rate of water in the membrane in s-1. \"\"\" fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) # water volume fraction of # the membrane if lambda_eq(C_v, s, T, Kshape) >= lambdaa: # type_flow = absorption return (1.14e-5 * fv) / Hcl * np.exp(2416 * (1 / 303 - 1 / T)) else: # type_flow = desorption return (4.59e-5 * fv) / Hcl * np.exp(2416 * (1 / 303 - 1 / T)) h_a(P, T, Wgc, Hgc) This function calculates the effective convective-conductive mass transfer coefficient at the anode, in m.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Wgc ( float ) \u2013 Width of the gas channel in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Returns: float \u2013 Effective convective-conductive mass transfer coefficient at the anode in m.s-1. Source code in modules/transitory_functions.py def h_a(P, T, Wgc, Hgc): \"\"\"This function calculates the effective convective-conductive mass transfer coefficient at the anode, in m.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Wgc : float Width of the gas channel in m. Hgc : float Thickness of the gas channel in m. Returns ------- float Effective convective-conductive mass transfer coefficient at the anode in m.s-1. \"\"\" Sh = 0.9247 * np.log(Wgc / Hgc) + 2.3787 # Sherwood coefficient. return Sh * Da(P, T) / Hgc h_c(P, T, Wgc, Hgc) This function calculates the effective convective-conductive mass transfer coefficient at the cathode, in m.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Wgc ( float ) \u2013 Width of the gas channel in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Returns: float \u2013 Effective convective-conductive mass transfer coefficient at the cathode in m.s-1. Source code in modules/transitory_functions.py def h_c(P, T, Wgc, Hgc): \"\"\"This function calculates the effective convective-conductive mass transfer coefficient at the cathode, in m.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Wgc : float Width of the gas channel in m. Hgc : float Thickness of the gas channel in m. Returns ------- float Effective convective-conductive mass transfer coefficient at the cathode in m.s-1. \"\"\" Sh = 0.9247 * np.log(Wgc / Hgc) + 2.3787 # Sherwood coefficient. return Sh * Dc(P, T) / Hgc k_H2(lambdaa, T, kappa_co) This function calculates the permeability coefficient of the membrane for hydrogen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns: float \u2013 Permeability coefficient of the membrane for hydrogen in mol.m\u22121.s\u22121.Pa\u22121. Source code in modules/transitory_functions.py def k_H2(lambdaa, T, kappa_co): \"\"\"This function calculates the permeability coefficient of the membrane for hydrogen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters ---------- lambdaa : float Water content in the membrane. T : float Temperature in K. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns ------- float Permeability coefficient of the membrane for hydrogen in mol.m\u22121.s\u22121.Pa\u22121. \"\"\" # Initialisation of the constants E_H2_v = 2.1e4 # J.mol-1. It is the activation energy of H2 for crossover in the under saturated membrane. E_H2_l = 1.8e4 # J.mol-1. It is the activation energy of H2 for crossover in the liquide-equilibrated membrane. Tref = 303.15 # K. # Calculation of the permeability coefficient of the membrane for hydrogen if lambdaa < 17.6: fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) return kappa_co * (0.29 + 2.2 * fv) * 1e-14 * np.exp(E_H2_v / R * (1 / Tref - 1 / T)) else: return kappa_co * 1.8 * 1e-14 * np.exp(E_H2_l / R * (1 / Tref - 1 / T)) k_O2(lambdaa, T, kappa_co) This function calculates the permeability coefficient of the membrane for oxygen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns: float \u2013 Permeability coefficient of the membrane for oxygen in mol.m\u22121.s\u22121.Pa\u22121. Source code in modules/transitory_functions.py def k_O2(lambdaa, T, kappa_co): \"\"\"This function calculates the permeability coefficient of the membrane for oxygen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters ---------- lambdaa : float Water content in the membrane. T : float Temperature in K. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns ------- float Permeability coefficient of the membrane for oxygen in mol.m\u22121.s\u22121.Pa\u22121. \"\"\" # Initialisation of the constants E_O2_v = 2.2e4 # J.mol-1. It is the activation energy of oxygen for crossover in the under saturated membrane. E_O2_l = 2.0e4 # J.mol-1. It is the activation energy of oxygen for crossover in the liquide-equilibrated membrane. Tref = 303.15 # K. # Calculation of the permeability coefficient of the membrane for oxygen if lambdaa < 17.6: fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) return kappa_co * (0.11 + 1.9 * fv) * 1e-14 * np.exp(E_O2_v / R * (1 / Tref - 1 / T)) else: return kappa_co * 1.2 * 1e-14 * np.exp(E_O2_l / R * (1 / Tref - 1 / T)) lambda_eq(C_v, s, T, Kshape) This function calculates the equilibrium water content in the membrane. Hinatsu's expression modified with Bao's formulation has been selected. Parameters: C_v ( float ) \u2013 Water concentration variable in mol.m-3. s ( float ) \u2013 Liquid water saturation variable. T ( float ) \u2013 Temperature in K. Kshape ( float ) \u2013 Mathematical factor governing lambda_eq smoothing Returns: float \u2013 Equilibrium water content in the membrane. Source code in modules/transitory_functions.py def lambda_eq(C_v, s, T, Kshape): \"\"\"This function calculates the equilibrium water content in the membrane. Hinatsu's expression modified with Bao's formulation has been selected. Parameters ---------- C_v : float Water concentration variable in mol.m-3. s : float Liquid water saturation variable. T : float Temperature in K. Kshape : float Mathematical factor governing lambda_eq smoothing Returns ------- float Equilibrium water content in the membrane. \"\"\" a_w = C_v / C_v_sat(T) + 2 * s # water activity return 0.5 * (0.300 + 10.8 * a_w - 16.0 * a_w ** 2 + 14.1 * a_w ** 3) * (1 - np.tanh(100 * (a_w - 1))) \\ + 0.5 * (9.2 + 8.6 * (1 - np.exp(-Kshape * (a_w - 1)))) * (1 + np.tanh(100 * (a_w - 1))) nu_l(T) This function calculates the liquid water kinematic viscosity, in m\u00b2.s-1, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Liquid water kinematic viscosity in m\u00b2.s-1. Source code in modules/transitory_functions.py def nu_l(T): \"\"\"This function calculates the liquid water kinematic viscosity, in m\u00b2.s-1, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Liquid water kinematic viscosity in m\u00b2.s-1. \"\"\" mu_l = 2.414 * 10 ** (-5 + 247.8 / (T - 140.0)) # Pa.s. It is the liquid water dynamic viscosity. return mu_l / rho_H2O(T) rho_H2O(T) This function calculates the water density, in kg.m-3, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Water density in kg.m-3. Source code in modules/transitory_functions.py def rho_H2O(T): \"\"\"This function calculates the water density, in kg.m-3, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Water density in kg.m-3. \"\"\" return ((999.83952 + 16.945176 * (T - 273.15) - 7.9870401e-3 * (T - 273.15) ** 2 - 46.170461e-6 * (T - 273.15) ** 3 + 105.56302e-9 * (T - 273.15) ** 4 - 280.54253e-12 * (T - 273.15) ** 5) / (1 + 16.879850e-3 * (T - 273.15))) sigma(T) This function calculates the water surface tension, in N.m-1, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Water surface tension in N.m-1. Source code in modules/transitory_functions.py def sigma(T): \"\"\"This function calculates the water surface tension, in N.m-1, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Water surface tension in N.m-1. \"\"\" return 235.8e-3 * ((647.15 - T) / 647.15) ** 1.256 * (1 - 0.625 * (647.15 - T) / 647.15)","title":"Transitory functions"},{"location":"functions/modules/transitory_functions/#transitory-functions","text":"This module contains transitory functions which all have a specific physical meaning for modeling the PEM fuel cell.","title":"Transitory functions"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.C_v_sat","text":"This function calculates the saturated vapor concentration for a perfect gas, in mol.m-3, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Saturated vapor concentration for a perfect gas in mol.m-3. Source code in modules/transitory_functions.py def C_v_sat(T): \"\"\"This function calculates the saturated vapor concentration for a perfect gas, in mol.m-3, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Saturated vapor concentration for a perfect gas in mol.m-3. \"\"\" return Psat(T) / (R * T)","title":"C_v_sat"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.D","text":"This function calculates the diffusion coefficient of water in the membrane, in m\u00b2.s-1. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. Returns: float \u2013 Diffusion coefficient of water in the membrane in m\u00b2.s-1. Source code in modules/transitory_functions.py def D(lambdaa): \"\"\"This function calculates the diffusion coefficient of water in the membrane, in m\u00b2.s-1. Parameters ---------- lambdaa : float Water content in the membrane. Returns ------- float Diffusion coefficient of water in the membrane in m\u00b2.s-1. \"\"\" return 4.1e-10 * (lambdaa / 25.0) ** 0.15 * (1.0 + np.tanh((lambdaa - 2.5) / 1.4))","title":"D"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Da","text":"This function calculates the diffusion coefficient at the anode, in m\u00b2.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Returns: float \u2013 Diffusion coefficient at the anode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Da(P, T): \"\"\"This function calculates the diffusion coefficient at the anode, in m\u00b2.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Returns ------- float Diffusion coefficient at the anode in m\u00b2.s-1. \"\"\" return 1.644e-4 * (T / 333) ** 2.334 * (101325 / P)","title":"Da"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Da_eff","text":"This function calculates the effective diffusion coefficient at the anode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: s ( float ) \u2013 Liquid water saturation variable. epsilon ( float ) \u2013 Porosity. P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Effective diffusion coefficient at the anode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Da_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl): \"\"\"This function calculates the effective diffusion coefficient at the anode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- s : float Liquid water saturation variable. epsilon : float Porosity. P : float Pressure in Pa. T : float Temperature in K. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Effective diffusion coefficient at the anode in m\u00b2.s-1. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta2 = -1.59 elif 0.67 <= epsilon_gdl < 0.8: beta2 = -0.90 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon * ((epsilon - 0.11) / (1 - 0.11)) ** 0.785 * np.exp(beta2 * epsilon_c) * (1 - s) ** 2 * Da(P, T)","title":"Da_eff"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Dc","text":"This function calculates the diffusion coefficient at the cathode, in m\u00b2.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Returns: float \u2013 Diffusion coefficient at the cathode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Dc(P, T): \"\"\"This function calculates the diffusion coefficient at the cathode, in m\u00b2.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Returns ------- float Diffusion coefficient at the cathode in m\u00b2.s-1. \"\"\" return 3.242e-5 * (T / 333) ** 2.334 * (101325 / P)","title":"Dc"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Dc_eff","text":"This function calculates the effective diffusion coefficient at the cathode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: s ( float ) \u2013 Liquid water saturation variable. epsilon ( float ) \u2013 Porosity. P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Effective diffusion coefficient at the cathode in m\u00b2.s-1. Source code in modules/transitory_functions.py def Dc_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl): \"\"\"This function calculates the effective diffusion coefficient at the cathode, in m\u00b2.s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- s : float Liquid water saturation variable. epsilon : float Porosity. P : float Pressure in Pa. T : float Temperature in K. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Effective diffusion coefficient at the cathode in m\u00b2.s-1. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta2 = -1.59 elif 0.67 <= epsilon_gdl < 0.8: beta2 = -0.90 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon * ((epsilon - 0.11) / (1 - 0.11)) ** 0.785 * np.exp(beta2 * epsilon_c) * (1 - s) ** 2 * Dc(P, T)","title":"Dc_eff"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.K0","text":"This function calculates the intrinsic permeability, in m\u00b2, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters: epsilon ( float ) \u2013 Porosity. epsilon_c ( float ) \u2013 Compression ratio of the GDL. epsilon_gdl ( float ) \u2013 Porosity of the GDL. Returns: float \u2013 Intrinsic permeability in m\u00b2. Source code in modules/transitory_functions.py def K0(epsilon, epsilon_c, epsilon_gdl): \"\"\"This function calculates the intrinsic permeability, in m\u00b2, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl. Parameters ---------- epsilon : float Porosity. epsilon_c : float Compression ratio of the GDL. epsilon_gdl : float Porosity of the GDL. Returns ------- float Intrinsic permeability in m\u00b2. \"\"\" # According to the GDL porosity, the GDL compression effect is different. if 0.55 <= epsilon_gdl < 0.67: beta1 = -3.60 elif 0.67 <= epsilon_gdl < 0.8: beta1 = -2.60 else: raise ValueError(\"In order to calculate the effects of the GDL compression on its structure, \" \"epsilon_gdl should be between 0.55 and 0.8.\") return epsilon / (8 * np.log(epsilon) ** 2) * (epsilon - 0.11) ** (0.785 + 2) * \\ 4.6e-6 ** 2 / ((1 - 0.11) ** 0.785 * ((0.785 + 1) * epsilon - 0.11) ** 2) * np.exp(beta1 * epsilon_c)","title":"K0"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Psat","text":"This function calculates the saturated partial pressure of vapor, in Pa, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Saturated partial pressure of vapor in Pa. Source code in modules/transitory_functions.py def Psat(T): \"\"\"This function calculates the saturated partial pressure of vapor, in Pa, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Saturated partial pressure of vapor in Pa. \"\"\" return 101325 * 10 ** (-2.1794 + 0.02953 * (T - 273.15) - 9.1837e-5 * (T - 273.15) ** 2 + 1.4454e-7 * (T - 273.15) ** 3)","title":"Psat"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.Svl","text":"This function calculates the phase transfer rate of water condensation or evaporation, in mol.m-3.s-1. Parameters: s ( float ) \u2013 Liquid water saturation variable. C_v ( float ) \u2013 Water concentration variable in mol.m-3. Ctot ( float ) \u2013 Total gas concentration in mol.m-3. epsilon ( float ) \u2013 Porosity. T ( float ) \u2013 Temperature in K. gamma_cond ( float ) \u2013 Overall condensation rate constant for water in s-1. gamma_evap ( float ) \u2013 Overall evaporation rate constant for water in Pa-1.s-1. Returns: float \u2013 Phase transfer rate of water condensation or evaporation in mol.m-3.s-1. Source code in modules/transitory_functions.py def Svl(s, C_v, Ctot, epsilon, T, gamma_cond, gamma_evap): \"\"\"This function calculates the phase transfer rate of water condensation or evaporation, in mol.m-3.s-1. Parameters ---------- s : float Liquid water saturation variable. C_v : float Water concentration variable in mol.m-3. Ctot : float Total gas concentration in mol.m-3. epsilon : float Porosity. T : float Temperature in K. gamma_cond : float Overall condensation rate constant for water in s-1. gamma_evap : float Overall evaporation rate constant for water in Pa-1.s-1. Returns ------- float Phase transfer rate of water condensation or evaporation in mol.m-3.s-1. \"\"\" if C_v > C_v_sat(T): # condensation return gamma_cond * epsilon * (1 - s) * (C_v / Ctot) * (C_v - C_v_sat(T)) else: # evaporation return -gamma_evap * epsilon * s * rho_H2O(T) / M_H2O * R * T * (C_v_sat(T) - C_v)","title":"Svl"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.gamma_sorp","text":"This function calculates the sorption rate of water in the membrane, in s-1. Parameters: C_v ( float ) \u2013 Water concentration variable in mol.m-3. s ( float ) \u2013 Liquid water saturation variable. lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. Hcl ( float ) \u2013 Thickness of the CL layer. Kshape ( float ) \u2013 Mathematical factor governing lambda_eq smoothing Returns: float \u2013 Sorption rate of water in the membrane in s-1. Source code in modules/transitory_functions.py def gamma_sorp(C_v, s, lambdaa, T, Hcl, Kshape): \"\"\"This function calculates the sorption rate of water in the membrane, in s-1. Parameters ---------- C_v : float Water concentration variable in mol.m-3. s : float Liquid water saturation variable. lambdaa : float Water content in the membrane. T : float Temperature in K. Hcl : float Thickness of the CL layer. Kshape : float Mathematical factor governing lambda_eq smoothing Returns ------- float Sorption rate of water in the membrane in s-1. \"\"\" fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) # water volume fraction of # the membrane if lambda_eq(C_v, s, T, Kshape) >= lambdaa: # type_flow = absorption return (1.14e-5 * fv) / Hcl * np.exp(2416 * (1 / 303 - 1 / T)) else: # type_flow = desorption return (4.59e-5 * fv) / Hcl * np.exp(2416 * (1 / 303 - 1 / T))","title":"gamma_sorp"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.h_a","text":"This function calculates the effective convective-conductive mass transfer coefficient at the anode, in m.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Wgc ( float ) \u2013 Width of the gas channel in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Returns: float \u2013 Effective convective-conductive mass transfer coefficient at the anode in m.s-1. Source code in modules/transitory_functions.py def h_a(P, T, Wgc, Hgc): \"\"\"This function calculates the effective convective-conductive mass transfer coefficient at the anode, in m.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Wgc : float Width of the gas channel in m. Hgc : float Thickness of the gas channel in m. Returns ------- float Effective convective-conductive mass transfer coefficient at the anode in m.s-1. \"\"\" Sh = 0.9247 * np.log(Wgc / Hgc) + 2.3787 # Sherwood coefficient. return Sh * Da(P, T) / Hgc","title":"h_a"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.h_c","text":"This function calculates the effective convective-conductive mass transfer coefficient at the cathode, in m.s-1. Parameters: P ( float ) \u2013 Pressure in Pa. T ( float ) \u2013 Temperature in K. Wgc ( float ) \u2013 Width of the gas channel in m. Hgc ( float ) \u2013 Thickness of the gas channel in m. Returns: float \u2013 Effective convective-conductive mass transfer coefficient at the cathode in m.s-1. Source code in modules/transitory_functions.py def h_c(P, T, Wgc, Hgc): \"\"\"This function calculates the effective convective-conductive mass transfer coefficient at the cathode, in m.s-1. Parameters ---------- P : float Pressure in Pa. T : float Temperature in K. Wgc : float Width of the gas channel in m. Hgc : float Thickness of the gas channel in m. Returns ------- float Effective convective-conductive mass transfer coefficient at the cathode in m.s-1. \"\"\" Sh = 0.9247 * np.log(Wgc / Hgc) + 2.3787 # Sherwood coefficient. return Sh * Dc(P, T) / Hgc","title":"h_c"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.k_H2","text":"This function calculates the permeability coefficient of the membrane for hydrogen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns: float \u2013 Permeability coefficient of the membrane for hydrogen in mol.m\u22121.s\u22121.Pa\u22121. Source code in modules/transitory_functions.py def k_H2(lambdaa, T, kappa_co): \"\"\"This function calculates the permeability coefficient of the membrane for hydrogen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters ---------- lambdaa : float Water content in the membrane. T : float Temperature in K. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns ------- float Permeability coefficient of the membrane for hydrogen in mol.m\u22121.s\u22121.Pa\u22121. \"\"\" # Initialisation of the constants E_H2_v = 2.1e4 # J.mol-1. It is the activation energy of H2 for crossover in the under saturated membrane. E_H2_l = 1.8e4 # J.mol-1. It is the activation energy of H2 for crossover in the liquide-equilibrated membrane. Tref = 303.15 # K. # Calculation of the permeability coefficient of the membrane for hydrogen if lambdaa < 17.6: fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) return kappa_co * (0.29 + 2.2 * fv) * 1e-14 * np.exp(E_H2_v / R * (1 / Tref - 1 / T)) else: return kappa_co * 1.8 * 1e-14 * np.exp(E_H2_l / R * (1 / Tref - 1 / T))","title":"k_H2"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.k_O2","text":"This function calculates the permeability coefficient of the membrane for oxygen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters: lambdaa ( float ) \u2013 Water content in the membrane. T ( float ) \u2013 Temperature in K. kappa_co ( float ) \u2013 Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns: float \u2013 Permeability coefficient of the membrane for oxygen in mol.m\u22121.s\u22121.Pa\u22121. Source code in modules/transitory_functions.py def k_O2(lambdaa, T, kappa_co): \"\"\"This function calculates the permeability coefficient of the membrane for oxygen, in mol.m\u22121.s\u22121.Pa\u22121. Parameters ---------- lambdaa : float Water content in the membrane. T : float Temperature in K. kappa_co : float Crossover correction coefficient in mol.m-1.s-1.Pa-1. Returns ------- float Permeability coefficient of the membrane for oxygen in mol.m\u22121.s\u22121.Pa\u22121. \"\"\" # Initialisation of the constants E_O2_v = 2.2e4 # J.mol-1. It is the activation energy of oxygen for crossover in the under saturated membrane. E_O2_l = 2.0e4 # J.mol-1. It is the activation energy of oxygen for crossover in the liquide-equilibrated membrane. Tref = 303.15 # K. # Calculation of the permeability coefficient of the membrane for oxygen if lambdaa < 17.6: fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T)) return kappa_co * (0.11 + 1.9 * fv) * 1e-14 * np.exp(E_O2_v / R * (1 / Tref - 1 / T)) else: return kappa_co * 1.2 * 1e-14 * np.exp(E_O2_l / R * (1 / Tref - 1 / T))","title":"k_O2"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.lambda_eq","text":"This function calculates the equilibrium water content in the membrane. Hinatsu's expression modified with Bao's formulation has been selected. Parameters: C_v ( float ) \u2013 Water concentration variable in mol.m-3. s ( float ) \u2013 Liquid water saturation variable. T ( float ) \u2013 Temperature in K. Kshape ( float ) \u2013 Mathematical factor governing lambda_eq smoothing Returns: float \u2013 Equilibrium water content in the membrane. Source code in modules/transitory_functions.py def lambda_eq(C_v, s, T, Kshape): \"\"\"This function calculates the equilibrium water content in the membrane. Hinatsu's expression modified with Bao's formulation has been selected. Parameters ---------- C_v : float Water concentration variable in mol.m-3. s : float Liquid water saturation variable. T : float Temperature in K. Kshape : float Mathematical factor governing lambda_eq smoothing Returns ------- float Equilibrium water content in the membrane. \"\"\" a_w = C_v / C_v_sat(T) + 2 * s # water activity return 0.5 * (0.300 + 10.8 * a_w - 16.0 * a_w ** 2 + 14.1 * a_w ** 3) * (1 - np.tanh(100 * (a_w - 1))) \\ + 0.5 * (9.2 + 8.6 * (1 - np.exp(-Kshape * (a_w - 1)))) * (1 + np.tanh(100 * (a_w - 1)))","title":"lambda_eq"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.nu_l","text":"This function calculates the liquid water kinematic viscosity, in m\u00b2.s-1, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Liquid water kinematic viscosity in m\u00b2.s-1. Source code in modules/transitory_functions.py def nu_l(T): \"\"\"This function calculates the liquid water kinematic viscosity, in m\u00b2.s-1, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Liquid water kinematic viscosity in m\u00b2.s-1. \"\"\" mu_l = 2.414 * 10 ** (-5 + 247.8 / (T - 140.0)) # Pa.s. It is the liquid water dynamic viscosity. return mu_l / rho_H2O(T)","title":"nu_l"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.rho_H2O","text":"This function calculates the water density, in kg.m-3, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Water density in kg.m-3. Source code in modules/transitory_functions.py def rho_H2O(T): \"\"\"This function calculates the water density, in kg.m-3, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Water density in kg.m-3. \"\"\" return ((999.83952 + 16.945176 * (T - 273.15) - 7.9870401e-3 * (T - 273.15) ** 2 - 46.170461e-6 * (T - 273.15) ** 3 + 105.56302e-9 * (T - 273.15) ** 4 - 280.54253e-12 * (T - 273.15) ** 5) / (1 + 16.879850e-3 * (T - 273.15)))","title":"rho_H2O"},{"location":"functions/modules/transitory_functions/#modules.transitory_functions.sigma","text":"This function calculates the water surface tension, in N.m-1, as a function of the temperature. Parameters: T ( float ) \u2013 Temperature in K. Returns: float \u2013 Water surface tension in N.m-1. Source code in modules/transitory_functions.py def sigma(T): \"\"\"This function calculates the water surface tension, in N.m-1, as a function of the temperature. Parameters ---------- T : float Temperature in K. Returns ------- float Water surface tension in N.m-1. \"\"\" return 235.8e-3 * ((647.15 - T) / 647.15) ** 1.256 * (1 - 0.625 * (647.15 - T) / 647.15)","title":"sigma"}]}
\ No newline at end of file
diff --git a/sitemap.xml.gz b/sitemap.xml.gz
index 925ff29..c2b9c4e 100644
Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ