# PEM Electrolyser and Fuel Cell Models (MathWorks Simscape examples) > **Markdown report of non-markdown source files.** > > | | | > |---|---| > | **Sources** | `Simulations/Ready Made PEM Electrolyzer/` · `Simulations/Ready Made PEM fuel cell/` · duplicated in `Simulations/Big Ugly Folder/` | > | **Origin** | **MathWorks Simscape shipped examples**, obtained via `openExample(...)` | > | **Licence** | © 2020–2024 The MathWorks, Inc. — see [Provenance](#provenance-and-licensing) | > | **Status** | Current — but **still at vendor default parameters** | > | **Report generated** | 2026-07-25 | ## Provenance and licensing > [!WARNING] > **This is unmodified third-party code.** Every `.m` and `.ssc` file in both folders carries a > MathWorks copyright line; not one carries SHIFT attribution. Unlike the > [EST model](existing-est-model.md) — which ships its MIT LICENSE and upstream URL — this > vendored code is **marked nowhere in the repository**. ``` Ready Made PEM Electrolyzer/Electrolyzer.ssc:9 % Copyright 2021-2024 The MathWorks, Inc. Ready Made PEM Electrolyzer/PEMElectrolysisSystemExample.m:57 % Copyright 2021 The MathWorks, Inc. Ready Made PEM Electrolyzer/PEMElectrolysisSystemParameters.m:6 % Copyright 2021 The MathWorks, Inc. Ready Made PEM fuel cell/FuelCell.ssc:10 % Copyright 2020-2024 The MathWorks, Inc. Ready Made PEM fuel cell/PEMFuelCellSystemExample.m:64 % Copyright 2020-2021 The MathWorks, Inc. Ready Made PEM fuel cell/PEMFuelCellSystemParameters.m:6 % Copyright 2020 The MathWorks, Inc. …and 8 more Plot*.m files, all MathWorks ``` How they were obtained is recorded only as a comment in `Constants.m`: ```matlab %openExample('simscape/PEMElectrolysisSystemExample') %openExample('simscape/PEMFuelCellSystemExample') ``` **Recommended:** add a `PROVENANCE.md` to each folder stating that the contents are unmodified MathWorks Simscape examples retrieved via `openExample`, and that redistribution is governed by the MathWorks licence terms. ## The unfinished sizing work `Constants.m` records the requirement and the plan, verbatim: > `%Ready made electrolyser -` > `%Good news: it has a solar profile.` > `%Bad news: random constants - we want it at 128m3 hydrogen production a day` > `%I have attempted to find volume via the volumetric flow rate, however this` > `%uses "standard conditions". THIS BRINGS IT TO 12.8m3, JUST ADJUST (power?)` > `%SO ITS 10 TIMES BIGGER AND WE ARE GOOD!` > > `%openExample('simscape/PEMFuelCellSystemExample')` > `%This one is also PEM so it should work?` > > `%To do: Check if PEM is ok, change parameters for electrolyzer so that` > `%production is exactely 10times bigger, adjust fuel cell, create grid,` > `%ensure its power output is appropriate` > [!IMPORTANT] > **That TODO has not been carried out.** The parameter files are still at MathWorks demo > defaults: > > - The electrolyser's 24-hour `solar_profile_power` still peaks at exactly **100 kW** — the > vendor's round demo number, not a SHIFT-derived profile. > - The fuel cell still loads **`PEMFuelCellSystemDriveCycle.mat`** — an *automotive drive > cycle*, wholly inappropriate for a hospital microgrid. > > **No SHIFT-specific hydrogen system parameterisation exists anywhere in this tree**, despite > `Constants.m` recording the requirement since the earliest revision. This is the single > largest gap between the [simulator specification](../02-specifications/simulator-io-interface.md) > and the models that are supposed to implement it. Note also that the "just multiply by 10" approach to sizing is recorded as an unverified assumption (*"This one is also PEM so it should work?"*), and that scaling a Simscape electrolyser's hydrogen output by 10× is not achieved by scaling power alone — cell count, active area, and current density all enter. ## Electrolyser parameters `PEMElectrolysisSystemParameters.m` — 71 lines, 11,972 B, MD5 `7871b9ab`. Byte-identical in `Ready Made PEM Electrolyzer/` and `Big Ugly Folder/`. ### Environment | Parameter | Value | Unit | |---|---:|---| | `env_p` | 0.101325 | MPa | | `env_T` | 20 | °C | ### Solar profile (24 h) | Parameter | Value | Unit | |---|---|---| | `solar_profile_time` | `(0:23)' * 3600` | s | | `solar_profile_power` | `[0 0 0 0 0 0 0.572 13.1 44.9 74.5 96.4 100 97.5 89.5 65.8 34.0 7.61 0 0 0 0 0 0 0]'` | kW | ### Stack The comment header in the source says *"Fuel cell stack"* — a MathWorks copy-paste artefact in the *electrolysis* file. | Parameter | Value | Unit | Description | |---|---:|---|---| | `stack_num_cells` | 50 | – | Number of cells | | `stack_area` | 280 | cm² | Cell area | | `stack_t_membrane` | 125 | µm | Membrane thickness | | `stack_t_gdl_A` | 25 | µm | Anode gas diffusion layer thickness | | `stack_t_gdl_C` | 250 | µm | Cathode gas diffusion layer thickness | | `stack_w_channels` | 1 | cm | Gas channel width and height | | `stack_num_channels` | 8 | – | Gas channels per cell | | `stack_io` | 1e-04 | A/cm² | Exchange current density | | `stack_alpha` | 0.7 | – | Charge transfer coefficient | | `stack_D_gdl_A` | 0.07 | cm²/s | Water diffusivity in anode GDL | | `stack_D_gdl_C` | 0.07 | cm²/s | Water diffusivity in cathode GDL | | `stack_membrane_rho` | 2000 | kg/m³ | Density of dry membrane | | `stack_membrane_MW` | 1.1 | kg/mol | Equivalent weight of dry membrane | | `stack_mea_rho` | 1800 | **kg/s** *(sic)* | Overall density of MEA — vendor unit typo, should be kg/m³ | | `stack_mea_cp` | 870 | J/(kg·K) | Overall specific heat of MEA | ### Piping and heat exchanger | Parameter | Value | Unit | Description | |---|---:|---|---| | `water_pipe_D` | 0.01 | m | Water pipe diameter | | `gas_pipe_D` | 0.01 | m | Gas pipe diameter | | `exchanger_L` | 1 | m | Overall radiator length | | `exchanger_W` | 0.025 | m | Overall radiator width | | `exchanger_H` | 0.5 | m | Overall radiator height | | `exchanger_N_tubes` | 25 | – | Number of coolant tubes | | `exchanger_tube_H` | 0.0015 | m | Height of each coolant tube | | `exchanger_fin_spacing` | 0.002 | – | Fin spacing | | `exchanger_eta_fin` | 0.7 | – | Fin efficiency | Derived quantities computed in the script: `exchanger_gap_H`, `exchanger_air_area_primary`, `exchanger_N_fins`, `exchanger_air_area_fins`, `exchanger_tube_Leq`. ## Fuel cell parameters `PEMFuelCellSystemParameters.m` — 94 lines, 12,709 B, MD5 `6eaf6bf3`. Byte-identical in `Ready Made PEM fuel cell/` and `Big Ugly Folder/`. Line 8 executes `load PEMFuelCellSystemDriveCycle.mat` (13,667 B). ### Environment | Parameter | Value | Unit | |---|---:|---| | `env_p` | 0.101325 | MPa | | `env_T` | 20 | °C | | `env_RH` | 0.5 | – (relative humidity) | | `env_yO2` | 0.21 | – (oxygen mole fraction) | ### Fuel tank | Parameter | Value | Unit | |---|---:|---| | `tank_p` | 70 | MPa | | `tank_yH2` | `1 − 3e-4` | – (hydrogen mole fraction) | | `tank_V` | 120 | L | > `tank_V = 120 L` at 70 MPa is an **automotive** hydrogen tank. The > [project spec](../02-specifications/simulator-io-interface.md#13-hydrogen-tank) calls for > **up to 200 kg across two tanks** — roughly three orders of magnitude larger. Another > consequence of the untouched vendor defaults. ### Stack | Parameter | Value | Unit | Description | |---|---:|---|---| | `stack_num_cells` | **400** | – | Number of cells (vs. 50 in the electrolyser) | | `stack_area` | 280 | cm² | Cell area | | `stack_t_membrane` | 125 | µm | Membrane thickness | | `stack_t_gdl` | 250 | µm | Gas diffusion layer thickness | | `stack_w_channels` | 1 | cm | Gas channel width/height | | `stack_num_channels` | 8 | – | Gas channels per cell | | `stack_io` | 1e-04 | A/cm² | Exchange current density | | `stack_iL` | 1.4 | A/cm² | Limiting current density | | `stack_alpha` | 0.7 | – | Charge transfer coefficient | | `stack_D_gdl` | 0.07 | cm²/s | Water diffusivity in GDL | | `stack_membrane_rho` | 2000 | kg/m³ | Density of dry membrane | | `stack_membrane_MW` | 1.1 | kg/mol | Equivalent weight of dry membrane | | `stack_mea_rho` | 1800 | **kg/s** *(sic)* | Vendor unit typo, should be kg/m³ | | `stack_mea_cp` | 870 | J/(kg·K) | Overall specific heat of MEA | ### Gas tubes and coolant | Parameter | Value | Unit | Description | |---|---:|---|---| | `anode_tube_D` | 0.01 | m | Hydrogen tube diameter | | `cathode_tube_D` | 0.05 | m | Air tube diameter | | `coolant_w_channels` | 1 | cm | Coolant channel width/height | | `coolant_num_passes` | 12 | – | Coolant channel passes per layer | | `coolant_num_layers` | 20 | – | Coolant layers in stack | | `coolant_tube_D` | 0.05 | m | Coolant tube diameter | ### Radiator | Parameter | Value | Unit | Description | |---|---:|---|---| | `radiator_L` | 1 | m | Overall radiator length | | `radiator_W` | 0.025 | m | Overall radiator width | | `radiator_H` | 0.5 | m | Overall radiator height | | `radiator_N_tubes` | 25 | – | Number of coolant tubes | | `radiator_tube_H` | 0.0015 | m | Height of each coolant tube | | `radiator_fin_spacing` | 0.002 | – | Fin spacing | | `radiator_eta_fin` | 0.7 | – | Fin efficiency | | `radiator_t_wall` | 1e-4 | m | Material thickness | | `radiator_rho` | 2700 | **kg/s** *(sic)* | Vendor unit typo, should be kg/m³ (2700 = aluminium) | | `radiator_cp` | 910 | J/(kg·K) | Radiator material specific heat | ### Compressor map | Parameter | Value | Unit | |---|---|---| | `comp_p_ratio_TLU` | `[1; 1.25; 1.5; 1.75; 2]` | – (pressure ratio) | | `comp_rpm_TLU` | `[0, 1800, 3600]` | rpm | ```matlab comp_mdot_corr_TLU = [ 0, 0.05, 0.1; 0, 0.0375, 0.075; 0, 0.025, 0.05; 0, 0.0125, 0.025; 0, 0, 0] * 4; % [kg/s] Corrected mass flow rate table ``` ## Gas properties (shared by both files) | Gas | `_R` [J/(kg·K)] | `_D` [mm²/s] | |---|---:|---:| | H₂ | 4124.48151675695 | 74 | | O₂ | 259.836612622973 | 18 | | N₂ | 296.802103844292 | — | Each gas also carries 52-element lookup vectors sharing the temperature grid `_T = [-56.55, -50:10:-10, -5:1:5, 10:10:350]` °C, with `_h` in kJ/kg (specific enthalpy), `_mu` in µPa·s (dynamic viscosity), and `_k` in mW/(m·K) (thermal conductivity). ## What differs between the two models The two parameter files share identical gas property tables and identical membrane/MEA parameters. The substantive differences: | Aspect | Electrolyser | Fuel cell | |---|---|---| | `stack_num_cells` | 50 | **400** | | Limiting current density | — | `stack_iL = 1.4 A/cm²` | | Gas diffusion layer | Split anode/cathode (`_A` 25 µm / `_C` 250 µm) | Single `stack_t_gdl` = 250 µm | | Fuel storage | — | `tank_*` block, 120 L @ 70 MPa | | Air handling | — | `env_RH`, `env_yO2`, compressor map | | Cooling | Heat exchanger | Coolant channels + radiator | | Drive input | 24 h solar profile | Automotive drive cycle `.mat` | ## Supporting scripts Both folders ship MathWorks' plotting and example scripts, all copyright MathWorks: | Electrolyser | Fuel cell | |---|---| | `PEMElectrolysisSystemExample.m` | `PEMFuelCellSystemExample.m` | | `PEMElectrolysisSystemPlot1IV.m` | `PEMFuelCellSystemPlot1IV.m` | | `PEMElectrolysisSystemPlot2Power.m` | `PEMFuelCellSystemPlot2Power.m` | | `PEMElectrolysisSystemPlot3Hydrogen.m` | `PEMFuelCellSystemPlot3Efficiency.m` | | | `PEMFuelCellSystemPlot4T.m` | | | `PEMFuelCellSystemPlot5Energy.m` | The `Plot*.m` files carry polished vendor documentation citing textbook figures — for example *"The theoretical maximum efficiency for a PEM fuel cell is 83%. However, actual efficiency is around 60% due to internal losses"*, which lines up with the 40% fuel-cell loss figure in [AI Efficiency Improvements](../01-project/ai-efficiency-improvements.md). The `.ssc` component sources use the Simscape `foundation.moist_air.moist_air` and `foundation.thermal_liquid.thermal_liquid` domains. ## Related - [Simulink Model Inventory](simulink-model-inventory.md) — including the `Constants.m` staleness - [Simulator I/O Interface §1.1–1.3](../02-specifications/simulator-io-interface.md#11-electrolyser) — the parameters these should match - [UCSD Equipment Manual](../03-energy-management/ucsd-equipment-manual.md) — real-world PEM electrolyser specifications - [AI Efficiency Improvements](../01-project/ai-efficiency-improvements.md) — the loss targets - [Existing EST Model](existing-est-model.md) — the other vendored subtree