Compare commits

..

8 Commits

Author SHA1 Message Date
Nicolas cc1057a99b CD for pypi: environment added 2025-07-28 17:11:23 +02:00
Nicolas e2a6541119 Docs: Link to repo added 2025-07-28 17:11:23 +02:00
Nicolas dd86a1a83a doc path renamed to "api" 2025-07-28 17:11:23 +02:00
Nicolas Kruse 38709c03ac md_to_code.py updated to handle print functions in the last line 2025-07-28 15:06:32 +02:00
Nicolas Kruse 77b80a31fc sofc example fixes of the extension 2025-07-28 15:06:32 +02:00
Nicolas 138e33e5b6 sofc example extended 2025-07-28 15:06:32 +02:00
Nicolas 14bd6605bc switched docs deployment method 2025-07-28 15:06:32 +02:00
Nicolas eb171fd424 fix in SOEC example 2025-07-28 15:06:32 +02:00
12 changed files with 70 additions and 23 deletions

View File

@ -14,7 +14,7 @@ exclude =
dist,
.conda,
tests/autogenerated_*,
docs/source/_autogenerated
docs/source/api
.venv,
venv

View File

@ -9,7 +9,7 @@ permissions:
contents: write
jobs:
build-and-deploy:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@ -41,8 +41,24 @@ jobs:
rm ./source/*.rst
make html
touch ./build/html/.nojekyll
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@v4
mkdir -p ./build/html/_autogenerated
cp ./build/html/api/* ./build/html/_autogenerated/
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
branch: gh-pages
folder: docs/build/html
path: docs/build/html
deploy:
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

View File

@ -10,6 +10,10 @@ jobs:
name: Build and publish
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/${{ github.event.repository.name }}/
steps:
- uses: actions/checkout@v3

2
.gitignore vendored
View File

@ -9,7 +9,7 @@ __pycache__
.pytest_cache
tests/autogenerated_*.py
docs/build/
docs/source/_autogenerated/
docs/source/api/
venv/
.venv/
thermo_data/combined_data.yaml

View File

@ -27,7 +27,7 @@ def write_classes(f: TextIOWrapper, patterns: list[str], module_name: str, title
write_dochtree(f, title, classes)
for cls in classes:
with open(f'docs/source/_autogenerated/{cls}.md', 'w') as f2:
with open(f'docs/source/api/{cls}.md', 'w') as f2:
f2.write(f'# {module_name}.{cls}\n')
f2.write('```{eval-rst}\n')
f2.write(f'.. autoclass:: {module_name}.{cls}\n')
@ -43,7 +43,7 @@ def write_functions(f: TextIOWrapper, patterns: list[str], module_name: str, tit
module = importlib.import_module(module_name)
functions = [
name for name, obj in inspect.getmembers(module, inspect.isfunction)
name for name, _ in inspect.getmembers(module, inspect.isfunction)
if (any(fnmatch.fnmatch(name, pat) for pat in patterns if pat not in exclude))
]
@ -54,7 +54,7 @@ def write_functions(f: TextIOWrapper, patterns: list[str], module_name: str, tit
for func in functions:
if not func.startswith('_'):
with open(f'docs/source/_autogenerated/{func}.md', 'w') as f2:
with open(f'docs/source/api/{func}.md', 'w') as f2:
f2.write(f'# {module_name}.{func}\n')
f2.write('```{eval-rst}\n')
f2.write(f'.. autofunction:: {module_name}.{func}\n')
@ -74,9 +74,9 @@ def write_dochtree(f: TextIOWrapper, title: str, items: list[str]):
if __name__ == "__main__":
# Ensure the output directory exists
os.makedirs('docs/source/_autogenerated', exist_ok=True)
os.makedirs('docs/source/api', exist_ok=True)
with open('docs/source/_autogenerated/index.md', 'w') as f:
with open('docs/source/api/index.md', 'w') as f:
f.write('# Classes and functions\n\n')
write_classes(f, ['*'], 'gaspype', title='Classes')

View File

@ -1,8 +1,9 @@
```{toctree}
:maxdepth: 1
:hidden:
_autogenerated/index
_autogenerated/examples
api/index
api/examples
repo
```
```{include} ../../README.md

View File

@ -51,7 +51,7 @@ def render_examples(filter: str, example_file: str):
f.write('## Download Jupyter Notebooks\n\n')
for path, name in zip(files, names):
if name.lower() != 'readme':
run_rendering(path, 'docs/source/_autogenerated')
run_rendering(path, 'docs/source/api')
notebook = name + '.ipynb'
f.write(f'- [{notebook}]({notebook})\n\n')
@ -63,4 +63,4 @@ def render_examples(filter: str, example_file: str):
if __name__ == "__main__":
render_examples('examples/*.md', 'docs/source/_autogenerated/examples.md')
render_examples('examples/*.md', 'docs/source/api/examples.md')

3
docs/source/repo.md Normal file
View File

@ -0,0 +1,3 @@
# Code repository
Code repository is on GitHub: [github.com/DLR-Institute-of-Future-Fuels/gaspype](https://github.com/DLR-Institute-of-Future-Fuels/gaspype).

View File

@ -11,11 +11,11 @@ The conversion is done like the following automated by the
[docs/source/render_examples.py](../docs/source/render_examples.py) script:
``` bash
# Converting markdown with code sections to Jupyter Notebook and run it:
notedown examples/soec_methane.md --to notebook --output docs/source/_autogenerated/soec_methane.ipynb --run
notedown examples/soec_methane.md --to notebook --output docs/source/api/soec_methane.ipynb --run
# Converting the Jupyter Notebook to Markdown and a folder with image
# files placed in docs/source/_autogenerated/:
jupyter nbconvert --to markdown docs/source/_autogenerated/soec_methane.ipynb --output soec_methane.md
# files placed in docs/source/api/:
jupyter nbconvert --to markdown docs/source/api/soec_methane.ipynb --output soec_methane.md
```
A new example Markdown file can be created from a Jupyter Notebook running

View File

@ -1,7 +1,7 @@
# SOEC Co-Electrolysis
This example shows a 1D isothermal SOEC (Solid oxide electrolyzer cell) model.
Converting CO2 and H2 into syngas.
This example shows a 1D isothermal SOEC (Solid oxide electrolyzer cell) model for
converting carbon dioxide and steam into syngas.
The operating parameters chosen here are not necessarily realistic. For example,
a utilization of 0.95 causes issues with the formation of solid carbon.
@ -66,13 +66,12 @@ ax.plot(conversion, np.stack([o2_fuel_side, o2_air_side], axis=1), '-')
ax.legend(['o2_fuel_side', 'o2_air_side'])
```
The high oxygen partial pressure at the inlet is in reality lower.
The assumption that gas inter-diffusion in the flow direction is slower
than the gas velocity does not hold at this very high gradient. However
often the oxygen partial pressure is still to high to prevent oxidation of the
cell/electrode. This can be effectively prevented by recycling small amounts of
the output gas.
the hydrogen riche output gas.
Calculation of the local nernst potential between fuel and air side:
```python

View File

@ -116,3 +116,26 @@ ax.set_ylabel("Current density / A/cm²")
ax.plot(z_position, node_current, '-')
```
Based on the cell current and voltage the energy balance can be calculated.
In the following the electric cell output power (often referred to as "DC power")
and lower heating value (LHV) are calculated. The numbers here are per cell area for
being cell and stack size independent. The quotient of both is often referred to as
LHV based DC efficiency.
```python
dc_power = cell_voltage * terminal_current # W/cm²
print(f"DC power: {dc_power:.2f} W/cm²")
lhv = gp.fluid({'CH4': 1, 'H2O': -2, 'CO2': -1}).get_H(25 + 273.15) # J/mol (LHV of methane)
# LHV based chemical input power:
lhv_power = lhv * terminal_current / (2 * z_O2 * F) # W/cm² (two O2 per CH4 for full oxidation)
efficiency = dc_power / lhv_power
print(f"LHV based DC efficiency: {efficiency*100:.1f} %")
# Or by shortening the therms:
lhv_voltage = lhv / (2 * z_O2 * F) # V
print(f"LHV voltage: {lhv_voltage:.2f} V")
efficiency = cell_voltage / lhv_voltage # LHV based DC efficiency
print(f"LHV based DC efficiency: {efficiency*100:.1f} %")
```

View File

@ -96,6 +96,7 @@ def segments_to_test(segments: Iterable[markdown_segment], script_language: str
ret_block_flag = lines[-1] if (not re.match(r'^[^(]*=', lines[-1]) and
not lines[-1].startswith('import ') and
not lines[-1].startswith('from ') and
not lines[-1].startswith('print(') and
not lines[-1].startswith(' ')) else None
# print('Last line: ', ret_block_flag, '-----------', lines[-1])