Compare commits
8 Commits
0e01d5e7be
...
cc1057a99b
Author | SHA1 | Date |
---|---|---|
|
cc1057a99b | |
|
e2a6541119 | |
|
dd86a1a83a | |
|
38709c03ac | |
|
77b80a31fc | |
|
138e33e5b6 | |
|
14bd6605bc | |
|
eb171fd424 |
2
.flake8
2
.flake8
|
@ -14,7 +14,7 @@ exclude =
|
||||||
dist,
|
dist,
|
||||||
.conda,
|
.conda,
|
||||||
tests/autogenerated_*,
|
tests/autogenerated_*,
|
||||||
docs/source/_autogenerated
|
docs/source/api
|
||||||
.venv,
|
.venv,
|
||||||
venv
|
venv
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-deploy:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
@ -41,8 +41,24 @@ jobs:
|
||||||
rm ./source/*.rst
|
rm ./source/*.rst
|
||||||
make html
|
make html
|
||||||
touch ./build/html/.nojekyll
|
touch ./build/html/.nojekyll
|
||||||
- name: Deploy to GitHub Pages
|
mkdir -p ./build/html/_autogenerated
|
||||||
uses: JamesIves/github-pages-deploy-action@v4
|
cp ./build/html/api/* ./build/html/_autogenerated/
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-pages-artifact@v3
|
||||||
with:
|
with:
|
||||||
branch: gh-pages
|
path: docs/build/html
|
||||||
folder: 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
|
|
@ -10,6 +10,10 @@ jobs:
|
||||||
name: Build and publish
|
name: Build and publish
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
environment:
|
||||||
|
name: pypi
|
||||||
|
url: https://pypi.org/project/${{ github.event.repository.name }}/
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ __pycache__
|
||||||
.pytest_cache
|
.pytest_cache
|
||||||
tests/autogenerated_*.py
|
tests/autogenerated_*.py
|
||||||
docs/build/
|
docs/build/
|
||||||
docs/source/_autogenerated/
|
docs/source/api/
|
||||||
venv/
|
venv/
|
||||||
.venv/
|
.venv/
|
||||||
thermo_data/combined_data.yaml
|
thermo_data/combined_data.yaml
|
||||||
|
|
|
@ -27,7 +27,7 @@ def write_classes(f: TextIOWrapper, patterns: list[str], module_name: str, title
|
||||||
write_dochtree(f, title, classes)
|
write_dochtree(f, title, classes)
|
||||||
|
|
||||||
for cls in 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(f'# {module_name}.{cls}\n')
|
||||||
f2.write('```{eval-rst}\n')
|
f2.write('```{eval-rst}\n')
|
||||||
f2.write(f'.. autoclass:: {module_name}.{cls}\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)
|
module = importlib.import_module(module_name)
|
||||||
|
|
||||||
functions = [
|
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))
|
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:
|
for func in functions:
|
||||||
if not func.startswith('_'):
|
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(f'# {module_name}.{func}\n')
|
||||||
f2.write('```{eval-rst}\n')
|
f2.write('```{eval-rst}\n')
|
||||||
f2.write(f'.. autofunction:: {module_name}.{func}\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__":
|
if __name__ == "__main__":
|
||||||
# Ensure the output directory exists
|
# 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')
|
f.write('# Classes and functions\n\n')
|
||||||
|
|
||||||
write_classes(f, ['*'], 'gaspype', title='Classes')
|
write_classes(f, ['*'], 'gaspype', title='Classes')
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
```{toctree}
|
```{toctree}
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
:hidden:
|
:hidden:
|
||||||
_autogenerated/index
|
api/index
|
||||||
_autogenerated/examples
|
api/examples
|
||||||
|
repo
|
||||||
```
|
```
|
||||||
|
|
||||||
```{include} ../../README.md
|
```{include} ../../README.md
|
||||||
|
|
|
@ -51,7 +51,7 @@ def render_examples(filter: str, example_file: str):
|
||||||
f.write('## Download Jupyter Notebooks\n\n')
|
f.write('## Download Jupyter Notebooks\n\n')
|
||||||
for path, name in zip(files, names):
|
for path, name in zip(files, names):
|
||||||
if name.lower() != 'readme':
|
if name.lower() != 'readme':
|
||||||
run_rendering(path, 'docs/source/_autogenerated')
|
run_rendering(path, 'docs/source/api')
|
||||||
notebook = name + '.ipynb'
|
notebook = name + '.ipynb'
|
||||||
f.write(f'- [{notebook}]({notebook})\n\n')
|
f.write(f'- [{notebook}]({notebook})\n\n')
|
||||||
|
|
||||||
|
@ -63,4 +63,4 @@ def render_examples(filter: str, example_file: str):
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
render_examples('examples/*.md', 'docs/source/_autogenerated/examples.md')
|
render_examples('examples/*.md', 'docs/source/api/examples.md')
|
||||||
|
|
|
@ -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).
|
|
@ -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:
|
[docs/source/render_examples.py](../docs/source/render_examples.py) script:
|
||||||
``` bash
|
``` bash
|
||||||
# Converting markdown with code sections to Jupyter Notebook and run it:
|
# 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
|
# Converting the Jupyter Notebook to Markdown and a folder with image
|
||||||
# files placed in docs/source/_autogenerated/:
|
# files placed in docs/source/api/:
|
||||||
jupyter nbconvert --to markdown docs/source/_autogenerated/soec_methane.ipynb --output soec_methane.md
|
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
|
A new example Markdown file can be created from a Jupyter Notebook running
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# SOEC Co-Electrolysis
|
# SOEC Co-Electrolysis
|
||||||
|
|
||||||
This example shows a 1D isothermal SOEC (Solid oxide electrolyzer cell) model.
|
This example shows a 1D isothermal SOEC (Solid oxide electrolyzer cell) model for
|
||||||
Converting CO2 and H2 into syngas.
|
converting carbon dioxide and steam into syngas.
|
||||||
|
|
||||||
The operating parameters chosen here are not necessarily realistic. For example,
|
The operating parameters chosen here are not necessarily realistic. For example,
|
||||||
a utilization of 0.95 causes issues with the formation of solid carbon.
|
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'])
|
ax.legend(['o2_fuel_side', 'o2_air_side'])
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
The high oxygen partial pressure at the inlet is in reality lower.
|
The high oxygen partial pressure at the inlet is in reality lower.
|
||||||
The assumption that gas inter-diffusion in the flow direction is slower
|
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
|
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
|
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
|
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:
|
Calculation of the local nernst potential between fuel and air side:
|
||||||
```python
|
```python
|
||||||
|
|
|
@ -116,3 +116,26 @@ ax.set_ylabel("Current density / A/cm²")
|
||||||
ax.plot(z_position, node_current, '-')
|
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} %")
|
||||||
|
```
|
||||||
|
|
|
@ -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
|
ret_block_flag = lines[-1] if (not re.match(r'^[^(]*=', lines[-1]) and
|
||||||
not lines[-1].startswith('import ') and
|
not lines[-1].startswith('import ') and
|
||||||
not lines[-1].startswith('from ') and
|
not lines[-1].startswith('from ') and
|
||||||
|
not lines[-1].startswith('print(') and
|
||||||
not lines[-1].startswith(' ')) else None
|
not lines[-1].startswith(' ')) else None
|
||||||
# print('Last line: ', ret_block_flag, '-----------', lines[-1])
|
# print('Last line: ', ret_block_flag, '-----------', lines[-1])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue